https://forum.pjrc.com/threads/23681-Many-axis-joystick?p=41943&viewfull=1#post41943teensy4-core
#endif | #endif | ||||
#ifdef JOYSTICK_INTERFACE | #ifdef JOYSTICK_INTERFACE | ||||
#if JOYSTICK_SIZE == 12 | |||||
static uint8_t joystick_report_desc[] = { | static uint8_t joystick_report_desc[] = { | ||||
0x05, 0x01, // Usage Page (Generic Desktop) | 0x05, 0x01, // Usage Page (Generic Desktop) | ||||
0x09, 0x04, // Usage (Joystick) | 0x09, 0x04, // Usage (Joystick) | ||||
0x81, 0x02, // Input (variable,absolute) | 0x81, 0x02, // Input (variable,absolute) | ||||
0xC0 // End Collection | 0xC0 // End Collection | ||||
}; | }; | ||||
#endif | |||||
#elif JOYSTICK_SIZE == 64 | |||||
// extreme joystick (to use this, edit JOYSTICK_SIZE to 64 in usb_desc.h) | |||||
// 128 buttons 16 | |||||
// 6 axes 12 | |||||
// 17 sliders 34 | |||||
// 4 pov 2 | |||||
static uint8_t joystick_report_desc[] = { | |||||
0x05, 0x01, // Usage Page (Generic Desktop) | |||||
0x09, 0x04, // Usage (Joystick) | |||||
0xA1, 0x01, // Collection (Application) | |||||
0x15, 0x00, // Logical Minimum (0) | |||||
0x25, 0x01, // Logical Maximum (1) | |||||
0x75, 0x01, // Report Size (1) | |||||
0x95, 0x80, // Report Count (128) | |||||
0x05, 0x09, // Usage Page (Button) | |||||
0x19, 0x01, // Usage Minimum (Button #1) | |||||
0x29, 0x80, // Usage Maximum (Button #128) | |||||
0x81, 0x02, // Input (variable,absolute) | |||||
0x05, 0x01, // Usage Page (Generic Desktop) | |||||
0x09, 0x01, // Usage (Pointer) | |||||
0xA1, 0x00, // Collection () | |||||
0x15, 0x00, // Logical Minimum (0) | |||||
0x27, 0xFF, 0xFF, 0, 0, // Logical Maximum (65535) | |||||
0x75, 0x10, // Report Size (16) | |||||
0x95, 23, // Report Count (23) | |||||
0x09, 0x30, // Usage (X) | |||||
0x09, 0x31, // Usage (Y) | |||||
0x09, 0x32, // Usage (Z) | |||||
0x09, 0x33, // Usage (Rx) | |||||
0x09, 0x34, // Usage (Ry) | |||||
0x09, 0x35, // Usage (Rz) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x09, 0x36, // Usage (Slider) | |||||
0x81, 0x02, // Input (variable,absolute) | |||||
0xC0, // End Collection | |||||
0x15, 0x00, // Logical Minimum (0) | |||||
0x25, 0x07, // Logical Maximum (7) | |||||
0x35, 0x00, // Physical Minimum (0) | |||||
0x46, 0x3B, 0x01, // Physical Maximum (315) | |||||
0x75, 0x04, // Report Size (4) | |||||
0x95, 0x04, // Report Count (4) | |||||
0x65, 0x14, // Unit (20) | |||||
0x05, 0x01, // Usage Page (Generic Desktop) | |||||
0x09, 0x39, // Usage (Hat switch) | |||||
0x09, 0x39, // Usage (Hat switch) | |||||
0x09, 0x39, // Usage (Hat switch) | |||||
0x09, 0x39, // Usage (Hat switch) | |||||
0x81, 0x42, // Input (variable,absolute,null_state) | |||||
0xC0 // End Collection | |||||
}; | |||||
#endif // JOYSTICK_SIZE | |||||
#endif // JOYSTICK_INTERFACE | |||||
#ifdef MULTITOUCH_INTERFACE | #ifdef MULTITOUCH_INTERFACE | ||||
// https://forum.pjrc.com/threads/32331-USB-HID-Touchscreen-support-needed | // https://forum.pjrc.com/threads/32331-USB-HID-Touchscreen-support-needed |
#define MOUSE_INTERVAL 1 | #define MOUSE_INTERVAL 1 | ||||
#define JOYSTICK_INTERFACE 3 // Joystick | #define JOYSTICK_INTERFACE 3 // Joystick | ||||
#define JOYSTICK_ENDPOINT 4 | #define JOYSTICK_ENDPOINT 4 | ||||
#define JOYSTICK_SIZE 16 | |||||
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick | |||||
#define JOYSTICK_INTERVAL 2 | #define JOYSTICK_INTERVAL 2 | ||||
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | ||||
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY | ||||
#define MOUSE_INTERVAL 2 | #define MOUSE_INTERVAL 2 | ||||
#define JOYSTICK_INTERFACE 4 // Joystick | #define JOYSTICK_INTERFACE 4 // Joystick | ||||
#define JOYSTICK_ENDPOINT 6 | #define JOYSTICK_ENDPOINT 6 | ||||
#define JOYSTICK_SIZE 16 | |||||
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick | |||||
#define JOYSTICK_INTERVAL 1 | #define JOYSTICK_INTERVAL 1 | ||||
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | ||||
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY | #define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY | ||||
#define SEREMU_RX_INTERVAL 2 | #define SEREMU_RX_INTERVAL 2 | ||||
#define JOYSTICK_INTERFACE 2 // Joystick | #define JOYSTICK_INTERFACE 2 // Joystick | ||||
#define JOYSTICK_ENDPOINT 5 | #define JOYSTICK_ENDPOINT 5 | ||||
#define JOYSTICK_SIZE 16 | |||||
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick | |||||
#define JOYSTICK_INTERVAL 1 | #define JOYSTICK_INTERVAL 1 | ||||
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | #define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | ||||
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY | #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY | ||||
#define FLIGHTSIM_RX_INTERVAL 1 | #define FLIGHTSIM_RX_INTERVAL 1 | ||||
#define JOYSTICK_INTERFACE 7 // Joystick | #define JOYSTICK_INTERFACE 7 // Joystick | ||||
#define JOYSTICK_ENDPOINT 10 | #define JOYSTICK_ENDPOINT 10 | ||||
#define JOYSTICK_SIZE 16 | |||||
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick | |||||
#define JOYSTICK_INTERVAL 1 | #define JOYSTICK_INTERVAL 1 | ||||
/* | /* | ||||
#define MTP_INTERFACE 8 // MTP Disk | #define MTP_INTERFACE 8 // MTP Disk |
#ifdef JOYSTICK_INTERFACE // defined by usb_dev.h -> usb_desc.h | #ifdef JOYSTICK_INTERFACE // defined by usb_dev.h -> usb_desc.h | ||||
#if F_CPU >= 20000000 | #if F_CPU >= 20000000 | ||||
uint32_t usb_joystick_data[3]; | |||||
uint32_t usb_joystick_data[(JOYSTICK_SIZE+3)/4]; | |||||
// Maximum number of transmit packets to queue so we don't starve other endpoints for memory | // Maximum number of transmit packets to queue so we don't starve other endpoints for memory | ||||
yield(); | yield(); | ||||
} | } | ||||
transmit_previous_timeout = 0; | transmit_previous_timeout = 0; | ||||
memcpy(tx_packet->buf, usb_joystick_data, 12); | |||||
tx_packet->len = 12; | |||||
memcpy(tx_packet->buf, usb_joystick_data, JOYSTICK_SIZE); | |||||
tx_packet->len = JOYSTICK_SIZE; | |||||
usb_tx(JOYSTICK_ENDPOINT, tx_packet); | usb_tx(JOYSTICK_ENDPOINT, tx_packet); | ||||
//serial_print("ok\n"); | //serial_print("ok\n"); | ||||
return 0; | return 0; |
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
int usb_joystick_send(void); | int usb_joystick_send(void); | ||||
extern uint32_t usb_joystick_data[3]; | |||||
extern uint32_t usb_joystick_data[(JOYSTICK_SIZE+3)/4]; | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif | ||||
public: | public: | ||||
void begin(void) { } | void begin(void) { } | ||||
void end(void) { } | void end(void) { } | ||||
#if JOYSTICK_SIZE == 12 | |||||
void button(uint8_t button, bool val) { | void button(uint8_t button, bool val) { | ||||
if (--button >= 32) return; | if (--button >= 32) return; | ||||
if (val) usb_joystick_data[0] |= (1 << button); | if (val) usb_joystick_data[0] |= (1 << button); | ||||
usb_joystick_data[1] = (usb_joystick_data[1] & 0xFFFFFFF0) | val; | usb_joystick_data[1] = (usb_joystick_data[1] & 0xFFFFFFF0) | val; | ||||
if (!manual_mode) usb_joystick_send(); | if (!manual_mode) usb_joystick_send(); | ||||
} | } | ||||
#elif JOYSTICK_SIZE == 64 | |||||
void button(unsigned int num, bool val) { | |||||
if (--num >= 128) return; | |||||
uint32_t *p = usb_joystick_data + (num >> 5); | |||||
num &= 0x1F; | |||||
if (val) *p |= (1 << num); | |||||
else *p &= ~(1 << num); | |||||
if (!manual_mode) usb_joystick_send(); | |||||
} | |||||
void X(unsigned int position) { analog16(0, position); } | |||||
void Y(unsigned int position) { analog16(1, position); } | |||||
void Z(unsigned int position) { analog16(2, position); } | |||||
void Xrotate(unsigned int position) { analog16(3, position); } | |||||
void Yrotate(unsigned int position) { analog16(4, position); } | |||||
void Zrotate(unsigned int position) { analog16(5, position); } | |||||
void slider(unsigned int num, unsigned int position) { | |||||
if (--num >= 17) return; | |||||
analog16(num + 6, position); | |||||
} | |||||
inline void hat(unsigned int num, int angle) { | |||||
uint32_t val=15; | |||||
if (angle > 0 && angle < 23) val = 0; | |||||
else if (angle < 68) val = 1; | |||||
else if (angle < 113) val = 2; | |||||
else if (angle < 158) val = 3; | |||||
else if (angle < 203) val = 4; | |||||
else if (angle < 245) val = 5; | |||||
else if (angle < 293) val = 6; | |||||
else if (angle < 338) val = 7; | |||||
else if (angle < 360) val = 0; | |||||
uint32_t *p = usb_joystick_data; | |||||
switch(num) { | |||||
case 1: | |||||
p[15] = (p[15] & 0xFFF0FFFF) | (val << 16); break; | |||||
case 2: | |||||
p[15] = (p[15] & 0xFF0FFFFF) | (val << 20); break; | |||||
case 3: | |||||
p[15] = (p[15] & 0xF0FFFFFF) | (val << 24); break; | |||||
case 4: | |||||
p[15] = (p[15] & 0x0FFFFFFF) | (val << 28); break; | |||||
default: | |||||
return; | |||||
} | |||||
if (!manual_mode) usb_joystick_send(); | |||||
} | |||||
#endif | |||||
void useManualSend(bool mode) { | void useManualSend(bool mode) { | ||||
manual_mode = mode; | manual_mode = mode; | ||||
} | } | ||||
} | } | ||||
private: | private: | ||||
static uint8_t manual_mode; | static uint8_t manual_mode; | ||||
#if JOYSTICK_SIZE == 64 | |||||
void analog16(unsigned int num, unsigned int value) { | |||||
if (value > 0xFFFF) value = 0xFFFF; | |||||
uint16_t *p = (uint16_t *)(&usb_joystick_data[4]); | |||||
p[num] = value; | |||||
if (!manual_mode) usb_joystick_send(); | |||||
} | |||||
#endif | |||||
}; | }; | ||||
extern usb_joystick_class Joystick; | extern usb_joystick_class Joystick; | ||||