1
0
Fork 0
qmk_firmware/keyboards/sekigon/keyboard_quantizer/mini/matrix.c

163 lines
4.9 KiB
C

// Copyright 2023 sekigon-gonnoc
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
#include "print.h"
#include "tusb.h"
#include "pio_usb_ll.h"
static uint8_t kbd_addr;
static uint8_t kbd_instance;
static int32_t led_count = -1;
static uint8_t hid_report_buffer[64];
static volatile uint8_t hid_report_size;
static uint8_t hid_instance;
static bool hid_disconnect_flag;
static uint8_t pre_keyreport[8];
#define LED_BLINK_TIME_MS 50
#define KQ_PIN_LED 7
#define MATRIX_MODIFIER_ROW 21
extern void busy_wait_us(uint64_t delay_us);
static bool send_led_report(uint8_t* leds);
void matrix_init_custom(void) {
// Configure LED pin
setPinOutput(KQ_PIN_LED);
writePinHigh(KQ_PIN_LED);
}
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
bool matrix_has_changed = false;
// If keyboard is disconnected, clear matrix
if (hid_disconnect_flag) {
for (uint8_t rowIdx = 0; rowIdx < MATRIX_ROWS; rowIdx++) {
if (current_matrix[rowIdx] != 0) {
matrix_has_changed = true;
current_matrix[rowIdx] = 0;
}
}
hid_disconnect_flag = false;
return matrix_has_changed;
}
// If keyboard report is received, apply it to matrix
if (hid_report_size > 0) {
hid_report_size = 0;
dprintf("%02x %02x %02x %02x %02x %02x %02x %02x\n", hid_report_buffer[0], hid_report_buffer[1], hid_report_buffer[2], hid_report_buffer[3], hid_report_buffer[4], hid_report_buffer[5], hid_report_buffer[6], hid_report_buffer[7]);
if (memcmp(pre_keyreport, hid_report_buffer, 8) == 0) {
// no change
matrix_has_changed = false;
return matrix_has_changed;
} else {
matrix_has_changed = true;
memcpy(pre_keyreport, hid_report_buffer, 8);
}
// clear all bit
for (uint8_t rowIdx = 0; rowIdx < MATRIX_ROWS; rowIdx++) {
current_matrix[rowIdx] = 0;
}
// set bits
for (uint8_t keyIdx = 0; keyIdx < 6; keyIdx++) {
uint8_t key = hid_report_buffer[keyIdx + 2];
uint8_t rowIdx = key / (sizeof(uint8_t) * 8);
uint8_t colIdx = key - rowIdx * (sizeof(uint8_t) * 8);
current_matrix[rowIdx] |= (1 << colIdx);
}
// modifier bits
current_matrix[MATRIX_MODIFIER_ROW] = hid_report_buffer[0];
return matrix_has_changed;
} else {
return false;
}
return matrix_has_changed;
}
void housekeeping_task_kb(void) {
// Control keyboard indicator LED
static uint8_t keyboard_led;
if (keyboard_led != host_keyboard_leds()) {
uint8_t led_backup = keyboard_led;
keyboard_led = host_keyboard_leds();
if (!send_led_report(&keyboard_led)) {
keyboard_led = led_backup;
}
}
// Blink LED when USB reports are received
if (led_count >= 0) {
if (timer_elapsed(led_count) < LED_BLINK_TIME_MS) {
writePinLow(KQ_PIN_LED);
} else if (timer_elapsed(led_count) < 2 * LED_BLINK_TIME_MS) {
writePinHigh(KQ_PIN_LED);
} else {
led_count = -1;
}
}
}
static bool send_led_report(uint8_t* leds) {
if (kbd_addr != 0) {
return tuh_hid_set_report(kbd_addr, kbd_instance, 0, HID_REPORT_TYPE_OUTPUT, leds, sizeof(*leds));
}
return false;
}
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) {
dprintf("HID mounted:%d:%d\n", dev_addr, instance);
if (led_count < 0) {
led_count = timer_read();
}
for (int instance = 0; instance < tuh_hid_instance_count(dev_addr); instance++) {
tuh_hid_receive_report(dev_addr, instance);
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) {
kbd_addr = dev_addr;
kbd_instance = instance;
}
}
}
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
dprintf("HID unmounted:%d:%d\n", dev_addr, instance);
memset(pre_keyreport, 0, sizeof(pre_keyreport));
hid_disconnect_flag = true;
kbd_addr = 0;
kbd_instance = 0;
}
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
dprintf("Report received\n");
if (led_count < 0) {
led_count = timer_read();
}
if (len > 0 && instance == kbd_instance) {
int cnt = 0;
while (hid_report_size > 0 && cnt++ < 50000) {
busy_wait_us(1);
continue;
}
hid_instance = instance;
memcpy(hid_report_buffer, report, len);
__DSB();
// hid_report_size is used as trigger of report parser
hid_report_size = len;
}
tuh_hid_receive_report(dev_addr, instance);
}