-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2c8668d
Showing
11 changed files
with
338 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Prerequisites | ||
*.d | ||
|
||
# Compiled Object files | ||
*.slo | ||
*.lo | ||
*.o | ||
*.obj | ||
|
||
# Precompiled Headers | ||
*.gch | ||
*.pch | ||
|
||
# Compiled Dynamic libraries | ||
*.so | ||
*.dylib | ||
*.dll | ||
|
||
# Fortran module files | ||
*.mod | ||
*.smod | ||
|
||
# Compiled Static libraries | ||
*.lai | ||
*.la | ||
*.a | ||
*.lib | ||
|
||
# Executables | ||
*.exe | ||
*.out | ||
*.app | ||
|
||
test.sh | ||
work/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/* | ||
JoystickWin.cpp | ||
*/ | ||
|
||
#include "JoystickWin.h" | ||
|
||
#if defined(_USING_HID) | ||
|
||
static const uint8_t _hidReportDescriptor[] PROGMEM = { | ||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls) | ||
0x09, 0x04, // Usage (Joystick) | ||
0xA1, 0x01, // Collection (Application) | ||
0x85, 0x04, // Report ID (4) | ||
0x05, 0x09, // Usage Page (Button) | ||
0x19, 0x01, // Usage Minimum (0x01) | ||
0x29, 0x20, // Usage Maximum (0x20) | ||
0x15, 0x00, // Logical Minimum (0) | ||
0x25, 0x01, // Logical Maximum (1) | ||
0x75, 0x01, // Report Size (1) | ||
0x95, 0x20, // Report Count (32) | ||
0x55, 0x00, // Unit Exponent (0) | ||
0x65, 0x00, // Unit (None) | ||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls) | ||
0x09, 0x39, // Usage (Hat switch) | ||
0x15, 0x00, // Logical Minimum (0) | ||
0x25, 0x07, // Logical Maximum (7) | ||
0x35, 0x00, // Physical Minimum (0) | ||
0x46, 0x3B, 0x01, // Physical Maximum (315) | ||
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) | ||
0x75, 0x04, // Report Size (4) | ||
0x95, 0x01, // Report Count (1) | ||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
0x09, 0x39, // Usage (Hat switch) | ||
0x15, 0x00, // Logical Minimum (0) | ||
0x25, 0x07, // Logical Maximum (7) | ||
0x35, 0x00, // Physical Minimum (0) | ||
0x46, 0x3B, 0x01, // Physical Maximum (315) | ||
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) | ||
0x75, 0x04, // Report Size (4) | ||
0x95, 0x01, // Report Count (1) | ||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
0x09, 0x01, // Usage (Pointer) | ||
0x15, 0x00, // Logical Minimum (0) | ||
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) | ||
0x75, 0x10, // Report Size (16) | ||
0x95, 0x06, // Report Count (6) | ||
0xA1, 0x00, // Collection (Physical) | ||
0x09, 0x30, // Usage (X) | ||
0x09, 0x31, // Usage (Y) | ||
0x09, 0x32, // Usage (Z) | ||
0x09, 0x33, // Usage (Rx) | ||
0x09, 0x34, // Usage (Ry) | ||
0x09, 0x35, // Usage (Rz) | ||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
0xC0, // End Collection | ||
0x05, 0x02, // Usage Page (Sim Ctrls) | ||
0x15, 0x00, // Logical Minimum (0) | ||
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) | ||
0x75, 0x10, // Report Size (16) | ||
0x95, 0x05, // Report Count (5) | ||
0xA1, 0x00, // Collection (Physical) | ||
0x09, 0xBA, // Usage (Rudder) | ||
0x09, 0xBB, // Usage (Throttle) | ||
0x09, 0xC4, // Usage (Accelerator) | ||
0x09, 0xC5, // Usage (Brake) | ||
0x09, 0xC8, // Usage (Steering) | ||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) | ||
0xC0, // End Collection | ||
0xC0, // End Collection | ||
}; | ||
|
||
//================================================================================ | ||
//================================================================================ | ||
// JoystickWin | ||
|
||
JoystickWin_::JoystickWin_(void) { | ||
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor)); | ||
HID().AppendDescriptor(&node); | ||
} | ||
|
||
void JoystickWin_::begin(void) { | ||
_hid_report.buttons = 0; | ||
_hid_report.hat1 = 8; | ||
_hid_report.hat2 = 8; | ||
_hid_report.x = AXIS_MID; | ||
_hid_report.y = AXIS_MID; | ||
_hid_report.z = AXIS_MID; | ||
_hid_report.rx = AXIS_MID; | ||
_hid_report.ry = AXIS_MID; | ||
_hid_report.rz = AXIS_MID; | ||
_hid_report.rudder = AXIS_MID; | ||
_hid_report.throttle = AXIS_MID; | ||
_hid_report.accelerator = AXIS_MID; | ||
_hid_report.brake = AXIS_MID; | ||
_hid_report.steering = AXIS_MID; | ||
sendReport(); | ||
} | ||
|
||
void JoystickWin_::end(void) { | ||
begin(); | ||
} | ||
|
||
void JoystickWin_::sendReport() { | ||
HID().SendReport(4, (void *)&_hid_report, sizeof(_hid_report)); | ||
} | ||
|
||
void JoystickWin_::press(int b) { | ||
constrain(b, 0, BUTTONS_MAX - 1); | ||
_hid_report.buttons |= (uint32_t)(1UL << b); | ||
} | ||
|
||
void JoystickWin_::release(int b) { | ||
constrain(b, 0, BUTTONS_MAX - 1); | ||
_hid_report.buttons &= ~(uint32_t)(1UL << b); | ||
} | ||
|
||
void JoystickWin_::releaseAll() { | ||
_hid_report.buttons = 0; | ||
} | ||
|
||
bool JoystickWin_::isPressed(int b) { | ||
constrain(b, 0, BUTTONS_MAX - 1); | ||
return ((_hid_report.buttons & (uint32_t)(1UL << b)) != 0) ? true : false; | ||
} | ||
|
||
void JoystickWin_::hat1(int d) { | ||
constrain(d, 0, 15); | ||
_hid_report.hat1 = d; | ||
} | ||
|
||
void JoystickWin_::hat2(int d) { | ||
constrain(d, 0, 15); | ||
_hid_report.hat2 = d; | ||
} | ||
|
||
JoystickWin_ JoystickWin; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
JoystickWin.h | ||
*/ | ||
|
||
#ifndef JOYSTICKWIN_H_ | ||
#define JOYSTICKWIN_H_ | ||
|
||
#include "HID.h" | ||
|
||
#if !defined(_USING_HID) | ||
|
||
#warning "Using legacy HID core (non pluggable)" | ||
|
||
#else | ||
|
||
#define AXIS_MIN (0) | ||
#define AXIS_MID (AXIS_MAX / 2) | ||
#define AXIS_MAX (0xFFFFUL) | ||
#define BUTTONS_MAX (32) | ||
|
||
//================================================================================ | ||
//================================================================================ | ||
// JoystickWin | ||
|
||
// This overlays the data format specified by the HID report descriptor in | ||
// JoystickWin.cpp | ||
typedef struct __attribute__((__packed__)) { | ||
uint32_t buttons; | ||
uint8_t hat1:4; | ||
uint8_t hat2:4; | ||
uint16_t x; | ||
uint16_t y; | ||
uint16_t z; | ||
uint16_t rx; | ||
uint16_t ry; | ||
uint16_t rz; | ||
uint16_t rudder; | ||
uint16_t throttle; | ||
uint16_t accelerator; | ||
uint16_t brake; | ||
uint16_t steering; | ||
} JoystickWin_Report_t; | ||
|
||
class JoystickWin_ { | ||
private: | ||
JoystickWin_Report_t _hid_report; | ||
public: | ||
JoystickWin_(void); | ||
void begin(void); | ||
void end(void); | ||
void press(int b); | ||
void release(int b); | ||
void releaseAll(); | ||
bool isPressed(int b); | ||
void hat1(int d); | ||
void hat2(int d); | ||
void x(uint16_t a) { _hid_report.x = a; } | ||
void y(uint16_t a) { _hid_report.y = a; } | ||
void z(uint16_t a) { _hid_report.z = a; } | ||
void rx(uint16_t a) { _hid_report.rx = a; } | ||
void ry(uint16_t a) { _hid_report.ry = a; } | ||
void rz(uint16_t a) { _hid_report.rz = a; } | ||
void rudder(uint16_t a) { _hid_report.rudder = a; } | ||
void throttle(uint16_t a) { _hid_report.throttle = a; } | ||
void accelerator(uint16_t a) { _hid_report.accelerator = a; } | ||
void brake(uint16_t a) { _hid_report.brake = a; } | ||
void steering(uint16_t a) { _hid_report.steering = a; } | ||
void sendReport(); | ||
}; | ||
extern JoystickWin_ JoystickWin; | ||
|
||
#endif | ||
#endif // JOYSTICKWIN_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Arduino USB Joystick for Windows | ||
|
||
USB HID Joystick with 11 axes, 2 8-way direction pads, and 32 buttons. These | ||
are apparently the limits of the Windows generic joystick device driver. | ||
|
||
The following joystick class works when plugged into a computer running Windows | ||
11 and a computer running Ubuntu Linux. The class depends only on HID.h and | ||
does not contain board specific code so it may work on other boards. | ||
|
||
Oddly on some boards (Uno R4 WiFi and Due), the Serial port must be opened to | ||
use the joystick. This code is in the test sketch, not the Joystick class. | ||
|
||
## Tested boards | ||
|
||
The joystick properties window does not show all the axes. The Point | ||
of View Hat has two indicator arrows because there are two direction hats. | ||
|
||
![Arduino Micro running JoystickWin on Win11](./images/micro.jpg "Arduino Micro running JoystickWin on Win11") | ||
|
||
<em>Arduino Micro (same processor as in Pro Micro and Leonardo) running JoystickWin on Win11</em> | ||
|
||
![Arduino Due running JoystickWin on Win11](./images/due.jpg "Arduino Due running JoystickWin on Win11") | ||
|
||
<em>Arduino Due running JoystickWin on Win11</em> | ||
|
||
![Arduino Nano 33 IoT running JoystickWin on Win11](./images/nano33iot.jpg "Arduino Nano 33 IoT running JoystickWin on Win11") | ||
|
||
<em>Arduino Nano 33 IoT running JoystickWin on Win11</em> | ||
|
||
![Arduino Uno R4 WiFi running JoystickWin on Win11](./images/unor4wifi.jpg "Arduino Uno R4 WiFi running JoystickWin on Win11") | ||
|
||
<em>Arduino Uno R4 WiFi running JoystickWin on Win11</em> | ||
|
||
## Limitations | ||
|
||
This driver does not work on Arduino boards using mbed because mbed USB | ||
works differently. For example, Giga R1. | ||
|
||
This driver does not work on boards without an integrated USB controller such | ||
as Uno and Mega. See UnoJoy. | ||
|
||
This driver is a generic jumbo joystick that does not emulate any commercial | ||
joystick/gamepad such as PS3 or Xbox 360 so game software that require a | ||
specific brand/model of joystick/gamepad will not work. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include "JoystickWin.h" | ||
|
||
void setup() { | ||
#if defined(ARDUINO_ARCH_RENESAS_UNO) || defined(ARDUINO_SAM_DUE) | ||
Serial.begin(115200); | ||
while (!Serial && (millis() < 3000)) delay(10); | ||
Serial.print("sizeof JoystickWin_Report_t: "); | ||
Serial.println(sizeof(JoystickWin_Report_t)); | ||
#endif | ||
JoystickWin.begin(); | ||
} | ||
|
||
void loop() { | ||
static uint8_t count = 0; | ||
if (count >= BUTTONS_MAX) { | ||
JoystickWin.releaseAll(); | ||
count = 0; | ||
} | ||
JoystickWin.press(count); | ||
count++; | ||
|
||
// Go through all hat switch directions | ||
static uint8_t dir = 0; | ||
JoystickWin.hat1(dir++); | ||
JoystickWin.hat2(dir++); | ||
if (dir > 7) | ||
dir = 0; | ||
|
||
// Move axes to random positions | ||
JoystickWin.x(random(AXIS_MAX + 1)); | ||
JoystickWin.y(random(AXIS_MAX + 1)); | ||
JoystickWin.z(random(AXIS_MAX + 1)); | ||
JoystickWin.rx(random(AXIS_MAX + 1)); | ||
JoystickWin.ry(random(AXIS_MAX + 1)); | ||
JoystickWin.rz(random(AXIS_MAX + 1)); | ||
JoystickWin.rudder(random(AXIS_MAX + 1)); | ||
JoystickWin.throttle(random(AXIS_MAX + 1)); | ||
JoystickWin.accelerator(random(AXIS_MAX + 1)); | ||
JoystickWin.brake(random(AXIS_MAX + 1)); | ||
JoystickWin.steering(random(AXIS_MAX + 1)); | ||
|
||
// The above updates values in RAM. The following | ||
// sends the values to the USB host. | ||
JoystickWin.sendReport(); | ||
|
||
delay(100); | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.