merge with master

This commit is contained in:
Andrew J. Kroll 2017-08-14 04:17:57 -04:00
commit d0e32182cb
124 changed files with 4878 additions and 941 deletions

78
.travis.yml Normal file
View file

@ -0,0 +1,78 @@
language: python
python:
- "2.7"
# Cache PlatformIO packages using Travis CI container-based infrastructure
sudo: false
cache:
directories:
- "~/.platformio"
# Generated using: find examples -type f -name "*.ino" | rev | cut -d/ -f2- | rev | sed 's/^/ - PLATFORMIO_CI_SRC=/' > tmp.yml
env:
- PLATFORMIO_CI_SRC=examples/acm/acm_terminal
- PLATFORMIO_CI_SRC=examples/adk/adk_barcode
- PLATFORMIO_CI_SRC=examples/adk/ArduinoBlinkLED
- PLATFORMIO_CI_SRC=examples/adk/demokit_20
- PLATFORMIO_CI_SRC=examples/adk/term_test
- PLATFORMIO_CI_SRC=examples/adk/term_time
- PLATFORMIO_CI_SRC=examples/Bluetooth/BTHID
- PLATFORMIO_CI_SRC=examples/Bluetooth/PS3BT
- PLATFORMIO_CI_SRC=examples/Bluetooth/PS3Multi
- PLATFORMIO_CI_SRC=examples/Bluetooth/PS3SPP
- PLATFORMIO_CI_SRC=examples/Bluetooth/PS4BT
- PLATFORMIO_CI_SRC=examples/Bluetooth/SPP
- PLATFORMIO_CI_SRC=examples/Bluetooth/SPPMulti
- PLATFORMIO_CI_SRC=examples/Bluetooth/Wii
- PLATFORMIO_CI_SRC=examples/Bluetooth/WiiBalanceBoard
- PLATFORMIO_CI_SRC=examples/Bluetooth/WiiIRCamera PLATFORMIO_BUILD_FLAGS="-DWIICAMERA"
- PLATFORMIO_CI_SRC=examples/Bluetooth/WiiMulti
- PLATFORMIO_CI_SRC=examples/Bluetooth/WiiUProController
- PLATFORMIO_CI_SRC=examples/board_qc
- PLATFORMIO_CI_SRC=examples/cdc_XR21B1411/XR_terminal
- PLATFORMIO_CI_SRC=examples/ftdi/USBFTDILoopback
- PLATFORMIO_CI_SRC=examples/HID/le3dp
- PLATFORMIO_CI_SRC=examples/HID/scale
- PLATFORMIO_CI_SRC=examples/HID/SRWS1
- PLATFORMIO_CI_SRC=examples/HID/USBHID_desc
- PLATFORMIO_CI_SRC=examples/HID/USBHIDBootKbd
- PLATFORMIO_CI_SRC=examples/HID/USBHIDBootKbdAndMouse
- PLATFORMIO_CI_SRC=examples/HID/USBHIDBootMouse
- PLATFORMIO_CI_SRC=examples/HID/USBHIDJoystick
- PLATFORMIO_CI_SRC=examples/HID/USBHIDMultimediaKbd
- PLATFORMIO_CI_SRC=examples/hub_demo
- PLATFORMIO_CI_SRC=examples/max_LCD
- PLATFORMIO_CI_SRC=examples/pl2303/pl2303_gprs_terminal
- PLATFORMIO_CI_SRC=examples/pl2303/pl2303_gps
- PLATFORMIO_CI_SRC=examples/pl2303/pl2303_tinygps
- PLATFORMIO_CI_SRC=examples/pl2303/pl2303_xbee_terminal
- PLATFORMIO_CI_SRC=examples/PS3USB
- PLATFORMIO_CI_SRC=examples/PS4USB
- PLATFORMIO_CI_SRC=examples/PSBuzz
# - PLATFORMIO_CI_SRC=examples/testusbhostFAT
- PLATFORMIO_CI_SRC=examples/USB_desc
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/bidirectional_converter
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/eVY1_sample
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter_multi
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/USBH_MIDI_dump
- PLATFORMIO_CI_SRC=examples/Xbox/XBOXOLD
- PLATFORMIO_CI_SRC=examples/Xbox/XBOXONE
- PLATFORMIO_CI_SRC=examples/Xbox/XBOXRECV
- PLATFORMIO_CI_SRC=examples/Xbox/XBOXUSB
install:
- pip install -U platformio
- export PLATFORMIO_BUILD_FLAGS="$PLATFORMIO_BUILD_FLAGS -DDEBUG_USB_HOST -Wall -Werror"
#
# Libraries from PlatformIO Library Registry:
#
# http://platformio.org/lib/show/62/MIDI
# http://platformio.org/lib/show/416/TinyGPS
# http://platformio.org/lib/show/417/SPI4Teensy3
- platformio lib install 62 416 417
script:
- platformio ci --lib="." --board=uno --board=due --board=genuino101 --board=teensy30 --board=teensy31 --board=teensy35 --board=teensy36 --board=teensylc
- platformio ci --lib="." --board=esp12e --board=nodemcu --project-option="build_flags=-Wno-unused-function" # Workaround https://github.com/esp8266/Arduino/pull/2881

105
BTD.cpp Executable file → Normal file
View file

@ -101,6 +101,9 @@ uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
}
if (udd->bDeviceClass == 0x09) // Some dongles have an USB hub inside
goto FailHub;
epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor
epInfo[1].epAddr = udd->bNumConfigurations; // Steal and abuse from epInfo structure to save memory
@ -109,6 +112,15 @@ uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
FailHub:
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPlease create a hub instance in your code: \"USBHub Hub1(&Usb);\""), 0x80);
#endif
pUsb->setAddr(bAddress, 0, 0); // Reset address
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
Release();
return rcode;
FailGetDevDescr:
#ifdef DEBUG_USB_HOST
NotifyFailGetDevDescr(rcode);
@ -242,7 +254,7 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command
hci_counter = 0;
hci_state = HCI_INIT_STATE;
watingForConnection = false;
waitingForConnection = false;
bPollEnable = true;
#ifdef DEBUG_USB_HOST
@ -290,7 +302,8 @@ void BTD::Initialize() {
for(i = 0; i < BTD_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
for(i = 0; i < BTD_NUM_SERVICES; i++) {
@ -371,8 +384,8 @@ uint8_t BTD::Release() {
uint8_t BTD::Poll() {
if(!bPollEnable)
return 0;
if((long)(millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval
qNextPollTime = millis() + pollInterval; // Set new poll time
if((int32_t)((uint32_t)millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval
qNextPollTime = (uint32_t)millis() + pollInterval; // Set new poll time
HCI_event_task(); // Poll the HCI event pipe
HCI_task(); // HCI state machine
ACL_event_task(); // Poll the ACL input pipe too
@ -388,7 +401,7 @@ void BTD::disconnect() {
void BTD::HCI_event_task() {
uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf); // Input on endpoint 1
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf, pollInterval); // Input on endpoint 1
if(!rcode || rcode == hrNAK) { // Check for errors
switch(hcibuf[0]) { // Switch on event type
@ -445,11 +458,17 @@ void BTD::HCI_event_task() {
for(uint8_t j = 0; j < 3; j++)
classOfDevice[j] = hcibuf[j + 4 + offset];
#ifdef EXTRADEBUG
Notify(PSTR("\r\nClass of device: "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
#endif
if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information
if(classOfDevice[0] & 0x08) // Check if it's the new Wiimote with motion plus inside that was detected
motionPlusInside = true;
else
motionPlusInside = false;
checkRemoteName = true; // Check remote name to distinguish between the different controllers
for(uint8_t j = 0; j < 6; j++)
disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];
@ -472,16 +491,6 @@ void BTD::HCI_event_task() {
hci_set_flag(HCI_FLAG_DEVICE_FOUND);
break;
}
#ifdef EXTRADEBUG
else {
Notify(PSTR("\r\nClass of device: "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
Notify(PSTR(" "), 0x80);
D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
}
#endif
}
}
break;
@ -555,7 +564,7 @@ void BTD::HCI_event_task() {
case EV_PIN_CODE_REQUEST:
if(pairWithWii) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPairing with wiimote"), 0x80);
Notify(PSTR("\r\nPairing with Wiimote"), 0x80);
#endif
hci_pin_code_request_reply();
} else if(btdPin != NULL) {
@ -580,16 +589,25 @@ void BTD::HCI_event_task() {
break;
case EV_AUTHENTICATION_COMPLETE:
if(pairWithWii && !connectToWii) {
if(!hcibuf[2]) { // Check if pairing was successful
if(pairWithWii && !connectToWii) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80);
Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80);
#endif
connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device
} else if(pairWithHIDDevice && !connectToHIDDevice) {
connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device
} else if(pairWithHIDDevice && !connectToHIDDevice) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPairing successful with HID device"), 0x80);
Notify(PSTR("\r\nPairing successful with HID device"), 0x80);
#endif
connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device
connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device
}
} else {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nPairing Failed: "), 0x80);
D_PrintHex<uint8_t > (hcibuf[2], 0x80);
#endif
hci_disconnect(hci_handle);
hci_state = HCI_DISCONNECT_STATE;
}
break;
/* We will just ignore the following events */
@ -705,7 +723,7 @@ void BTD::HCI_task() {
if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote
#ifdef DEBUG_USB_HOST
if(pairWithWii)
Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press sync if you are using a Wii U Pro Controller"), 0x80);
Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press the SYNC button if you are using a Wii U Pro Controller or a Wii Balance Board"), 0x80);
else
Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80);
#endif
@ -736,8 +754,8 @@ void BTD::HCI_task() {
else
Notify(PSTR("device"), 0x80);
#endif
if(motionPlusInside) {
hci_remote_name(); // We need to know the name to distinguish between a Wiimote and a Wii U Pro Controller
if(checkRemoteName) {
hci_remote_name(); // We need to know the name to distinguish between the Wiimote, the new Wiimote with Motion Plus inside, a Wii U Pro Controller and a Wii Balance Board
hci_state = HCI_REMOTE_NAME_STATE;
} else
hci_state = HCI_CONNECT_DEVICE_STATE;
@ -752,6 +770,7 @@ void BTD::HCI_task() {
else
Notify(PSTR("\r\nConnecting to HID device"), 0x80);
#endif
checkRemoteName = false;
hci_connect();
hci_state = HCI_CONNECTED_DEVICE_STATE;
}
@ -783,14 +802,14 @@ void BTD::HCI_task() {
Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80);
#endif
hci_write_scan_enable();
watingForConnection = true;
waitingForConnection = true;
hci_state = HCI_CONNECT_IN_STATE;
}
break;
case HCI_CONNECT_IN_STATE:
if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) {
watingForConnection = false;
waitingForConnection = false;
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nIncoming Connection Request"), 0x80);
#endif
@ -809,6 +828,9 @@ void BTD::HCI_task() {
#endif
if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
incomingWii = true;
motionPlusInside = false;
wiiUProController = false;
pairWiiUsingSync = false;
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWiimote is connecting"), 0x80);
#endif
@ -821,11 +843,12 @@ void BTD::HCI_task() {
#ifdef DEBUG_USB_HOST
Notify(PSTR(" - Wii U Pro Controller"), 0x80);
#endif
motionPlusInside = true;
wiiUProController = true;
} else {
motionPlusInside = false;
wiiUProController = false;
wiiUProController = motionPlusInside = pairWiiUsingSync = true;
} else if(strncmp((const char*)remote_name, "Nintendo RVL-WBC-01", 19) == 0) {
#ifdef DEBUG_USB_HOST
Notify(PSTR(" - Wii Balance Board"), 0x80);
#endif
pairWiiUsingSync = true;
}
}
if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) {
@ -834,7 +857,7 @@ void BTD::HCI_task() {
#endif
incomingPS4 = true;
}
if(pairWithWii && motionPlusInside)
if(pairWithWii && checkRemoteName)
hci_state = HCI_CONNECT_DEVICE_STATE;
else {
hci_accept_connection();
@ -886,7 +909,7 @@ void BTD::HCI_task() {
memset(l2capinbuf, 0, BULK_MAXPKTSIZE);
connectToWii = incomingWii = pairWithWii = false;
connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = false;
connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false;
incomingPS4 = false;
hci_state = HCI_SCANNING_STATE;
@ -899,7 +922,7 @@ void BTD::HCI_task() {
void BTD::ACL_event_task() {
uint16_t length = BULK_MAXPKTSIZE;
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf); // Input on endpoint 2
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf, pollInterval); // Input on endpoint 2
if(!rcode) { // Check for errors
if(length > 0) { // Check if any data was read
@ -1085,9 +1108,9 @@ void BTD::hci_pin_code_request_reply() {
hcibuf[8] = disc_bdaddr[5];
if(pairWithWii) {
hcibuf[9] = 6; // Pin length is the length of the Bluetooth address
if(wiiUProController) {
if(pairWiiUsingSync) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nParing with Wii U Pro Controller"), 0x80);
Notify(PSTR("\r\nPairing with Wii controller via SYNC"), 0x80);
#endif
for(uint8_t i = 0; i < 6; i++)
hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards

13
BTD.h Executable file → Normal file
View file

@ -19,7 +19,7 @@
#define _btd_h_
#include "Usb.h"
#include "hid.h"
#include "usbhid.h"
//PID and VID of the Sony PS3 devices
#define PS3_VID 0x054C // Sony Corporation
@ -432,7 +432,7 @@ public:
/**@}*/
/** Use this to see if it is waiting for a incoming connection. */
bool watingForConnection;
bool waitingForConnection;
/** This is used by the service to know when to store the device information. */
bool l2capConnectionClaimed;
/** This is used by the SPP library to claim the current SDP incoming request. */
@ -476,14 +476,15 @@ public:
/** True if it's a Wii U Pro Controller. */
bool wiiUProController;
/** Call this function to pair with a Wiimote */
/** Call this function to pair with a HID device */
void pairWithHID() {
waitingForConnection = false;
pairWithHIDDevice = true;
hci_state = HCI_CHECK_DEVICE_SERVICE;
};
/** Used to only send the ACL data to the Wiimote. */
/** Used to only send the ACL data to the HID device. */
bool connectToHIDDevice;
/** True if a Wiimote is connecting. */
/** True if a HID device is connecting. */
bool incomingHIDDevice;
/** True when it should pair with a device like a mouse or keyboard. */
bool pairWithHIDDevice;
@ -535,6 +536,8 @@ private:
uint8_t pollInterval;
bool bPollEnable;
bool pairWiiUsingSync; // True if pairing was done using the Wii SYNC button.
bool checkRemoteName; // Used to check remote device's name before connecting.
bool incomingPS4; // True if a PS4 controller is connecting
uint8_t classOfDevice[3]; // Class of device of last device

View file

@ -22,7 +22,7 @@
BTHID::BTHID(BTD *p, bool pair, const char *pin) :
BluetoothService(p), // Pointer to USB class instance - mandatory
protocolMode(HID_BOOT_PROTOCOL) {
protocolMode(USB_HID_BOOT_PROTOCOL) {
for(uint8_t i = 0; i < NUM_PARSERS; i++)
pRptParser[i] = NULL;
@ -192,12 +192,12 @@ void BTHID::ACLData(uint8_t* l2capinbuf) {
switch(l2capinbuf[9]) {
case 0x01: // Keyboard or Joystick events
if(pRptParser[KEYBOARD_PARSER_ID])
pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
break;
case 0x02: // Mouse events
if(pRptParser[MOUSE_PARSER_ID])
pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<USBHID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
break;
#ifdef EXTRADEBUG
default:
@ -380,11 +380,11 @@ void BTHID::setProtocol() {
Notify(PSTR("\r\nSet protocol mode: "), 0x80);
D_PrintHex<uint8_t > (protocolMode, 0x80);
#endif
if (protocolMode != HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) {
if (protocolMode != USB_HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80);
#endif
protocolMode = HID_BOOT_PROTOCOL; // Use Boot Protocol by default
protocolMode = USB_HID_BOOT_PROTOCOL; // Use Boot Protocol by default
}
uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33
pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]);

11
BTHID.h
View file

@ -67,22 +67,27 @@ public:
/**
* Set HID protocol mode.
* @param mode HID protocol to use. Either HID_BOOT_PROTOCOL or HID_RPT_PROTOCOL.
* @param mode HID protocol to use. Either USB_HID_BOOT_PROTOCOL or HID_RPT_PROTOCOL.
*/
void setProtocolMode(uint8_t mode) {
protocolMode = mode;
};
/**@{*/
/**
* Used to set the leds on a keyboard.
* @param data See KBDLEDS in hidboot.h
* @param data See ::KBDLEDS in hidboot.h
*/
void setLeds(struct KBDLEDS data) {
setLeds(*((uint8_t*)&data));
};
void setLeds(uint8_t data);
/**@}*/
/** True if a device is connected */
bool connected;
/** Call this to start the paring sequence with a device */
/** Call this to start the pairing sequence with a device */
void pair(void) {
if(pBtd)
pBtd->pairWithHID();

View file

@ -82,15 +82,15 @@ int16_t PS3BT::getSensor(SensorEnum a) {
return 0;
}
double PS3BT::getAngle(AngleEnum a) {
double accXval, accYval, accZval;
float PS3BT::getAngle(AngleEnum a) {
float accXval, accYval, accZval;
if(PS3Connected) {
// Data for the Kionix KXPC4 used in the DualShock 3
const double zeroG = 511.5; // 1.65/3.3*1023 (1.65V)
accXval = -((double)getSensor(aX) - zeroG);
accYval = -((double)getSensor(aY) - zeroG);
accZval = -((double)getSensor(aZ) - zeroG);
const float zeroG = 511.5f; // 1.65/3.3*1023 (1.65V)
accXval = -((float)getSensor(aX) - zeroG);
accYval = -((float)getSensor(aY) - zeroG);
accZval = -((float)getSensor(aZ) - zeroG);
} else if(PS3MoveConnected) {
// It's a Kionix KXSC4 inside the Motion controller
const uint16_t zeroG = 0x8000;
@ -104,36 +104,36 @@ double PS3BT::getAngle(AngleEnum a) {
// atan2 outputs the value of -π to π (radians)
// We are then converting it to 0 to 2π and then to degrees
if(a == Pitch)
return (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
return (atan2f(accYval, accZval) + PI) * RAD_TO_DEG;
else
return (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
return (atan2f(accXval, accZval) + PI) * RAD_TO_DEG;
}
double PS3BT::get9DOFValues(SensorEnum a) { // Thanks to Manfred Piendl
float PS3BT::get9DOFValues(SensorEnum a) { // Thanks to Manfred Piendl
if(!PS3MoveConnected)
return 0;
int16_t value = getSensor(a);
if(a == mXmove || a == mYmove || a == mZmove) {
if(value > 2047)
value -= 0x1000;
return (double)value / 3.2; // unit: muT = 10^(-6) Tesla
return (float)value / 3.2f; // unit: muT = 10^(-6) Tesla
} else if(a == aXmove || a == aYmove || a == aZmove) {
if(value < 0)
value += 0x8000;
else
value -= 0x8000;
return (double)value / 442.0; // unit: m/(s^2)
return (float)value / 442.0f; // unit: m/(s^2)
} else if(a == gXmove || a == gYmove || a == gZmove) {
if(value < 0)
value += 0x8000;
else
value -= 0x8000;
if(a == gXmove)
return (double)value / 11.6; // unit: deg/s
return (float)value / 11.6f; // unit: deg/s
else if(a == gYmove)
return (double)value / 11.2; // unit: deg/s
return (float)value / 11.2f; // unit: deg/s
else // gZmove
return (double)value / 9.6; // unit: deg/s
return (float)value / 9.6f; // unit: deg/s
} else
return 0;
}
@ -158,9 +158,9 @@ bool PS3BT::getStatus(StatusEnum c) {
}
void PS3BT::printStatusString() {
char statusOutput[100]; // Max string length plus null character
char statusOutput[102]; // Max string length plus null character
if(PS3Connected || PS3NavigationConnected) {
strcpy_P(statusOutput, PSTR("ConnectionStatus: "));
strcpy_P(statusOutput, PSTR("\r\nConnectionStatus: "));
if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged"));
else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged"));
@ -185,7 +185,7 @@ void PS3BT::printStatusString() {
else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off"));
else strcat_P(statusOutput, PSTR("Error"));
} else if(PS3MoveConnected) {
strcpy_P(statusOutput, PSTR("PowerRating: "));
strcpy_P(statusOutput, PSTR("\r\nPowerRating: "));
if(getStatus(MoveCharging)) strcat_P(statusOutput, PSTR("Charging"));
else if(getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR("Not Charging"));
@ -196,7 +196,7 @@ void PS3BT::printStatusString() {
else if(getStatus(MoveFull)) strcat_P(statusOutput, PSTR("Full"));
else strcat_P(statusOutput, PSTR("Error"));
} else
strcpy_P(statusOutput, PSTR("Error"));
strcpy_P(statusOutput, PSTR("\r\nError"));
USB_HOST_SERIAL.write(statusOutput);
}
@ -339,7 +339,7 @@ void PS3BT::ACLData(uint8_t* ACLData) {
if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) {
/* Read Report */
if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
lastMessageTime = millis(); // Store the last message time
lastMessageTime = (uint32_t)millis(); // Store the last message time
if(PS3Connected || PS3NavigationConnected)
ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16));
@ -420,7 +420,7 @@ void PS3BT::L2CAP_task() {
l2cap_state = TURN_ON_LED;
} else
l2cap_state = PS3_ENABLE_SIXAXIS;
timer = millis();
timer = (uint32_t)millis();
}
break;
@ -454,18 +454,18 @@ void PS3BT::L2CAP_task() {
void PS3BT::Run() {
switch(l2cap_state) {
case PS3_ENABLE_SIXAXIS:
if(millis() - timer > 1000) { // loop 1 second before sending the command
if((int32_t)((uint32_t)millis() - timer) > 1000) { // loop 1 second before sending the command
memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
for(uint8_t i = 15; i < 19; i++)
l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position
enable_sixaxis();
l2cap_state = TURN_ON_LED;
timer = millis();
timer = (uint32_t)millis();
}
break;
case TURN_ON_LED:
if(millis() - timer > 1000) { // loop 1 second before sending the command
if((int32_t)((uint32_t)millis() - timer) > 1000) { // loop 1 second before sending the command
if(remote_name_first == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80);
@ -477,7 +477,7 @@ void PS3BT::Run() {
#endif
PS3NavigationConnected = true;
} else if(remote_name_first == 'M') { // First letter in Motion Controller ('M')
timer = millis();
timer = (uint32_t)millis();
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80);
#endif
@ -494,9 +494,9 @@ void PS3BT::Run() {
case L2CAP_DONE:
if(PS3MoveConnected) { // The Bulb and rumble values, has to be send at approximately every 5th second for it to stay on
if(millis() - timer > 4000) { // Send at least every 4th second
if((int32_t)((uint32_t)millis() - timer) > 4000) { // Send at least every 4th second
HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
timer = millis();
timer = (uint32_t)millis();
}
}
break;
@ -510,10 +510,10 @@ void PS3BT::Run() {
// Playstation Sixaxis Dualshock and Navigation Controller commands
void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) {
if(millis() - timerHID <= 150) // Check if is has been more than 150ms since last command
delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands
if((int32_t)((uint32_t)millis() - timerHID) <= 150) // Check if is has been more than 150ms since last command
delay((uint32_t)(150 - ((uint32_t)millis() - timerHID))); // There have to be a delay between commands
pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel
timerHID = millis();
timerHID = (uint32_t)millis();
}
void PS3BT::setAllOff() {
@ -528,12 +528,13 @@ void PS3BT::setAllOff() {
}
void PS3BT::setRumbleOff() {
HIDBuffer[3] = 0x00;
HIDBuffer[4] = 0x00;
HIDBuffer[5] = 0x00;
HIDBuffer[6] = 0x00;
HID_Command(HIDBuffer, HID_BUFFERSIZE);
uint8_t rumbleBuf[HID_BUFFERSIZE];
memcpy(rumbleBuf, HIDBuffer, HID_BUFFERSIZE);
rumbleBuf[3] = 0x00;
rumbleBuf[4] = 0x00;
rumbleBuf[5] = 0x00;
rumbleBuf[6] = 0x00;
HID_Command(rumbleBuf, HID_BUFFERSIZE);
}
void PS3BT::setRumbleOn(RumbleEnum mode) {
@ -546,11 +547,13 @@ void PS3BT::setRumbleOn(RumbleEnum mode) {
}
void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {
HIDBuffer[3] = rightDuration;
HIDBuffer[4] = rightPower;
HIDBuffer[5] = leftDuration;
HIDBuffer[6] = leftPower;
HID_Command(HIDBuffer, HID_BUFFERSIZE);
uint8_t rumbleBuf[HID_BUFFERSIZE];
memcpy(rumbleBuf, HIDBuffer, HID_BUFFERSIZE);
rumbleBuf[3] = rightDuration;
rumbleBuf[4] = rightPower;
rumbleBuf[5] = leftDuration;
rumbleBuf[6] = leftPower;
HID_Command(rumbleBuf, HID_BUFFERSIZE);
}
void PS3BT::setLedRaw(uint8_t value) {
@ -592,10 +595,10 @@ void PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Nav
// Playstation Move Controller commands
void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) {
if(millis() - timerHID <= 150)// Check if is has been less than 150ms since last command
delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands
if((int32_t)((uint32_t)millis() - timerHID) <= 150)// Check if is has been less than 150ms since last command
delay((uint32_t)(150 - ((uint32_t)millis() - timerHID))); // There have to be a delay between commands
pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel
timerHID = millis();
timerHID = (uint32_t)millis();
}
void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values
@ -629,6 +632,6 @@ void PS3BT::onInit() {
if(PS3MoveConnected)
moveSetBulb(Red);
else // Dualshock 3 or Navigation controller
setLedOn(LED1);
setLedOn(static_cast<LEDEnum>(LED1));
}
}

View file

@ -89,13 +89,13 @@ public:
* @param a Either ::Pitch or ::Roll.
* @return Return the angle in the range of 0-360.
*/
double getAngle(AngleEnum a);
float getAngle(AngleEnum a);
/**
* Read the sensors inside the Move controller.
* @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove.
* @return The value in SI units.
*/
double get9DOFValues(SensorEnum a);
float get9DOFValues(SensorEnum a);
/**
* Get the status from the controller.
* @param c The ::StatusEnum you want to read.

64
PS3USB.cpp Executable file → Normal file
View file

@ -28,7 +28,8 @@ bPollEnable(false) // don't start polling before dongle is connected
for(uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
@ -220,7 +221,7 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
bPollEnable = true;
Notify(PSTR("\r\n"), 0x80);
timer = millis();
timer = (uint32_t)millis();
return 0; // Successful configuration
/* Diagnostic messages */
@ -275,16 +276,16 @@ uint8_t PS3USB::Poll() {
if(PS3Connected || PS3NavigationConnected) {
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
if(millis() - timer > 100) { // Loop 100ms before processing data
if((int32_t)((uint32_t)millis() - timer) > 100) { // Loop 100ms before processing data
readReport();
#ifdef PRINTREPORT
printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
#endif
}
} else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB
if(millis() - timer > 4000) { // Send at least every 4th second
if((int32_t)((uint32_t)millis() - timer) > 4000) { // Send at least every 4th second
Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
timer = millis();
timer = (uint32_t)millis();
}
}
return 0;
@ -335,25 +336,23 @@ uint16_t PS3USB::getSensor(SensorEnum a) {
return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]);
}
double PS3USB::getAngle(AngleEnum a) {
float PS3USB::getAngle(AngleEnum a) {
if(PS3Connected) {
double accXval;
double accYval;
double accZval;
float accXval, accYval, accZval;
// Data for the Kionix KXPC4 used in the DualShock 3
const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V)
accXval = -((double)getSensor(aX) - zeroG);
accYval = -((double)getSensor(aY) - zeroG);
accZval = -((double)getSensor(aZ) - zeroG);
const float zeroG = 511.5f; // 1.65/3.3*1023 (1,65V)
accXval = -((float)getSensor(aX) - zeroG);
accYval = -((float)getSensor(aY) - zeroG);
accZval = -((float)getSensor(aZ) - zeroG);
// Convert to 360 degrees resolution
// atan2 outputs the value of -π to π (radians)
// We are then converting it to 0 to 2π and then to degrees
if(a == Pitch)
return (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
return (atan2f(accYval, accZval) + PI) * RAD_TO_DEG;
else
return (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
return (atan2f(accXval, accZval) + PI) * RAD_TO_DEG;
} else
return 0;
}
@ -363,9 +362,9 @@ bool PS3USB::getStatus(StatusEnum c) {
}
void PS3USB::printStatusString() {
char statusOutput[100]; // Max string length plus null character
char statusOutput[102]; // Max string length plus null character
if(PS3Connected || PS3NavigationConnected) {
strcpy_P(statusOutput, PSTR("ConnectionStatus: "));
strcpy_P(statusOutput, PSTR("\r\nConnectionStatus: "));
if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged"));
else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged"));
@ -390,7 +389,7 @@ void PS3USB::printStatusString() {
else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off"));
else strcat_P(statusOutput, PSTR("Error"));
} else
strcpy_P(statusOutput, PSTR("Error"));
strcpy_P(statusOutput, PSTR("\r\nError"));
USB_HOST_SERIAL.write(statusOutput);
}
@ -409,12 +408,13 @@ void PS3USB::setAllOff() {
}
void PS3USB::setRumbleOff() {
writeBuf[1] = 0x00;
writeBuf[2] = 0x00; // Low mode off
writeBuf[3] = 0x00;
writeBuf[4] = 0x00; // High mode off
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
uint8_t rumbleBuf[EP_MAXPKTSIZE];
memcpy(rumbleBuf, writeBuf, EP_MAXPKTSIZE);
rumbleBuf[1] = 0x00;
rumbleBuf[2] = 0x00; // Low mode off
rumbleBuf[3] = 0x00;
rumbleBuf[4] = 0x00; // High mode off
PS3_Command(rumbleBuf, PS3_REPORT_BUFFER_SIZE);
}
void PS3USB::setRumbleOn(RumbleEnum mode) {
@ -429,11 +429,13 @@ void PS3USB::setRumbleOn(RumbleEnum mode) {
}
void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {
writeBuf[1] = rightDuration;
writeBuf[2] = rightPower;
writeBuf[3] = leftDuration;
writeBuf[4] = leftPower;
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
uint8_t rumbleBuf[EP_MAXPKTSIZE];
memcpy(rumbleBuf, writeBuf, EP_MAXPKTSIZE);
rumbleBuf[1] = rightDuration;
rumbleBuf[2] = rightPower;
rumbleBuf[3] = leftDuration;
rumbleBuf[4] = leftPower;
PS3_Command(rumbleBuf, PS3_REPORT_BUFFER_SIZE);
}
void PS3USB::setLedRaw(uint8_t value) {
@ -555,7 +557,7 @@ void PS3USB::getMoveCalibration(uint8_t *data) {
// bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL);
for(byte j = 0; j < 49; j++)
for(uint8_t j = 0; j < 49; j++)
data[49 * i + j] = buf[j];
}
}
@ -567,6 +569,6 @@ void PS3USB::onInit() {
if(PS3MoveConnected)
moveSetBulb(Red);
else // Dualshock 3 or Navigation controller
setLedOn(LED1);
setLedOn(static_cast<LEDEnum>(LED1));
}
}

View file

@ -19,7 +19,7 @@
#define _ps3usb_h_
#include "Usb.h"
#include "hid.h"
#include "usbhid.h"
#include "PS3Enums.h"
/* PS3 data taken from descriptors */
@ -177,7 +177,7 @@ public:
* @param a Either ::Pitch or ::Roll.
* @return Return the angle in the range of 0-360.
*/
double getAngle(AngleEnum a);
float getAngle(AngleEnum a);
/**
* Get the ::StatusEnum from the controller.
* @param c The ::StatusEnum you want to read.

View file

@ -17,6 +17,18 @@
#include "PS4Parser.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 PS4 Controller
@ -62,7 +74,7 @@ uint8_t PS4Parser::getAnalogHat(AnalogHatEnum a) {
}
void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
if (len > 0 && buf) {
if (len > 1 && buf) {
#ifdef PRINTREPORT
Notify(PSTR("\r\n"), 0x80);
for (uint8_t i = 0; i < len; i++) {
@ -72,10 +84,17 @@ void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
#endif
if (buf[0] == 0x01) // Check report ID
memcpy(&ps4Data, buf + 1, min(len - 1, sizeof(ps4Data)));
else if (buf[0] == 0x11) // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
memcpy(&ps4Data, buf + 3, min(len - 3, sizeof(ps4Data)));
else {
memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), MFK_CASTUINT8T sizeof(ps4Data)));
else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
if (len < 4) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReport is too short: "), 0x80);
D_PrintHex<uint8_t > (len, 0x80);
#endif
return;
}
memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), MFK_CASTUINT8T sizeof(ps4Data)));
} else {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nUnknown report id: "), 0x80);
D_PrintHex<uint8_t > (buf[0], 0x80);
@ -107,3 +126,28 @@ void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
if (ps4Output.reportChanged)
sendOutputReport(&ps4Output); // Send output report
}
void PS4Parser::Reset() {
uint8_t i;
for (i = 0; i < sizeof(ps4Data.hatValue); i++)
ps4Data.hatValue[i] = 127; // Center value
ps4Data.btn.val = 0;
oldButtonState.val = 0;
for (i = 0; i < sizeof(ps4Data.trigger); i++)
ps4Data.trigger[i] = 0;
for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) {
for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++)
ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad
}
ps4Data.btn.dpad = DPAD_OFF;
oldButtonState.dpad = DPAD_OFF;
buttonClickState.dpad = 0;
oldDpad = 0;
ps4Output.bigRumble = ps4Output.smallRumble = 0;
ps4Output.r = ps4Output.g = ps4Output.b = 0;
ps4Output.flashOn = ps4Output.flashOff = 0;
ps4Output.reportChanged = false;
};

View file

@ -120,18 +120,6 @@ struct PS4Output {
bool reportChanged; // The data is send when data is received from the controller
} __attribute__((packed));
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,
};
/** This class parses all the data sent by the PS4 controller */
class PS4Parser {
public:
@ -225,11 +213,11 @@ public:
* @param a Either ::Pitch or ::Roll.
* @return Return the angle in the range of 0-360.
*/
double getAngle(AngleEnum a) {
float getAngle(AngleEnum a) {
if (a == Pitch)
return (atan2(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG;
return (atan2f(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG;
else
return (atan2(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG;
return (atan2f(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG;
};
/**
@ -366,29 +354,7 @@ protected:
void Parse(uint8_t len, uint8_t *buf);
/** Used to reset the different buffers to their default values */
void Reset() {
uint8_t i;
for (i = 0; i < sizeof(ps4Data.hatValue); i++)
ps4Data.hatValue[i] = 127; // Center value
ps4Data.btn.val = 0;
oldButtonState.val = 0;
for (i = 0; i < sizeof(ps4Data.trigger); i++)
ps4Data.trigger[i] = 0;
for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) {
for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++)
ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad
}
ps4Data.btn.dpad = DPAD_OFF;
oldButtonState.dpad = DPAD_OFF;
buttonClickState.dpad = 0;
oldDpad = 0;
ps4Output.bigRumble = ps4Output.smallRumble = 0;
ps4Output.r = ps4Output.g = ps4Output.b = 0;
ps4Output.flashOn = ps4Output.flashOff = 0;
ps4Output.reportChanged = false;
};
void Reset();
/**
* Send the output to the PS4 controller. This is implemented in PS4BT.h and PS4USB.h.

View file

@ -21,8 +21,9 @@
#include "hiduniversal.h"
#include "PS4Parser.h"
#define PS4_VID 0x054C // Sony Corporation
#define PS4_PID 0x05C4 // PS4 Controller
#define PS4_VID 0x054C // Sony Corporation
#define PS4_PID 0x05C4 // PS4 Controller
#define PS4_PID_SLIM 0x09CC // PS4 Slim Controller
/**
* This class implements support for the PS4 controller via USB.
@ -44,7 +45,7 @@ public:
* @return Returns true if it is connected.
*/
bool connected() {
return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID;
return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM);
};
/**
@ -64,8 +65,8 @@ protected:
* @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) {
if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID)
virtual void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
if (HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM))
PS4Parser::Parse(len, buf);
};
@ -75,7 +76,7 @@ protected:
* This is useful for instance if you want to set the LEDs in a specific way.
*/
virtual uint8_t OnInitSuccessful() {
if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) {
if (HIDUniversal::VID == PS4_VID && (HIDUniversal::PID == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM)) {
PS4Parser::Reset();
if (pFuncOnInit)
pFuncOnInit(); // Call the user function
@ -120,7 +121,7 @@ protected:
* @return Returns true if the device's VID and PID matches this driver.
*/
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
return (vid == PS4_VID && pid == PS4_PID);
return (vid == PS4_VID && (pid == PS4_PID || HIDUniversal::PID == PS4_PID_SLIM));
};
/**@}*/

View file

@ -20,8 +20,8 @@
// 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) {
void PSBuzz::ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 2 && buf) {
#ifdef PRINTREPORT
Notify(PSTR("\r\n"), 0x80);
for (uint8_t i = 0; i < len; i++) {
@ -29,7 +29,7 @@ void PSBuzz::ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
Notify(PSTR(" "), 0x80);
}
#endif
memcpy(&psbuzzButtons, buf + 2, min(len - 2, sizeof(psbuzzButtons)));
memcpy(&psbuzzButtons, buf + 2, min((uint8_t)(len - 2), MFK_CASTUINT8T sizeof(psbuzzButtons)));
if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed
buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable

View file

@ -143,7 +143,7 @@ protected:
* @param len The length of the incoming data.
* @param buf Pointer to the data buffer.
*/
void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
/**
* Called when a device is successfully initialized.

View file

@ -2,6 +2,7 @@
The code is released under the GNU General Public License.
__________
[![Build Status](https://travis-ci.org/felis/USB_Host_Shield_2.0.svg?branch=master)](https://travis-ci.org/felis/USB_Host_Shield_2.0)
# Summary
This is Revision 2.0 of MAX3421E-based USB Host Shield Library for AVR's.
@ -12,7 +13,7 @@ Some information can also be found at: <http://blog.tkjelectronics.dk/>.
The shield can be purchased at the main site: <http://www.circuitsathome.com/products-page/arduino-shields> or from [TKJ Electronics](http://tkjelectronics.com/): <http://shop.tkjelectronics.dk/product_info.php?products_id=43>.
![USB Host Shield](http://www.circuitsathome.com/wp/wp-content/uploads/2012/02/UHS_20_main-288x216.jpg)
![USB Host Shield](http://shop.tkjelectronics.dk/images/USB_Host_Shield1.jpg)
For more information about the hardware see the [Hardware Manual](http://www.circuitsathome.com/usb-host-shield-hardware-manual).
@ -25,6 +26,10 @@ For more information about the hardware see the [Hardware Manual](http://www.cir
* 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
* __guruthree__
* [Xbox ONE](#xbox-one-library) controller support
* __Yuuichi Akagawa__ - [@YuuichiAkagawa](https://twitter.com/yuuichiakagawa)
* Developer of the [MIDI](#midi-library) library
# Donate
@ -35,6 +40,8 @@ Help yourself by helping us support you! Many thousands of hours have been spent
# Table of Contents
* [How to include the library](#how-to-include-the-library)
* [Arduino Library Manager](#arduino-library-manager)
* [Manual installation](#manual-installation)
* [How to use the library](#how-to-use-the-library)
* [Documentation](#documentation)
* [Enable debugging](#enable-debugging)
@ -47,13 +54,24 @@ Help yourself by helping us support you! Many thousands of hours have been spent
* [Xbox Libraries](#xbox-libraries)
* [Xbox library](#xbox-library)
* [Xbox 360 Library](#xbox-360-library)
* [Xbox ONE Library](#xbox-one-library)
* [Wii library](#wii-library)
* [PS Buzz Library](#ps-buzz-library)
* [HID Libraries](#hid-libraries)
* [MIDI Library](#midi-library)
* [Interface modifications](#interface-modifications)
* [FAQ](#faq)
# How to include the library
### Arduino Library Manager
First install Arduino IDE version 1.6.2 or newer, then simply use the Arduino Library Manager to install the library.
Please see the following page for instructions: <http://www.arduino.cc/en/Guide/Libraries#toc3>.
### Manual installation
First download the library by clicking on the following link: <https://github.com/felis/USB_Host_Shield_2.0/archive/master.zip>.
Then uncompress the zip folder and rename the directory to "USB\_Host\_Shield\_20", as any special characters are not supported by the Arduino IDE.
@ -92,15 +110,24 @@ By default serial debugging is disabled. To turn it on simply change ```ENABLE_U
Currently the following boards are supported by the library:
* All official Arduino AVR boards (Uno, Duemilanove, Mega, Mega 2560, Mega ADK, Leonardo etc.)
* Arduino Due
* If you are using the Arduino Due, then you must include the Arduino SPI library like so: ```#include <SPI.h>``` in your .ino file.
* Teensy (Teensy++ 1.0, Teensy 2.0, Teensy++ 2.0, and Teensy 3.x)
* Arduino Due, Intel Galileo, Intel Galileo 2, and Intel Edison
* Note that the Intel Galileo uses pin 2 and 3 as INT and SS pin respectively by default, so some modifications to the shield are needed. See the "Interface modifications" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information.
* Note native USB host is not supported on any of these platforms. You will have to use the shield for now.
* Teensy (Teensy++ 1.0, Teensy 2.0, Teensy++ 2.0, Teensy 3.x, and Teensy LC)
* Note if you are using the Teensy 3.x you should download this SPI library as well: <https://github.com/xxxajk/spi4teensy3>. You should then add ```#include <spi4teensy3.h>``` to your .ino file.
* Balanduino
* Sanguino
* Black Widdow
* RedBearLab nRF51822
* If you are using the RedBearLab nRF51822, then you must include the RedBearLab SPI library like so: ```#include <SPI.h>``` in your .ino file.
* Digilent chipKIT
* Please see: <http://www.circuitsathome.com/mcu/usb/running-usb-host-code-on-digilent-chipkit-board>.
* STM32F4
* Currently the [NUCLEO-F446RE](http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF262063) is supported featuring the STM32F446. Take a look at the following example code: <https://github.com/Lauszus/Nucleo_F446RE_USBHost>.
* ESP8266 is supported using the [ESP8266 Arduino core](https://github.com/esp8266/Arduino)
* Note it uses pin 15 and 5 for SS and INT respectively
* Also please be aware that:
* GPIO16 is **NOT** usable, as it will be used for some other purposes. For example, reset the SoC itself from sleep mode.
* GPIO6 to 11 is also **NOT** usable, as they are used to connect SPI flash chip and it is used for storing the executable binary content.
The following boards need to be activated manually in [settings.h](settings.h):
@ -154,7 +181,7 @@ The [PS4BT.ino](examples/Bluetooth/PS4BT/PS4BT.ino) and [PS4USB.ino](examples/PS
Before you can use the PS4 controller via Bluetooth you will need to pair with it.
Simply create the PS4BT instance like so: ```PS4BT PS4(&Btd, PAIR);``` and then hold down the Share button and then hold down the PS without releasing the Share button. The PS4 controller will then start to blink rapidly indicating that it is in paring mode.
Simply create the PS4BT instance like so: ```PS4BT PS4(&Btd, PAIR);``` and then hold down the Share button and then hold down the PS without releasing the Share button. The PS4 controller will then start to blink rapidly indicating that it is in pairing mode.
It should then automatically pair the dongle with your controller. This only have to be done once.
@ -229,9 +256,17 @@ All the information regarding the Xbox 360 controller protocol are form these si
* <http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/WirelessUsbInfo>
* <https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL>
#### Xbox ONE Library
An Xbox ONE controller is supported via USB in the [XBOXONE](XBOXONE.cpp) class. It is heavily based on the 360 library above. In addition to cross referencing the above, information on the protocol was found at:
* <https://github.com/quantus/xbox-one-controller-protocol>
* <https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c>
* <https://github.com/kylelemons/xbox/blob/master/xbox.go>
### [Wii library](Wii.cpp)
The [Wii](Wii.cpp) library support the Wiimote, but also the Nunchuch and Motion Plus extensions via Bluetooth. The Wii U Pro Controller is also supported via Bluetooth.
The [Wii](Wii.cpp) library support the Wiimote, but also the Nunchuch and Motion Plus extensions via Bluetooth. The Wii U Pro Controller and Wii Balance Board are also supported via Bluetooth.
First you have to pair with the controller, this is done automatically by the library if you create the instance like so:
@ -239,7 +274,7 @@ First you have to pair with the controller, this is done automatically by the li
WII Wii(&Btd, PAIR);
```
And then press 1 & 2 at once on the Wiimote or press sync if you are using a Wii U Pro Controller.
And then press 1 & 2 at once on the Wiimote or the SYNC buttons if you are using a Wii U Pro Controller or a Wii Balance Board.
After that you can simply create the instance like so:
@ -259,13 +294,13 @@ The Wii IR camera can also be used, but you will have to activate the code for i
The [WiiIRCamera.ino](examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino) example shows how it can be used.
All the information about the Wii controllers are from these sites:
* <http://wiibrew.org/wiki/Wiimote>
* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers>
* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Nunchuck>
* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus>
* <http://wiibrew.org/wiki/Wii_Balance_Board>
* The old library created by _Tomoyuki Tanaka_: <https://github.com/moyuchin/WiiRemote_on_Arduino> also helped a lot.
### [PS Buzz Library](PSBuzz.cpp)
@ -281,6 +316,20 @@ 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
### HID Libraries
HID devices are also supported by the library. However these require you to write your own driver. A few example are provided in the [examples/HID](examples/HID) directory. Including an example for the [SteelSeries SRW-S1 Steering Wheel](examples/HID/SRWS1/SRWS1.ino).
### [MIDI Library](usbh_midi.cpp)
The library support MIDI devices.
You can convert USB MIDI keyboard to legacy serial MIDI.
* [USB_MIDI_converter.ino](examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino)
* [USB_MIDI_converter_multi.ino](examples/USBH_MIDI/USB_MIDI_converter_multi/USB_MIDI_converter_multi.ino)
For information see the following page: <http://yuuichiakagawa.github.io/USBH_MIDI/>.
# Interface modifications
The shield is using SPI for communicating with the MAX3421E USB host controller. It uses the SCK, MISO and MOSI pins via the ICSP on your board.
@ -322,4 +371,8 @@ LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
```
* This means that your dongle does not support 2.0+EDR, so you will need another dongle. Please see the following [list](https://github.com/felis/USB_Host_Shield_2.0/wiki/Bluetooth-dongles) for tested working dongles.
* This means that your dongle does not support 2.0+EDR, so you will need another dongle. Please see the following [list](https://github.com/felis/USB_Host_Shield_2.0/wiki/Bluetooth-dongles) for tested working dongles.
> When compiling I am getting the following error: "fatal error: SPI.h: No such file or directory".
* Please make sure to include the SPI library like so: ```#include <SPI.h>``` in your .ino file.

View file

@ -370,7 +370,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
#endif
sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send credit
creditSent = true;
timer = millis();
timer = (uint32_t)millis();
waitForLastCommand = true;
}
} else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit
@ -421,7 +421,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
}
void SPP::Run() {
if(waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it
if(waitForLastCommand && (int32_t)((uint32_t)millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80);
#endif

2
SPP.h
View file

@ -120,7 +120,9 @@ public:
*/
size_t write(const uint8_t* data, size_t size);
/** Pull in write(const char *str) from Print */
#if !defined(RBL_NRF51822)
using Print::write;
#endif
#else
/**
* Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.

40
Usb.cpp
View file

@ -92,7 +92,7 @@ uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_l
return USB_ERROR_EP_NOT_FOUND_IN_TBL;
*nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
*nak_limit--;
(*nak_limit)--;
/*
USBTRACE2("\r\nAddress: ", addr);
USBTRACE2(" EP: ", ep);
@ -203,7 +203,7 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque
/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
fe USB xfer timeout */
uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) {
uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {
EpInfo *pep = NULL;
uint16_t nak_limit = 0;
@ -215,10 +215,10 @@ uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t*
USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
return rcode;
}
return InTransfer(pep, nak_limit, nbytesptr, data);
return InTransfer(pep, nak_limit, nbytesptr, data, bInterval);
}
uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) {
uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval /*= 0*/) {
uint8_t rcode = 0;
uint8_t pktsize;
@ -234,7 +234,7 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
if(rcode == hrTOGERR) {
// yes, we flip it wrong here so that next time it is actually correct!
pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1;
regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
continue;
}
@ -280,7 +280,8 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
//printf("\r\n");
rcode = 0;
break;
} // if
} else if(bInterval > 0)
delay(bInterval); // Delay according to polling interval
} //while( 1 )
return ( rcode);
}
@ -312,7 +313,7 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
if(maxpktsize < 1 || maxpktsize > 64)
return USB_ERROR_INVALID_MAX_PKT_SIZE;
unsigned long timeout = millis() + USB_XFER_TIMEOUT;
uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
@ -327,7 +328,7 @@ uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8
regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
rcode = (regRd(rHRSL) & 0x0f);
while(rcode && ((long)(millis() - timeout) < 0L)) {
while(rcode && ((int32_t)((uint32_t)millis() - timeout) < 0L)) {
switch(rcode) {
case hrNAK:
nak_count++;
@ -374,17 +375,17 @@ breakout:
/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
unsigned long timeout = millis() + USB_XFER_TIMEOUT;
uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
uint8_t tmpdata;
uint8_t rcode = hrSUCCESS;
uint8_t retry_count = 0;
uint16_t nak_count = 0;
while((long)(millis() - timeout) < 0L) {
while((int32_t)((uint32_t)millis() - timeout) < 0L) {
regWr(rHXFR, (token | ep)); //launch the transfer
rcode = USB_ERROR_TRANSFER_TIMEOUT;
while((long)(millis() - timeout) < 0L) //wait for transfer completion
while((int32_t)((uint32_t)millis() - timeout) < 0L) //wait for transfer completion
{
tmpdata = regRd(rHIRQ);
@ -425,7 +426,7 @@ void USB::Task(void) //USB state machine
{
uint8_t rcode;
uint8_t tmpdata;
static unsigned long delay = 0;
static uint32_t delay = 0;
//USB_DEVICE_DESCRIPTOR buf;
bool lowspeed = false;
@ -450,7 +451,7 @@ void USB::Task(void) //USB state machine
//intentional fallthrough
case FSHOST: //attached
if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
delay = millis() + USB_SETTLE_DELAY;
delay = (uint32_t)millis() + USB_SETTLE_DELAY;
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
}
break;
@ -475,7 +476,7 @@ void USB::Task(void) //USB state machine
case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
break;
case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
if((long)(millis() - delay) >= 0L)
if((int32_t)((uint32_t)millis() - delay) >= 0L)
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
else break; // don't fall through
case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
@ -487,22 +488,22 @@ void USB::Task(void) //USB state machine
tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
regWr(rMODE, tmpdata);
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
//delay = millis() + 20; //20ms wait after reset per USB spec
//delay = (uint32_t)millis() + 20; //20ms wait after reset per USB spec
}
break;
case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
if(regRd(rHIRQ) & bmFRAMEIRQ) {
//when first SOF received _and_ 20ms has passed we can continue
/*
if (delay < millis()) //20ms passed
if (delay < (uint32_t)millis()) //20ms passed
usb_task_state = USB_STATE_CONFIGURING;
*/
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
delay = millis() + 20;
delay = (uint32_t)millis() + 20;
}
break;
case USB_ATTACHED_SUBSTATE_WAIT_RESET:
if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
if((int32_t)((uint32_t)millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
else break; // don't fall through
case USB_STATE_CONFIGURING:
@ -662,7 +663,8 @@ uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
epInfo.epAddr = 0;
epInfo.maxPktSize = 8;
epInfo.epAttribs = 0;
epInfo.bmSndToggle = 0;
epInfo.bmRcvToggle = 0;
epInfo.bmNakPower = USB_NAK_MAX_POWER;
//delay(2000);

View file

@ -37,8 +37,12 @@ typedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 1.0 and 2.0
typedef MAX3421e<P53, P54> MAX3421E; // Arduino Mega ADK
#elif defined(ARDUINO_AVR_BALANDUINO)
typedef MAX3421e<P20, P19> MAX3421E; // Balanduino
#elif defined(__ARDUINO_X86__) && PLATFORM_ID == 0x06
typedef MAX3421e<P3, P2> MAX3421E; // The Intel Galileo supports much faster read and write speed at pin 2 and 3
#elif defined(ESP8266)
typedef MAX3421e<P15, P5> MAX3421E; // ESP8266 boards
#else
typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.) or Teensy 2.0 and 3.0
typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.x
#endif
/* Common setup data constant combinations */
@ -243,7 +247,7 @@ public:
/**/
uint8_t ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction);
uint8_t ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit);
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data);
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval = 0);
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data);
uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit);
@ -260,7 +264,7 @@ private:
void init();
uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit);
uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data);
uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data);
uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval = 0);
uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed);
};

148
Wii.cpp Executable file → Normal file
View file

@ -108,6 +108,7 @@ void WII::Reset() {
motionPlusInside = false;
pBtd->wiiUProController = false;
wiiUProControllerConnected = false;
wiiBalanceBoardConnected = false;
l2cap_event_flag = 0; // Reset flags
l2cap_state = L2CAP_WAIT;
}
@ -120,9 +121,9 @@ void WII::disconnect() { // Use this void to disconnect any of the controllers
#endif
initExtension1(); // This will disable the Motion Plus extension
}
timer = millis() + 1000; // We have to wait for the message before the rest of the channels can be deactivated
timer = (uint32_t)millis() + 1000; // We have to wait for the message before the rest of the channels can be deactivated
} else
timer = millis(); // Don't wait
timer = (uint32_t)millis(); // Don't wait
// First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);
Reset();
@ -263,7 +264,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
else if(wiiUProControllerConnected)
ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16));
else if(motionPlusConnected) {
if(l2capinbuf[20] & 0x02) // Only update the wiimote buttons, since the extension bytes are from the Motion Plus
if(l2capinbuf[20] & 0x02) // Only update the Wiimote buttons, since the extension bytes are from the Motion Plus
ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000)));
else if(nunchuckConnected) // Update if it's a report from the Nunchuck
ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14));
@ -295,11 +296,8 @@ void WII::ACLData(uint8_t* l2capinbuf) {
#endif
wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)
batteryLevel = l2capinbuf[15]; // Update battery level
#ifdef DEBUG_USB_HOST
if(l2capinbuf[12] & 0x01)
Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80);
#endif
if(checkExtension) { // If this is false it means that the user must have called getBatteryLevel()
if(!checkBatteryLevel) { // If this is true it means that the user must have called getBatteryLevel()
if(l2capinbuf[12] & 0x02) { // Check if a extension is connected
#ifdef DEBUG_USB_HOST
if(!unknownExtensionConnected)
@ -329,15 +327,33 @@ void WII::ACLData(uint8_t* l2capinbuf) {
nunchuckConnected = false; // It must be the Nunchuck controller then
wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED);
onInit();
setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
} else
setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
#ifdef WIICAMERA
if(!isIRCameraEnabled()) // We still want to read from the IR camera, so do not change the report mode
#endif
setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
} else {
#ifdef WIICAMERA
if(!isIRCameraEnabled()) // We still want to read from the IR camera, so do not change the report mode
#endif
setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
}
}
} else
checkExtension = true; // Check for extensions by default
}
else {
#ifdef EXTRADEBUG
Notify(PSTR("\r\nChecking battery level"), 0x80);
#endif
checkBatteryLevel = false; // Check for extensions by default
}
#ifdef DEBUG_USB_HOST
if(l2capinbuf[12] & 0x01)
Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80);
#endif
break;
case 0x21: // Read Memory Data
if((l2capinbuf[12] & 0x0F) == 0) { // No error
uint8_t reportLength = (l2capinbuf[12] >> 4) + 1; // // Bit 4-7 is the length - 1
// See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) {
#ifdef DEBUG_USB_HOST
@ -380,6 +396,27 @@ void WII::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80);
#endif
wiiUProControllerConnected = true;
} else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x02) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWii Balance Board connected"), 0x80);
#endif
setReportMode(false, 0x32); // Read the Wii Balance Board extension
wii_set_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD);
}
// Wii Balance Board calibration reports (24 bits in total)
else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x24 && reportLength == 16) { // First 16-bit
for(uint8_t i = 0; i < 2; i++) {
for(uint8_t j = 0; j < 4; j++)
wiiBalanceBoardCal[i][j] = l2capinbuf[16 + 8 * i + 2 * j] | l2capinbuf[15 + 8 * i + 2 * j] << 8;
}
} else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x34 && reportLength == 8) { // Last 8-bit
for(uint8_t j = 0; j < 4; j++)
wiiBalanceBoardCal[2][j] = l2capinbuf[16 + 2 * j] | l2capinbuf[15 + 2 * j] << 8;
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nWii Balance Board calibration values read successfully"), 0x80);
#endif
wii_clear_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD);
wiiBalanceBoardConnected = true;
}
#ifdef DEBUG_USB_HOST
else {
@ -387,7 +424,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
Notify(PSTR("\r\nData: "), 0x80);
for(uint8_t i = 0; i < ((l2capinbuf[12] >> 4) + 1); i++) { // bit 4-7 is the length-1
for(uint8_t i = 0; i < reportLength; i++) {
D_PrintHex<uint8_t > (l2capinbuf[15 + i], 0x80);
Notify(PSTR(" "), 0x80);
}
@ -415,13 +452,18 @@ void WII::ACLData(uint8_t* l2capinbuf) {
case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA
break;
case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE
// See: http://wiibrew.org/wiki/Wii_Balance_Board#Data_Format
wiiBalanceBoardRaw[TopRight] = l2capinbuf[13] | l2capinbuf[12] << 8; // Top right
wiiBalanceBoardRaw[BotRight] = l2capinbuf[15] | l2capinbuf[14] << 8; // Bottom right
wiiBalanceBoardRaw[TopLeft] = l2capinbuf[17] | l2capinbuf[16] << 8; // Top left
wiiBalanceBoardRaw[BotLeft] = l2capinbuf[19] | l2capinbuf[18] << 8; // Bottom left
break;
case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II
#ifdef WIICAMERA
// Read the IR data
IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position
IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position
IR_object_s1 = (l2capinbuf[17] & 0x0F); // size value, 0-15
IR_object_s1 = (l2capinbuf[17] & 0x0F); // Size value, 0-15
IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4));
IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2));
@ -460,6 +502,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
break;
case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes
// (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
#if 1 // Set this to 0 if you don't want to use an extension, this reduceds the size of the library a lot!
if(motionPlusConnected) {
if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension
if(motionValuesReset) { // We will only use the values when the gyro value has been set
@ -467,9 +510,9 @@ void WII::ACLData(uint8_t* l2capinbuf) {
gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero);
gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero);
yawGyroSpeed = (double)gyroYawRaw / ((double)gyroYawZero / yawGyroScale);
rollGyroSpeed = -(double)gyroRollRaw / ((double)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values
pitchGyroSpeed = (double)gyroPitchRaw / ((double)gyroPitchZero / pitchGyroScale);
yawGyroSpeed = (float)gyroYawRaw / ((float)gyroYawZero / yawGyroScale);
rollGyroSpeed = -(float)gyroRollRaw / ((float)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values
pitchGyroSpeed = (float)gyroPitchRaw / ((float)gyroPitchZero / pitchGyroScale);
/* The onboard gyro has two ranges for slow and fast mode */
if(!(l2capinbuf[18] & 0x02)) // Check if fast mode is used
@ -479,13 +522,13 @@ void WII::ACLData(uint8_t* l2capinbuf) {
if(!(l2capinbuf[19] & 0x02)) // Check if fast mode is used
rollGyroSpeed *= 4.545;
compPitch = (0.93 * (compPitch + (pitchGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimotePitch()); // Use a complimentary filter to calculate the angle
compRoll = (0.93 * (compRoll + (rollGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimoteRoll());
compPitch = (0.93f * (compPitch + (pitchGyroSpeed * (float)((uint32_t)micros() - timer) / 1000000.0f)))+(0.07f * getWiimotePitch()); // Use a complimentary filter to calculate the angle
compRoll = (0.93f * (compRoll + (rollGyroSpeed * (float)((uint32_t)micros() - timer) / 1000000.0f)))+(0.07f * getWiimoteRoll());
gyroYaw += (yawGyroSpeed * ((double)(micros() - timer) / 1000000));
gyroRoll += (rollGyroSpeed * ((double)(micros() - timer) / 1000000));
gyroPitch += (pitchGyroSpeed * ((double)(micros() - timer) / 1000000));
timer = micros();
gyroYaw += (yawGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
gyroRoll += (rollGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
gyroPitch += (pitchGyroSpeed * ((float)((uint32_t)micros() - timer) / 1000000.0f));
timer = (uint32_t)micros();
/*
// Uncomment these lines to tune the gyro scale variabels
Notify(PSTR("\r\ngyroYaw: "), 0x80);
@ -502,7 +545,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
Notify(wiimotePitch, 0x80);
*/
} else {
if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values
if((int32_t)((uint32_t)micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nThe gyro values has been reset"), 0x80);
#endif
@ -519,7 +562,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
gyroPitch = 0;
motionValuesReset = true;
timer = micros();
timer = (uint32_t)micros();
}
}
} else {
@ -563,6 +606,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8);
hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8);
}
#endif
break;
#ifdef DEBUG_USB_HOST
default:
@ -654,7 +698,7 @@ void WII::L2CAP_task() {
/* The next states are in run() */
case L2CAP_INTERRUPT_DISCONNECT:
if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((long)(millis() - timer) >= 0L)) {
if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((int32_t)((uint32_t)millis() - timer) >= 0L)) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
#endif
@ -679,7 +723,7 @@ void WII::L2CAP_task() {
}
void WII::Run() {
if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((long)(millis() - timer) >= 0L))
if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((int32_t)((uint32_t)millis() - timer) >= 0L))
L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough
switch(l2cap_state) {
@ -721,7 +765,7 @@ void WII::Run() {
if(wii_check_flag(WII_FLAG_MOTION_PLUS_CONNECTED)) {
stateCounter = 0;
l2cap_state = WII_INIT_MOTION_PLUS_STATE;
timer = micros();
timer = (uint32_t)micros();
if(unknownExtensionConnected) {
#ifdef DEBUG_USB_HOST
@ -751,13 +795,21 @@ void WII::Run() {
if(unknownExtensionConnected) // Check if there is a extension is connected to the port
initExtension1();
else
stateCounter = 399;
stateCounter = 499;
} else if(stateCounter == 200)
initExtension2();
else if(stateCounter == 300) {
readExtensionType();
unknownExtensionConnected = false;
} else if(stateCounter == 400) {
if(wii_check_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD)) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nReading Wii Balance Board calibration values"), 0x80);
#endif
readWiiBalanceBoardCalibration();
} else
stateCounter = 499;
} else if(stateCounter == 500) {
stateCounter = 0;
l2cap_state = TURN_ON_LED;
}
@ -839,8 +891,8 @@ void WII::Run() {
/************************************************************/
/* HID Commands */
/************************************************************/
void WII::HID_Command(uint8_t* data, uint8_t nbytes) {
if(motionPlusInside)
pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new Wiimote with the Motion Plus Inside or Wii U Pro controller
@ -914,12 +966,16 @@ void WII::setLedStatus() {
}
uint8_t WII::getBatteryLevel() {
checkExtension = false; // This is needed so the library knows that the status response is a response to this function
checkBatteryLevel = true; // This is needed so the library knows that the status response is a response to this function
statusRequest(); // This will update the battery level
return batteryLevel;
};
void WII::setReportMode(bool continuous, uint8_t mode) {
#ifdef EXTRADEBUG
Notify(PSTR("\r\nReport mode was changed to: "), 0x80);
D_PrintHex<uint8_t > (mode, 0x80);
#endif
uint8_t cmd_buf[4];
cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
cmd_buf[1] = 0x12;
@ -941,8 +997,8 @@ void WII::statusRequest() {
/************************************************************/
/* Memmory Commands */
/************************************************************/
void WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) {
uint8_t cmd_buf[23];
cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
@ -1030,9 +1086,12 @@ void WII::checkMotionPresent() {
readData(0xA600FA, 6, false);
}
void WII::readWiiBalanceBoardCalibration() {
readData(0xA40024, 24, false);
}
/************************************************************/
/* WII Commands */
/************************************************************/
bool WII::getButtonPress(ButtonEnum b) { // Return true when a button is pressed
@ -1084,6 +1143,27 @@ void WII::onInit() {
setLedStatus();
}
/************************************************************/
/* Wii Balance Board Commands */
/************************************************************/
float WII::getWeight(BalanceBoardEnum pos) {
// Use interpolating between two points - based on: https://github.com/skorokithakis/gr8w8upd8m8/blob/master/gr8w8upd8m8.py
// wiiBalanceBoardCal[pos][0] is calibration values for 0 kg
// wiiBalanceBoardCal[pos][1] is calibration values for 17 kg
// wiiBalanceBoardCal[pos][2] is calibration values for 34 kg
if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[0][pos])
return 0.0f; // Below 0 kg
else if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[1][pos]) // Between 0 and 17 kg
return 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[0][pos]) / (float)(wiiBalanceBoardCal[1][pos] - wiiBalanceBoardCal[0][pos]);
else // More than 17 kg
return 17.0f + 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[1][pos]) / (float)(wiiBalanceBoardCal[2][pos] - wiiBalanceBoardCal[1][pos]);
};
float WII::getTotalWeight() {
return getWeight(TopRight) + getWeight(BotRight) + getWeight(TopLeft) + getWeight(BotLeft);
};
/************************************************************/
/* The following functions are for the IR camera */
/************************************************************/

86
Wii.h Executable file → Normal file
View file

@ -24,8 +24,9 @@
#include "controllerEnums.h"
/* Wii event flags */
#define WII_FLAG_MOTION_PLUS_CONNECTED 0x01
#define WII_FLAG_NUNCHUCK_CONNECTED 0x02
#define WII_FLAG_MOTION_PLUS_CONNECTED (1 << 0)
#define WII_FLAG_NUNCHUCK_CONNECTED (1 << 1)
#define WII_FLAG_CALIBRATE_BALANCE_BOARD (1 << 2)
#define wii_check_flag(flag) (wii_event_flag & (flag))
#define wii_set_flag(flag) (wii_event_flag |= (flag))
@ -39,6 +40,14 @@ enum HatEnum {
HatY = 1,
};
/** Enum used to read the weight on Wii Balance Board. */
enum BalanceBoardEnum {
TopRight = 0,
BotRight = 1,
TopLeft = 2,
BotLeft = 3,
};
/**
* This BluetoothService class implements support for the Wiimote including the Nunchuck and Motion Plus extension.
*
@ -76,7 +85,7 @@ public:
/** @name Wii Controller functions */
/** Call this to start the paring sequence with a controller */
/** Call this to start the pairing sequence with a controller */
void pair(void) {
if(pBtd)
pBtd->pairWithWiimote();
@ -98,7 +107,7 @@ public:
* Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
* @return Pitch in the range from 0-360.
*/
double getPitch() {
float getPitch() {
if(motionPlusConnected)
return compPitch;
return getWiimotePitch();
@ -108,7 +117,7 @@ public:
* Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
* @return Roll in the range from 0-360.
*/
double getRoll() {
float getRoll() {
if(motionPlusConnected)
return compRoll;
return getWiimoteRoll();
@ -120,7 +129,7 @@ public:
* <B>NOTE:</B> This angle will drift a lot and is only available if the Motion Plus extension is connected.
* @return The angle calculated using the gyro.
*/
double getYaw() {
float getYaw() {
return gyroYaw;
};
@ -191,6 +200,8 @@ public:
bool motionPlusConnected;
/** Variable used to indicate if a Wii U Pro controller is connected. */
bool wiiUProControllerConnected;
/** Variable used to indicate if a Wii Balance Board is connected. */
bool wiiBalanceBoardConnected;
/**@}*/
/* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
@ -198,24 +209,24 @@ public:
/**@{*/
/** Pitch and roll calculated from the accelerometer inside the Wiimote. */
double getWiimotePitch() {
return (atan2(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG;
float getWiimotePitch() {
return (atan2f(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG;
};
double getWiimoteRoll() {
return (atan2(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG;
float getWiimoteRoll() {
return (atan2f(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG;
};
/**@}*/
/**@{*/
/** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
double getNunchuckPitch() {
return (atan2(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
float getNunchuckPitch() {
return (atan2f(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
};
double getNunchuckRoll() {
return (atan2(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
float getNunchuckRoll() {
return (atan2f(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
};
/**@}*/
@ -227,17 +238,17 @@ public:
/* Variables for the gyro inside the Motion Plus */
/** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */
double gyroPitch;
float gyroPitch;
/** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */
double gyroRoll;
float gyroRoll;
/** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */
double gyroYaw;
float gyroYaw;
/**@{*/
/** The speed in deg/s from the gyro. */
double pitchGyroSpeed;
double rollGyroSpeed;
double yawGyroSpeed;
float pitchGyroSpeed;
float rollGyroSpeed;
float yawGyroSpeed;
/**@}*/
/**@{*/
@ -261,6 +272,31 @@ public:
int16_t gyroPitchZero;
/**@}*/
/** @name Wii Balance Board functions */
/**
* Used to get the weight at the specific position on the Wii Balance Board.
* @param pos ::BalanceBoardEnum to read from.
* @return Returns the weight in kg.
*/
float getWeight(BalanceBoardEnum pos);
/**
* Used to get total weight on the Wii Balance Board.
* @return Returns the weight in kg.
*/
float getTotalWeight();
/**
* Used to get the raw reading at the specific position on the Wii Balance Board.
* @param pos ::BalanceBoardEnum to read from.
* @return Returns the raw reading.
*/
uint16_t getWeightRaw(BalanceBoardEnum pos) {
return wiiBalanceBoardRaw[pos];
};
/**@}*/
#ifdef WIICAMERA
/** @name Wiimote IR camera functions
* You will have to set ::ENABLE_WII_IR_CAMERA in settings.h to 1 in order use the IR camera.
@ -415,7 +451,7 @@ private:
uint16_t stateCounter;
bool unknownExtensionConnected;
bool extensionConnected;
bool checkExtension; // Set to false when getBatteryLevel() is called otherwise if should be true
bool checkBatteryLevel; // Set to true when getBatteryLevel() is called otherwise if should be false
bool motionPlusInside; // True if it's a new Wiimote with the Motion Plus extension build into it
/* L2CAP Channels */
@ -437,13 +473,17 @@ private:
void readData(uint32_t offset, uint16_t size, bool EEPROM);
void readExtensionType();
void readCalData();
void readWiiBalanceBoardCalibration(); // Used by the library to read the Wii Balance Board calibration values
void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote
void initMotionPlus();
void activateMotionPlus();
double compPitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected
double compRoll; // Fusioned angle using a complimentary filter if the Motion Plus is connected
uint16_t wiiBalanceBoardRaw[4]; // Wii Balance Board raw values
uint16_t wiiBalanceBoardCal[3][4]; // Wii Balance Board calibration values
float compPitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected
float compRoll; // Fusioned angle using a complimentary filter if the Motion Plus is connected
bool activateNunchuck;
bool motionValuesReset; // This bool is true when the gyro values has been reset

View file

@ -51,7 +51,8 @@ bPollEnable(false) { // don't start polling before dongle is connected
for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}

View file

@ -19,7 +19,7 @@
#define _xboxold_h_
#include "Usb.h"
#include "hid.h"
#include "usbhid.h"
#include "controllerEnums.h"
/* Data Xbox taken from descriptors */

383
XBOXONE.cpp Normal file
View file

@ -0,0 +1,383 @@
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
Copyright (C) 2015 guruthree
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
guruthree
Web : https://github.com/guruthree/
*/
#include "XBOXONE.h"
// To enable serial debugging see "settings.h"
//#define EXTRADEBUG // Uncomment to get even more debugging data
//#define PRINTREPORT // Uncomment to print the report send by the Xbox ONE Controller
XBOXONE::XBOXONE(USB *p) :
pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory
bPollEnable(false) { // don't start polling before dongle is connected
for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
if(pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry
}
uint8_t XBOXONE::Init(uint8_t parent, uint8_t port, bool lowspeed) {
uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
uint8_t rcode;
UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL;
uint16_t PID;
uint16_t VID;
// get memory address of USB device address pool
AddressPool &addrPool = pUsb->GetAddressPool();
#ifdef EXTRADEBUG
Notify(PSTR("\r\nXBOXONE Init"), 0x80);
#endif
// check if address has already been assigned to an instance
if(bAddress) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress in use"), 0x80);
#endif
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
}
// Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0);
if(!p) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nAddress not found"), 0x80);
#endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
}
if(!p->epinfo) {
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif
return USB_ERROR_EPINFO_IS_NULL;
}
// Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo;
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo;
p->lowspeed = lowspeed;
// Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
// Restore p->epinfo
p->epinfo = oldep_ptr;
if(rcode)
goto FailGetDevDescr;
VID = udd->idVendor;
PID = udd->idProduct;
if(!VIDPIDOK(VID, PID)) // Check VID
goto FailUnknownDevice;
// Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port);
if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from device descriptor
epInfo[0].maxPktSize = udd->bMaxPacketSize0;
// Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress);
if(rcode) {
p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nsetAddr: "), 0x80);
D_PrintHex<uint8_t > (rcode, 0x80);
#endif
return rcode;
}
#ifdef EXTRADEBUG
Notify(PSTR("\r\nAddr: "), 0x80);
D_PrintHex<uint8_t > (bAddress, 0x80);
#endif
//delay(300); // Spec says you should wait at least 200ms
p->lowspeed = false;
//get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress);
if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if(rcode)
goto FailSetDevTblEntry;
/* The application will work in reduced host mode, so we can save program and data
memory space. After verifying the VID we will use known values for the
configuration values for device, interface, endpoints and HID for the XBOXONE Controllers */
/* Initialize data structures for endpoints of device */
epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x01; // XBOX one output endpoint
epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0;
epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0;
epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX one input endpoint
epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0;
epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0;
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if(rcode)
goto FailSetDevTblEntry;
delay(200); // Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
if(rcode)
goto FailSetConfDescr;
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nXbox One Controller Connected\r\n"), 0x80);
#endif
delay(200); // let things settle
// initialize the controller for input
writeBuf[0] = 0x05;
writeBuf[1] = 0x20;
writeBuf[2] = 0x00;
writeBuf[3] = 0x01;
writeBuf[4] = 0x00;
rcode = XboxCommand(writeBuf, 5);
if (rcode)
goto Fail;
onInit();
XboxOneConnected = true;
bPollEnable = true;
return 0; // Successful configuration
/* Diagnostic messages */
FailGetDevDescr:
#ifdef DEBUG_USB_HOST
NotifyFailGetDevDescr();
goto Fail;
#endif
FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST
NotifyFailSetDevTblEntry();
goto Fail;
#endif
FailSetConfDescr:
#ifdef DEBUG_USB_HOST
NotifyFailSetConfDescr();
#endif
goto Fail;
FailUnknownDevice:
#ifdef DEBUG_USB_HOST
NotifyFailUnknownDevice(VID, PID);
#endif
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
Fail:
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nXbox One Init Failed, error code: "), 0x80);
NotifyFail(rcode);
#endif
Release();
return rcode;
}
/* Performs a cleanup after failed Init() attempt */
uint8_t XBOXONE::Release() {
XboxOneConnected = false;
pUsb->GetAddressPool().FreeAddress(bAddress);
bAddress = 0;
bPollEnable = false;
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nXbox One Controller Disconnected\r\n"), 0x80);
#endif
return 0;
}
uint8_t XBOXONE::Poll() {
if(!bPollEnable)
return 0;
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf);
if (!rcode) {
readReport();
#ifdef PRINTREPORT
printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller
#endif
}
#ifdef DEBUG_USB_HOST
else if (rcode != 0x04) { // not a matter of no update to send
Notify(PSTR("\r\nXbox One Poll Failed, error code: "), 0x80);
NotifyFail(rcode);
}
#endif
return rcode;
}
void XBOXONE::readReport() {
if(readBuf == NULL)
return;
if(readBuf[0] == 0x07) {
// The XBOX button has a separate message
if(readBuf[4] == 1)
ButtonState |= pgm_read_word(&XBOX_BUTTONS[XBOX]);
else
ButtonState &= ~pgm_read_word(&XBOX_BUTTONS[XBOX]);
if(ButtonState != OldButtonState) {
ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
OldButtonState = ButtonState;
}
}
if(readBuf[0] != 0x20) { // Check if it's the correct report, otherwise return - the controller also sends different status reports
#ifdef EXTRADEBUG
Notify(PSTR("\r\nXbox Poll: "), 0x80);
D_PrintHex<uint8_t > (readBuf[0], 0x80); // 0x03 is a heart beat report!
#endif
return;
}
uint16_t xbox = ButtonState & pgm_read_word(&XBOX_BUTTONS[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);
triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);
triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);
hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);
hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);
//Notify(PSTR("\r\nButtonState"), 0x80);
//PrintHex<uint16_t>(ButtonState, 0x80);
if(ButtonState != OldButtonState) {
ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
OldButtonState = ButtonState;
}
// Handle click detection for triggers
if(triggerValue[0] != 0 && triggerValueOld[0] == 0)
L2Clicked = true;
triggerValueOld[0] = triggerValue[0];
if(triggerValue[1] != 0 && triggerValueOld[1] == 0)
R2Clicked = true;
triggerValueOld[1] = triggerValue[1];
}
void XBOXONE::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller
#ifdef PRINTREPORT
if(readBuf == NULL)
return;
for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) {
D_PrintHex<uint8_t > (readBuf[i], 0x80);
Notify(PSTR(" "), 0x80);
}
Notify(PSTR("\r\n"), 0x80);
#endif
}
uint16_t XBOXONE::getButtonPress(ButtonEnum b) {
if(b == L2) // These are analog buttons
return triggerValue[0];
else if(b == R2)
return triggerValue[1];
return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b])));
}
bool XBOXONE::getButtonClick(ButtonEnum b) {
if(b == L2) {
if(L2Clicked) {
L2Clicked = false;
return true;
}
return false;
} else if(b == R2) {
if(R2Clicked) {
R2Clicked = false;
return true;
}
return false;
}
uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);
bool click = (ButtonClickState & button);
ButtonClickState &= ~button; // clear "click" event
return click;
}
int16_t XBOXONE::getAnalogHat(AnalogHatEnum a) {
return hatValue[a];
}
/* Xbox Controller commands */
uint8_t XBOXONE::XboxCommand(uint8_t* data, uint16_t nbytes) {
uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ XBOX_OUTPUT_PIPE ].epAddr, nbytes, data);
#ifdef DEBUG_USB_HOST
Notify(PSTR("\r\nXboxCommand, Return: "), 0x80);
D_PrintHex<uint8_t > (rcode, 0x80);
#endif
return rcode;
}
void XBOXONE::onInit() {
// a short buzz to show the controller is active
writeBuf[0] = 0x09;
writeBuf[1] = 0x08;
writeBuf[2] = 0x00;
writeBuf[3] = 0x09;
writeBuf[4] = 0x00;
writeBuf[5] = 0x0f;
writeBuf[6] = 0x04;
writeBuf[7] = 0x04;
writeBuf[8] = 0x20;
writeBuf[9] = 0x20;
writeBuf[10] = 0x80;
XboxCommand(writeBuf, 11);
if(pFuncOnInit)
pFuncOnInit(); // Call the user function
}

196
XBOXONE.h Normal file
View file

@ -0,0 +1,196 @@
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
Copyright (C) 2015 guruthree
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
guruthree
Web : https://github.com/guruthree/
*/
#ifndef _xboxone_h_
#define _xboxone_h_
#include "Usb.h"
#include "xboxEnums.h"
/* Data Xbox ONE taken from descriptors */
#define EP_MAXPKTSIZE 32 // max size for data via USB
/* Names we give to the 3 XboxONE pipes */
#define XBOX_CONTROL_PIPE 0
#define XBOX_OUTPUT_PIPE 1
#define XBOX_INPUT_PIPE 2
// PID and VID of the different devices - see: https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c
// Official controllers
#define XBOX_VID1 0x045E // Microsoft Corporation
#define XBOX_ONE_PID1 0x02D1 // Microsoft X-Box One pad
#define XBOX_ONE_PID2 0x02DD // Microsoft X-Box One pad (Firmware 2015)
#define XBOX_ONE_PID3 0x02E3 // Microsoft X-Box One Elite pad
#define XBOX_ONE_PID4 0x02EA // Microsoft X-Box One S pad
// Unofficial controllers
#define XBOX_VID2 0x0738 // Mad Catz
#define XBOX_VID3 0x0E6F // Afterglow
#define XBOX_VID4 0x0F0D // HORIPAD ONE
#define XBOX_VID5 0x1532 // Razer
#define XBOX_VID6 0x24C6 // PowerA
#define XBOX_ONE_PID5 0x4A01 // Mad Catz FightStick TE 2 - might have different mapping for triggers?
#define XBOX_ONE_PID6 0x0139 // Afterglow Prismatic Wired Controller
#define XBOX_ONE_PID7 0x0146 // Rock Candy Wired Controller for Xbox One
#define XBOX_ONE_PID8 0x0067 // HORIPAD ONE
#define XBOX_ONE_PID9 0x0A03 // Razer Wildcat
#define XBOX_ONE_PID10 0x541A // PowerA Xbox One Mini Wired Controller
#define XBOX_ONE_PID11 0x542A // Xbox ONE spectra
#define XBOX_ONE_PID12 0x543A // PowerA Xbox One wired controller
#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer
#define XBOX_MAX_ENDPOINTS 3
/** This class implements support for a Xbox ONE controller connected via USB. */
class XBOXONE : public USBDeviceConfig {
public:
/**
* Constructor for the XBOXONE class.
* @param pUsb Pointer to USB class instance.
*/
XBOXONE(USB *pUsb);
/** @name USBDeviceConfig implementation */
/**
* Initialize the Xbox Controller.
* @param parent Hub number.
* @param port Port number on the hub.
* @param lowspeed Speed of the device.
* @return 0 on success.
*/
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
/**
* Release the USB device.
* @return 0 on success.
*/
virtual uint8_t Release();
/**
* Poll the USB Input endpoins and run the state machines.
* @return 0 on success.
*/
virtual uint8_t Poll();
/**
* Get the device address.
* @return The device address.
*/
virtual uint8_t GetAddress() {
return bAddress;
};
/**
* Used to check if the controller has been initialized.
* @return True if it's ready.
*/
virtual bool isReady() {
return bPollEnable;
};
/**
* 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 bool VIDPIDOK(uint16_t vid, uint16_t pid) {
return ((vid == XBOX_VID1 || vid == XBOX_VID2 || vid == XBOX_VID3 || vid == XBOX_VID4 || vid == XBOX_VID5 || vid == XBOX_VID6) &&
(pid == XBOX_ONE_PID1 || pid == XBOX_ONE_PID2 || pid == XBOX_ONE_PID3 || pid == XBOX_ONE_PID4 ||
pid == XBOX_ONE_PID5 || pid == XBOX_ONE_PID6 || pid == XBOX_ONE_PID7 || pid == XBOX_ONE_PID8 ||
pid == XBOX_ONE_PID9 || pid == XBOX_ONE_PID10 || pid == XBOX_ONE_PID11 || pid == XBOX_ONE_PID12));
};
/**@}*/
/** @name Xbox 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 getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a word if reading ::L2 or ::R2.
*/
uint16_t getButtonPress(ButtonEnum b);
bool getButtonClick(ButtonEnum b);
/**
* Return the analog value from the joysticks on the controller.
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
* @return Returns a signed 16-bit integer.
*/
int16_t getAnalogHat(AnalogHatEnum a);
/**
* Used to call your own function when the controller is successfully initialized.
* @param funcOnInit Function to call.
*/
void attachOnInit(void (*funcOnInit)(void)) {
pFuncOnInit = funcOnInit;
};
/**@}*/
/** True if a Xbox ONE controller is connected. */
bool XboxOneConnected;
protected:
/** Pointer to USB class instance. */
USB *pUsb;
/** Device address. */
uint8_t bAddress;
/** Endpoint info structure. */
EpInfo epInfo[XBOX_MAX_ENDPOINTS];
private:
/**
* Called when the controller is successfully initialized.
* Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
*/
void onInit();
void (*pFuncOnInit)(void); // Pointer to function called in onInit()
bool bPollEnable;
/* Variables to store the buttons */
uint16_t ButtonState;
uint16_t OldButtonState;
uint16_t ButtonClickState;
int16_t hatValue[4];
uint16_t triggerValue[2];
uint16_t triggerValueOld[2];
bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not
bool R2Clicked;
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
uint8_t writeBuf[12]; // General purpose buffer for output data
void readReport(); // read incoming data
void printReport(); // print incoming date - Uncomment for debugging
/* Private commands */
uint8_t XboxCommand(uint8_t* data, uint16_t nbytes);
};
#endif

View file

@ -29,7 +29,8 @@ bPollEnable(false) { // don't start polling before dongle is connected
for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
@ -292,8 +293,8 @@ uint8_t XBOXRECV::Release() {
uint8_t XBOXRECV::Poll() {
if(!bPollEnable)
return 0;
if(!checkStatusTimer || ((millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds
checkStatusTimer = millis();
if(!checkStatusTimer || ((int32_t)((uint32_t)millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds
checkStatusTimer = (uint32_t)millis();
checkStatus();
}
@ -571,13 +572,13 @@ void XBOXRECV::onInit(uint8_t controller) {
else {
LEDEnum led;
if(controller == 0)
led = LED1;
led = static_cast<LEDEnum>(LED1);
else if(controller == 1)
led = LED2;
led = static_cast<LEDEnum>(LED2);
else if(controller == 2)
led = LED3;
led = static_cast<LEDEnum>(LED3);
else
led = LED4;
led = static_cast<LEDEnum>(LED4);
setLedOn(led, controller);
}
}

View file

@ -27,7 +27,8 @@ bPollEnable(false) { // don't start polling before dongle is connected
for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
@ -357,5 +358,5 @@ void XBOXUSB::onInit() {
if(pFuncOnInit)
pFuncOnInit(); // Call the user function
else
setLedOn(LED1);
setLedOn(static_cast<LEDEnum>(LED1));
}

View file

@ -19,7 +19,7 @@
#define _xboxusb_h_
#include "Usb.h"
#include "hid.h"
#include "usbhid.h"
#include "xboxEnums.h"
/* Data Xbox 360 taken from descriptors */

View file

@ -169,7 +169,8 @@ public:
thePool[0].epinfo = &dev0ep;
dev0ep.epAddr = 0;
dev0ep.maxPktSize = 8;
dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0
dev0ep.bmSndToggle = 0; // Set DATA0/1 toggles to 0
dev0ep.bmRcvToggle = 0;
dev0ep.bmNakPower = USB_NAK_MAX_POWER;
InitAllAddresses();

View file

@ -45,7 +45,8 @@ ready(false) {
for(uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++...

320
avrpins.h
View file

@ -763,14 +763,12 @@ public:
#endif // Arduino pin definitions
#endif // __AVR__
#if defined(__arm__)
#elif defined(__arm__)
// pointers are 32 bits on ARM
#define pgm_read_pointer(p) pgm_read_dword(p)
#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))
#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__))
#include "core_pins.h"
#include "avr_emulation.h"
@ -834,6 +832,102 @@ MAKE_PIN(P30, CORE_PIN30_PORTREG, CORE_PIN30_BIT, CORE_PIN30_CONFIG);
MAKE_PIN(P31, CORE_PIN31_PORTREG, CORE_PIN31_BIT, CORE_PIN31_CONFIG);
MAKE_PIN(P32, CORE_PIN32_PORTREG, CORE_PIN32_BIT, CORE_PIN32_CONFIG);
MAKE_PIN(P33, CORE_PIN33_PORTREG, CORE_PIN33_BIT, CORE_PIN33_CONFIG);
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
MAKE_PIN(P34, CORE_PIN34_PORTREG, CORE_PIN34_BIT, CORE_PIN34_CONFIG);
MAKE_PIN(P35, CORE_PIN35_PORTREG, CORE_PIN35_BIT, CORE_PIN35_CONFIG);
MAKE_PIN(P36, CORE_PIN36_PORTREG, CORE_PIN36_BIT, CORE_PIN36_CONFIG);
MAKE_PIN(P37, CORE_PIN37_PORTREG, CORE_PIN37_BIT, CORE_PIN37_CONFIG);
MAKE_PIN(P38, CORE_PIN38_PORTREG, CORE_PIN38_BIT, CORE_PIN38_CONFIG);
MAKE_PIN(P39, CORE_PIN39_PORTREG, CORE_PIN39_BIT, CORE_PIN39_CONFIG);
MAKE_PIN(P40, CORE_PIN40_PORTREG, CORE_PIN40_BIT, CORE_PIN40_CONFIG);
MAKE_PIN(P41, CORE_PIN41_PORTREG, CORE_PIN41_BIT, CORE_PIN41_CONFIG);
MAKE_PIN(P42, CORE_PIN42_PORTREG, CORE_PIN42_BIT, CORE_PIN42_CONFIG);
MAKE_PIN(P43, CORE_PIN43_PORTREG, CORE_PIN43_BIT, CORE_PIN43_CONFIG);
MAKE_PIN(P44, CORE_PIN44_PORTREG, CORE_PIN44_BIT, CORE_PIN44_CONFIG);
MAKE_PIN(P45, CORE_PIN45_PORTREG, CORE_PIN45_BIT, CORE_PIN45_CONFIG);
MAKE_PIN(P46, CORE_PIN46_PORTREG, CORE_PIN46_BIT, CORE_PIN46_CONFIG);
MAKE_PIN(P47, CORE_PIN47_PORTREG, CORE_PIN47_BIT, CORE_PIN47_CONFIG);
MAKE_PIN(P48, CORE_PIN48_PORTREG, CORE_PIN48_BIT, CORE_PIN48_CONFIG);
MAKE_PIN(P49, CORE_PIN49_PORTREG, CORE_PIN49_BIT, CORE_PIN49_CONFIG);
MAKE_PIN(P50, CORE_PIN50_PORTREG, CORE_PIN50_BIT, CORE_PIN50_CONFIG);
MAKE_PIN(P51, CORE_PIN51_PORTREG, CORE_PIN51_BIT, CORE_PIN51_CONFIG);
MAKE_PIN(P52, CORE_PIN52_PORTREG, CORE_PIN52_BIT, CORE_PIN52_CONFIG);
MAKE_PIN(P53, CORE_PIN53_PORTREG, CORE_PIN53_BIT, CORE_PIN53_CONFIG);
MAKE_PIN(P54, CORE_PIN54_PORTREG, CORE_PIN54_BIT, CORE_PIN54_CONFIG);
MAKE_PIN(P55, CORE_PIN55_PORTREG, CORE_PIN55_BIT, CORE_PIN55_CONFIG);
MAKE_PIN(P56, CORE_PIN56_PORTREG, CORE_PIN56_BIT, CORE_PIN56_CONFIG);
MAKE_PIN(P57, CORE_PIN57_PORTREG, CORE_PIN57_BIT, CORE_PIN57_CONFIG);
MAKE_PIN(P58, CORE_PIN58_PORTREG, CORE_PIN58_BIT, CORE_PIN58_CONFIG);
MAKE_PIN(P59, CORE_PIN59_PORTREG, CORE_PIN59_BIT, CORE_PIN59_CONFIG);
MAKE_PIN(P60, CORE_PIN60_PORTREG, CORE_PIN60_BIT, CORE_PIN60_CONFIG);
MAKE_PIN(P61, CORE_PIN61_PORTREG, CORE_PIN61_BIT, CORE_PIN61_CONFIG);
MAKE_PIN(P62, CORE_PIN62_PORTREG, CORE_PIN62_BIT, CORE_PIN62_CONFIG);
MAKE_PIN(P63, CORE_PIN63_PORTREG, CORE_PIN63_BIT, CORE_PIN63_CONFIG);
#endif
#undef MAKE_PIN
#elif defined(CORE_TEENSY) && (defined(__MKL26Z64__))
// we could get lower level by making these macros work properly.
// for now just use the semi optimised version, it costs a lookup in the pin pgm table per op
// but for now it will do.
//#define GPIO_BITBAND_ADDR(reg, bit) (((volatile uint8_t *)&(reg) + ((bit) >> 3)))
//#define GPIO_BITBAND_MASK(reg, bit) (1<<((bit) & 7))
//#define GPIO_BITBAND_PTR(reg, bit) ((volatile uint8_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#include "core_pins.h"
#include "avr_emulation.h"
#define MAKE_PIN(className, baseReg, pinNum, configReg) \
class className { \
public: \
static void Set() { \
*portSetRegister(pinNum) = digitalPinToBitMask(pinNum); \
} \
static void Clear() { \
*portClearRegister(pinNum) = digitalPinToBitMask(pinNum); \
} \
static void SetDirRead() { \
configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \
*portModeRegister(pinNum) &= ~digitalPinToBitMask(pinNum); \
} \
static void SetDirWrite() { \
configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \
*portModeRegister(pinNum) |= digitalPinToBitMask(pinNum); \
} \
static uint8_t IsSet() { \
return (*portInputRegister(pinNum) & digitalPinToBitMask(pinNum)) ? 1 : 0; \
} \
};
MAKE_PIN(P0, CORE_PIN0_PORTREG, 0, CORE_PIN0_CONFIG);
MAKE_PIN(P1, CORE_PIN1_PORTREG, 1, CORE_PIN1_CONFIG);
MAKE_PIN(P2, CORE_PIN2_PORTREG, 2, CORE_PIN2_CONFIG);
MAKE_PIN(P3, CORE_PIN3_PORTREG, 3, CORE_PIN3_CONFIG);
MAKE_PIN(P4, CORE_PIN4_PORTREG, 4, CORE_PIN4_CONFIG);
MAKE_PIN(P5, CORE_PIN5_PORTREG, 5, CORE_PIN5_CONFIG);
MAKE_PIN(P6, CORE_PIN6_PORTREG, 6, CORE_PIN6_CONFIG);
MAKE_PIN(P7, CORE_PIN7_PORTREG, 7, CORE_PIN7_CONFIG);
MAKE_PIN(P8, CORE_PIN8_PORTREG, 8, CORE_PIN8_CONFIG);
MAKE_PIN(P9, CORE_PIN9_PORTREG, 9, CORE_PIN9_CONFIG);
MAKE_PIN(P10, CORE_PIN10_PORTREG, 10, CORE_PIN10_CONFIG);
MAKE_PIN(P11, CORE_PIN11_PORTREG, 11, CORE_PIN11_CONFIG);
MAKE_PIN(P12, CORE_PIN12_PORTREG, 12, CORE_PIN12_CONFIG);
MAKE_PIN(P13, CORE_PIN13_PORTREG, 13, CORE_PIN13_CONFIG);
MAKE_PIN(P14, CORE_PIN14_PORTREG, 14, CORE_PIN14_CONFIG);
MAKE_PIN(P15, CORE_PIN15_PORTREG, 15, CORE_PIN15_CONFIG);
MAKE_PIN(P16, CORE_PIN16_PORTREG, 16, CORE_PIN16_CONFIG);
MAKE_PIN(P17, CORE_PIN17_PORTREG, 17, CORE_PIN17_CONFIG);
MAKE_PIN(P18, CORE_PIN18_PORTREG, 18, CORE_PIN18_CONFIG);
MAKE_PIN(P19, CORE_PIN19_PORTREG, 19, CORE_PIN19_CONFIG);
MAKE_PIN(P20, CORE_PIN20_PORTREG, 20, CORE_PIN20_CONFIG);
MAKE_PIN(P21, CORE_PIN21_PORTREG, 21, CORE_PIN21_CONFIG);
MAKE_PIN(P22, CORE_PIN22_PORTREG, 22, CORE_PIN22_CONFIG);
MAKE_PIN(P23, CORE_PIN23_PORTREG, 23, CORE_PIN23_CONFIG);
MAKE_PIN(P24, CORE_PIN24_PORTREG, 24, CORE_PIN24_CONFIG);
MAKE_PIN(P25, CORE_PIN25_PORTREG, 25, CORE_PIN25_CONFIG);
MAKE_PIN(P26, CORE_PIN26_PORTREG, 26, CORE_PIN26_CONFIG);
#undef MAKE_PIN
@ -1012,14 +1106,183 @@ MAKE_PIN(P24, Pin_nRF51822_to_Arduino(D24));
#undef MAKE_PIN
#elif defined(STM32F446xx)
// NUCLEO-F446RE
#define MAKE_PIN(className, port, pin) \
class className { \
public: \
static void Set() { \
HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET); \
} \
static void Clear() { \
HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET); \
} \
static void SetDirRead() { \
static GPIO_InitTypeDef GPIO_InitStruct; \
GPIO_InitStruct.Pin = pin; \
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
GPIO_InitStruct.Pull = GPIO_NOPULL; \
HAL_GPIO_Init(port, &GPIO_InitStruct); \
} \
static void SetDirWrite() { \
static GPIO_InitTypeDef GPIO_InitStruct; \
GPIO_InitStruct.Pin = pin; \
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \
GPIO_InitStruct.Pull = GPIO_NOPULL; \
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; \
HAL_GPIO_Init(port, &GPIO_InitStruct); \
} \
static GPIO_PinState IsSet() { \
return HAL_GPIO_ReadPin(port, pin); \
} \
};
MAKE_PIN(P0, GPIOA, GPIO_PIN_3); // D0
MAKE_PIN(P1, GPIOA, GPIO_PIN_2); // D1
MAKE_PIN(P2, GPIOA, GPIO_PIN_10); // D2
MAKE_PIN(P3, GPIOB, GPIO_PIN_3); // D3
MAKE_PIN(P4, GPIOB, GPIO_PIN_5); // D4
MAKE_PIN(P5, GPIOB, GPIO_PIN_4); // D5
MAKE_PIN(P6, GPIOB, GPIO_PIN_10); // D6
MAKE_PIN(P7, GPIOA, GPIO_PIN_8); // D7
MAKE_PIN(P8, GPIOA, GPIO_PIN_9); // D8
MAKE_PIN(P9, GPIOC, GPIO_PIN_7); // D9
MAKE_PIN(P10, GPIOB, GPIO_PIN_6); // D10
MAKE_PIN(P11, GPIOA, GPIO_PIN_7); // D11
MAKE_PIN(P12, GPIOA, GPIO_PIN_6); // D12
MAKE_PIN(P13, GPIOA, GPIO_PIN_5); // D13
MAKE_PIN(P14, GPIOA, GPIO_PIN_0); // A0
MAKE_PIN(P15, GPIOA, GPIO_PIN_1); // A1
MAKE_PIN(P16, GPIOA, GPIO_PIN_4); // A2
MAKE_PIN(P17, GPIOB, GPIO_PIN_0); // A3
MAKE_PIN(P18, GPIOC, GPIO_PIN_1); // A4
MAKE_PIN(P19, GPIOC, GPIO_PIN_0); // A5
#undef MAKE_PIN
#else
#error "Please define board in avrpins.h"
#endif
#endif // __arm__
#elif defined(__ARDUINO_ARC__)
#if defined(__MIPSEL__)
#include <avr/pgmspace.h>
// Pointers are 32 bits on arc
#define pgm_read_pointer(p) pgm_read_dword(p)
#define MAKE_PIN(className, pin) \
class className { \
public: \
static void Set() { \
digitalWrite(pin, HIGH);\
} \
static void Clear() { \
digitalWrite(pin, LOW); \
} \
static void SetDirRead() { \
pinMode(pin, INPUT); \
} \
static void SetDirWrite() { \
pinMode(pin, OUTPUT); \
} \
static uint8_t IsSet() { \
return digitalRead(pin); \
} \
};
MAKE_PIN(P0, 0);
MAKE_PIN(P1, 1);
MAKE_PIN(P2, 2);
MAKE_PIN(P3, 3); //PWM
MAKE_PIN(P4, 4);
MAKE_PIN(P5, 5); //PWM
MAKE_PIN(P6, 6); //PWM
MAKE_PIN(P7, 7);
MAKE_PIN(P8, 8);
MAKE_PIN(P9, 9); //PWM
MAKE_PIN(P10, 10); //SPI SS
MAKE_PIN(P11, 11); //SPI MOSI
MAKE_PIN(P12, 12); //SPI MISO
MAKE_PIN(P13, 13); //SPI SCK / BUILTIN LED
MAKE_PIN(P14, 14); // A0
MAKE_PIN(P15, 15); // A1
MAKE_PIN(P16, 16); // A2
MAKE_PIN(P17, 17); // A3
MAKE_PIN(P18, 18); // A4 SDA
MAKE_PIN(P19, 19); // A5 SCL
MAKE_PIN(P20, 20); // ATN
#undef MAKE_PIN
#elif defined(__ARDUINO_X86__) // Intel Galileo, Intel Galileo 2 and Intel Edison
#include <avr/pgmspace.h>
// Pointers are 32 bits on x86
#define pgm_read_pointer(p) pgm_read_dword(p)
#if PLATFORM_ID == 0xE1 // Edison platform id
#define pinToFastPin(pin) 1 // As far as I can tell all pins can be used as fast pins
#endif
// Pin 2 and 3 on the Intel Galileo supports a higher rate,
// so it is recommended to use one of these as the SS pin.
#define MAKE_PIN(className, pin) \
class className { \
public: \
static void Set() { \
fastDigitalWrite(pin, HIGH); \
} \
static void Clear() { \
fastDigitalWrite(pin, LOW); \
} \
static void SetDirRead() { \
if (pinToFastPin(pin)) \
pinMode(pin, INPUT_FAST); \
else \
pinMode(pin, INPUT); \
} \
static void SetDirWrite() { \
if (pinToFastPin(pin)) \
pinMode(pin, OUTPUT_FAST); \
else \
pinMode(pin, OUTPUT); \
} \
static uint8_t IsSet() { \
return fastDigitalRead(pin); \
} \
};
MAKE_PIN(P0, 0);
MAKE_PIN(P1, 1);
MAKE_PIN(P2, 2);
MAKE_PIN(P3, 3);
MAKE_PIN(P4, 4);
MAKE_PIN(P5, 5);
MAKE_PIN(P6, 6);
MAKE_PIN(P7, 7);
MAKE_PIN(P8, 8);
MAKE_PIN(P9, 9);
MAKE_PIN(P10, 10);
MAKE_PIN(P11, 11);
MAKE_PIN(P12, 12);
MAKE_PIN(P13, 13);
MAKE_PIN(P14, 14); // A0
MAKE_PIN(P15, 15); // A1
MAKE_PIN(P16, 16); // A2
MAKE_PIN(P17, 17); // A3
MAKE_PIN(P18, 18); // A4
MAKE_PIN(P19, 19); // A5
#undef MAKE_PIN
#elif defined(__MIPSEL__)
// MIPSEL (MIPS architecture using a little endian byte order)
// MIPS size_t = 4
@ -1062,6 +1325,51 @@ MAKE_PIN(P12, 12); //
MAKE_PIN(P13, 13); //
#undef MAKE_PIN
#elif defined(ESP8266)
#define pgm_read_pointer(p) pgm_read_ptr(p)
#define MAKE_PIN(className, pin) \
class className { \
public: \
static void Set() { \
digitalWrite(pin, HIGH);\
} \
static void Clear() { \
digitalWrite(pin, LOW); \
} \
static void SetDirRead() { \
pinMode(pin, INPUT); \
} \
static void SetDirWrite() { \
pinMode(pin, OUTPUT); \
} \
static uint8_t IsSet() { \
return digitalRead(pin); \
} \
};
// Pinout for ESP-12 module
// 0 .. 16 - Digital pins
// GPIO 6 to 11 and 16 are not usable in this library.
MAKE_PIN(P0, 0);
MAKE_PIN(P1, 1); // TX0
MAKE_PIN(P2, 2); // TX1
MAKE_PIN(P3, 3); // RX0
MAKE_PIN(P4, 4); // SDA
MAKE_PIN(P5, 5); // SCL
MAKE_PIN(P12, 12); // MISO
MAKE_PIN(P13, 13); // MOSI
MAKE_PIN(P14, 14); // SCK
MAKE_PIN(P15, 15); // SS
#undef MAKE_PIN
#else
#error "Please define board in avrpins.h"
#endif
#endif //_avrpins_h_

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
/* Copyright (C) 2015 Circuits At Home, LTD. 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

View file

@ -34,7 +34,8 @@ ready(false) {
for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i == epDataInIndex) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
@ -247,7 +248,8 @@ void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
// Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0;
epInfo[index].bmSndToggle = 0;
epInfo[index].bmRcvToggle = 0;
bNumEP++;

View file

@ -20,16 +20,18 @@ const uint8_t FTDI::epDataInIndex = 1;
const uint8_t FTDI::epDataOutIndex = 2;
const uint8_t FTDI::epInterruptInIndex = 3;
FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) :
FTDI::FTDI(USB *p, FTDIAsyncOper *pasync, uint16_t idProduct) :
pAsync(pasync),
pUsb(p),
bAddress(0),
bNumEP(1),
wFTDIType(0) {
wFTDIType(0),
wIdProduct(idProduct) {
for(uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
epInfo[i].bmNakPower = (i==epDataInIndex) ? USB_NAK_NOWAIT: USB_NAK_MAX_POWER;
}
if(pUsb)
@ -84,13 +86,17 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
if(rcode) {
goto FailGetDevDescr;
}
if(udd->idVendor != FTDI_VID && udd->idProduct != FTDI_PID) {
USBTRACE("FTDI NO SUPPORT??\r\n");
Serial.println(udd->idVendor, HEX);
Serial.println(udd->idProduct, HEX);
if(udd->idVendor != FTDI_VID || udd->idProduct != wIdProduct)
{
USBTRACE("FTDI Init: Product not supported\r\n");
USBTRACE2("Expected VID:", FTDI_VID);
USBTRACE2("Found VID:", udd->idVendor);
USBTRACE2("Expected PID:", wIdProduct);
USBTRACE2("Found PID:", udd->idProduct);
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
}
}
// Save type of FTDI chip
wFTDIType = udd->bcdDevice;
@ -234,7 +240,8 @@ void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t prot
// Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0;
epInfo[index].bmSndToggle = 0;
epInfo[index].bmRcvToggle = 0;
bNumEP++;
@ -257,11 +264,11 @@ uint8_t FTDI::Poll() {
//if (!bPollEnable)
// return 0;
//if (qNextPollTime <= millis())
//if (qNextPollTime <= (uint32_t)millis())
//{
// USB_HOST_SERIAL.println(bAddress, HEX);
// qNextPollTime = millis() + 100;
// qNextPollTime = (uint32_t)millis() + 100;
//}
return rcode;
}
@ -286,8 +293,8 @@ uint8_t FTDI::SetBaudRate(uint32_t baud) {
if(divisor3 != 0) baud_value |= 0x8000; // 0.25
if(baud_value == 1) baud_value = 0; /* special case for maximum baud rate */
} else {
static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3};
static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1};
static const uint8_t divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3};
static const uint8_t divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1};
baud_value = divisor3 >> 3;
baud_value |= divfrac [divisor3 & 0x7] << 14;

View file

@ -107,13 +107,14 @@ class FTDI : public USBDeviceConfig, public UsbConfigXtracter {
uint32_t qNextPollTime; // next poll time
bool bPollEnable; // poll enable flag
uint16_t wFTDIType; // Type of FTDI chip
uint16_t wIdProduct; // expected PID
EpInfo epInfo[FTDI_MAX_ENDPOINTS];
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
public:
FTDI(USB *pusb, FTDIAsyncOper *pasync);
FTDI(USB *pusb, FTDIAsyncOper *pasync, uint16_t idProduct = FTDI_PID);
uint8_t SetBaudRate(uint32_t baud);
uint8_t SetModemControl(uint16_t control);

View file

@ -30,6 +30,9 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL;
uint8_t num_of_conf; // number of configurations
#ifdef PL2303_COMPAT
enum pl2303_type pltype = unknown;
#endif
AddressPool &addrPool = pUsb->GetAddressPool();
@ -66,9 +69,21 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
if(rcode)
goto FailGetDevDescr;
if(udd->idVendor != PL_VID && udd->idProduct != PL_PID)
if(udd->idVendor != PL_VID && CHECK_PID(udd->idProduct))
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
/* determine chip variant */
#ifdef PL2303_COMPAT
if(udd->bDeviceClass == 0x02 )
pltype = type_0;
else if(udd->bMaxPacketSize0 == 0x40 )
pltype = rev_HX;
else if(udd->bDeviceClass == 0x00)
pltype = type_1;
else if(udd->bDeviceClass == 0xff)
pltype = type_1;
#endif
// Save type of PL chip
wPLType = udd->bcdDevice;
@ -145,6 +160,28 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
if(rcode)
goto FailSetConfDescr;
#ifdef PL2303_COMPAT
/* Shamanic dance - sending Prolific init data as-is */
vendorRead( 0x84, 0x84, 0, buf );
vendorWrite( 0x04, 0x04, 0 );
vendorRead( 0x84, 0x84, 0, buf );
vendorRead( 0x83, 0x83, 0, buf );
vendorRead( 0x84, 0x84, 0, buf );
vendorWrite( 0x04, 0x04, 1 );
vendorRead( 0x84, 0x84, 0, buf);
vendorRead( 0x83, 0x83, 0, buf);
vendorWrite( 0, 0, 1 );
vendorWrite( 1, 0, 0 );
if( pltype == rev_HX ) {
vendorWrite( 2, 0, 0x44 );
vendorWrite( 0x06, 0x06, 0 ); // From W7 init
}
else {
vendorWrite( 2, 0, 0x24 );
}
/* Shamanic dance end */
#endif
/* Calling post-init callback */
rcode = pAsync->OnInit(this);
if(rcode)
@ -200,11 +237,11 @@ Fail:
// //if (!bPollEnable)
// // return 0;
//
// //if (qNextPollTime <= millis())
// //if (qNextPollTime <= (uint32_t)millis())
// //{
// // USB_HOST_SERIAL.println(bAddress, HEX);
//
// // qNextPollTime = millis() + 100;
// // qNextPollTime = (uint32_t)millis() + 100;
// //}
// return rcode;
//}

View file

@ -19,8 +19,10 @@ e-mail : support@circuitsathome.com
#include "cdcacm.h"
//#define PL2303_COMPAT // Uncomment it if you have compatibility problems
#define PL_VID 0x067B
#define PL_PID ( 0x2303 || 0x0609 )
#define CHECK_PID(pid) ( pid != 0x2303 && pid != 0x0609 )
//#define PL_PID 0x0609
@ -109,8 +111,9 @@ enum tXO_State {
enum pl2303_type {
unknown,
type_1, /* don't know the difference between type 0 and */
rev_X, /* type 1, until someone from prolific tells us... */
type_0, /* don't know the difference between type 0 and */
type_1, /* type 1, until someone from prolific tells us... */
rev_X,
rev_HX, /* HX version of the pl2303 chip */
rev_H
};
@ -130,6 +133,27 @@ public:
//// UsbConfigXtracter implementation
//virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
#ifdef PL2303_COMPAT
private:
/* Prolific proprietary requests */
uint8_t vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf );
uint8_t vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index );
#endif
};
#ifdef PL2303_COMPAT
/* vendor read request */
inline uint8_t PL2303::vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf )
{
return( pUsb->ctrlReq(bAddress, 0, VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, val_lo, val_hi, index, 1, 1, buf, NULL ));
}
/* vendor write request */
inline uint8_t PL2303::vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index )
{
return( pUsb->ctrlReq(bAddress, 0, VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, val_lo, val_hi, index, 0, 0, NULL, NULL ));
}
#endif
#endif // __CDCPROLIFIC_H__

View file

@ -119,16 +119,13 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
switch(dscrType) {
case USB_DESCRIPTOR_INTERFACE:
isGoodInterface = false;
break;
case USB_DESCRIPTOR_CONFIGURATION:
theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
break;
case USB_DESCRIPTOR_ENDPOINT:
theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
break;
case HID_DESCRIPTOR_HID:
theBuffer.valueSize = dscrLen - 2;
break;
}
theBuffer.valueSize = dscrLen - 2;
valParser.Initialize(&theBuffer);
stateParseDescr = 4;
case 4:

View file

@ -26,11 +26,12 @@
/** Enum used to turn on the LEDs on the different controllers. */
enum LEDEnum {
OFF = 0,
#ifndef RBL_NRF51822
LED1 = 1,
LED2 = 2,
LED3 = 3,
LED4 = 4,
#endif
LED5 = 5,
LED6 = 6,
LED7 = 7,
@ -55,6 +56,7 @@ enum ColorsEnum {
/** r = 0, g = 255, b = 255 */
Lightblue = 0xFFFF,
/** r = 255, g = 0, b = 255 */
Purple = 0xFF00FF,
Purble = 0xFF00FF,
/** r = 255, g = 255, b = 255 */

View file

@ -8,11 +8,12 @@
#include <usbhub.h>
#include "KeyboardParser.h"
#include "MouseParser.h"
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside
@ -39,12 +40,12 @@ void setup() {
while (1); // Halt
}
bthid.SetReportParser(KEYBOARD_PARSER_ID, (HIDReportParser*)&keyboardPrs);
bthid.SetReportParser(MOUSE_PARSER_ID, (HIDReportParser*)&mousePrs);
bthid.SetReportParser(KEYBOARD_PARSER_ID, &keyboardPrs);
bthid.SetReportParser(MOUSE_PARSER_ID, &mousePrs);
// If "Boot Protocol Mode" does not work, then try "Report Protocol Mode"
// If that does not work either, then uncomment PRINTREPORT in BTHID.cpp to see the raw report
bthid.setProtocolMode(HID_BOOT_PROTOCOL); // Boot Protocol Mode
bthid.setProtocolMode(USB_HID_BOOT_PROTOCOL); // Boot Protocol Mode
//bthid.setProtocolMode(HID_RPT_PROTOCOL); // Report Protocol Mode
Serial.print(F("\r\nHID Bluetooth Library Started"));

View file

@ -3,7 +3,7 @@
class KbdRptParser : public KeyboardReportParser {
protected:
virtual uint8_t HandleLockingKeys(HID *hid, uint8_t key);
virtual uint8_t HandleLockingKeys(USBHID *hid, uint8_t key);
virtual void OnControlKeysChanged(uint8_t before, uint8_t after);
virtual void OnKeyDown(uint8_t mod, uint8_t key);
virtual void OnKeyUp(uint8_t mod, uint8_t key);
@ -13,7 +13,7 @@ class KbdRptParser : public KeyboardReportParser {
void PrintKey(uint8_t mod, uint8_t key);
};
uint8_t KbdRptParser::HandleLockingKeys(HID *hid, uint8_t key) {
uint8_t KbdRptParser::HandleLockingKeys(USBHID *hid, uint8_t key) {
uint8_t old_keys = kbdLockingKeys.bLeds;
switch (key) {

View file

@ -6,11 +6,12 @@
#include <PS3BT.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside
@ -20,8 +21,7 @@ BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
PS3BT PS3(&Btd); // This will just create the instance
//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch
bool printTemperature;
bool printAngle;
bool printTemperature, printAngle;
void setup() {
Serial.begin(115200);
@ -60,15 +60,20 @@ void loop() {
Serial.print(PS3.getAnalogButton(R2));
}
}
if (PS3.getButtonClick(PS)) {
Serial.print(F("\r\nPS"));
PS3.disconnect();
}
else {
if (PS3.getButtonClick(TRIANGLE))
if (PS3.getButtonClick(TRIANGLE)) {
Serial.print(F("\r\nTraingle"));
if (PS3.getButtonClick(CIRCLE))
PS3.setRumbleOn(RumbleLow);
}
if (PS3.getButtonClick(CIRCLE)) {
Serial.print(F("\r\nCircle"));
PS3.setRumbleOn(RumbleHigh);
}
if (PS3.getButtonClick(CROSS))
Serial.print(F("\r\nCross"));
if (PS3.getButtonClick(SQUARE))

View file

@ -7,11 +7,12 @@
#include <PS3BT.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

View file

@ -12,11 +12,12 @@
#include <PS3BT.h>
#include <SPP.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

View file

@ -7,11 +7,11 @@
#include <PS4BT.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside
@ -19,7 +19,7 @@ BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
/* You can create the instance of the PS4BT class in two ways */
// This will start an inquiry and then pair with the PS4 controller - you only have to do this once
// You will need to hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in paring mode
// You will need to hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in pairing mode
PS4BT PS4(&Btd, PAIR);
// After that you can simply create the instance like so and then press the PS button on the device

View file

@ -6,11 +6,12 @@
#include <SPP.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

View file

@ -6,11 +6,12 @@
#include <SPP.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

View file

@ -6,11 +6,12 @@
#include <Wii.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

View file

@ -0,0 +1,51 @@
/*
Example sketch for the Wii Balance Board Bluetooth 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 <Wii.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment 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 class in two ways */
WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wii Balance Board - you only have to do this once
//WII Wii(&Btd); // After that you can simply create the instance like so and then press the power button on the Wii Balance Board
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\nWii Balance Board Bluetooth Library Started"));
}
void loop() {
Usb.Task();
if (Wii.wiiBalanceBoardConnected) {
Serial.print(F("\r\nWeight: "));
for (uint8_t i = 0; i < 4; i++) {
Serial.print(Wii.getWeight((BalanceBoardEnum)i));
Serial.print(F("\t"));
}
Serial.print(F("Total Weight: "));
Serial.print(Wii.getTotalWeight());
if (Wii.getButtonClick(A)) {
Serial.print(F("\r\nA"));
//Wii.setLedToggle(LED1); // The Wii Balance Board has one LED as well
Wii.disconnect();
}
}
}

View file

@ -13,11 +13,12 @@ Otherwise, wire up a IR LED yourself.
#include <Wii.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
#ifndef WIICAMERA // Used to check if WIICAMERA is defined
#error "Please set ENABLE_WII_IR_CAMERA to 1 in settings.h"

View file

@ -7,11 +7,12 @@
#include <Wii.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

View file

@ -6,11 +6,12 @@
#include <Wii.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside

View file

@ -0,0 +1,49 @@
/* Copyright (C) 2016 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 "SRWS1.h"
void SRWS1::ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
if (HIDUniversal::VID != STEELSERIES_VID || HIDUniversal::PID != STEELSERIES_SRWS1_PID) // Make sure the right device is actually connected
return;
#if 0
if (len && buf) {
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(&srws1Data, buf, min(len, sizeof(srws1Data)));
static SRWS1DataButtons oldButtonState;
if (srws1Data.btn.val != oldButtonState.val) { // Check if anything has changed
buttonClickState.val = srws1Data.btn.val & ~oldButtonState.val; // Update click state variable
oldButtonState.val = srws1Data.btn.val;
}
}
// See: https://github.com/torvalds/linux/blob/master/drivers/hid/hid-steelseries.c
void SRWS1::setLeds(uint16_t leds) {
uint8_t buf[3];
buf[0] = 0x40; // Report ID
buf[1] = leds & 0xFF;
buf[2] = (leds >> 8) & 0x7F;
pUsb->outTransfer(bAddress, epInfo[ hidInterfaces[0].epIndex[epInterruptOutIndex] ].epAddr, sizeof(buf), buf);
}

View file

@ -0,0 +1,95 @@
/* Copyright (C) 2016 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 __srws1_h__
#define __srws1_h__
#include <hiduniversal.h>
#define STEELSERIES_VID 0x1038
#define STEELSERIES_SRWS1_PID 0x1410
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 = 0xF,
};
union SRWS1DataButtons {
struct {
uint8_t dpad : 4;
uint8_t dummy : 3;
uint8_t select : 1;
uint8_t back : 1;
uint8_t lookLeft : 1;
uint8_t lights : 1;
uint8_t lookBack : 1;
uint8_t rearBrakeBalance : 1;
uint8_t frontBrakeBalance : 1;
uint8_t requestPit : 1;
uint8_t leftGear : 1;
uint8_t camera : 1;
uint8_t lookRight : 1;
uint8_t boost : 1;
uint8_t horn : 1;
uint8_t hud : 1;
uint8_t launchControl : 1;
uint8_t speedLimiter : 1;
uint8_t rightGear : 1;
} __attribute__((packed));
uint32_t val : 24;
} __attribute__((packed));
struct SRWS1Data {
int16_t tilt; // Range [-1800:1800]
uint16_t rightTrigger : 12; // Range [0:1023] i.e. only 10 bits
uint16_t leftTrigger : 12; // Range [0:1023] i.e. only 10 bits
SRWS1DataButtons btn;
uint8_t assists : 4;
uint8_t steeringSensitivity : 4;
uint8_t assistValues : 4;
} __attribute__((packed));
class SRWS1 : public HIDUniversal {
public:
SRWS1(USB *p) : HIDUniversal(p) {};
bool connected() {
return HIDUniversal::isReady() && HIDUniversal::VID == STEELSERIES_VID && HIDUniversal::PID == STEELSERIES_SRWS1_PID;
};
void setLeds(uint16_t leds);
SRWS1Data srws1Data;
SRWS1DataButtons buttonClickState;
private:
void ParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); // Called by the HIDUniversal library
uint8_t OnInitSuccessful() { // Called by the HIDUniversal library on success
if (HIDUniversal::VID != STEELSERIES_VID || HIDUniversal::PID != STEELSERIES_SRWS1_PID) // Make sure the right device is actually connected
return 1;
setLeds(0);
return 0;
};
};
#endif

View file

@ -0,0 +1,180 @@
/*
Example sketch for the SteelSeries SRW-S1 Steering Wheel - developed by Kristian Lauszus
For more information visit my blog: http://blog.tkjelectronics.dk/ or
send me an e-mail: kristianl@tkjelectronics.com
*/
#include <SPI.h>
#include "SRWS1.h"
USB Usb;
SRWS1 srw1(&Usb);
bool printTilt;
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.println(F("\r\nSteelSeries SRW-S1 Steering Wheel example started"));
}
void loop() {
Usb.Task();
if (srw1.connected()) {
if (printTilt) { // Show tilt angle using the LEDs
srw1.setLeds(1 << map(srw1.srws1Data.tilt, -1800, 1800, 0, 14)); // Turn on a LED according to tilt value
Serial.println(srw1.srws1Data.tilt);
} else { // Show strobe light effect
static uint32_t timer;
if ((int32_t)((uint32_t)millis() - timer) > 12) {
timer = (uint32_t)millis(); // Reset timer
static uint16_t leds = 0;
//PrintHex<uint16_t > (leds, 0x80); Serial.println();
srw1.setLeds(leds); // Update LEDs
static bool dirUp = true;
if (dirUp) {
leds <<= 1;
if (leds == 0x8000) // All are actually turned off, as there is only 15 LEDs
dirUp = false; // If we have reached the end i.e. all LEDs are off, then change direction
else if (!(leds & 0x8000)) // If last bit is not set, then set the lowest bit
leds |= 1; // Set lowest bit
} else {
leds >>= 1;
if (leds == 0) // Check if all LEDs are off
dirUp = true; // If all LEDs are off, then repeat the sequence
else if (!(leds & 0x1)) // If last bit is not set, then set the top bit
leds |= 1 << 15; // Set top bit
}
}
}
if (srw1.srws1Data.leftTrigger) {
Serial.print(F("L2: "));
Serial.println(srw1.srws1Data.leftTrigger);
}
if (srw1.srws1Data.rightTrigger) {
Serial.print(F("R2: "));
Serial.println(srw1.srws1Data.rightTrigger);
}
if (srw1.buttonClickState.select) {
srw1.buttonClickState.select = 0; // Clear event
Serial.println(F("Select"));
printTilt = !printTilt; // Print tilt value & show it using the LEDs as well
}
if (srw1.buttonClickState.back) {
srw1.buttonClickState.back = 0; // Clear event
Serial.println(F("Back"));
}
if (srw1.buttonClickState.lookLeft) {
srw1.buttonClickState.lookLeft = 0; // Clear event
Serial.println(F("Look Left"));
}
if (srw1.buttonClickState.lights) {
srw1.buttonClickState.lights = 0; // Clear event
Serial.println(F("Lights"));
}
if (srw1.buttonClickState.lookBack) {
srw1.buttonClickState.lookBack = 0; // Clear event
Serial.println(F("Look Back"));
}
if (srw1.buttonClickState.rearBrakeBalance) {
srw1.buttonClickState.rearBrakeBalance = 0; // Clear event
Serial.println(F("R. Brake Balance"));
}
if (srw1.buttonClickState.frontBrakeBalance) {
srw1.buttonClickState.frontBrakeBalance = 0; // Clear event
Serial.println(F("F. Brake Balance"));
}
if (srw1.buttonClickState.requestPit) {
srw1.buttonClickState.requestPit = 0; // Clear event
Serial.println(F("Request Pit"));
}
if (srw1.buttonClickState.leftGear) {
srw1.buttonClickState.leftGear = 0; // Clear event
Serial.println(F("Left Gear"));
}
if (srw1.buttonClickState.camera) {
srw1.buttonClickState.camera = 0; // Clear event
Serial.println(F("Camera"));
}
if (srw1.buttonClickState.lookRight) {
srw1.buttonClickState.lookRight = 0; // Clear event
Serial.println(F("Look right"));
}
if (srw1.buttonClickState.boost) {
srw1.buttonClickState.boost = 0; // Clear event
Serial.println(F("Boost"));
}
if (srw1.buttonClickState.horn) {
srw1.buttonClickState.horn = 0; // Clear event
Serial.println(F("Horn"));
}
if (srw1.buttonClickState.hud) {
srw1.buttonClickState.hud = 0; // Clear event
Serial.println(F("HUD"));
}
if (srw1.buttonClickState.launchControl) {
srw1.buttonClickState.launchControl = 0; // Clear event
Serial.println(F("Launch Control"));
}
if (srw1.buttonClickState.speedLimiter) {
srw1.buttonClickState.speedLimiter = 0; // Clear event
Serial.println(F("Speed Limiter"));
}
if (srw1.buttonClickState.rightGear) {
srw1.buttonClickState.rightGear = 0; // Clear event
Serial.println(F("Right gear"));
}
if (srw1.srws1Data.assists) Serial.println(srw1.srws1Data.assists);
if (srw1.srws1Data.steeringSensitivity) Serial.println(srw1.srws1Data.steeringSensitivity);
if (srw1.srws1Data.assistValues) Serial.println(srw1.srws1Data.assistValues);
switch (srw1.srws1Data.btn.dpad) {
case DPAD_UP:
Serial.println(F("Up"));
break;
case DPAD_UP_RIGHT:
Serial.println(F("UP & right"));
break;
case DPAD_RIGHT:
Serial.println(F("Right"));
break;
case DPAD_RIGHT_DOWN:
Serial.println(F("Right & down"));
break;
case DPAD_DOWN:
Serial.println(F("Down"));
break;
case DPAD_DOWN_LEFT:
Serial.println(F("Down & left"));
break;
case DPAD_LEFT:
Serial.println(F("Left"));
break;
case DPAD_LEFT_UP:
Serial.println(F("Left & up"));
break;
case DPAD_OFF:
break;
default:
Serial.print(F("Unknown state: "));
PrintHex<uint8_t > (srw1.srws1Data.btn.dpad, 0x80);
Serial.println();
break;
}
}
}

View file

@ -1,10 +1,11 @@
#include <hidboot.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class KbdRptParser : public KeyboardReportParser
{
@ -97,9 +98,7 @@ void KbdRptParser::OnKeyPressed(uint8_t key)
USB Usb;
//USBHub Hub(&Usb);
HIDBoot<HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
uint32_t next_time;
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
KbdRptParser Prs;
@ -116,9 +115,7 @@ void setup()
delay( 200 );
next_time = millis() + 5000;
HidKeyboard.SetReportParser(0, (HIDReportParser*)&Prs);
HidKeyboard.SetReportParser(0, &Prs);
}
void loop()

View file

@ -1,10 +1,11 @@
#include <hidboot.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class MouseRptParser : public MouseReportParser
{
@ -140,11 +141,9 @@ void KbdRptParser::OnKeyPressed(uint8_t key)
USB Usb;
USBHub Hub(&Usb);
HIDBoot < HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE > HidComposite(&Usb);
HIDBoot<HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
HIDBoot<HID_PROTOCOL_MOUSE> HidMouse(&Usb);
//uint32_t next_time;
HIDBoot < USB_HID_PROTOCOL_KEYBOARD | USB_HID_PROTOCOL_MOUSE > HidComposite(&Usb);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
HIDBoot<USB_HID_PROTOCOL_MOUSE> HidMouse(&Usb);
KbdRptParser KbdPrs;
MouseRptParser MousePrs;
@ -162,12 +161,10 @@ void setup()
delay( 200 );
//next_time = millis() + 5000;
HidComposite.SetReportParser(0, (HIDReportParser*)&KbdPrs);
HidComposite.SetReportParser(1, (HIDReportParser*)&MousePrs);
HidKeyboard.SetReportParser(0, (HIDReportParser*)&KbdPrs);
HidMouse.SetReportParser(0, (HIDReportParser*)&MousePrs);
HidComposite.SetReportParser(0, &KbdPrs);
HidComposite.SetReportParser(1, &MousePrs);
HidKeyboard.SetReportParser(0, &KbdPrs);
HidMouse.SetReportParser(0, &MousePrs);
}
void loop()

View file

@ -1,10 +1,11 @@
#include <hidboot.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class MouseRptParser : public MouseReportParser
{
@ -51,9 +52,7 @@ void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi)
USB Usb;
USBHub Hub(&Usb);
HIDBoot<HID_PROTOCOL_MOUSE> HidMouse(&Usb);
uint32_t next_time;
HIDBoot<USB_HID_PROTOCOL_MOUSE> HidMouse(&Usb);
MouseRptParser Prs;
@ -70,9 +69,7 @@ void setup()
delay( 200 );
next_time = millis() + 5000;
HidMouse.SetReportParser(0,(HIDReportParser*)&Prs);
HidMouse.SetReportParser(0, &Prs);
}
void loop()

View file

@ -1,11 +1,12 @@
#include <hid.h>
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
#include "hidjoystickrptparser.h"

View file

@ -8,7 +8,7 @@ oldButtons(0) {
oldPad[i] = 0xD;
}
void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
bool match = true;
// Checking if there are changes in report since the method was last called
@ -43,11 +43,12 @@ void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t
for (uint8_t i = 0; i < 0x0C; i++) {
uint16_t mask = (0x0001 << i);
if (((mask & changes) > 0) && joyEvents)
if (((mask & changes) > 0) && joyEvents) {
if ((buttons & mask) > 0)
joyEvents->OnButtonDn(i + 1);
else
joyEvents->OnButtonUp(i + 1);
}
}
oldButtons = buttons;
}

View file

@ -1,7 +1,7 @@
#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__
#include <hid.h>
#include <usbhid.h>
struct GamePadEventData {
uint8_t X, Y, Z1, Z2, Rz;
@ -27,7 +27,7 @@ class JoystickReportParser : public HIDReportParser {
public:
JoystickReportParser(JoystickEvents *evt);
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};
#endif // __HIDJOYSTICKRPTPARSER_H__

View file

@ -0,0 +1,68 @@
#include <hidcomposite.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
// Override HIDComposite to be able to select which interface we want to hook into
class HIDSelector : public HIDComposite
{
public:
HIDSelector(USB *p) : HIDComposite(p) {};
protected:
void ParseHIDData(USBHID *hid, uint8_t ep, bool is_rpt_id, uint8_t len, uint8_t *buf); // Called by the HIDComposite library
bool SelectInterface(uint8_t iface, uint8_t proto);
};
// Return true for the interface we want to hook into
bool HIDSelector::SelectInterface(uint8_t iface, uint8_t proto)
{
if (proto != 0)
return true;
return false;
}
// Will be called for all HID data received from the USB interface
void HIDSelector::ParseHIDData(USBHID *hid, uint8_t ep, bool is_rpt_id, uint8_t len, uint8_t *buf) {
#if 1
if (len && buf) {
Notify(PSTR("\r\n"), 0x80);
for (uint8_t i = 0; i < len; i++) {
D_PrintHex<uint8_t > (buf[i], 0x80);
Notify(PSTR(" "), 0x80);
}
}
#endif
}
USB Usb;
//USBHub Hub(&Usb);
HIDSelector hidSelector(&Usb);
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
Serial.println("Start");
if (Usb.Init() == -1)
Serial.println("OSC did not start.");
// Set this to higher values to enable more debug information
// minimum 0x00, maximum 0xff, default 0x80
UsbDEBUGlvl = 0xff;
delay( 200 );
}
void loop()
{
Usb.Task();
}

View file

@ -1,13 +1,14 @@
#include <hid.h>
#include <usbhid.h>
#include <hiduniversal.h>
#include <hidescriptorparser.h>
#include <usbhub.h>
#include "pgmstrings.h"
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class HIDUniversal2 : public HIDUniversal
{

View file

@ -1,15 +1,16 @@
/* Simplified Logitech Extreme 3D Pro Joystick Report Parser */
#include <hid.h>
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>
#include "le3dp_rptparser.h"
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
USBHub Hub(&Usb);

View file

@ -4,7 +4,7 @@ JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
joyEvents(evt)
{}
void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
{
bool match = true;

View file

@ -1,7 +1,7 @@
#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__
#include <hid.h>
#include <usbhid.h>
struct GamePadEventData
{
@ -36,7 +36,7 @@ class JoystickReportParser : public HIDReportParser
public:
JoystickReportParser(JoystickEvents *evt);
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};
#endif // __HIDJOYSTICKRPTPARSER_H__

View file

@ -1,16 +1,17 @@
/* Digital Scale Output. Written for Stamps.com Model 510 */
/* 5lb Digital Scale; any HID scale with Usage page 0x8d should work */
#include <hid.h>
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>
#include "scale_rptparser.h"
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
USBHub Hub(&Usb);

View file

@ -1,4 +1,7 @@
/* Parser for standard HID scale (usage page 0x8d) data input report (ID 3) */
#ifdef ARDUINO_SAM_DUE
#include <avr/dtostrf.h>
#endif
#include "scale_rptparser.h"
const char* UNITS[13] = {
@ -21,7 +24,7 @@ ScaleReportParser::ScaleReportParser(ScaleEvents *evt) :
scaleEvents(evt)
{}
void ScaleReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
void ScaleReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
{
bool match = true;

View file

@ -2,7 +2,7 @@
#define __SCALERPTPARSER_H__
#include <max_LCD.h>
#include <hid.h>
#include <usbhid.h>
/* Scale status constants */
#define REPORT_FAULT 0x01
@ -49,7 +49,7 @@ class ScaleReportParser : public HIDReportParser
public:
ScaleReportParser(ScaleEvents *evt);
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};
#endif // __SCALERPTPARSER_H__

View file

@ -5,11 +5,12 @@
*/
#include <PS3USB.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
/* You can create the instance of the class in two ways */
@ -133,7 +134,7 @@ void loop() {
PS3.moveSetBulb(Lightblue);
} else if (state == 6) {
PS3.moveSetRumble(225);
PS3.moveSetBulb(Purble);
PS3.moveSetBulb(Purple);
} else if (state == 7) {
PS3.moveSetRumble(250);
PS3.moveSetBulb(White);

View file

@ -6,11 +6,11 @@
#include <PS4USB.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
PS4USB PS4(&Usb);

View file

@ -6,11 +6,11 @@
#include <PSBuzz.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
PSBuzz Buzz(&Usb);

View file

@ -0,0 +1,97 @@
/*
*******************************************************************************
* USB-MIDI dump utility
* Copyright (C) 2013-2017 Yuuichi Akagawa
*
* for use with USB Host Shield 2.0 from Circuitsathome.com
* https://github.com/felis/USB_Host_Shield_2.0
*
* This is sample program. Do not expect perfect behavior.
*******************************************************************************
*/
#include <usbh_midi.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub(&Usb);
USBH_MIDI Midi(&Usb);
void MIDI_poll();
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
boolean bFirst;
uint16_t pid, vid;
void setup()
{
bFirst = true;
vid = pid = 0;
Serial.begin(115200);
if (Usb.Init() == -1) {
while (1); //halt
}//if (Usb.Init() == -1...
delay( 200 );
}
void loop()
{
Usb.Task();
//uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
MIDI_poll();
}
//delay(1ms)
//doDelay(t1, (uint32_t)micros(), 1000);
}
// Poll USB MIDI Controler and send to serial MIDI
void MIDI_poll()
{
char buf[20];
uint8_t bufMidi[64];
uint16_t rcvd;
if (Midi.vid != vid || Midi.pid != pid) {
sprintf(buf, "VID:%04X, PID:%04X", Midi.vid, Midi.pid);
Serial.println(buf);
vid = Midi.vid;
pid = Midi.pid;
}
if (Midi.RecvData( &rcvd, bufMidi) == 0 ) {
uint32_t time = (uint32_t)millis();
sprintf(buf, "%04X%04X: ", (uint16_t)(time >> 16), (uint16_t)(time & 0xFFFF)); // Split variable to prevent warnings on the ESP8266 platform
Serial.print(buf);
Serial.print(rcvd);
Serial.print(':');
for (int i = 0; i < 64; i++) {
sprintf(buf, " %02X", bufMidi[i]);
Serial.print(buf);
}
Serial.println("");
}
}
// Delay time (max 16383 us)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
uint32_t t3;
if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2);
} else {
t3 = t2 - t1;
}
if ( t3 < delayTime ) {
delayMicroseconds(delayTime - t3);
}
}

View file

@ -0,0 +1,90 @@
/*
*******************************************************************************
* USB-MIDI to Legacy Serial MIDI converter
* Copyright (C) 2012-2017 Yuuichi Akagawa
*
* Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com
*
* This is sample program. Do not expect perfect behavior.
*******************************************************************************
*/
#include <usbh_midi.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
#ifdef USBCON
#define _MIDI_SERIAL_PORT Serial1
#else
#define _MIDI_SERIAL_PORT Serial
#endif
//////////////////////////
// MIDI Pin assign
// 2 : GND
// 4 : +5V(Vcc) with 220ohm
// 5 : TX
//////////////////////////
USB Usb;
USBH_MIDI Midi(&Usb);
void MIDI_poll();
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
void setup()
{
_MIDI_SERIAL_PORT.begin(31250);
if (Usb.Init() == -1) {
while (1); //halt
}//if (Usb.Init() == -1...
delay( 200 );
}
void loop()
{
Usb.Task();
uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
MIDI_poll();
}
//delay(1ms)
doDelay(t1, (uint32_t)micros(), 1000);
}
// Poll USB MIDI Controler and send to serial MIDI
void MIDI_poll()
{
uint8_t outBuf[ 3 ];
uint8_t size;
do {
if ( (size = Midi.RecvData(outBuf)) > 0 ) {
//MIDI Output
_MIDI_SERIAL_PORT.write(outBuf, size);
}
} while (size > 0);
}
// Delay time (max 16383 us)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
uint32_t t3;
if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2);
} else {
t3 = t2 - t1;
}
if ( t3 < delayTime ) {
delayMicroseconds(delayTime - t3);
}
}

View file

@ -0,0 +1,98 @@
/*
*******************************************************************************
* USB-MIDI to Legacy Serial MIDI converter
* Copyright (C) 2012-2017 Yuuichi Akagawa
*
* Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com
*
* This is sample program. Do not expect perfect behavior.
*******************************************************************************
*/
#include <usbh_midi.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
#ifdef USBCON
#define _MIDI_SERIAL_PORT Serial1
#else
#define _MIDI_SERIAL_PORT Serial
#endif
//////////////////////////
// MIDI Pin assign
// 2 : GND
// 4 : +5V(Vcc) with 220ohm
// 5 : TX
//////////////////////////
USB Usb;
USBHub Hub1(&Usb);
USBH_MIDI Midi1(&Usb);
USBH_MIDI Midi2(&Usb);
void MIDI_poll();
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
void setup()
{
_MIDI_SERIAL_PORT.begin(31250);
if (Usb.Init() == -1) {
while (1); //halt
}//if (Usb.Init() == -1...
delay( 200 );
}
void loop()
{
Usb.Task();
uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
MIDI_poll();
}
//delay(1ms)
doDelay(t1, (uint32_t)micros(), 1000);
}
// Poll USB MIDI Controler and send to serial MIDI
void MIDI_poll()
{
uint8_t outBuf[ 3 ];
uint8_t size;
do {
if ( (size = Midi1.RecvData(outBuf)) > 0 ) {
//MIDI Output
_MIDI_SERIAL_PORT.write(outBuf, size);
}
} while (size > 0);
do {
if ( (size = Midi2.RecvData(outBuf)) > 0 ) {
//MIDI Output
_MIDI_SERIAL_PORT.write(outBuf, size);
}
} while (size > 0);
}
// Delay time (max 16383 us)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
uint32_t t3;
if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2);
} else {
t3 = t2 - t1;
}
if ( t3 < delayTime ) {
delayMicroseconds(delayTime - t3);
}
}

View file

@ -0,0 +1,159 @@
/*
*******************************************************************************
* Legacy Serial MIDI and USB Host bidirectional converter
* Copyright (C) 2013-2017 Yuuichi Akagawa
*
* for use with Arduino MIDI library
* https://github.com/FortySevenEffects/arduino_midi_library/
*
* Note:
* - If you want use with Leonardo, you must choose Arduino MIDI library v4.0 or higher.
* - This is sample program. Do not expect perfect behavior.
*******************************************************************************
*/
#include <MIDI.h>
#include <usbh_midi.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
//Arduino MIDI library v4.2 compatibility
#ifdef MIDI_CREATE_DEFAULT_INSTANCE
MIDI_CREATE_DEFAULT_INSTANCE();
#endif
#ifdef USBCON
#define _MIDI_SERIAL_PORT Serial1
#else
#define _MIDI_SERIAL_PORT Serial
#endif
//////////////////////////
// MIDI Pin assign
// 2 : GND
// 4 : +5V(Vcc) with 220ohm
// 5 : TX
//////////////////////////
USB Usb;
USBH_MIDI Midi(&Usb);
void MIDI_poll();
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
//If you want handle System Exclusive message, enable this #define otherwise comment out it.
#define USBH_MIDI_SYSEX_ENABLE
#ifdef USBH_MIDI_SYSEX_ENABLE
//SysEx:
void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
Midi.SendSysEx(sysexmsg, sizeofsysex);
}
#endif
void setup()
{
MIDI.begin(MIDI_CHANNEL_OMNI);
#ifdef USBH_MIDI_SYSEX_ENABLE
MIDI.setHandleSystemExclusive(handle_sysex);
#endif
if (Usb.Init() == -1) {
while (1); //halt
}//if (Usb.Init() == -1...
delay( 200 );
}
void loop()
{
uint8_t msg[4];
Usb.Task();
uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
MIDI_poll();
if (MIDI.read()) {
msg[0] = MIDI.getType();
switch (msg[0]) {
case midi::ActiveSensing :
break;
case midi::SystemExclusive :
//SysEx is handled by event.
break;
default :
msg[1] = MIDI.getData1();
msg[2] = MIDI.getData2();
Midi.SendData(msg, 0);
break;
}
}
}
//delay(1ms)
doDelay(t1, (uint32_t)micros(), 1000);
}
// Poll USB MIDI Controler and send to serial MIDI
void MIDI_poll()
{
uint8_t size;
#ifdef USBH_MIDI_SYSEX_ENABLE
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
uint8_t rcode = 0; //return code
uint16_t rcvd;
uint8_t readPtr = 0;
rcode = Midi.RecvData( &rcvd, recvBuf);
//data check
if (rcode != 0) return;
if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
return ;
}
uint8_t *p = recvBuf;
while (readPtr < MIDI_EVENT_PACKET_SIZE) {
if (*p == 0 && *(p + 1) == 0) break; //data end
uint8_t outbuf[3];
uint8_t rc = Midi.extractSysExData(p, outbuf);
if ( rc == 0 ) {
p++;
size = Midi.lookupMsgSize(*p);
_MIDI_SERIAL_PORT.write(p, size);
p += 3;
} else {
_MIDI_SERIAL_PORT.write(outbuf, rc);
p += 4;
}
readPtr += 4;
}
#else
uint8_t outBuf[3];
do {
if ( (size = Midi.RecvData(outBuf)) > 0 ) {
//MIDI Output
_MIDI_SERIAL_PORT.write(outBuf, size);
}
} while (size > 0);
#endif
}
// Delay time (max 16383 us)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
uint32_t t3;
if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2);
} else {
t3 = t2 - t1;
}
if ( t3 < delayTime ) {
delayMicroseconds(delayTime - t3);
}
}

View file

@ -0,0 +1,93 @@
/*
*******************************************************************************
* eVY1 Shield sample - Say 'Konnichiwa'
* Copyright (C) 2014-2016 Yuuichi Akagawa
*
* This is sample program. Do not expect perfect behavior.
*******************************************************************************
*/
#include <usbh_midi.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub(&Usb);
USBH_MIDI Midi(&Usb);
void MIDI_poll();
void noteOn(uint8_t note);
void noteOff(uint8_t note);
uint16_t pid, vid;
uint8_t exdata[] = {
0xf0, 0x43, 0x79, 0x09, 0x00, 0x50, 0x10,
'k', ' ', 'o', ',', //Ko
'N', '\\', ',', //N
'J', ' ', 'i', ',', //Ni
't', 'S', ' ', 'i', ',', //Chi
'w', ' ', 'a', //Wa
0x00, 0xf7
};
void setup()
{
vid = pid = 0;
Serial.begin(115200);
if (Usb.Init() == -1) {
while (1); //halt
}//if (Usb.Init() == -1...
delay( 200 );
}
void loop()
{
Usb.Task();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
MIDI_poll();
noteOn(0x3f);
delay(400);
noteOff(0x3f);
delay(100);
}
}
// Poll USB MIDI Controler
void MIDI_poll()
{
uint8_t inBuf[ 3 ];
//first call?
if (Midi.vid != vid || Midi.pid != pid) {
vid = Midi.vid; pid = Midi.pid;
Midi.SendSysEx(exdata, sizeof(exdata));
delay(500);
}
Midi.RecvData(inBuf);
}
//note On
void noteOn(uint8_t note)
{
uint8_t buf[3];
buf[0] = 0x90;
buf[1] = note;
buf[2] = 0x7f;
Midi.SendData(buf);
}
//note Off
void noteOff(uint8_t note)
{
uint8_t buf[3];
buf[0] = 0x80;
buf[1] = note;
buf[2] = 0x00;
Midi.SendData(buf);
}

View file

@ -1,11 +1,12 @@
#include <usbhub.h>
#include "pgmstrings.h"
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub1(&Usb);
@ -16,35 +17,33 @@ USB Usb;
//USBHub Hub6(&Usb);
//USBHub Hub7(&Usb);
uint32_t next_time;
void PrintAllAddresses(UsbDevice *pdev)
{
UsbDeviceAddress adr;
adr.devAddress = pdev->address.devAddress;
Serial.print("\r\nAddr:");
Serial.print(adr.devAddress, HEX);
Serial.print("(");
Serial.print(adr.bmHub, HEX);
Serial.print(".");
Serial.print(adr.bmParent, HEX);
Serial.print(".");
Serial.print(adr.bmAddress, HEX);
Serial.println(")");
UsbDeviceAddress adr;
adr.devAddress = pdev->address.devAddress;
Serial.print("\r\nAddr:");
Serial.print(adr.devAddress, HEX);
Serial.print("(");
Serial.print(adr.bmHub, HEX);
Serial.print(".");
Serial.print(adr.bmParent, HEX);
Serial.print(".");
Serial.print(adr.bmAddress, HEX);
Serial.println(")");
}
void PrintAddress(uint8_t addr)
{
UsbDeviceAddress adr;
adr.devAddress = addr;
Serial.print("\r\nADDR:\t");
Serial.println(adr.devAddress,HEX);
Serial.print("DEV:\t");
Serial.println(adr.bmAddress,HEX);
Serial.print("PRNT:\t");
Serial.println(adr.bmParent,HEX);
Serial.print("HUB:\t");
Serial.println(adr.bmHub,HEX);
UsbDeviceAddress adr;
adr.devAddress = addr;
Serial.print("\r\nADDR:\t");
Serial.println(adr.devAddress, HEX);
Serial.print("DEV:\t");
Serial.println(adr.bmAddress, HEX);
Serial.print("PRNT:\t");
Serial.println(adr.bmParent, HEX);
Serial.print("HUB:\t");
Serial.println(adr.bmHub, HEX);
}
void setup()
@ -56,71 +55,70 @@ void setup()
Serial.println("Start");
if (Usb.Init() == -1)
Serial.println("OSC did not start.");
Serial.println("OSC did not start.");
delay( 200 );
next_time = millis() + 10000;
}
byte getdevdescr( byte addr, byte &num_conf );
uint8_t getdevdescr( uint8_t addr, uint8_t &num_conf );
void PrintDescriptors(uint8_t addr)
{
uint8_t rcode = 0;
byte num_conf = 0;
uint8_t rcode = 0;
uint8_t num_conf = 0;
rcode = getdevdescr( (byte)addr, num_conf );
if( rcode )
rcode = getdevdescr( (uint8_t)addr, num_conf );
if ( rcode )
{
printProgStr(Gen_Error_str);
print_hex( rcode, 8 );
}
Serial.print("\r\n");
for (int i = 0; i < num_conf; i++)
{
rcode = getconfdescr( addr, i ); // get configuration descriptor
if ( rcode )
{
printProgStr(Gen_Error_str);
print_hex( rcode, 8 );
}
Serial.print("\r\n");
for (int i=0; i<num_conf; i++)
{
rcode = getconfdescr( addr, i ); // get configuration descriptor
if( rcode )
{
printProgStr(Gen_Error_str);
print_hex(rcode, 8);
}
Serial.println("\r\n");
print_hex(rcode, 8);
}
Serial.println("\r\n");
}
}
void PrintAllDescriptors(UsbDevice *pdev)
{
Serial.println("\r\n");
print_hex(pdev->address.devAddress, 8);
Serial.println("\r\n--");
PrintDescriptors( pdev->address.devAddress );
Serial.println("\r\n");
print_hex(pdev->address.devAddress, 8);
Serial.println("\r\n--");
PrintDescriptors( pdev->address.devAddress );
}
void loop()
{
Usb.Task();
if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
//if (millis() >= next_time)
{
Usb.ForEachUsbDevice(&PrintAllDescriptors);
Usb.ForEachUsbDevice(&PrintAllAddresses);
Usb.ForEachUsbDevice(&PrintAllDescriptors);
Usb.ForEachUsbDevice(&PrintAllAddresses);
while( 1 ); //stop
while ( 1 ) { // stop
#ifdef ESP8266
yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
}
}
}
byte getdevdescr( byte addr, byte &num_conf )
uint8_t getdevdescr( uint8_t addr, uint8_t &num_conf )
{
USB_DEVICE_DESCRIPTOR buf;
byte rcode;
uint8_t rcode;
rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf );
if( rcode ) {
return( rcode );
if ( rcode ) {
return ( rcode );
}
printProgStr(Dev_Header_str);
printProgStr(Dev_Length_str);
@ -152,82 +150,82 @@ byte getdevdescr( byte addr, byte &num_conf )
printProgStr(Dev_Nconf_str);
print_hex( buf.bNumConfigurations, 8 );
num_conf = buf.bNumConfigurations;
return( 0 );
return ( 0 );
}
void printhubdescr(uint8_t *descrptr, uint8_t addr)
{
HubDescriptor *pHub = (HubDescriptor*) descrptr;
uint8_t len = *((uint8_t*)descrptr);
HubDescriptor *pHub = (HubDescriptor*) descrptr;
uint8_t len = *((uint8_t*)descrptr);
printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
printProgStr(PSTR("bDescLength:\t\t"));
Serial.println(pHub->bDescLength, HEX);
printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
printProgStr(PSTR("bDescLength:\t\t"));
Serial.println(pHub->bDescLength, HEX);
printProgStr(PSTR("bDescriptorType:\t"));
Serial.println(pHub->bDescriptorType, HEX);
printProgStr(PSTR("bDescriptorType:\t"));
Serial.println(pHub->bDescriptorType, HEX);
printProgStr(PSTR("bNbrPorts:\t\t"));
Serial.println(pHub->bNbrPorts, HEX);
printProgStr(PSTR("bNbrPorts:\t\t"));
Serial.println(pHub->bNbrPorts, HEX);
printProgStr(PSTR("LogPwrSwitchMode:\t"));
Serial.println(pHub->LogPwrSwitchMode, BIN);
printProgStr(PSTR("LogPwrSwitchMode:\t"));
Serial.println(pHub->LogPwrSwitchMode, BIN);
printProgStr(PSTR("CompoundDevice:\t\t"));
Serial.println(pHub->CompoundDevice, BIN);
printProgStr(PSTR("CompoundDevice:\t\t"));
Serial.println(pHub->CompoundDevice, BIN);
printProgStr(PSTR("OverCurrentProtectMode:\t"));
Serial.println(pHub->OverCurrentProtectMode, BIN);
printProgStr(PSTR("OverCurrentProtectMode:\t"));
Serial.println(pHub->OverCurrentProtectMode, BIN);
printProgStr(PSTR("TTThinkTime:\t\t"));
Serial.println(pHub->TTThinkTime, BIN);
printProgStr(PSTR("TTThinkTime:\t\t"));
Serial.println(pHub->TTThinkTime, BIN);
printProgStr(PSTR("PortIndicatorsSupported:"));
Serial.println(pHub->PortIndicatorsSupported, BIN);
printProgStr(PSTR("PortIndicatorsSupported:"));
Serial.println(pHub->PortIndicatorsSupported, BIN);
printProgStr(PSTR("Reserved:\t\t"));
Serial.println(pHub->Reserved, HEX);
printProgStr(PSTR("Reserved:\t\t"));
Serial.println(pHub->Reserved, HEX);
printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
Serial.println(pHub->bPwrOn2PwrGood, HEX);
printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
Serial.println(pHub->bPwrOn2PwrGood, HEX);
printProgStr(PSTR("bHubContrCurrent:\t"));
Serial.println(pHub->bHubContrCurrent, HEX);
printProgStr(PSTR("bHubContrCurrent:\t"));
Serial.println(pHub->bHubContrCurrent, HEX);
for (uint8_t i=7; i<len; i++)
print_hex(descrptr[i], 8);
for (uint8_t i = 7; i < len; i++)
print_hex(descrptr[i], 8);
//for (uint8_t i=1; i<=pHub->bNbrPorts; i++)
// PrintHubPortStatus(&Usb, addr, i, 1);
//for (uint8_t i=1; i<=pHub->bNbrPorts; i++)
// PrintHubPortStatus(&Usb, addr, i, 1);
}
byte getconfdescr( byte addr, byte conf )
uint8_t getconfdescr( uint8_t addr, uint8_t conf )
{
uint8_t buf[ BUFSIZE ];
uint8_t* buf_ptr = buf;
byte rcode;
byte descr_length;
byte descr_type;
unsigned int total_length;
uint8_t rcode;
uint8_t descr_length;
uint8_t descr_type;
uint16_t total_length;
rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length
LOBYTE( total_length ) = buf[ 2 ];
HIBYTE( total_length ) = buf[ 3 ];
if( total_length > 256 ) { //check if total length is larger than buffer
if ( total_length > 256 ) { //check if total length is larger than buffer
printProgStr(Conf_Trunc_str);
total_length = 256;
}
rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
while( buf_ptr < buf + total_length ) { //parsing descriptors
while ( buf_ptr < buf + total_length ) { //parsing descriptors
descr_length = *( buf_ptr );
descr_type = *( buf_ptr + 1 );
switch( descr_type ) {
case( USB_DESCRIPTOR_CONFIGURATION ):
switch ( descr_type ) {
case ( USB_DESCRIPTOR_CONFIGURATION ):
printconfdescr( buf_ptr );
break;
case( USB_DESCRIPTOR_INTERFACE ):
case ( USB_DESCRIPTOR_INTERFACE ):
printintfdescr( buf_ptr );
break;
case( USB_DESCRIPTOR_ENDPOINT ):
case ( USB_DESCRIPTOR_ENDPOINT ):
printepdescr( buf_ptr );
break;
case 0x29:
@ -236,19 +234,19 @@ byte getconfdescr( byte addr, byte conf )
default:
printunkdescr( buf_ptr );
break;
}//switch( descr_type
}//switch( descr_type
buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer
}//while( buf_ptr <=...
return( 0 );
return ( rcode );
}
/* prints hex numbers with leading zeroes */
// copyright, Peter H Anderson, Baltimore, MD, Nov, '07
// source: http://www.phanderson.com/arduino/arduino_display.html
void print_hex(int v, int num_places)
{
int mask=0, n, num_nibbles, digit;
int mask = 0, n, num_nibbles, digit;
for (n=1; n<=num_places; n++) {
for (n = 1; n <= num_places; n++) {
mask = (mask << 1) | 0x0001;
}
v = v & mask; // truncate v to specified number of places
@ -258,15 +256,15 @@ void print_hex(int v, int num_places)
++num_nibbles;
}
do {
digit = ((v >> (num_nibbles-1) * 4)) & 0x0f;
digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;
Serial.print(digit, HEX);
}
while(--num_nibbles);
while (--num_nibbles);
}
/* function to print configuration descriptor */
void printconfdescr( uint8_t* descr_ptr )
{
USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
printProgStr(Conf_Header_str);
printProgStr(Conf_Totlen_str);
print_hex( conf_ptr->wTotalLength, 16 );
@ -285,7 +283,7 @@ void printconfdescr( uint8_t* descr_ptr )
/* function to print interface descriptor */
void printintfdescr( uint8_t* descr_ptr )
{
USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
printProgStr(Int_Header_str);
printProgStr(Int_Number_str);
print_hex( intf_ptr->bInterfaceNumber, 8 );
@ -306,7 +304,7 @@ void printintfdescr( uint8_t* descr_ptr )
/* function to print endpoint descriptor */
void printepdescr( uint8_t* descr_ptr )
{
USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
printProgStr(End_Header_str);
printProgStr(End_Address_str);
print_hex( ep_ptr->bEndpointAddress, 8 );
@ -322,8 +320,8 @@ void printepdescr( uint8_t* descr_ptr )
/*function to print unknown descriptor */
void printunkdescr( uint8_t* descr_ptr )
{
byte length = *descr_ptr;
byte i;
uint8_t length = *descr_ptr;
uint8_t i;
printProgStr(Unk_Header_str);
printProgStr(Unk_Length_str);
print_hex( *descr_ptr, 8 );
@ -331,7 +329,7 @@ void printunkdescr( uint8_t* descr_ptr )
print_hex( *(descr_ptr + 1 ), 8 );
printProgStr(Unk_Contents_str);
descr_ptr += 2;
for( i = 0; i < length; i++ ) {
for ( i = 0; i < length; i++ ) {
print_hex( *descr_ptr, 8 );
descr_ptr++;
}
@ -339,10 +337,10 @@ void printunkdescr( uint8_t* descr_ptr )
/* Print a string from Program Memory directly to save RAM */
void printProgStr(prog_char str[])
void printProgStr(const char* str)
{
char c;
if(!str) return;
while((c = pgm_read_byte(str++)))
if (!str) return;
while ((c = pgm_read_byte(str++)))
Serial.print(c);
}

View file

@ -6,11 +6,12 @@
#include <XBOXOLD.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
USBHub Hub1(&Usb); // The controller has a built in hub, so this instance is needed

View file

@ -0,0 +1,108 @@
/*
Example sketch for the Xbox ONE USB library - by guruthree, based on work by
Kristian Lauszus.
*/
#include <XBOXONE.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
USB Usb;
XBOXONE Xbox(&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.print(F("\r\nXBOX USB Library Started"));
}
void loop() {
Usb.Task();
if (Xbox.XboxOneConnected) {
if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {
Serial.print(F("LeftHatX: "));
Serial.print(Xbox.getAnalogHat(LeftHatX));
Serial.print("\t");
}
if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) {
Serial.print(F("LeftHatY: "));
Serial.print(Xbox.getAnalogHat(LeftHatY));
Serial.print("\t");
}
if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {
Serial.print(F("RightHatX: "));
Serial.print(Xbox.getAnalogHat(RightHatX));
Serial.print("\t");
}
if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
Serial.print(F("RightHatY: "));
Serial.print(Xbox.getAnalogHat(RightHatY));
}
Serial.println();
}
if (Xbox.getButtonPress(L2) > 0 || Xbox.getButtonPress(R2) > 0) {
if (Xbox.getButtonPress(L2) > 0) {
Serial.print(F("L2: "));
Serial.print(Xbox.getButtonPress(L2));
Serial.print("\t");
}
if (Xbox.getButtonPress(R2) > 0) {
Serial.print(F("R2: "));
Serial.print(Xbox.getButtonPress(R2));
Serial.print("\t");
}
Serial.println();
}
if (Xbox.getButtonClick(UP))
Serial.println(F("Up"));
if (Xbox.getButtonClick(DOWN))
Serial.println(F("Down"));
if (Xbox.getButtonClick(LEFT))
Serial.println(F("Left"));
if (Xbox.getButtonClick(RIGHT))
Serial.println(F("Right"));
if (Xbox.getButtonClick(START))
Serial.println(F("Start"));
if (Xbox.getButtonClick(BACK))
Serial.println(F("Back"));
if (Xbox.getButtonClick(XBOX))
Serial.println(F("Xbox"));
if (Xbox.getButtonClick(SYNC))
Serial.println(F("Sync"));
if (Xbox.getButtonClick(L1))
Serial.println(F("L1"));
if (Xbox.getButtonClick(R1))
Serial.println(F("R1"));
if (Xbox.getButtonClick(L2))
Serial.println(F("L2"));
if (Xbox.getButtonClick(R2))
Serial.println(F("R2"));
if (Xbox.getButtonClick(L3))
Serial.println(F("L3"));
if (Xbox.getButtonClick(R3))
Serial.println(F("R3"));
if (Xbox.getButtonClick(A))
Serial.println(F("A"));
if (Xbox.getButtonClick(B))
Serial.println(F("B"));
if (Xbox.getButtonClick(X))
Serial.println(F("X"));
if (Xbox.getButtonClick(Y))
Serial.println(F("Y"));
}
delay(1);
}

View file

@ -6,11 +6,12 @@
*/
#include <XBOXRECV.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
XBOXRECV Xbox(&Usb);

View file

@ -5,11 +5,12 @@
*/
#include <XBOXUSB.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
XBOXUSB Xbox(&Usb);

View file

@ -3,11 +3,11 @@
#include "pgmstrings.h"
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class ACMAsyncOper : public CDCAsyncOper
{

View file

@ -20,8 +20,8 @@
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
ADK adk(&Usb, "TKJElectronics", // Manufacturer Name
@ -68,8 +68,8 @@ void loop() {
digitalWrite(LED, msg[0] ? HIGH : LOW);
}
if (millis() - timer >= 1000) { // Send data every 1s
timer = millis();
if ((int32_t)((uint32_t)millis() - timer) >= 1000) { // Send data every 1s
timer = (uint32_t)millis();
rcode = adk.SndData(sizeof(timer), (uint8_t*)&timer);
if (rcode && rcode != hrNAK) {
Serial.print(F("\r\nData send: "));

View file

@ -4,16 +4,17 @@
#include <adk.h>
#include <hidboot.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
USBHub Hub1(&Usb);
USBHub Hub2(&Usb);
HIDBoot<HID_PROTOCOL_KEYBOARD> Keyboard(&Usb);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
ADK adk(&Usb,"Circuits@Home, ltd.",
"USB Host Shield",
@ -54,9 +55,17 @@ uint8_t keylcl;
if( keylcl == 0x13 ) {
rcode = adk.SndData( strlen( new_line ), (uint8_t *)new_line );
if (rcode && rcode != hrNAK) {
Serial.print(F("\r\nData send: "));
Serial.print(rcode, HEX);
}
}
else {
rcode = adk.SndData( 1, &keylcl );
if (rcode && rcode != hrNAK) {
Serial.print(F("\r\nData send: "));
Serial.print(rcode, HEX);
}
}
Serial.print((char) keylcl );
@ -79,7 +88,7 @@ void setup()
while(1); //halt
}//if (Usb.Init() == -1...
Keyboard.SetReportParser(0, (HIDReportParser*)&Prs);
HidKeyboard.SetReportParser(0, &Prs);
delay( 200 );
}

View file

@ -1,10 +1,11 @@
#include <adk.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
USBHub hub0(&Usb);

View file

@ -1,33 +1,34 @@
#include <adk.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
//USBHub Hub(&Usb);
ADK adk(&Usb,"Circuits@Home, ltd.",
"USB Host Shield",
"Arduino Terminal for Android",
"1.0",
"http://www.circuitsathome.com",
"0000000000000001");
ADK adk(&Usb, "Circuits@Home, ltd.",
"USB Host Shield",
"Arduino Terminal for Android",
"1.0",
"http://www.circuitsathome.com",
"0000000000000001");
void setup()
{
Serial.begin(115200);
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
Serial.println("\r\nADK demo start");
Serial.println("\r\nADK demo start");
if (Usb.Init() == -1) {
Serial.println("OSCOKIRQ failed to assert");
while(1); //halt
}//if (Usb.Init() == -1...
if (Usb.Init() == -1) {
Serial.println("OSCOKIRQ failed to assert");
while (1); //halt
}//if (Usb.Init() == -1...
}
void loop()
@ -36,29 +37,37 @@ void loop()
uint8_t msg[64] = { 0x00 };
const char* recv = "Received: ";
Usb.Task();
Usb.Task();
if( adk.isReady() == false ) {
return;
}
uint16_t len = 64;
if ( adk.isReady() == false ) {
return;
}
uint16_t len = 64;
rcode = adk.RcvData(&len, msg);
if( rcode & ( rcode != hrNAK )) {
USBTRACE2("Data rcv. :", rcode );
}
if(len > 0) {
USBTRACE("\r\nData Packet.");
rcode = adk.RcvData(&len, msg);
if ( rcode & ( rcode != hrNAK )) {
USBTRACE2("Data rcv. :", rcode );
}
if (len > 0) {
USBTRACE("\r\nData Packet.");
for( uint8_t i = 0; i < len; i++ ) {
for ( uint8_t i = 0; i < len; i++ ) {
Serial.print((char)msg[i]);
}
/* sending back what was received */
rcode = adk.SndData( strlen( recv ), (uint8_t *)recv );
if (rcode && rcode != hrNAK) {
Serial.print(F("\r\nData send: "));
Serial.print(rcode, HEX);
}
rcode = adk.SndData( strlen(( char * )msg ), msg );
if (rcode && rcode != hrNAK) {
Serial.print(F("\r\nData send: "));
Serial.print(rcode, HEX);
}
}//if( len > 0 )...
}//if( len > 0 )...
delay( 1000 );
delay( 1000 );
}

View file

@ -1,32 +1,33 @@
#include <adk.h>
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
ADK adk(&Usb,"Circuits@Home, ltd.",
"USB Host Shield",
"Arduino Terminal for Android",
"1.0",
"http://www.circuitsathome.com",
"0000000000000001");
ADK adk(&Usb, "Circuits@Home, ltd.",
"USB Host Shield",
"Arduino Terminal for Android",
"1.0",
"http://www.circuitsathome.com",
"0000000000000001");
void setup()
{
Serial.begin(115200);
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
Serial.println("\r\nADK demo start");
Serial.println("\r\nADK demo start");
if (Usb.Init() == -1) {
Serial.println("OSCOKIRQ failed to assert");
while(1); //halt
}//if (Usb.Init() == -1...
if (Usb.Init() == -1) {
Serial.println("OSCOKIRQ failed to assert");
while (1); //halt
}//if (Usb.Init() == -1...
}
void loop()
@ -35,15 +36,23 @@ void loop()
const char* sec_ela = " seconds elapsed\r";
uint8_t rcode;
Usb.Task();
if( adk.isReady() == false ) {
return;
}
Usb.Task();
if ( adk.isReady() == false ) {
return;
}
ultoa( millis()/1000, (char *)buf, 10 );
ultoa((uint32_t)millis() / 1000, (char *)buf, 10 );
rcode = adk.SndData( strlen((char *)buf), buf );
rcode = adk.SndData( strlen( sec_ela), (uint8_t *)sec_ela );
rcode = adk.SndData( strlen((char *)buf), buf );
if (rcode && rcode != hrNAK) {
Serial.print(F("\r\nData send: "));
Serial.print(rcode, HEX);
}
rcode = adk.SndData( strlen( sec_ela), (uint8_t *)sec_ela );
if (rcode && rcode != hrNAK) {
Serial.print(F("\r\nData send: "));
Serial.print(rcode, HEX);
}
delay( 1000 );
delay( 1000 );
}

View file

@ -4,12 +4,13 @@
/* otherwise press any key after getting GPIO error to complete the test */
/**/
#include <usbhub.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library
#include <SPI.h> // Hack to use the SPI library
#endif
#include <SPI.h> // Hack to use the SPI library
/* variables */
uint8_t rcode;
@ -59,6 +60,9 @@ void setup() {
uint8_t sample_rd = 0;
uint8_t gpinpol_copy = Usb.regRd(rGPINPOL);
for(uint8_t i = 0; i < 16; i++) {
#ifdef ESP8266
yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
for(uint16_t j = 0; j < 65535; j++) {
Usb.regWr(rGPINPOL, sample_wr);
sample_rd = Usb.regRd(rGPINPOL);
@ -80,26 +84,29 @@ void setup() {
/* GPIO test */
/* in order to simplify board layout, GPIN pins on text fixture are connected to GPOUT */
/* in reverse order, i.e, GPIN0 is connected to GPOUT7, GPIN1 to GPOUT6, etc. */
//{
// uint8_t tmpbyte;
// E_Notify(PSTR("\r\nGPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on"), 0x80);
// for(uint8_t sample_gpio = 0; sample_gpio < 255; sample_gpio++) {
// Usb.gpioWr(sample_gpio);
// tmpbyte = Usb.gpioRd();
// /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */
// tmpbyte = ((tmpbyte * 0x0802LU & 0x22110LU) | (tmpbyte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
// if(sample_gpio != tmpbyte) {
// E_Notify(PSTR("\r\nTest failed. Value written: "), 0x80);
// print_hex(sample_gpio, 8);
// E_Notify(PSTR(" Value read: "), 0x80);
// print_hex(tmpbyte, 8);
// E_Notify(PSTR(" "), 0x80);
// press_any_key();
// break;
// }//if( sample_gpio != tmpbyte...
// }//for( uint8_t sample_gpio...
// E_Notify(PSTR("\r\nGPIO test passed."), 0x80);
//}//GPIO test
{
uint8_t tmpbyte;
E_Notify(PSTR("\r\nGPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on"), 0x80);
for(uint8_t sample_gpio = 0; sample_gpio < 255; sample_gpio++) {
#ifdef ESP8266
yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
Usb.gpioWr(sample_gpio);
tmpbyte = Usb.gpioRd();
/* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */
tmpbyte = ((tmpbyte * 0x0802LU & 0x22110LU) | (tmpbyte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
if(sample_gpio != tmpbyte) {
E_Notify(PSTR("\r\nTest failed. Value written: "), 0x80);
print_hex(sample_gpio, 8);
E_Notify(PSTR(" Value read: "), 0x80);
print_hex(tmpbyte, 8);
E_Notify(PSTR(" "), 0x80);
press_any_key();
break;
}//if( sample_gpio != tmpbyte...
}//for( uint8_t sample_gpio...
E_Notify(PSTR("\r\nGPIO test passed."), 0x80);
}//GPIO test
/* PLL test. Stops/starts MAX3421E oscillator several times */
{
E_Notify(PSTR("\r\nPLL test. 100 chip resets will be performed"), 0x80);
@ -111,6 +118,9 @@ void setup() {
/* Restart oscillator */
E_Notify(PSTR("\r\nResetting oscillator\r\n"), 0x80);
for(uint16_t i = 0; i < 100; i++) {
#ifdef ESP8266
yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
E_Notify(PSTR("\rReset number "), 0x80);
Serial.print(i, DEC);
Usb.regWr(rUSBCTL, bmCHIPRES); //reset
@ -120,7 +130,7 @@ void setup() {
}
Usb.regWr(rUSBCTL, 0x00); //release from reset
uint16_t j = 0;
for(j = 0; j < 65535; j++) { //tracking off to on time
for(j = 1; j < 65535; j++) { //tracking off to on time
if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) {
E_Notify(PSTR(" Time to stabilize - "), 0x80);
Serial.print(j, DEC);
@ -205,7 +215,11 @@ void loop() {
print_hex(buf.bNumConfigurations, 8);
/**/
E_Notify(PSTR("\r\n\nAll tests passed. Press RESET to restart test"), 0x80);
while(1);
while(1) {
#ifdef ESP8266
yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
}
}
break;
case( USB_STATE_ERROR):
@ -227,6 +241,9 @@ void halt55() {
while(1) {
Usb.regWr(0x55, 0x55);
#ifdef ESP8266
yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
}
}
@ -252,7 +269,11 @@ void print_hex(int v, int num_places) {
/* prints "Press any key" and returns when key is pressed */
void press_any_key() {
E_Notify(PSTR("\r\nPress any key to continue..."), 0x80);
while(Serial.available() <= 0); //wait for input
while(Serial.available() <= 0) { // wait for input
#ifdef ESP8266
yield(); // needed in order to reset the watchdog timer on the ESP8266
#endif
}
Serial.read(); //empty input buffer
return;
}

View file

@ -3,8 +3,8 @@
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class ACMAsyncOper : public CDCAsyncOper
{

View file

@ -2,11 +2,12 @@
#include <usbhub.h>
#include "pgmstrings.h"
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class FTDIAsync : public FTDIAsyncOper
{
@ -38,8 +39,6 @@ USB Usb;
FTDIAsync FtdiAsync;
FTDI Ftdi(&Usb, &FtdiAsync);
uint32_t next_time;
void setup()
{
Serial.begin( 115200 );
@ -52,8 +51,6 @@ void setup()
Serial.println("OSC did not start.");
delay( 200 );
next_time = millis() + 5000;
}
void loop()

View file

@ -1,10 +1,11 @@
#include <usbhub.h>
#include "pgmstrings.h"
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
USBHub Hub1(&Usb);
@ -16,31 +17,31 @@ uint32_t next_time;
void PrintAllAddresses(UsbDevice *pdev)
{
UsbDeviceAddress adr;
adr.devAddress = pdev->address.devAddress;
Serial.print("\r\nAddr:");
Serial.print(adr.devAddress, HEX);
Serial.print("(");
Serial.print(adr.bmHub, HEX);
Serial.print(".");
Serial.print(adr.bmParent, HEX);
Serial.print(".");
Serial.print(adr.bmAddress, HEX);
Serial.println(")");
UsbDeviceAddress adr;
adr.devAddress = pdev->address.devAddress;
Serial.print("Addr:");
Serial.print(adr.devAddress, HEX);
Serial.print("(");
Serial.print(adr.bmHub, HEX);
Serial.print(".");
Serial.print(adr.bmParent, HEX);
Serial.print(".");
Serial.print(adr.bmAddress, HEX);
Serial.println(")");
}
void PrintAddress(uint8_t addr)
{
UsbDeviceAddress adr;
adr.devAddress = addr;
Serial.print("\r\nADDR:\t");
Serial.println(adr.devAddress,HEX);
Serial.print("DEV:\t");
Serial.println(adr.bmAddress,HEX);
Serial.print("PRNT:\t");
Serial.println(adr.bmParent,HEX);
Serial.print("HUB:\t");
Serial.println(adr.bmHub,HEX);
UsbDeviceAddress adr;
adr.devAddress = addr;
Serial.print("\r\nADDR:\t");
Serial.println(adr.devAddress, HEX);
Serial.print("DEV:\t");
Serial.println(adr.bmAddress, HEX);
Serial.print("PRNT:\t");
Serial.println(adr.bmParent, HEX);
Serial.print("HUB:\t");
Serial.println(adr.bmHub, HEX);
}
void setup()
@ -52,71 +53,65 @@ void setup()
Serial.println("Start");
if (Usb.Init() == -1)
Serial.println("OSC did not start.");
Serial.println("OSC did not start.");
delay( 200 );
next_time = millis() + 10000;
next_time = (uint32_t)millis() + 10000;
}
byte getdevdescr( byte addr, byte &num_conf );
void PrintDescriptors(uint8_t addr)
{
uint8_t rcode = 0;
byte num_conf = 0;
uint8_t rcode = 0;
uint8_t num_conf = 0;
rcode = getdevdescr( (byte)addr, num_conf );
if( rcode )
{
rcode = getdevdescr( (uint8_t)addr, num_conf );
if ( rcode ) {
printProgStr(Gen_Error_str);
print_hex( rcode, 8 );
}
Serial.print("\r\n");
for (uint8_t i = 0; i < num_conf; i++) {
rcode = getconfdescr( addr, i ); // get configuration descriptor
if ( rcode ) {
printProgStr(Gen_Error_str);
print_hex( rcode, 8 );
}
Serial.print("\r\n");
for (int i=0; i<num_conf; i++)
{
rcode = getconfdescr( addr, i ); // get configuration descriptor
if( rcode )
{
printProgStr(Gen_Error_str);
print_hex(rcode, 8);
}
Serial.println("\r\n");
print_hex(rcode, 8);
}
Serial.println("\r\n");
}
}
void PrintAllDescriptors(UsbDevice *pdev)
{
Serial.println("\r\n");
print_hex(pdev->address.devAddress, 8);
Serial.println("\r\n--");
PrintDescriptors( pdev->address.devAddress );
Serial.println("\r\n");
print_hex(pdev->address.devAddress, 8);
Serial.println("\r\n--");
getallstrdescr(pdev->address.devAddress);
PrintDescriptors( pdev->address.devAddress );
}
void loop()
{
Usb.Task();
if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
if ((millis() - next_time) >= 0L)
{
Usb.ForEachUsbDevice(&PrintAllDescriptors);
Usb.ForEachUsbDevice(&PrintAllAddresses);
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) {
if ((int32_t)((uint32_t)millis() - next_time) >= 0L) {
Usb.ForEachUsbDevice(&PrintAllDescriptors);
Usb.ForEachUsbDevice(&PrintAllAddresses);
while( 1 ); //stop
while ( 1 ); //stop
}
}
}
byte getdevdescr( byte addr, byte &num_conf )
uint8_t getdevdescr( uint8_t addr, uint8_t &num_conf )
{
USB_DEVICE_DESCRIPTOR buf;
byte rcode;
rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf );
if( rcode ) {
return( rcode );
uint8_t rcode;
rcode = Usb.getDevDescr( addr, 0, DEV_DESCR_LEN, ( uint8_t *)&buf );
if ( rcode ) {
return ( rcode );
}
printProgStr(Dev_Header_str);
printProgStr(Dev_Length_str);
@ -148,82 +143,82 @@ byte getdevdescr( byte addr, byte &num_conf )
printProgStr(Dev_Nconf_str);
print_hex( buf.bNumConfigurations, 8 );
num_conf = buf.bNumConfigurations;
return( 0 );
return ( 0 );
}
void printhubdescr(uint8_t *descrptr, uint8_t addr)
{
HubDescriptor *pHub = (HubDescriptor*) descrptr;
uint8_t len = *((uint8_t*)descrptr);
HubDescriptor *pHub = (HubDescriptor*) descrptr;
uint8_t len = *((uint8_t*)descrptr);
printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
printProgStr(PSTR("bDescLength:\t\t"));
Serial.println(pHub->bDescLength, HEX);
printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
printProgStr(PSTR("bDescLength:\t\t"));
Serial.println(pHub->bDescLength, HEX);
printProgStr(PSTR("bDescriptorType:\t"));
Serial.println(pHub->bDescriptorType, HEX);
printProgStr(PSTR("bDescriptorType:\t"));
Serial.println(pHub->bDescriptorType, HEX);
printProgStr(PSTR("bNbrPorts:\t\t"));
Serial.println(pHub->bNbrPorts, HEX);
printProgStr(PSTR("bNbrPorts:\t\t"));
Serial.println(pHub->bNbrPorts, HEX);
printProgStr(PSTR("LogPwrSwitchMode:\t"));
Serial.println(pHub->LogPwrSwitchMode, BIN);
printProgStr(PSTR("LogPwrSwitchMode:\t"));
Serial.println(pHub->LogPwrSwitchMode, BIN);
printProgStr(PSTR("CompoundDevice:\t\t"));
Serial.println(pHub->CompoundDevice, BIN);
printProgStr(PSTR("CompoundDevice:\t\t"));
Serial.println(pHub->CompoundDevice, BIN);
printProgStr(PSTR("OverCurrentProtectMode:\t"));
Serial.println(pHub->OverCurrentProtectMode, BIN);
printProgStr(PSTR("OverCurrentProtectMode:\t"));
Serial.println(pHub->OverCurrentProtectMode, BIN);
printProgStr(PSTR("TTThinkTime:\t\t"));
Serial.println(pHub->TTThinkTime, BIN);
printProgStr(PSTR("TTThinkTime:\t\t"));
Serial.println(pHub->TTThinkTime, BIN);
printProgStr(PSTR("PortIndicatorsSupported:"));
Serial.println(pHub->PortIndicatorsSupported, BIN);
printProgStr(PSTR("PortIndicatorsSupported:"));
Serial.println(pHub->PortIndicatorsSupported, BIN);
printProgStr(PSTR("Reserved:\t\t"));
Serial.println(pHub->Reserved, HEX);
printProgStr(PSTR("Reserved:\t\t"));
Serial.println(pHub->Reserved, HEX);
printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
Serial.println(pHub->bPwrOn2PwrGood, HEX);
printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
Serial.println(pHub->bPwrOn2PwrGood, HEX);
printProgStr(PSTR("bHubContrCurrent:\t"));
Serial.println(pHub->bHubContrCurrent, HEX);
printProgStr(PSTR("bHubContrCurrent:\t"));
Serial.println(pHub->bHubContrCurrent, HEX);
for (uint8_t i=7; i<len; i++)
print_hex(descrptr[i], 8);
for (uint8_t i = 7; i < len; i++)
print_hex(descrptr[i], 8);
//for (uint8_t i=1; i<=pHub->bNbrPorts; i++)
// PrintHubPortStatus(&Usb, addr, i, 1);
//for (uint8_t i=1; i<=pHub->bNbrPorts; i++)
// PrintHubPortStatus(&Usb, addr, i, 1);
}
byte getconfdescr( byte addr, byte conf )
uint8_t getconfdescr( uint8_t addr, uint8_t conf )
{
uint8_t buf[ BUFSIZE ];
uint8_t* buf_ptr = buf;
byte rcode;
byte descr_length;
byte descr_type;
unsigned int total_length;
uint8_t rcode;
uint8_t descr_length;
uint8_t descr_type;
uint16_t total_length;
rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length
LOBYTE( total_length ) = buf[ 2 ];
HIBYTE( total_length ) = buf[ 3 ];
if( total_length > 256 ) { //check if total length is larger than buffer
if ( total_length > 256 ) { //check if total length is larger than buffer
printProgStr(Conf_Trunc_str);
total_length = 256;
}
rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
while( buf_ptr < buf + total_length ) { //parsing descriptors
while ( buf_ptr < buf + total_length ) { //parsing descriptors
descr_length = *( buf_ptr );
descr_type = *( buf_ptr + 1 );
switch( descr_type ) {
case( USB_DESCRIPTOR_CONFIGURATION ):
switch ( descr_type ) {
case ( USB_DESCRIPTOR_CONFIGURATION ):
printconfdescr( buf_ptr );
break;
case( USB_DESCRIPTOR_INTERFACE ):
case ( USB_DESCRIPTOR_INTERFACE ):
printintfdescr( buf_ptr );
break;
case( USB_DESCRIPTOR_ENDPOINT ):
case ( USB_DESCRIPTOR_ENDPOINT ):
printepdescr( buf_ptr );
break;
case 0x29:
@ -232,19 +227,97 @@ byte getconfdescr( byte addr, byte conf )
default:
printunkdescr( buf_ptr );
break;
}//switch( descr_type
}//switch( descr_type
buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer
}//while( buf_ptr <=...
return( 0 );
return ( rcode );
}
// function to get all string descriptors
uint8_t getallstrdescr(uint8_t addr)
{
uint8_t rcode = 0;
Usb.Task();
if ( Usb.getUsbTaskState() >= USB_STATE_CONFIGURING ) { // state configuring or higher
USB_DEVICE_DESCRIPTOR buf;
rcode = Usb.getDevDescr( addr, 0, DEV_DESCR_LEN, ( uint8_t *)&buf );
if ( rcode ) {
return ( rcode );
}
Serial.println("String Descriptors:");
if ( buf.iManufacturer > 0 ) {
Serial.print("Manufacturer:\t\t");
rcode = getstrdescr( addr, buf.iManufacturer ); // get manufacturer string
if ( rcode ) {
Serial.println( rcode, HEX );
}
Serial.print("\r\n");
}
if ( buf.iProduct > 0 ) {
Serial.print("Product:\t\t");
rcode = getstrdescr( addr, buf.iProduct ); // get product string
if ( rcode ) {
Serial.println( rcode, HEX );
}
Serial.print("\r\n");
}
if ( buf.iSerialNumber > 0 ) {
Serial.print("Serial:\t\t\t");
rcode = getstrdescr( addr, buf.iSerialNumber ); // get serial string
if ( rcode ) {
Serial.println( rcode, HEX );
}
Serial.print("\r\n");
}
}
return rcode;
}
// function to get single string description
uint8_t getstrdescr( uint8_t addr, uint8_t idx )
{
uint8_t buf[ 256 ];
uint8_t rcode;
uint8_t length;
uint8_t i;
uint16_t langid;
rcode = Usb.getStrDescr( addr, 0, 1, 0, 0, buf ); //get language table length
if ( rcode ) {
Serial.println("Error retrieving LangID table length");
return ( rcode );
}
length = buf[ 0 ]; //length is the first byte
rcode = Usb.getStrDescr( addr, 0, length, 0, 0, buf ); //get language table
if ( rcode ) {
Serial.print("Error retrieving LangID table ");
return ( rcode );
}
langid = (buf[3] << 8) | buf[2];
rcode = Usb.getStrDescr( addr, 0, 1, idx, langid, buf );
if ( rcode ) {
Serial.print("Error retrieving string length ");
return ( rcode );
}
length = buf[ 0 ];
rcode = Usb.getStrDescr( addr, 0, length, idx, langid, buf );
if ( rcode ) {
Serial.print("Error retrieving string ");
return ( rcode );
}
for ( i = 2; i < length; i += 2 ) { //string is UTF-16LE encoded
Serial.print((char) buf[i]);
}
return ( rcode );
}
/* prints hex numbers with leading zeroes */
// copyright, Peter H Anderson, Baltimore, MD, Nov, '07
// source: http://www.phanderson.com/arduino/arduino_display.html
void print_hex(int v, int num_places)
{
int mask=0, n, num_nibbles, digit;
int mask = 0, n, num_nibbles, digit;
for (n=1; n<=num_places; n++) {
for (n = 1; n <= num_places; n++) {
mask = (mask << 1) | 0x0001;
}
v = v & mask; // truncate v to specified number of places
@ -254,15 +327,16 @@ void print_hex(int v, int num_places)
++num_nibbles;
}
do {
digit = ((v >> (num_nibbles-1) * 4)) & 0x0f;
digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;
Serial.print(digit, HEX);
}
while(--num_nibbles);
while (--num_nibbles);
}
/* function to print configuration descriptor */
void printconfdescr( uint8_t* descr_ptr )
{
USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
printProgStr(Conf_Header_str);
printProgStr(Conf_Totlen_str);
print_hex( conf_ptr->wTotalLength, 16 );
@ -278,10 +352,11 @@ void printconfdescr( uint8_t* descr_ptr )
print_hex( conf_ptr->bMaxPower, 8 );
return;
}
/* function to print interface descriptor */
void printintfdescr( uint8_t* descr_ptr )
{
USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
printProgStr(Int_Header_str);
printProgStr(Int_Number_str);
print_hex( intf_ptr->bInterfaceNumber, 8 );
@ -299,10 +374,11 @@ void printintfdescr( uint8_t* descr_ptr )
print_hex( intf_ptr->iInterface, 8 );
return;
}
/* function to print endpoint descriptor */
void printepdescr( uint8_t* descr_ptr )
{
USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
printProgStr(End_Header_str);
printProgStr(End_Address_str);
print_hex( ep_ptr->bEndpointAddress, 8 );
@ -315,11 +391,12 @@ void printepdescr( uint8_t* descr_ptr )
return;
}
/*function to print unknown descriptor */
void printunkdescr( uint8_t* descr_ptr )
{
byte length = *descr_ptr;
byte i;
uint8_t length = *descr_ptr;
uint8_t i;
printProgStr(Unk_Header_str);
printProgStr(Unk_Length_str);
print_hex( *descr_ptr, 8 );
@ -327,18 +404,17 @@ void printunkdescr( uint8_t* descr_ptr )
print_hex( *(descr_ptr + 1 ), 8 );
printProgStr(Unk_Contents_str);
descr_ptr += 2;
for( i = 0; i < length; i++ ) {
for ( i = 0; i < length; i++ ) {
print_hex( *descr_ptr, 8 );
descr_ptr++;
}
}
/* Print a string from Program Memory directly to save RAM */
void printProgStr(prog_char str[])
void printProgStr(const char* str)
{
char c;
if(!str) return;
while((c = pgm_read_byte(str++)))
if (!str) return;
while ((c = pgm_read_byte(str++)))
Serial.print(c);
}

View file

@ -4,11 +4,12 @@
// pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3]
#include <max_LCD.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
USB Usb;
Max_LCD lcd(&Usb);
@ -24,5 +25,5 @@ void loop() {
// Set the cursor to column 0, line 1 (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// Print the number of seconds since reset:
lcd.print(millis() / 1000);
lcd.print((uint32_t)millis() / 1000);
}

View file

@ -4,11 +4,12 @@
/* CDC support */
#include <cdcacm.h>
#include <cdcprolific.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class PLAsyncOper : public CDCAsyncOper
{

View file

@ -5,11 +5,12 @@
/* CDC support */
#include <cdcacm.h>
#include <cdcprolific.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class PLAsyncOper : public CDCAsyncOper {
public:
@ -70,7 +71,7 @@ void loop() {
if(Pl.isReady()) {
/* reading the GPS */
if((long)(millis() - read_delay) >= 0L) {
if((int32_t)((uint32_t)millis() - read_delay) >= 0L) {
read_delay += READ_DELAY;
rcode = Pl.RcvData(&rcvd, buf);
if(rcode && rcode != hrNAK)

View file

@ -11,11 +11,12 @@
#include <cdcprolific.h>
#include <TinyGPS.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
/* This sample code demonstrates the normal use of a TinyGPS object.
Modified to be used with USB Host Shield Library r2.0
@ -63,7 +64,7 @@ TinyGPS gps;
void gpsdump(TinyGPS &gps);
bool feedgps();
void printFloat(double f, int digits = 2);
void printFloat(double f, int16_t digits = 2);
void setup()
{
@ -93,10 +94,10 @@ void loop()
if( Pl.isReady()) {
bool newdata = false;
unsigned long start = millis();
uint32_t start = (uint32_t)millis();
// Every 5 seconds we print an update
while (millis() - start < 5000) {
while ((int32_t)((uint32_t)millis() - start) < 5000) {
if( feedgps()) {
newdata = true;
}
@ -112,7 +113,7 @@ void loop()
}//if( Usb.getUsbTaskState() == USB_STATE_RUNNING...
}
void printFloat(double number, int digits)
void printFloat(double number, int16_t digits)
{
// Handle negative numbers
if (number < 0.0)
@ -129,7 +130,7 @@ void printFloat(double number, int digits)
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
uint32_t int_part = (uint32_t)number;
double remainder = number - (double)int_part;
Serial.print(int_part);
@ -153,7 +154,7 @@ void gpsdump(TinyGPS &gps)
float flat, flon;
unsigned long age, date, time, chars;
int year;
byte month, day, hour, minute, second, hundredths;
uint8_t month, day, hour, minute, second, hundredths;
unsigned short sentences, failed;
gps.get_position(&lat, &lon, &age);

View file

@ -5,11 +5,12 @@
/* CDC support */
#include <cdcacm.h>
#include <cdcprolific.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
#include <SPI.h>
class PLAsyncOper : public CDCAsyncOper
{

@ -1 +1 @@
Subproject commit d35bb955e3818f0c14e47c8a1998003da8dc1b5a
Subproject commit 94c560c854c7a1dfc35e9de9db05de1b202de6c6

View file

@ -2,13 +2,16 @@
# These are set for a mega 1280 + quadram plus my serial patch.
# If you lack quadram, or want to disable LFN, just change _FS_TINY=1 _USE_LFN=0
#
# If your board is a mega 2560 uncomment the following two lines
# BOARD = mega2560
# PROGRAMMER = wiring
# ...and then comment out the following two lines
# If your board is a mega 2560 comment out the following two lines
BOARD = mega
BOARD_SUB = mega.menu.cpu.atmega1280
PROGRAMMER = arduino
# ...and then uncomment out the following two lines
#BOARD_SUB = mega.menu.cpu.atmega2560
#PROGRAMMER = wiring
#BOARD = teensypp2
#BOARD = teensy3
#BOARD = teensy31
@ -53,6 +56,9 @@ LIB_DIRS += ../testusbhostFAT/generic_storage
LIB_DIRS += ../testusbhostFAT/RTClib
LIB_DIRS += $(ARD_HOME)/libraries/Wire
LIB_DIRS += $(ARD_HOME)/libraries/Wire/utility
LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire
LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire/utility
LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/SPI
# And finally, the part that brings everything together for you.
include Arduino_Makefile_master/_Makefile.master

@ -1 +1 @@
Subproject commit 7fd6a306ca53d08bf53b2bbfc1b80eb056f2c55b
Subproject commit c30fcdf1f112de581de7b145a97630539e5cff44

Some files were not shown because too many files have changed in this diff Show more