-
Install Arduino IDE
-
Install teensyduino using its installer
-
Run the following:
cd /Applications/Arduino.app/Contents/Java/hardware/teensy git init git add -A git commit -m 'Initial commit' git apply 0001-NKRO.patch
-
Example script:
void setup() { } void loop() { Nkro.set_key(KEY_A); Nkro.send_nkro_now(); delay(1000); Nkro.reset_keys(); delay(1000); }
From 1ba54c9a4c9ecf3565eb3a5a88a635365396d34f Mon Sep 17 00:00:00 2001
From: Ethan Smith <[email protected]>
Date: Thu, 19 Sep 2019 12:51:58 -0400
Subject: [PATCH] NKRO
---
avr/cores/teensy3/WProgram.h | 1 +
avr/cores/teensy3/usb_desc.c | 70 ++++++++++++++++-
avr/cores/teensy3/usb_desc.h | 49 +++++++++---
avr/cores/teensy3/usb_dev.h | 7 ++
avr/cores/teensy3/usb_inst.cpp | 3 +
avr/cores/teensy3/usb_nkro.c | 132 +++++++++++++++++++++++++++++++++
avr/cores/teensy3/usb_nkro.h | 43 +++++++++++
avr/cores/teensy3/usb_undef.h | 19 ++++-
8 files changed, 312 insertions(+), 12 deletions(-)
create mode 100644 avr/cores/teensy3/usb_nkro.c
create mode 100644 avr/cores/teensy3/usb_nkro.h
diff --git a/avr/cores/teensy3/WProgram.h b/avr/cores/teensy3/WProgram.h
index e67de41..6eed438 100644
--- a/avr/cores/teensy3/WProgram.h
+++ b/avr/cores/teensy3/WProgram.h
@@ -54,6 +54,7 @@
#include "usb_serial.h"
#include "usb_seremu.h"
#include "usb_keyboard.h"
+#include "usb_nkro.h"
#include "usb_mouse.h"
#include "usb_joystick.h"
#include "usb_midi.h"
diff --git a/avr/cores/teensy3/usb_desc.c b/avr/cores/teensy3/usb_desc.c
index 182ae6d..fe560c3 100644
--- a/avr/cores/teensy3/usb_desc.c
+++ b/avr/cores/teensy3/usb_desc.c
@@ -188,6 +188,33 @@ static uint8_t keymedia_report_desc[] = {
};
#endif
+#ifdef NKRO_INTERFACE
+static uint8_t nkro_hid_report_desc[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ // bitmap of modifiers
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ // bitmap of keys
+ 0x95, NKRO_REPORT_KEYS*8, // Report Count (),
+ 0x75, 0x01, // Report Size (1),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum(1),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, NKRO_REPORT_KEYS*8-1, // Usage Maximum (),
+ 0x81, 0x02, // Input (Data, Variable, Absolute),
+ 0xc0 // End Collection
+};
+#endif
+
#ifdef MOUSE_INTERFACE
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
static uint8_t mouse_report_desc[] = {
@@ -542,7 +569,15 @@ static uint8_t flightsim_report_desc[] = {
#define JOYSTICK_INTERFACE_DESC_SIZE 0
#endif
-#define MTP_INTERFACE_DESC_POS JOYSTICK_INTERFACE_DESC_POS+JOYSTICK_INTERFACE_DESC_SIZE
+#define NKRO_INTERFACE_DESC_POS JOYSTICK_INTERFACE_DESC_POS+JOYSTICK_INTERFACE_DESC_SIZE
+#ifdef NKRO_INTERFACE
+#define NKRO_INTERFACE_DESC_SIZE 9+9+7
+#define NKRO_DESC_OFFSET NKRO_INTERFACE_DESC_POS+9
+#else
+#define NKRO_INTERFACE_DESC_SIZE 0
+#endif
+
+#define MTP_INTERFACE_DESC_POS NKRO_INTERFACE_DESC_POS+NKRO_INTERFACE_DESC_SIZE
#ifdef MTP_INTERFACE
#define MTP_INTERFACE_DESC_SIZE 9+7+7+7
#else
@@ -1091,6 +1126,35 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
JOYSTICK_INTERVAL, // bInterval
#endif // JOYSTICK_INTERFACE
+#ifdef NKRO_INTERFACE
+ // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+ 9, // bLength
+ 4, // bDescriptorType
+ NKRO_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ 0x00, // bInterfaceSubClass (0x01 = Boot)
+ 0x00, // bInterfaceProtocol (0x01 = Keyboard)
+ 0, // iInterface
+ // HID interface descriptor, HID 1.11 spec, section 6.2.1
+ 9, // bLength
+ 0x21, // bDescriptorType
+ 0x11, 0x01, // bcdHID
+ 0, // bCountryCode
+ 1, // bNumDescriptors
+ 0x22, // bDescriptorType
+ LSB(sizeof(nkro_hid_report_desc)), // wDescriptorLength
+ MSB(sizeof(nkro_hid_report_desc)),
+ // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+ 7, // bLength
+ 5, // bDescriptorType
+ NKRO_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (0x03=intr)
+ NKRO_SIZE, 0, // wMaxPacketSize
+ NKRO_INTERVAL, // bInterval
+#endif // NKRO_INTERFACE
+
#ifdef MTP_INTERFACE
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
@@ -1517,6 +1581,10 @@ const usb_descriptor_list_t usb_descriptor_list[] = {
{0x2200, JOYSTICK_INTERFACE, joystick_report_desc, sizeof(joystick_report_desc)},
{0x2100, JOYSTICK_INTERFACE, config_descriptor+JOYSTICK_HID_DESC_OFFSET, 9},
#endif
+#ifdef NKRO_INTERFACE
+ {0x2200, NKRO_INTERFACE, nkro_hid_report_desc, sizeof(nkro_hid_report_desc)},
+ {0x2100, NKRO_INTERFACE, config_descriptor+NKRO_DESC_OFFSET, 9},
+#endif
#ifdef RAWHID_INTERFACE
{0x2200, RAWHID_INTERFACE, rawhid_report_desc, sizeof(rawhid_report_desc)},
{0x2100, RAWHID_INTERFACE, config_descriptor+RAWHID_HID_DESC_OFFSET, 9},
diff --git a/avr/cores/teensy3/usb_desc.h b/avr/cores/teensy3/usb_desc.h
index 95de05e..abc8bbd 100644
--- a/avr/cores/teensy3/usb_desc.h
+++ b/avr/cores/teensy3/usb_desc.h
@@ -148,9 +148,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define PRODUCT_NAME {'K','e','y','b','o','a','r','d'}
#define PRODUCT_NAME_LEN 8
#define EP0_SIZE 64
- #define NUM_ENDPOINTS 4
+ #define NUM_ENDPOINTS 5
#define NUM_USB_BUFFERS 14
- #define NUM_INTERFACE 3
+ #define NUM_INTERFACE 4
#define SEREMU_INTERFACE 1 // Serial emulation
#define SEREMU_TX_ENDPOINT 1
#define SEREMU_TX_SIZE 64
@@ -166,6 +166,11 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define KEYMEDIA_ENDPOINT 4
#define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4
+ #define NKRO_INTERFACE 6 // N-key rollover kbd
+ #define NKRO_ENDPOINT 5
+ #define NKRO_SIZE 32
+ #define NKRO_REPORT_KEYS ( NKRO_SIZE - 1 )
+ #define NKRO_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
@@ -181,9 +186,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define PRODUCT_NAME {'K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'}
#define PRODUCT_NAME_LEN 23
#define EP0_SIZE 64
- #define NUM_ENDPOINTS 6
+ #define NUM_ENDPOINTS 7
#define NUM_USB_BUFFERS 24
- #define NUM_INTERFACE 5
+ #define NUM_INTERFACE 6
#define SEREMU_INTERFACE 2 // Serial emulation
#define SEREMU_TX_ENDPOINT 1
#define SEREMU_TX_SIZE 64
@@ -207,12 +212,18 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define JOYSTICK_ENDPOINT 4
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 2
+ #define NKRO_INTERFACE 5 // N-key rollover kbd
+ #define NKRO_ENDPOINT 7
+ #define NKRO_SIZE 32
+ #define NKRO_REPORT_KEYS ( NKRO_SIZE - 1 )
+ #define NKRO_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY
+ #define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY
#elif defined(USB_SERIAL_HID)
#define VENDOR_ID 0x16C0
@@ -225,9 +236,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define PRODUCT_NAME {'S','e','r','i','a','l','/','K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'}
#define PRODUCT_NAME_LEN 30
#define EP0_SIZE 64
- #define NUM_ENDPOINTS 7
+ #define NUM_ENDPOINTS 8
#define NUM_USB_BUFFERS 30
- #define NUM_INTERFACE 6
+ #define NUM_INTERFACE 7
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
@@ -253,6 +264,11 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define JOYSTICK_ENDPOINT 6
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1
+ #define NKRO_INTERFACE 6 // N-key rollover kbd
+ #define NKRO_ENDPOINT 8
+ #define NKRO_SIZE 32
+ #define NKRO_REPORT_KEYS ( NKRO_SIZE - 1 )
+ #define NKRO_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY
@@ -260,6 +276,7 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY
+ #define ENDPOINT8_CONFIG ENDPOINT_TRANSIMIT_ONLY
#elif defined(USB_TOUCHSCREEN)
#define VENDOR_ID 0x16C0
@@ -269,9 +286,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define PRODUCT_NAME {'K','e','y','b','o','a','r','d','/','T','o','u','c','h','s','c','r','e','e','n'}
#define PRODUCT_NAME_LEN 20
#define EP0_SIZE 64
- #define NUM_ENDPOINTS 5
+ #define NUM_ENDPOINTS 6
#define NUM_USB_BUFFERS 15
- #define NUM_INTERFACE 4
+ #define NUM_INTERFACE 5
#define SEREMU_INTERFACE 1 // Serial emulation
#define SEREMU_TX_ENDPOINT 1
#define SEREMU_TX_SIZE 64
@@ -291,11 +308,17 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MULTITOUCH_ENDPOINT 5
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_FINGERS 10
+ #define NKRO_INTERFACE 4 // N-key rollover kbd
+ #define NKRO_ENDPOINT 6
+ #define NKRO_SIZE 32
+ #define NKRO_REPORT_KEYS ( NKRO_SIZE - 1 )
+ #define NKRO_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
+ #define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY
#elif defined(USB_HID_TOUCHSCREEN)
#define VENDOR_ID 0x16C0
@@ -305,9 +328,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define PRODUCT_NAME {'K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','T','o','u','c','h','s','c','r','e','e','n'}
#define PRODUCT_NAME_LEN 26
#define EP0_SIZE 64
- #define NUM_ENDPOINTS 6
+ #define NUM_ENDPOINTS 7
#define NUM_USB_BUFFERS 20
- #define NUM_INTERFACE 5
+ #define NUM_INTERFACE 6
#define SEREMU_INTERFACE 2 // Serial emulation
#define SEREMU_TX_ENDPOINT 1
#define SEREMU_TX_SIZE 64
@@ -331,12 +354,18 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MULTITOUCH_ENDPOINT 5
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_FINGERS 10
+ #define NKRO_INTERFACE 5 // N-key rollover kbd
+ #define NKRO_ENDPOINT 7
+ #define NKRO_SIZE 32
+ #define NKRO_REPORT_KEYS ( NKRO_SIZE - 1 )
+ #define NKRO_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY
+ #define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY
#elif defined(USB_MIDI)
#define VENDOR_ID 0x16C0
diff --git a/avr/cores/teensy3/usb_dev.h b/avr/cores/teensy3/usb_dev.h
index 1233d7f..4de8757 100644
--- a/avr/cores/teensy3/usb_dev.h
+++ b/avr/cores/teensy3/usb_dev.h
@@ -90,6 +90,13 @@ extern uint8_t keyboard_idle_count;
extern volatile uint8_t keyboard_leds;
#endif
+#ifdef NKRO_INTERFACE
+extern uint8_t nkro_report_data[NKRO_SIZE];
+extern uint8_t nkro_protocol;
+extern uint8_t nkro_idle_config;
+extern uint8_t nkro_idle_count;
+#endif
+
#ifdef MIDI_INTERFACE
extern void usb_midi_flush_output(void);
#endif
diff --git a/avr/cores/teensy3/usb_inst.cpp b/avr/cores/teensy3/usb_inst.cpp
index 224c13d..8987850 100644
--- a/avr/cores/teensy3/usb_inst.cpp
+++ b/avr/cores/teensy3/usb_inst.cpp
@@ -72,6 +72,9 @@ uint8_t usb_joystick_class::manual_mode = 0;
usb_serial_class Serial;
#endif
+#ifdef NKRO_INTERFACE
+usb_nkro_class Nkro;
+#endif
#else // F_CPU < 20 MHz
diff --git a/avr/cores/teensy3/usb_nkro.c b/avr/cores/teensy3/usb_nkro.c
new file mode 100644
index 0000000..5fc22f8
--- /dev/null
+++ b/avr/cores/teensy3/usb_nkro.c
@@ -0,0 +1,132 @@
+#include "usb_dev.h"
+#include "usb_nkro.h"
+#include "core_pins.h" // for yield()
+#include "keylayouts.h"
+//#include "HardwareSerial.h"
+#include <string.h> // for memcpy()
+
+#ifdef NKRO_INTERFACE // defined by usb_dev.h -> usb_desc.h
+
+// byte0: which modifier keys are currently pressed
+// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
+// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
+// bytes1-NKRO_SIZE: which keys are currently pressed, one bit
+// per key for codes 0 to ((8*NKRO_REPORT_SIZE) - 1)
+uint8_t nkro_report_data[NKRO_SIZE];
+
+// protocol setting from the host. We use exactly the same report
+// either way, so this variable only stores the setting since we
+// are required to be able to report which setting is in use.
+uint8_t nkro_protocol=1;
+
+// the idle configuration, how often we send the report to the
+// host (ms * 4) even when it hasn't changed
+uint8_t nkro_idle_config=125;
+
+// count until idle timeout
+uint8_t nkro_idle_count=0;
+
+
+// NKRO Keyboard
+void usb_nkro_reset_keys()
+{
+ uint8_t index;
+ for (index=0; index < NKRO_SIZE; index++)
+ {
+ nkro_report_data[index] = 0;
+ }
+}
+
+void usb_nkro_reset_key(uint8_t usb_keycode)
+{
+ uint8_t bit = usb_keycode % 8;
+ uint8_t byte = (usb_keycode / 8) + 1;
+
+ if (usb_keycode >= 240 && usb_keycode <= 247)
+ {
+ // Reset a modifier key
+ nkro_report_data[0] &= ~(1<< bit);
+ }
+ else if (byte > 0 && byte <= NKRO_REPORT_KEYS)
+ {
+ nkro_report_data[byte] &= ~(1 << bit);
+ }
+}
+
+void usb_nkro_set_key(uint8_t usb_keycode)
+{
+ uint8_t bit = usb_keycode % 8;
+ uint8_t byte = (usb_keycode / 8) + 1;
+
+ if (usb_keycode >= 240 && usb_keycode <= 247)
+ {
+ // Reset a modifier key
+ nkro_report_data[0] |= (1 << bit);
+ }
+ else if (byte > 0 && byte <= NKRO_REPORT_KEYS)
+ {
+ nkro_report_data[byte] |= (1 << bit);
+ }
+}
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 4
+
+static uint8_t transmit_previous_timeout=0;
+
+// When the PC isn't listening, how long do we wait before discarding data?
+#define TX_TIMEOUT_MSEC 50
+
+#if F_CPU == 240000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
+#elif F_CPU == 216000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)
+#elif F_CPU == 192000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1280)
+#elif F_CPU == 180000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1200)
+#elif F_CPU == 168000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1100)
+#elif F_CPU == 144000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 932)
+#elif F_CPU == 120000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 764)
+#elif F_CPU == 96000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
+#elif F_CPU == 72000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 512)
+#elif F_CPU == 48000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
+#elif F_CPU == 24000000
+ #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
+#endif
+
+
+int usb_nkro_send_nkro_now(void)
+{
+ uint32_t wait_count=0;
+ usb_packet_t *tx_packet;
+
+ while (1) {
+ if (!usb_configuration) {
+ return -1;
+ }
+ if (usb_tx_packet_count(NKRO_ENDPOINT) < TX_PACKET_LIMIT) {
+ tx_packet = usb_malloc();
+ if (tx_packet) break;
+ }
+ if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+ transmit_previous_timeout = 1;
+ return -1;
+ }
+ yield();
+ }
+ memcpy(tx_packet->buf, nkro_report_data, NKRO_SIZE);
+ tx_packet->len = NKRO_SIZE;
+ usb_tx(NKRO_ENDPOINT, tx_packet);
+
+ return 0;
+
+}
+
+#endif // NKRO_INTERFACE
diff --git a/avr/cores/teensy3/usb_nkro.h b/avr/cores/teensy3/usb_nkro.h
new file mode 100644
index 0000000..ea1c947
--- /dev/null
+++ b/avr/cores/teensy3/usb_nkro.h
@@ -0,0 +1,43 @@
+#ifndef USBnkro_h_
+#define USBnkro_h_
+
+#include "usb_desc.h"
+#include "keylayouts.h"
+
+#if defined (NKRO_INTERFACE)
+
+#include <inttypes.h>
+
+// C language implementation
+#ifdef __cplusplus
+extern "C" {
+#endif
+void usb_nkro_reset_keys();
+void usb_nkro_reset_key(uint8_t key);
+void usb_nkro_set_key(uint8_t key);
+int usb_nkro_send_nkro_now();
+#ifdef __cplusplus
+}
+#endif
+
+
+
+// C++ interface
+#ifdef __cplusplus
+#include "Stream.h"
+
+class usb_nkro_class
+{
+ public:
+ void reset_keys() { usb_nkro_reset_keys(); }
+ void reset_key(uint8_t key) { usb_nkro_reset_key(key); }
+ void set_key(uint8_t key) { usb_nkro_set_key(key); }
+ int send_nkro_now(void) { return usb_nkro_send_nkro_now(); }
+};
+
+extern usb_nkro_class Nkro;
+
+#endif // __cplusplus
+
+#endif // NKRO_INTERFACE
+#endif // USBnkro_h_
diff --git a/avr/cores/teensy3/usb_undef.h b/avr/cores/teensy3/usb_undef.h
index cbd8c83..af1c246 100644
--- a/avr/cores/teensy3/usb_undef.h
+++ b/avr/cores/teensy3/usb_undef.h
@@ -251,6 +251,21 @@
#ifdef MTP_EVENT_INTERVAL
#undef MTP_EVENT_INTERVAL
#endif
+#ifdef NKRO_INTERFACE
+#undef NKRO_INTERFACE
+#endif
+#ifdef NKRO_ENDPOINT
+#undef NKRO_ENDPOINT
+#endif
+#ifdef NKRO_SIZE
+#undef NKRO_SIZE
+#endif
+#ifdef NKRO_REPORT_KEYS
+#undef NKRO_REPORT_KEYS
+#endif
+#ifdef NKRO_INTERVAL
+#undef NKRO_INTERVAL
+#endif
#ifdef ENDPOINT1_CONFIG
#undef ENDPOINT1_CONFIG
#endif
@@ -296,4 +311,6 @@
#ifdef ENDPOINT15_CONFIG
#undef ENDPOINT15_CONFIG
#endif
-
+#ifdef ENDPOINT16_CONFIG
+#undef ENDPOINT16_CONFIG
+#endif
--
2.20.1
This worked! Even though I couldn't use the patch file and had to apply the changes manually. I now have NKRO with my Teensy 3.6. Thanks!