mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
merge with master
This commit is contained in:
commit
d0e32182cb
124 changed files with 4878 additions and 941 deletions
78
.travis.yml
Normal file
78
.travis.yml
Normal 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
105
BTD.cpp
Executable file → Normal 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
13
BTD.h
Executable file → Normal 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
|
||||
|
||||
|
|
10
BTHID.cpp
10
BTHID.cpp
|
@ -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
11
BTHID.h
|
@ -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();
|
||||
|
|
91
PS3BT.cpp
91
PS3BT.cpp
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
4
PS3BT.h
4
PS3BT.h
|
@ -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
64
PS3USB.cpp
Executable file → Normal 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));
|
||||
}
|
||||
}
|
||||
|
|
4
PS3USB.h
4
PS3USB.h
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
42
PS4Parser.h
42
PS4Parser.h
|
@ -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.
|
||||
|
|
15
PS4USB.h
15
PS4USB.h
|
@ -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));
|
||||
};
|
||||
/**@}*/
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
2
PSBuzz.h
2
PSBuzz.h
|
@ -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.
|
||||
|
|
73
README.md
73
README.md
|
@ -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.
|
||||
|
|
4
SPP.cpp
4
SPP.cpp
|
@ -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
2
SPP.h
|
@ -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
40
Usb.cpp
|
@ -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);
|
||||
|
|
10
UsbCore.h
10
UsbCore.h
|
@ -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
148
Wii.cpp
Executable file → Normal 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
86
Wii.h
Executable file → Normal 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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
383
XBOXONE.cpp
Normal 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
196
XBOXONE.h
Normal 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
|
15
XBOXRECV.cpp
15
XBOXRECV.cpp
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
|
3
adk.cpp
3
adk.cpp
|
@ -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
320
avrpins.h
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
|
||||
|
|
35
cdcftdi.cpp
35
cdcftdi.cpp
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
//}
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
51
examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino
Normal file
51
examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
49
examples/HID/SRWS1/SRWS1.cpp
Normal file
49
examples/HID/SRWS1/SRWS1.cpp
Normal 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);
|
||||
}
|
||||
|
95
examples/HID/SRWS1/SRWS1.h
Normal file
95
examples/HID/SRWS1/SRWS1.h
Normal 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
|
180
examples/HID/SRWS1/SRWS1.ino
Normal file
180
examples/HID/SRWS1/SRWS1.ino
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
68
examples/HID/USBHIDMultimediaKbd/USBHIDMultimediaKbd.ino
Normal file
68
examples/HID/USBHIDMultimediaKbd/USBHIDMultimediaKbd.ino
Normal 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();
|
||||
}
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
97
examples/USBH_MIDI/USBH_MIDI_dump/USBH_MIDI_dump.ino
Normal file
97
examples/USBH_MIDI/USBH_MIDI_dump/USBH_MIDI_dump.ino
Normal 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);
|
||||
}
|
||||
}
|
90
examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino
Normal file
90
examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
93
examples/USBH_MIDI/eVY1_sample/eVY1_sample.ino
Normal file
93
examples/USBH_MIDI/eVY1_sample/eVY1_sample.ino
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
108
examples/Xbox/XBOXONE/XBOXONE.ino
Normal file
108
examples/Xbox/XBOXONE/XBOXONE.ino
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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: "));
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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
Loading…
Reference in a new issue