Skip to content

Commit

Permalink
nkro support (untested)
Browse files Browse the repository at this point in the history
  • Loading branch information
carlossless committed Dec 24, 2024
1 parent a569ef5 commit 90aeb6c
Show file tree
Hide file tree
Showing 13 changed files with 234 additions and 12 deletions.
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ cc_base_args = [
'--out-fmt-ihx',

'-DSMK_VERSION=@0@'.format(meson.project_version()),
'-DNKRO_ENABLE=1', # TODO: move it into a feature
]

if get_option('buildtype') == 'debug'
Expand Down
1 change: 1 addition & 0 deletions src/kb/kb.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

void kb_init();
void kb_send_report(report_keyboard_t *report);
void kb_send_nkro(report_nkro_t *report);
void kb_send_extra(report_extra_t *report);

bool kb_process_record(uint16_t keycode, bool key_pressed);
Expand Down
5 changes: 5 additions & 0 deletions src/keyboards/example/kb.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ void kb_send_report(report_keyboard_t *report)
usb_send_report(report);
}

void kb_send_nkro(report_nkro_t *report)
{
usb_send_nkro(report);
}

void kb_send_extra(report_extra_t *report)
{
usb_send_extra(report);
Expand Down
5 changes: 5 additions & 0 deletions src/keyboards/eyooso-z11/kb.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ void kb_send_report(report_keyboard_t *report)
usb_send_report(report);
}

void kb_send_nkro(report_nkro_t *report)
{
usb_send_nkro(report);
}

void kb_send_extra(report_extra_t *report)
{
usb_send_extra(report);
Expand Down
14 changes: 14 additions & 0 deletions src/keyboards/nuphy-air60/kb.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,20 @@ void kb_send_report(report_keyboard_t *report)
}
}

void kb_send_nkro(report_nkro_t *report)
{
switch (user_keyboard_state.conn_mode) {
case KEYBOARD_CONN_MODE_USB:
usb_send_nkro(report);
break;
#ifdef RF_ENABLED
case KEYBOARD_CONN_MODE_RF:
// TODO: implement rf
break;
#endif
}
}

void kb_send_extra(report_extra_t *report)
{
switch (user_keyboard_state.conn_mode) {
Expand Down
30 changes: 26 additions & 4 deletions src/platform/sh68f90a/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,23 @@ const uint8_t hid_report_desc_extra[] = {
HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0),

#ifdef NKRO_ENABLE
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
HID_RI_USAGE(8, 0x06), // Keyboard
HID_RI_COLLECTION(8, 0x01), // Application
HID_RI_REPORT_ID(8, REPORT_ID_NKRO),
// Modifiers (8 bits)
HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad
HID_RI_USAGE_MINIMUM(8, 0x04),
HID_RI_USAGE_MAXIMUM(8, 0x70),
HID_RI_USAGE_MINIMUM(8, 0x00), // was 0x04
HID_RI_USAGE_MAXIMUM(8, NKRO_REPORT_BITS * 8 - 1), // was 0x70
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_SIZE(8, 1),
HID_RI_REPORT_COUNT(8, 120),
HID_RI_REPORT_COUNT(8, NKRO_REPORT_BITS * 8), // was 120
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0),
#endif // NKRO_ENABLE

// clang-format on
};

Expand Down Expand Up @@ -358,6 +361,20 @@ void usb_send_report(report_keyboard_t *report)
SET_EP1_IN_RDY;
}

void usb_send_nkro(report_nkro_t *report)
{
uint8_t timeout = 0;
while (timeout < 255 && EP2CON & _IEP2RDY) {
delay_us(40);
timeout++;
}

set_ep2_in_buffer(report->raw, sizeof(report_nkro_t));

SET_EP2_CNT(sizeof(report_nkro_t));
SET_EP2_IN_RDY;
}

void usb_send_extra(report_extra_t *report)
{
uint8_t timeout = 0;
Expand All @@ -366,12 +383,17 @@ void usb_send_extra(report_extra_t *report)
timeout++;
}

set_ep2_in_buffer((uint8_t *)report, sizeof(report_extra_t));
set_ep2_in_buffer(report->raw, sizeof(report_extra_t));

SET_EP2_CNT(sizeof(report_extra_t));
SET_EP2_IN_RDY;
}

uint8_t usb_device_state_get_protocol()
{
return interface0_protocol;
}

static void usb_setup_irq()
{
usb_req_setup_x req;
Expand Down
13 changes: 10 additions & 3 deletions src/platform/sh68f90a/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@
#include "report.h"
#include <stdint.h>

void usb_init();
void usb_send_report(report_keyboard_t *report);
void usb_send_extra(report_extra_t *report);
enum {
USB_PROTOCOL_BOOT = 0,
USB_PROTOCOL_REPORT = 1,
};

void usb_init();
void usb_send_report(report_keyboard_t *report);
void usb_send_nkro(report_nkro_t *report);
void usb_send_extra(report_extra_t *report);
uint8_t usb_device_state_get_protocol();

void usb_interrupt_handler() __interrupt(_INT_USB);
5 changes: 5 additions & 0 deletions src/smk/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ void host_keyboard_send(report_keyboard_t *report)
kb_send_report(report);
}

void host_nkro_send(report_nkro_t *report)
{
kb_send_nkro(report);
}

void host_system_send(uint16_t usage)
{
if (usage == last_system_usage) return;
Expand Down
1 change: 1 addition & 0 deletions src/smk/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
#include "report.h"

void host_keyboard_send(report_keyboard_t *report);
void host_nkro_send(report_nkro_t *report);
void host_system_send(uint16_t usage);
void host_consumer_send(uint16_t usage);
6 changes: 6 additions & 0 deletions src/smk/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@

volatile __xdata keyboard_state_t keyboard_state;

__xdata keymap_config_t keymap_config;

void keyboard_init()
{
keyboard_state.led_state = 0x00;

#ifdef NKRO_ENABLE
keymap_config.nkro = 1;
#endif
}
5 changes: 5 additions & 0 deletions src/smk/keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ typedef struct {
uint8_t led_state;
} keyboard_state_t;

typedef struct {
uint8_t nkro;
} keymap_config_t;

extern volatile __xdata keyboard_state_t keyboard_state;
extern __xdata keymap_config_t keymap_config;

void keyboard_init();
132 changes: 132 additions & 0 deletions src/smk/report.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,43 @@
#include "keycodes.h"
#include <string.h>
#include "kb.h"
#include "usb.h"
#include "keyboard.h"
#include "debug.h"

static uint8_t real_mods = 0;
static uint8_t weak_mods = 0;

__xdata report_keyboard_t keyboard_report;
__xdata report_keyboard_t last_report;

__xdata report_nkro_t nkro_report;
__xdata report_nkro_t last_nkro_report;

uint8_t biton(uint8_t bits);

void send_6kro_report();
#ifdef NKRO_ENABLE
void send_nkro_report();
#endif

/** \brief Send keyboard report
*
*/
void send_keyboard_report()
{
#ifdef NKRO_ENABLE
if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
send_nkro_report();
} else {
send_6kro_report();
}
#else
send_6kro_report();
#endif
}

void send_6kro_report()
{
keyboard_report.mods = real_mods;
keyboard_report.mods |= weak_mods;
Expand All @@ -26,6 +52,21 @@ void send_keyboard_report()
}
}

#ifdef NKRO_ENABLE
void send_nkro_report()
{
nkro_report.report_id = REPORT_ID_NKRO; // TODO: set this once
nkro_report.mods = real_mods;
nkro_report.mods |= weak_mods;

/* Only send the report if there are changes to propagate to the host. */
if (memcmp(&nkro_report, &last_nkro_report, sizeof(report_nkro_t)) != 0) {
memcpy(&last_nkro_report, &nkro_report, sizeof(report_nkro_t));
host_nkro_send(&nkro_report);
}
}
#endif

/** \brief has_anykey
*
*/
Expand All @@ -35,6 +76,13 @@ uint8_t has_anykey(report_keyboard_t *keyboard_report)
uint8_t *p = keyboard_report->keys;
uint8_t lp = sizeof(keyboard_report->keys);

#ifdef NKRO_ENABLE
if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
p = nkro_report.bits;
lp = sizeof(nkro_report.bits);
}
#endif

while (lp--) {
if (*p++) {
cnt++;
Expand All @@ -50,6 +98,14 @@ uint8_t has_anykey(report_keyboard_t *keyboard_report)
*/
uint8_t get_first_key(report_keyboard_t *keyboard_report)
{
#ifdef NKRO_ENABLE
if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
uint8_t i = 0;
for (; i < NKRO_REPORT_BITS && !nkro_report.bits[i]; i++)
;
return i << 3 | biton(nkro_report.bits[i]);
}
#endif
return keyboard_report->keys[0];
}

Expand All @@ -64,6 +120,16 @@ bool is_key_pressed(report_keyboard_t *keyboard_report, uint8_t key)
return false;
}

#ifdef NKRO_ENABLE
if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
if ((key >> 3) < NKRO_REPORT_BITS) {
return nkro_report.bits[key >> 3] & 1 << (key & 7);
} else {
return false;
}
}
#endif

for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
if (keyboard_report->keys[i] == key) {
return true;
Expand Down Expand Up @@ -110,11 +176,45 @@ void del_key_byte(report_keyboard_t *keyboard_report, uint8_t code)
}
}

#ifdef NKRO_ENABLE
/** \brief add key bit
*
* FIXME: Needs doc
*/
void add_key_bit(report_nkro_t *nkro_report, uint8_t code)
{
if ((code >> 3) < NKRO_REPORT_BITS) {
nkro_report->bits[code >> 3] |= 1 << (code & 7);
} else {
dprintf("add_key_bit: can't add: %02X\n", code);
}
}

/** \brief del key bit
*
* FIXME: Needs doc
*/
void del_key_bit(report_nkro_t *nkro_report, uint8_t code)
{
if ((code >> 3) < NKRO_REPORT_BITS) {
nkro_report->bits[code >> 3] &= ~(1 << (code & 7));
} else {
dprintf("del_key_bit: can't del: %02X\n", code);
}
}
#endif

/** \brief add key to report
*
*/
void add_key_to_report(report_keyboard_t *keyboard_report, uint8_t key)
{
#ifdef NKRO_ENABLE
if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
add_key_bit(&nkro_report, key);
return;
}
#endif
add_key_byte(keyboard_report, key);
}

Expand All @@ -123,6 +223,12 @@ void add_key_to_report(report_keyboard_t *keyboard_report, uint8_t key)
*/
void del_key_from_report(report_keyboard_t *keyboard_report, uint8_t key)
{
#ifdef NKRO_ENABLE
if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
del_key_bit(&nkro_report, key);
return;
}
#endif
del_key_byte(keyboard_report, key);
}

Expand All @@ -131,6 +237,12 @@ void del_key_from_report(report_keyboard_t *keyboard_report, uint8_t key)
*/
void clear_keys_from_report(report_keyboard_t *keyboard_report)
{
#ifdef NKRO_ENABLE
if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
memset(nkro_report.bits, 0, sizeof(nkro_report.bits));
return;
}
#endif
memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys));
}

Expand Down Expand Up @@ -177,3 +289,23 @@ uint8_t get_weak_mods(void)
{
return weak_mods;
}

// most significant on-bit - return highest location of on-bit
// NOTE: return 0 when bit0 is on or all bits are off
uint8_t biton(uint8_t bits)
{
uint8_t n = 0;
if (bits >> 4) {
bits >>= 4;
n += 4;
}
if (bits >> 2) {
bits >>= 2;
n += 2;
}
if (bits >> 1) {
bits >>= 1;
n += 1;
}
return n;
}
Loading

0 comments on commit 90aeb6c

Please sign in to comment.