diff --git a/keyboards/cue2keys/config.h b/keyboards/cue2keys/config.h new file mode 100644 index 00000000000..232d5dd0a8d --- /dev/null +++ b/keyboards/cue2keys/config.h @@ -0,0 +1,32 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#define FW_VERSION "20250419-1.2.0" + +// see `wear_leveling_rp2040_flash_config.h` +// currently, using 16MB SPI flash +#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 8192 + +// using W25Q128JVS as an EEPROM +#define EXTERNAL_EEPROM_PAGE_SIZE 256 +#define EXTERNAL_EEPROM_BYTE_COUNT (65536 * EXTERNAL_EEPROM_PAGE_SIZE) +#define EXTERNAL_EEPROM_ADDRESS_SIZE 4 + +#define EECONFIG_KB_DATA_SIZE 1024 // 1KB for kb_config_t +#define EECONFIG_KB_DATA_VERSION (0x01) + +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET // Activates the double-tap behavior +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_TIMEOUT 1000U // Timeout window in ms in which the double tap can occur. +#define RP2040_BOOTLOADER_DOUBLE_TAP_RESET_LED GP25 // Specify a optional status led by GPIO number which blinks when entering the bootloader + +#define I2C_DRIVER I2CD1 +#define I2C1_SDA_PIN GP2 +#define I2C1_SCL_PIN GP3 + +#define ENCODER_A_PINS {NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN} +#define ENCODER_B_PINS {NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN, NO_PIN} + +#define POINTING_DEVICE_AUTO_MOUSE_ENABLE +#define AUTO_MOUSE_DEFAULT_LAYER 3 diff --git a/keyboards/cue2keys/cue2keys.c b/keyboards/cue2keys/cue2keys.c new file mode 100644 index 00000000000..ada4abaae8b --- /dev/null +++ b/keyboards/cue2keys/cue2keys.c @@ -0,0 +1,418 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#include QMK_KEYBOARD_H +#include +#include +#include "matrix.h" +#include "atomic_util.h" +#include "i2clib.h" +#include "i2c_master.h" +#include "kb_config.h" +#include "./drivers/encoder_dynamic_res.h" + +extern DeviceList deviceList[MAX_MCP_NUM]; +extern uint16_t nDevices; + +#ifdef OLED_ENABLE +DisplayMode display_mode = DisplayMode_Layer; +#endif + +static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS; + +kb_config_t kb_config = {0}; + +uint16_t calc_auto_mouse_timeout_by_kbconfig(uint8_t value) { + return 100 * value; +} + +#ifdef POINTING_DEVICE_ENABLE +bool set_scrolling = false; + +// Variables to store accumulated scroll values +float scroll_accumulated_h = 0; +float scroll_accumulated_v = 0; +#endif + +void keyboard_post_init_kb(void) { + debug_enable = true; + // debug_matrix = true; + // debug_keyboard=true; + // debug_mouse=true; + + // initialize with the keyboard config data + eeconfig_read_kb_datablock(&kb_config.raw, 0, sizeof(kb_config)); +#ifdef POINTING_DEVICE_ENABLE + modular_adns5050_set_angle(0, kb_config.angle_L); + modular_adns5050_set_angle(1, kb_config.angle_R); + set_auto_mouse_timeout(calc_auto_mouse_timeout_by_kbconfig(kb_config.mouse_layer_off_delay_ms)); + modular_adns5050_set_led_off_length(kb_config.trackball_led_off_timeout * 5 * 60 * 1000); +#endif +#ifdef ENCODER_ENABLE + dynamic_res_encoder_update_res(0, kb_config.re_resolution_1); + dynamic_res_encoder_update_res(1, kb_config.re_resolution_2); + dynamic_res_encoder_update_res(2, kb_config.re_resolution_3); + dynamic_res_encoder_update_res(3, kb_config.re_resolution_4); + dynamic_res_encoder_update_res(4, kb_config.re_resolution_5); + dynamic_res_encoder_update_res(5, kb_config.re_resolution_6); + dynamic_res_encoder_update_res(6, kb_config.re_resolution_7); + dynamic_res_encoder_update_res(7, kb_config.re_resolution_8); + dynamic_res_encoder_update_res(8, kb_config.re_resolution_9); + dynamic_res_encoder_update_res(9, kb_config.re_resolution_10); + dynamic_res_encoder_update_res(10, kb_config.re_resolution_11); + dynamic_res_encoder_update_res(11, kb_config.re_resolution_12); + dynamic_res_encoder_update_res(12, kb_config.re_resolution_13); + dynamic_res_encoder_update_res(13, kb_config.re_resolution_14); + dynamic_res_encoder_update_res(14, kb_config.re_resolution_15); + dynamic_res_encoder_update_res(15, kb_config.re_resolution_16); +#endif + + i2c_init(); + do_scan(); + + keyboard_post_init_user(); +} + +void eeconfig_init_kb(void) { + memset(&kb_config.raw, 0, sizeof(kb_config)); + + // initialization of kb_config + my_kb_config_init(&kb_config); + + eeconfig_update_kb_datablock(&kb_config.raw, 0, sizeof(kb_config)); + eeconfig_init_user(); +} + +void matrix_init_custom(void) { + // initialize system pins + ATOMIC_BLOCK_FORCEON { + for (uint16_t i = 0; i < SYSTEM_KEY_NUM; i++) { + pin_t dpin = direct_pins[0][i]; + if (dpin != NO_PIN) gpio_set_pin_input_high(dpin); + } + } +} + +void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { + matrix_row_t row_data = 0; + + // system pins + if (current_row == 0) { + for (uint16_t i = 0; i < SYSTEM_KEY_NUM; i++) { + pin_t dpin = direct_pins[current_row][i]; + if (dpin != NO_PIN) { + uint8_t pin_state = gpio_read_pin(dpin); + row_data |= (matrix_row_t)(0x1 ^ pin_state) << i; + } + } + } + + for (uint16_t i = 0; i < nDevices; i++) { + // skip if the row is not the target + if (!(MATRIX_COLS * current_row <= deviceList[i].keymapShift && deviceList[i].keymapShift < MATRIX_COLS * (current_row + 1))) continue; + uint16_t shift_value = deviceList[i].keymapShift % MATRIX_COLS; + + bool success = change_channel(deviceList[i].ch); + if (!success) { + continue; + } + + Keys_Data data = {}; + if (deviceList[i].type == Type_PCA9557_Keys4 || deviceList[i].type == Type_PCA9557_Keys5) { + data = read_PCA9557_register(deviceList[i].address); + } else if (deviceList[i].type == Type_XL9555_Keys4 || deviceList[i].type == Type_XL9555_Keys5) { + data = read_XL9555_register(deviceList[i].address); + } else if (deviceList[i].type == Type_PCA9534A_RE_CLICKABLE) { + data = read_PCA9534A_register(deviceList[i].address); + } else { + dprintf("failed to read data. unknown type: %d, ch: %X, addr: %X\n", deviceList[i].type, deviceList[i].ch, deviceList[i].address); + continue; + } + + if (data.type == Type_PCA9557_Keys4 || data.type == Type_PCA9557_Keys5 || data.type == Type_XL9555_Keys4 || data.type == Type_XL9555_Keys5) { + row_data |= (matrix_row_t)data.data[0] << shift_value; + } else if (deviceList[i].type == Type_PCA9534A_RE_CLICKABLE) { + // pick lower 3 bits + row_data |= (matrix_row_t)(((data.data[0] & 0x04) >> 2)) << shift_value; + } else { + dprintf("failed to read data. unknown type: %d, ch: %X, addr: %X, data: %X\n", deviceList[i].type, deviceList[i].ch, deviceList[i].address, data.data[0]); + continue; + } + } + + current_matrix[current_row] = row_data; +} + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { +#ifdef POINTING_DEVICE_ENABLE + modular_adns5050_wake_up_all(true); +#endif + +// If console is enabled, it will print the matrix position and status of each key pressed +#ifdef CONSOLE_ENABLE + uprintf("KL: kc: 0x%04X, col: %2u, row: %2u, pressed: %u, time: %5u, int: %u, count: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed, record->event.time, record->tap.interrupted, record->tap.count); + uprintf("#device %u\n", sizeof(deviceList)); +#endif + + // system keys, but not combo keys + if (record->event.pressed && record->event.key.row == 0 && record->event.key.col == 0 && record->event.type != COMBO_EVENT) { + dprintf("GP9 pressed\n"); + display_mode = (display_mode + 1) % DisplayMode_MAX; +#ifdef OLED_ENABLE + oled_clear(); +#endif + return false; + } + + // process next oled page + if (record->event.pressed) { + switch (keycode) { + case NEXT_OLED_PAGE: + display_mode = (display_mode + 1) % DisplayMode_MAX; +#ifdef OLED_ENABLE + oled_clear(); +#endif + return false; + } + } + + // drag scroll +#ifdef POINTING_DEVICE_ENABLE + switch (keycode) { + case DRAG_SCROLL: + // Toggle set_scrolling + set_scrolling = record->event.pressed; + return false; + } + +#endif + + if (!process_kb_config_modification(&kb_config, keycode, record)) { + eeconfig_update_kb_datablock(&kb_config.raw, 0, sizeof(kb_config)); + switch (keycode) { + case AUTO_MOUSE_LAYER_P1: + set_auto_mouse_enable(kb_config.mouse_layer_on); + break; + case AUTO_MOUSE_LAYER_OFF_DELAY_P1: + case AUTO_MOUSE_LAYER_OFF_DELAY_M1: + set_auto_mouse_timeout(calc_auto_mouse_timeout_by_kbconfig(kb_config.mouse_layer_off_delay_ms)); + break; + case ANGLE_L_ADJUSTMENT_P1: + case ANGLE_L_ADJUSTMENT_M1: + case ANGLE_L_ADJUSTMENT_P30: + case ANGLE_L_ADJUSTMENT_M30: + modular_adns5050_set_angle(0, kb_config.angle_L); + break; + case ANGLE_R_ADJUSTMENT_P1: + case ANGLE_R_ADJUSTMENT_M1: + case ANGLE_R_ADJUSTMENT_P30: + case ANGLE_R_ADJUSTMENT_M30: + modular_adns5050_set_angle(1, kb_config.angle_R); + break; + } + return false; + } + + return process_record_user(keycode, record); +} + +#ifdef OLED_ENABLE +bool oled_task_kb(void) { + if (!oled_task_user()) { + return false; + } + + { + uint8_t current_layer = get_highest_layer(layer_state); + static char type_count_str[7]; + oled_write_P(PSTR("layer: "), false); + itoa(current_layer, type_count_str, 10); + oled_write_ln(type_count_str, false); + } + + if (display_mode == DisplayMode_Layer) { + // first line + { + static char type_count_str[7]; + oled_write_P(PSTR("# Device: "), false); + itoa(nDevices, type_count_str, 10); + oled_write_ln(type_count_str, false); + } + + // second line + { + { + static char type_count_str[7]; + oled_write_P(PSTR(" KEY4: "), false); + + uint16_t keynum = 0; + for (uint16_t i = 0; i < nDevices; i++) { + keynum += (int)(deviceList[i].type == Type_PCA9557_Keys4 || deviceList[i].type == Type_XL9555_Keys4); + } + itoa(keynum, type_count_str, 10); + oled_write_P(type_count_str, false); + oled_write_P(PSTR(", "), false); + } + { + static char type_count_str[7]; + oled_write_P(PSTR(" KEY5: "), false); + + uint16_t keynum = 0; + for (uint16_t i = 0; i < nDevices; i++) { + keynum += (int)(deviceList[i].type == Type_PCA9557_Keys5 || deviceList[i].type == Type_XL9555_Keys5); + } + itoa(keynum, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_ln(PSTR(""), false); + } + + // third line + { + { + static char type_count_str[7]; + oled_write_P(PSTR(" RE: "), false); + + uint16_t keynum = 0; + for (uint16_t i = 0; i < nDevices; i++) { + keynum += (int)(deviceList[i].type == Type_PCA9534A_RE_CLICKABLE); + } + itoa(keynum, type_count_str, 10); + oled_write_P(type_count_str, false); + oled_write_P(PSTR(", "), false); + } + { + static char type_count_str[7]; + oled_write_P(PSTR(" TB: "), false); + + uint16_t num = modular_adns5050_get_connected_count(); + itoa(num, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_ln(PSTR(""), false); + } + } else if (display_mode == DisplayMode_CONF_0) { + // debug output of the all kb_config data + debug_output_kb_config(&kb_config); + oled_kb_config_output(&kb_config, 0); + } else if (display_mode == DisplayMode_CONF_1) { + oled_kb_config_output(&kb_config, 1); + } else if (display_mode == DisplayMode_CONF_2) { + oled_kb_config_output(&kb_config, 2); + } else if (display_mode == DisplayMode_CONF_3) { + oled_kb_config_output(&kb_config, 3); + } else if (display_mode == DisplayMode_CONF_4) { + oled_kb_config_output(&kb_config, 4); + } else if (display_mode == DisplayMode_VERSION) { + oled_write_ln_P(PSTR("-- VERSION --"), false); + oled_write_ln_P(PSTR(FW_VERSION), false); + } else { + oled_write_ln_P(PSTR("-- INVALID MODE --"), false); + } + + return true; +} +#endif + +#ifdef ENCODER_ENABLE +uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b) { + uint8_t target = index; + for (uint16_t i = 0; i < nDevices; i++) { + if (deviceList[i].type == Type_PCA9534A_RE_CLICKABLE) { + // skip if this RE is not the indexed one + if (target != 0) { + target--; + continue; + } + + bool success = change_channel(deviceList[i].ch); + if (!success) { + continue; + } + + Keys_Data data = read_PCA9534A_register(deviceList[i].address); + // data -> XXXXX (click) (B) (A) + if (pad_b) { + return (data.data[0] & (0x01 << 1)) >> 1; + } else { + return (data.data[0] & (0x01 << 0)) >> 0; + } + } + } + + // if reaches + return 0; +} + +bool encoder_update_kb(uint8_t index, bool clockwise) { +# ifdef POINTING_DEVICE_ENABLE + modular_adns5050_wake_up_all(true); +# endif + return encoder_update_user(index, clockwise); +} + +// override existing weak function +void encoder_driver_task(void) { + for (uint8_t i = 0; i < NUM_ENCODERS; i++) { + dynamic_res_encoder_quadrature_handle_read(i, encoder_quadrature_read_pin(i, false), encoder_quadrature_read_pin(i, true)); + } +} +#endif + +#ifdef POINTING_DEVICE_ENABLE +void pointing_device_driver_init(void) { + modular_adns5050_pointing_device_driver.init(); + set_auto_mouse_layer(AUTO_MOUSE_DEFAULT_LAYER); // default + set_auto_mouse_enable(true); +} +report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { + float mag = 0.25 * (kb_config.pointer_speed_magnification + 1); + float scr_mag = 0.25 * (kb_config.drag_scroll_speed_magnification + 1); + report_mouse_t t = modular_adns5050_pointing_device_driver.get_report(mouse_report); + + // Check if drag scrolling is active + if (set_scrolling) { + // Calculate and accumulate scroll values based on mouse movement and divisors + scroll_accumulated_h += (float)t.x / SCROLL_DIVISOR_H; + scroll_accumulated_v += (float)t.y / SCROLL_DIVISOR_V; + + // Assign integer parts of accumulated scroll values to the mouse report + t.h = (int8_t)(scroll_accumulated_h * scr_mag); + t.v = (int8_t)(scroll_accumulated_v * scr_mag); + + if (kb_config.invert_drag_scroll_y) { + t.h *= -1; + } + if (kb_config.invert_drag_scroll_x) { + t.v *= -1; + } + + // Update accumulated scroll values by subtracting the integer parts + scroll_accumulated_h -= (int8_t)scroll_accumulated_h; + scroll_accumulated_v -= (int8_t)scroll_accumulated_v; + + // Clear the X and Y values of the mouse report + t.x = 0; + t.y = 0; + } else { + t.x *= mag; + t.y *= mag; + } + + return t; +} +uint16_t pointing_device_driver_get_cpi(void) { + return modular_adns5050_pointing_device_driver.get_cpi(); +} +void pointing_device_driver_set_cpi(uint16_t cpi) { + modular_adns5050_pointing_device_driver.set_cpi(cpi); +} + +bool is_mouse_record_kb(uint16_t keycode, keyrecord_t *record) { + if (layer_state_is(get_auto_mouse_layer()) && kb_config.all_keys_are_mouse_keys) { + return true; + } + + return is_mouse_record_user(keycode, record); +} +#endif diff --git a/keyboards/cue2keys/cue2keys.h b/keyboards/cue2keys/cue2keys.h new file mode 100644 index 00000000000..0a0e6e30883 --- /dev/null +++ b/keyboards/cue2keys/cue2keys.h @@ -0,0 +1,20 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include "quantum.h" +#include "kb_config.h" + +#ifdef OLED_ENABLE +typedef enum _DisplayMode { DisplayMode_Layer, DisplayMode_CONF_0, DisplayMode_CONF_1, DisplayMode_CONF_2, DisplayMode_CONF_3, DisplayMode_CONF_4, DisplayMode_VERSION, DisplayMode_MAX } DisplayMode; +#endif + +#ifdef POINTING_DEVICE_ENABLE +# include "drivers/modular_adns5050.h" +# define NUM_MODULAR_ADNS5050 ARRAY_SIZE(((pin_t[])MODULAR_ADNS5050_SCLK_PINS)) +# define SCROLL_DIVISOR_H 32.0 +# define SCROLL_DIVISOR_V 32.0 +#endif diff --git a/keyboards/cue2keys/drivers/encoder_dynamic_res.c b/keyboards/cue2keys/drivers/encoder_dynamic_res.c new file mode 100644 index 00000000000..02ac2180cb5 --- /dev/null +++ b/keyboards/cue2keys/drivers/encoder_dynamic_res.c @@ -0,0 +1,86 @@ +// Copyright 2018 Jack Humbert +// Copyright 2018-2023 Nick Brassel (@tzarc) +// Copyright 2025 @esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include "encoder.h" +#include "quantum.h" +#include "./drivers/encoder_dynamic_res.h" + +#ifdef ENCODER_ENABLE + +static uint8_t encoder_resolutions[NUM_ENCODERS] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; +static uint8_t encoder_state[NUM_ENCODERS] = {0}; +static int8_t encoder_pulses[NUM_ENCODERS] = {0}; +static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}; + +static void dynamic_res_encoder_handle_state_change(uint8_t index, uint8_t state) { + uint8_t i = index; + + const uint8_t resolution = encoder_resolutions[i]; + + static uint32_t timer = 0; + if (timer_elapsed32(timer) > 1000) { + for (uint8_t j = 0; j < NUM_ENCODERS; ++j) { + dprintf("enc[%u] res: %d pul: %d\n", j, encoder_resolutions[j], encoder_pulses[j]); + } + timer = timer_read32(); + } + + encoder_pulses[i] += encoder_LUT[state & 0xF]; + +# ifdef ENCODER_DEFAULT_POS + if ((encoder_pulses[i] >= resolution) || (encoder_pulses[i] <= -resolution) || ((state & 0x3) == ENCODER_DEFAULT_POS)) { + if (encoder_pulses[i] >= 1) { +# else + if (encoder_pulses[i] >= resolution) { +# endif + + encoder_queue_event(i, ENCODER_COUNTER_CLOCKWISE); + } + +# ifdef ENCODER_DEFAULT_POS + if (encoder_pulses[i] <= -1) { +# else + if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise +# endif + encoder_queue_event(i, ENCODER_CLOCKWISE); + } + encoder_pulses[i] %= resolution; +# ifdef ENCODER_DEFAULT_POS + encoder_pulses[i] = 0; + } +# endif +} + +void dynamic_res_encoder_quadrature_handle_read(uint8_t index, uint8_t pin_a_state, uint8_t pin_b_state) { + uint8_t state = pin_a_state | (pin_b_state << 1); + if ((encoder_state[index] & 0x3) != state) { + encoder_state[index] <<= 2; + encoder_state[index] |= state; + dynamic_res_encoder_handle_state_change(index, encoder_state[index]); + } +} + +void dynamic_res_encoder_update_res(uint8_t index, uint8_t res) { + switch (res) { + case 0: + encoder_resolutions[index] = 1; + break; + case 1: + encoder_resolutions[index] = 2; + break; + case 2: + encoder_resolutions[index] = 4; + break; + case 3: + encoder_resolutions[index] = 8; + break; + default: + encoder_resolutions[index] = 4; + } + encoder_state[index] = 0; + encoder_pulses[index] = 0; +} +#endif diff --git a/keyboards/cue2keys/drivers/encoder_dynamic_res.h b/keyboards/cue2keys/drivers/encoder_dynamic_res.h new file mode 100644 index 00000000000..db475faeb13 --- /dev/null +++ b/keyboards/cue2keys/drivers/encoder_dynamic_res.h @@ -0,0 +1,16 @@ +// Copyright 2018 Jack Humbert +// Copyright 2018-2023 Nick Brassel (@tzarc) +// Copyright 2025 @esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include + +#define ENCODER_CLOCKWISE true +#define ENCODER_COUNTER_CLOCKWISE false + +extern uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b); +void dynamic_res_encoder_quadrature_handle_read(uint8_t index, uint8_t pin_a_state, uint8_t pin_b_state); +void dynamic_res_encoder_update_res(uint8_t index, uint8_t res); diff --git a/keyboards/cue2keys/drivers/modular_adns5050.c b/keyboards/cue2keys/drivers/modular_adns5050.c new file mode 100644 index 00000000000..4e7d167b394 --- /dev/null +++ b/keyboards/cue2keys/drivers/modular_adns5050.c @@ -0,0 +1,383 @@ +/* + * Copyright 2025 esplo + * Copyright 2021 Colin Lam (Ploopy Corporation) + * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) + * Copyright 2019 Sunjun Kim + * Copyright 2019 Hiroyuki Okada + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "wait.h" +#include "debug.h" +#include "gpio.h" +#include "timer.h" +#include "pointing_device_internal.h" +#include "modular_adns5050.h" + +// Registers +// clang-format off +#define REG_PRODUCT_ID 0x00 +#define REG_REVISION_ID 0x01 +#define REG_MOTION 0x02 +#define REG_DELTA_X 0x03 +#define REG_DELTA_Y 0x04 +#define REG_SQUAL 0x05 +#define REG_SHUTTER_UPPER 0x06 +#define REG_SHUTTER_LOWER 0x07 +#define REG_MAXIMUM_PIXEL 0x08 +#define REG_PIXEL_SUM 0x09 +#define REG_MINIMUM_PIXEL 0x0a +#define REG_PIXEL_GRAB 0x0b +#define REG_MOUSE_CONTROL 0x0d +#define REG_MOUSE_CONTROL2 0x19 +#define REG_LED_DC_MODE 0x22 +#define REG_CHIP_RESET 0x3a +#define REG_PRODUCT_ID2 0x3e +#define REG_INV_REV_ID 0x3f +#define REG_MOTION_BURST 0x63 +// clang-format on + +const pointing_device_driver_t modular_adns5050_pointing_device_driver = { + .init = modular_adns5050_init, + .get_report = modular_adns5050_get_all_report, + .set_cpi = modular_adns5050_set_all_cpi, + .get_cpi = modular_adns5050_get_all_cpi, +}; + +// set zero for all elements +static bool connected[NUM_MODULAR_ADNS5050] = {false}; +static bool powered_down[NUM_MODULAR_ADNS5050] = {false}; + +const pin_t SCLK_PINS[] = MODULAR_ADNS5050_SCLK_PINS; +const pin_t SDIO_PINS[] = MODULAR_ADNS5050_SDIO_PINS; +const pin_t CS_PINS[] = MODULAR_ADNS5050_CS_PINS; +const pin_t RESET_PINS[] = MODULAR_ADNS5050_RESET_PINS; + +// angle for each sensor. +uint16_t angle[NUM_MODULAR_ADNS5050] = {0}; +uint32_t trackball_timeout_length = 5 * 60 * 1000; // default: 5 min +uint32_t trackball_timeout = 0; + +void modular_adns5050_init(void) { + for (uint8_t i = 0; i < NUM_MODULAR_ADNS5050; i++) { + // Initialize the ADNS serial pins. + gpio_set_pin_output(SCLK_PINS[i]); + gpio_set_pin_output(SDIO_PINS[i]); + gpio_set_pin_output(CS_PINS[i]); + + // RESET pin must be high + gpio_set_pin_output(RESET_PINS[i]); + gpio_write_pin_high(RESET_PINS[i]); + + powered_down[i] = true; + connected[i] = false; + } + + modular_adns5050_wake_up_all(false); +} + +report_mouse_t modular_adns5050_get_all_report(report_mouse_t mouse_report) { + for (uint8_t i = 0; i < NUM_MODULAR_ADNS5050; i++) { + report_mouse_t m = modular_adns5050_get_report(i, mouse_report); + mouse_report.x += m.x; + mouse_report.y += m.y; + } + modular_adns5050_check_timeout(); + + return mouse_report; +} + +uint16_t modular_adns5050_get_all_cpi(void) { + // get the maximum CPI since the CPI should be the same amoung all sensors + uint16_t maxCPI = 0; + for (uint8_t i = 0; i < NUM_MODULAR_ADNS5050; i++) { + uint16_t cpi = modular_adns5050_get_cpi(i); + maxCPI = (maxCPI > cpi) ? maxCPI : cpi; + } + return maxCPI; +} + +void modular_adns5050_set_all_cpi(uint16_t cpi) { + for (uint8_t i = 0; i < NUM_MODULAR_ADNS5050; i++) { + modular_adns5050_set_cpi(i, cpi); + } +} + +void modular_adns5050_power_down_all(void) { + for (uint8_t i = 0; i < NUM_MODULAR_ADNS5050; i++) { + if (powered_down[i]) { + continue; + } + modular_adns5050_power_down(i); + } +} + +void modular_adns5050_wake_up_all(bool connected_only) { + for (uint8_t i = 0; i < NUM_MODULAR_ADNS5050; i++) { + modular_adns5050_wake_up(i, connected_only); + } +} + +void modular_adns5050_check_timeout(void) { + if (trackball_timeout_length == 0) { + return; + } + if (timer_expired32(timer_read32(), trackball_timeout)) { + modular_adns5050_power_down_all(); + } +} + +uint8_t modular_adns5050_get_connected_count(void) { + uint8_t count = 0; + for (uint8_t i = 0; i < NUM_MODULAR_ADNS5050; i++) { + if (connected[i]) { + count++; + } + } + return count; +} + +void modular_adns5050_set_led_off_length(uint32_t length_ms) { + trackball_timeout_length = length_ms; +} + +void modular_adns5050_wake_up(uint8_t index, bool connected_only) { + trackball_timeout = timer_read32() + trackball_timeout_length; + + // skip if the sensor is already active + if (!powered_down[index]) { + return; + } + + if (connected_only && !connected[index]) { + return; + } + + // reboot the adns. + // if the adns hasn't initialized yet, this is harmless. + modular_adns5050_write_reg(index, REG_CHIP_RESET, 0x5a); + + // wait maximum time before adns is ready. + // this ensures that the adns is actuall ready after reset. + wait_ms(55); + + // check if ADNS-5050 is connected + // Product_ID must be 0x12 + // if you read this value before initialized, this value is 0x09 AFAIK + uint8_t product_id = modular_adns5050_read_reg(index, REG_PRODUCT_ID); + if (product_id != 0x12) { + powered_down[index] = true; + return; + } + + powered_down[index] = false; + connected[index] = true; + + // read a burst from the adns and then discard it. + // gets the adns ready for write commands + // (for example, setting the dpi). + modular_adns5050_read_burst(index); +} + +// Perform a synchronization with the ADNS. +// Just as with the serial protocol, this is used by the slave to send a +// synchronization signal to the master. +void modular_adns5050_sync(uint8_t index) { + gpio_write_pin_low(CS_PINS[index]); + wait_us(1); + gpio_write_pin_high(CS_PINS[index]); +} + +void modular_adns5050_cs_select(uint8_t index) { + gpio_write_pin_low(CS_PINS[index]); +} + +void modular_adns5050_cs_deselect(uint8_t index) { + gpio_write_pin_high(CS_PINS[index]); +} + +uint8_t modular_adns5050_serial_read(uint8_t index) { + gpio_set_pin_input(SDIO_PINS[index]); + uint8_t byte = 0; + + for (uint8_t i = 0; i < 8; ++i) { + gpio_write_pin_low(SCLK_PINS[index]); + wait_us(1); + + byte = (byte << 1) | gpio_read_pin(SDIO_PINS[index]); + + gpio_write_pin_high(SCLK_PINS[index]); + wait_us(1); + } + + return byte; +} + +void modular_adns5050_serial_write(uint8_t index, uint8_t data) { + gpio_set_pin_output(SDIO_PINS[index]); + + for (int8_t b = 7; b >= 0; b--) { + gpio_write_pin_low(SCLK_PINS[index]); + + if (data & (1 << b)) + gpio_write_pin_high(SDIO_PINS[index]); + else + gpio_write_pin_low(SDIO_PINS[index]); + + wait_us(2); + + gpio_write_pin_high(SCLK_PINS[index]); + } + + // tSWR. See page 15 of the ADNS spec sheet. + // Technically, this is only necessary if the next operation is an SDIO + // read. This is not guaranteed to be the case, but we're being lazy. + wait_us(4); + + // Note that tSWW is never necessary. All write operations require at + // least 32us, which exceeds tSWW, so there's never a need to wait for it. +} + +// Read a byte of data from a register on the ADNS. +// Don't forget to use the register map (as defined in the header file). +uint8_t modular_adns5050_read_reg(uint8_t index, uint8_t reg_addr) { + modular_adns5050_cs_select(index); + + modular_adns5050_serial_write(index, reg_addr); + + // We don't need a minimum tSRAD here. That's because a 4ms wait time is + // already included in adns5050_serial_write(), so we're good. + // See page 10 and 15 of the ADNS spec sheet. + // wait_us(4); + + uint8_t byte = modular_adns5050_serial_read(index); + + // tSRW & tSRR. See page 15 of the ADNS spec sheet. + // Technically, this is only necessary if the next operation is an SDIO + // read or write. This is not guaranteed to be the case. + // Honestly, this wait could probably be removed. + wait_us(1); + + modular_adns5050_cs_deselect(index); + + return byte; +} + +void modular_adns5050_write_reg(uint8_t index, uint8_t reg_addr, uint8_t data) { + modular_adns5050_cs_select(index); + modular_adns5050_serial_write(index, 0b10000000 | reg_addr); + modular_adns5050_serial_write(index, data); + modular_adns5050_cs_deselect(index); +} + +// Convert a two's complement byte from an unsigned data type into a signed +// data type. +int8_t modular_convert_twoscomp(uint8_t data) { + if ((data & 0x80) == 0x80) { + return -128 + (data & 0x7F); + } else { + return data; + } +} + +report_modular_adns5050_t modular_adns5050_read_burst(uint8_t index) { + modular_adns5050_cs_select(index); + + report_modular_adns5050_t data; + data.dx = 0; + data.dy = 0; + + if (powered_down[index]) { + return data; + } + + modular_adns5050_serial_write(index, REG_MOTION_BURST); + + // We don't need a minimum tSRAD here. That's because a 4ms wait time is + // already included in adns5050_serial_write(), so we're good. + // See page 10 and 15 of the ADNS spec sheet. + // wait_us(4); + + uint8_t x = modular_adns5050_serial_read(index); + uint8_t y = modular_adns5050_serial_read(index); + + // Burst mode returns a bunch of other shit that we don't really need. + // Setting CS to high ends burst mode early. + modular_adns5050_cs_deselect(index); + + data.dx = modular_convert_twoscomp(x); + data.dy = modular_convert_twoscomp(y); + + return data; +} + +// Don't forget to use the definitions for CPI in the header file. +void modular_adns5050_set_cpi(uint8_t index, uint16_t cpi) { + uint8_t cpival = constrain((cpi / 125), 0x1, 0xD); // limits to 0--119 + + modular_adns5050_write_reg(index, REG_MOUSE_CONTROL2, 0b10000 | cpival); +} + +uint16_t modular_adns5050_get_cpi(uint8_t index) { + uint8_t cpival = modular_adns5050_read_reg(index, REG_MOUSE_CONTROL2); + return (uint16_t)((cpival & 0b10000) * 125); +} + +bool modular_adns5050_check_signature(uint8_t index) { + uint8_t pid = modular_adns5050_read_reg(index, REG_PRODUCT_ID); + uint8_t rid = modular_adns5050_read_reg(index, REG_REVISION_ID); + uint8_t pid2 = modular_adns5050_read_reg(index, REG_PRODUCT_ID2); + + return (pid == 0x12 && rid == 0x01 && pid2 == 0x26); +} + +void modular_adns5050_power_down(uint8_t index) { + if (!powered_down[index]) { + powered_down[index] = true; + modular_adns5050_write_reg(index, REG_MOUSE_CONTROL, 0b10); + dprintf("mouse %d powered down\n", index); + } +} + +report_mouse_t modular_adns5050_get_report(uint8_t index, report_mouse_t mouse_report) { + report_modular_adns5050_t data = modular_adns5050_read_burst(index); + + if (data.dx != 0 || data.dy != 0) { + // use true just to update the timeout + modular_adns5050_wake_up(index, true); + + pd_dprintf("[%X] Raw ] X: %d, Y: %d\n", i, data.dx, data.dy); + double rad = angle[index] * (M_PI / 180); + mouse_xy_report_t x_rev = cos(rad) * data.dx + -sin(rad) * data.dy; + mouse_xy_report_t y_rev = sin(rad) * data.dx + cos(rad) * data.dy; + mouse_report.x += x_rev; + mouse_report.y += y_rev; + } + + return mouse_report; +} + +void modular_adns5050_set_angle(uint8_t index, uint16_t value) { + angle[index] = value; +} + +void modular_adns5050_add_angle(uint8_t index, int16_t value) { + angle[index] = (360 + angle[index] + value) % 360; +} + +uint16_t modular_adns5050_get_angle(uint8_t index) { + return angle[index]; +} diff --git a/keyboards/cue2keys/drivers/modular_adns5050.h b/keyboards/cue2keys/drivers/modular_adns5050.h new file mode 100644 index 00000000000..69c840bcf7f --- /dev/null +++ b/keyboards/cue2keys/drivers/modular_adns5050.h @@ -0,0 +1,107 @@ +/* + * Copyright 2025 esplo + * Copyright 2021 Colin Lam (Ploopy Corporation) + * Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) + * Copyright 2019 Sunjun Kim + * Copyright 2019 Hiroyuki Okada + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +// not re-use existing adns5050.h since the `ADNS5050_SCLK_PIN` should not be defined to avoid selecting invalid pins in functions + +#include +#include +#include "pointing_device.h" + +#define MODULAR_ADNS5050_SDIO_PINS {GP4, GP28} +#define MODULAR_ADNS5050_SCLK_PINS {GP6, GP26} +#define MODULAR_ADNS5050_CS_PINS {GP5, GP29} +#define MODULAR_ADNS5050_RESET_PINS {GP7, GP27} + +// Definitions for the ADNS serial line. +#ifndef MODULAR_ADNS5050_SCLK_PINS +# error "No clock pin defined -- missing MODULAR_ADNS5050_SCLK_PINS" +#endif + +#ifndef MODULAR_ADNS5050_SDIO_PINS +# error "No data pin defined -- missing MODULAR_ADNS5050_SDIO_PINS" +#endif + +#ifndef MODULAR_ADNS5050_CS_PINS +# error "No data pin defined -- missing MODULAR_ADNS5050_CS_PINS" +#endif + +#ifndef MODULAR_ADNS5050_RESET_PINS +# error "No data pin defined -- missing MODULAR_ADNS5050_RESET_PINS" +#endif + +#define NUM_MODULAR_ADNS5050 ARRAY_SIZE(((pin_t[])MODULAR_ADNS5050_SCLK_PINS)) + +// CPI values +// clang-format off +#define CPI125 0x11 +#define CPI250 0x12 +#define CPI375 0x13 +#define CPI500 0x14 +#define CPI625 0x15 +#define CPI750 0x16 +#define CPI875 0x17 +#define CPI1000 0x18 +#define CPI1125 0x19 +#define CPI1250 0x1a +#define CPI1375 0x1b +// clang-format on + +#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt))) + +typedef struct { + int8_t dx; + int8_t dy; +} report_modular_adns5050_t; + +const pointing_device_driver_t modular_adns5050_pointing_device_driver; + +// A bunch of functions to implement the ADNS5050-specific serial protocol. +// Note that the "serial.h" driver is insufficient, because it does not +// manually manipulate a serial clock signal. +void modular_adns5050_init(void); +report_mouse_t modular_adns5050_get_all_report(report_mouse_t mouse_report); +uint16_t modular_adns5050_get_all_cpi(void); +void modular_adns5050_set_all_cpi(uint16_t cpi); + +void modular_adns5050_power_down_all(void); +void modular_adns5050_wake_up_all(bool connected_only); +void modular_adns5050_check_timeout(void); +uint8_t modular_adns5050_get_connected_count(void); +void modular_adns5050_set_led_off_length(uint32_t length_ms); + +// functions for each sensors +void modular_adns5050_wake_up(uint8_t index, bool connected_only); +void modular_adns5050_sync(uint8_t index); +uint8_t modular_adns5050_serial_read(uint8_t index); +void modular_adns5050_serial_write(uint8_t index, uint8_t data); +uint8_t modular_adns5050_read_reg(uint8_t index, uint8_t reg_addr); +void modular_adns5050_write_reg(uint8_t index, uint8_t reg_addr, uint8_t data); +report_modular_adns5050_t modular_adns5050_read_burst(uint8_t index); +void modular_adns5050_set_cpi(uint8_t index, uint16_t cpi); +uint16_t modular_adns5050_get_cpi(uint8_t index); +bool modular_adns5050_check_signature(uint8_t index); +void modular_adns5050_power_down(uint8_t index); +report_mouse_t modular_adns5050_get_report(uint8_t index, report_mouse_t mouse_report); +void modular_adns5050_set_angle(uint8_t index, uint16_t angle); +void modular_adns5050_add_angle(uint8_t index, int16_t angle); +uint16_t modular_adns5050_get_angle(uint8_t index); diff --git a/keyboards/cue2keys/halconf.h b/keyboards/cue2keys/halconf.h new file mode 100644 index 00000000000..51ad23ebbbe --- /dev/null +++ b/keyboards/cue2keys/halconf.h @@ -0,0 +1,9 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#undef HAL_USE_I2C +#define HAL_USE_I2C TRUE + +#include_next diff --git a/keyboards/cue2keys/i2clib.c b/keyboards/cue2keys/i2clib.c new file mode 100644 index 00000000000..9162bf13170 --- /dev/null +++ b/keyboards/cue2keys/i2clib.c @@ -0,0 +1,398 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "i2clib.h" +#include +#include "i2c_master.h" +#include "debug.h" + +DeviceList deviceList[MAX_MCP_NUM]; +uint16_t nDevices = 0; + +bool change_channel(uint8_t channel) { + // channel must be 1-4 + if (channel < 1 || 4 < channel) { + dprintf("Invalid channel %u!\n", channel); + return false; + } + const uint8_t data = 0x01 << (channel - 1); + i2c_status_t expander_status = i2c_write_register(I2C_MULTIPX_ADDR << 1, 0x0, &data, 1, MY_I2C_TIMEOUT); + if (expander_status == I2C_STATUS_SUCCESS) { + return true; + } else { + dprintf("failed to change channel: %u!\n", expander_status); + return false; + } +} + +bool write_PCA9557_register_1byte(uint8_t address, uint8_t ctrl_addr, uint8_t data) { + i2c_status_t expander_status = i2c_write_register(address << 1, ctrl_addr, &data, 1, MY_I2C_TIMEOUT); + if (expander_status == I2C_STATUS_SUCCESS) { + dprintf("[PCA9557 set register] %X, reg:%X, data:%X\n", address, ctrl_addr, data); + return true; + } else { + dprintf("[PCA9557 set register] failed to set input %u! %X, reg:%X, data:%X\n", expander_status, address, ctrl_addr, data); + return false; + } +} + +Keys_Data read_PCA9557_register(uint8_t address) { + Keys_Data error_result = {.type = Type_Unknown}; + uint8_t inputData = 0; + i2c_status_t expander_status = i2c_read_register(address << 1, 0x0, &inputData, 1, MY_I2C_TIMEOUT); + + if (expander_status != I2C_STATUS_SUCCESS) { + dprintf("failed to read data from %X! %X\n", address, expander_status); + return error_result; + } + + // upper 3 bits are type indication + uint8_t type_data = (inputData & (0x07 << 5)) >> 5; + + Type type = Type_Unknown; + if (type_data == 2) { + type = Type_PCA9557_Keys5; + } else if (type_data == 1) { + type = Type_PCA9557_Keys4; + } else { + // unknown type + dprintf("failed to read type from %X! Type Unknown: %X, type_data: %X\n", address, type, type_data); + return error_result; + } + // lower 5 bits are key input data. They are pulled-up, so they need to be inverted + uint8_t data = (~inputData & 0x1F); + + if (type == Type_PCA9557_Keys4) { + // remove 1 bit if the device is `4 keys` + data &= 0x0F; + } else if (type == Type_PCA9557_Keys5) { + // 5 keys + // do nothing + } else { + // unknown + return error_result; + } + + Keys_Data d = {.type = type}; + memcpy(d.data, &data, 1); + + return d; +} + +bool write_XL9555_register_1byte(uint8_t address, uint8_t ctrl_addr, uint8_t data) { + i2c_status_t expander_status = i2c_write_register(address << 1, ctrl_addr, &data, 1, MY_I2C_TIMEOUT); + if (expander_status == I2C_STATUS_SUCCESS) { + dprintf("[XL9555 set register] %X, reg:%X, data:%X\n", address, ctrl_addr, data); + return true; + } else { + dprintf("[XL9555 set register] failed to set input %u! %X, reg:%X, data:%X\n", expander_status, address, ctrl_addr, data); + return false; + } +} + +Keys_Data read_XL9555_register(uint8_t address) { + Keys_Data error_result = {.type = Type_Unknown}; + uint8_t inputData[2] = {0x11, 0x22}; + i2c_status_t expander_status = i2c_read_register(address << 1, 0x0, inputData, 2, MY_I2C_TIMEOUT); + + if (expander_status != I2C_STATUS_SUCCESS) { + dprintf("failed to read data from %X! %X\n", address, expander_status); + return error_result; + } + + // upper 4 bits are type indication + // Note: temporary, this device + uint8_t type_data = (inputData[0] & 0xF0) >> 4; + + Type type = Type_Unknown; + if (type_data == 0x2) { + type = Type_XL9555_Keys5; + } else if (type_data == 0x0 || type_data == 0xF) { // temporary + type = Type_XL9555_Keys4; + } else { + // unknown type + dprintf("failed to read data from %X! Type Unknown: %X, type_data: %X\n", address, type, type_data); + return error_result; + } + // key input data are on 2 bytes + // inputData[0]: lower 4 bits + // inputData[1]: lower 1 bits + // They are pulled-up, so they need to be inverted + uint8_t data = (uint8_t)((inputData[1] << 4) | (0x0F & inputData[0])); + if (type == Type_XL9555_Keys4) { + // remove 1 bit if the device is `4 keys` + data &= 0x0F; + data ^= 0x0F; + } else if (type == Type_XL9555_Keys5) { + data ^= 0x1F; + } + + Keys_Data d = {.type = type}; + memcpy(d.data, &data, 1); + + return d; +} + +bool write_PCA9534A_register_1byte(uint8_t address, uint8_t ctrl_addr, uint8_t data) { + i2c_status_t expander_status = i2c_write_register(address << 1, ctrl_addr, &data, 1, MY_I2C_TIMEOUT); + if (expander_status == I2C_STATUS_SUCCESS) { + dprintf("[PCA9534A set register] %X, reg:%X, data:%X\n", address, ctrl_addr, data); + return true; + } else { + dprintf("[PCA9534A set register] failed to set input %u! %X, reg:%X, data:%X\n", expander_status, address, ctrl_addr, data); + return false; + } +} + +Keys_Data read_PCA9534A_register(uint8_t address) { + Keys_Data error_result = {.type = Type_Unknown}; + uint8_t inputData = 0; + i2c_status_t expander_status = i2c_read_register(address << 1, 0x0, &inputData, 1, MY_I2C_TIMEOUT); + + if (expander_status != I2C_STATUS_SUCCESS) { + dprintf("failed to read data from %X! %X\n", address, expander_status); + return error_result; + } + + // upper 3 bits are type indication + uint8_t type_data = (inputData & (0xFF << 5)) >> 5; + + Type type = Type_Unknown; + if (type_data == 2) { + type = Type_PCA9534A_RE_CLICKABLE; + } else { + // unknown type + dprintf("failed to read type from %X! Type Unknown: %X, type_data: %X, inputData: %X \n", address, type, type_data, inputData); + return error_result; + } + // lower 5 bits are input data + uint8_t data = (inputData & 0x1F); + + if (type == Type_PCA9534A_RE_CLICKABLE) { + // use only lower 3 bits. RO_A, RO_B, L_E + data &= 0x07; + } else { + // unknown + return error_result; + } + + Keys_Data d = {.type = type}; + memcpy(d.data, &data, 1); + + return d; +} + +Keys_Data init_PCA9557(uint8_t address) { + bool success = true; + + // pins: input + success &= write_PCA9557_register_1byte(address, 0x3, 0xFF); + // polarity: no change + success &= write_PCA9557_register_1byte(address, 0x2, 0x00); + + if (!success) { + dprintf("Failed to init PCA9557: %X\n", address); + Keys_Data data = {Type_Unknown}; + return data; + } + + // load inputs to detect the type + Keys_Data data = read_PCA9557_register(address); + return data; +} + +Keys_Data init_XL9555(uint8_t address) { + bool success = true; + + // pins: input + success &= write_XL9555_register_1byte(address, 0x6, 0xFF); + success &= write_XL9555_register_1byte(address, 0x7, 0xFF); + // polarity: no change + success &= write_XL9555_register_1byte(address, 0x4, 0x00); + success &= write_XL9555_register_1byte(address, 0x5, 0x00); + + if (!success) { + dprintf("Failed to init XL9555: %X\n", address); + Keys_Data data = {Type_Unknown}; + return data; + } + + // load inputs to detect the type + Keys_Data data = read_XL9555_register(address); + return data; +} + +Keys_Data init_PCA9534A(uint8_t address) { + bool success = true; + + // pins: input + success &= write_PCA9534A_register_1byte(address, 0x3, 0xFF); + // polarity: no change + success &= write_PCA9534A_register_1byte(address, 0x2, 0x00); + + if (!success) { + dprintf("Failed to init PCA9534A: %X\n", address); + Keys_Data data = {Type_Unknown}; + return data; + } + + // load inputs to detect the type + Keys_Data data = read_PCA9534A_register(address); + return data; +} + +typedef enum { + ShiftType_Key_Start = 0, + ShiftType_RE_Start = 1, +} ShiftType; + +uint16_t get_keymap_shift(uint8_t ch, ShiftType type) { + uint16_t keyShift = MAX_KEY_PER_CH_NUM * 5; + uint16_t reShift = MAX_RE_PER_CH_NUM * 1; + uint16_t chShift = keyShift + reShift + CH_BUFFER_NUM; + + if (type == ShiftType_Key_Start) { + return SYSTEM_KEY_NUM + chShift * (ch - 1); + } else if (type == ShiftType_RE_Start) { + return SYSTEM_KEY_NUM + chShift * (ch - 1) + keyShift; + } else { + dprintf("Invalid Shift Type: %d", type); + return 0; + } +} + +uint16_t get_updated_keymap_shift(uint16_t keymapShift, uint16_t shiftValue) { + int prevAlign = keymapShift / MATRIX_COLS; + int nextAlign = (keymapShift + shiftValue - 1) / MATRIX_COLS; + if (prevAlign != nextAlign) { + // shiftValue = nextAlign * MATRIX_COLS - keymapShift; + keymapShift = nextAlign * MATRIX_COLS; + } + + return keymapShift; +} + +void do_scan(void) { + nDevices = 0; + + dprintf("Scanning...\n"); + + // firstly, access to the I2C multiplexer + { + i2c_status_t error = i2c_ping_address(I2C_MULTIPX_ADDR << 1, MY_I2C_TIMEOUT); + if (error == I2C_STATUS_SUCCESS) { + dprintf(" MUX found at address 0x%02X\n", I2C_MULTIPX_ADDR); + } else { + dprintf(" MUX Unknown error (%u) at address 0x%02X\n", error, I2C_MULTIPX_ADDR); + } + } + + for (uint8_t ch = 1; ch <= MAX_MEX_CH; ch++) { + change_channel(ch); + + uint16_t keymapShift = get_keymap_shift(ch, ShiftType_Key_Start); + + // detect PCA9557 + for (uint8_t address = PCA9557_FROM_ADDR; address < PCA9557_END_ADDR; address++) { + i2c_status_t error = i2c_ping_address(address << 1, MY_I2C_TIMEOUT); + if (error == I2C_STATUS_SUCCESS) { + dprintf("[PCA9557_init] %d, 0x%X \n", ch, address); + Keys_Data data = init_PCA9557(address); + + if (data.type == Type_Unknown) { + dprintf("[PCA9557_init] Failed: %d, 0x%X, type: %d \n", ch, address, data.type); + continue; + } + + int shiftValue = 0; + if (data.type == Type_PCA9557_Keys4) { + shiftValue = 5; // Ideally, this value should be 4. However, for easy re-layout, use the same value as key5 + } else if (data.type == Type_PCA9557_Keys5) { + shiftValue = 5; + } else { + dprintf("[PCA9557_init] type is not covered: %d \n", data.type); + } + + keymapShift = get_updated_keymap_shift(keymapShift, shiftValue); + deviceList[nDevices] = (DeviceList){.ch = ch, .address = address, .type = data.type, .keymapShift = keymapShift}; + keymapShift += shiftValue; + nDevices++; + } else { + dprintf(" Missing: (%u) at address 0x%02X\n", error, address); + } + } + + // XL9555 devices can overwrite PCA9557 devices' results + keymapShift = get_keymap_shift(ch, ShiftType_Key_Start); + + // detect XL9555 + for (uint8_t address = XL9555_FROM_ADDR; address < XL9555_END_ADDR; address++) { + i2c_status_t error = i2c_ping_address(address << 1, MY_I2C_TIMEOUT); + if (error == I2C_STATUS_SUCCESS) { + dprintf("[XL9555_init] %d, 0x%X \n", ch, address); + Keys_Data data = init_XL9555(address); + + if (data.type == Type_Unknown) { + dprintf("[XL9555_init] Failed: %d, 0x%X, type: %d \n", ch, address, data.type); + continue; + } + + int shiftValue = 0; + if (data.type == Type_XL9555_Keys4) { + shiftValue = 5; // Ideally, this value should be 4, but for easy re-layout, use the same value as key5 + } else if (data.type == Type_XL9555_Keys5) { + shiftValue = 5; + } else { + dprintf("[XL9555_init] type is not covered: %d \n", data.type); + } + + keymapShift = get_updated_keymap_shift(keymapShift, shiftValue); + deviceList[nDevices] = (DeviceList){.ch = ch, .address = address, .type = data.type, .keymapShift = keymapShift}; + keymapShift += shiftValue; + nDevices++; + } else { + dprintf(" Missing: (%u) at address 0x%02X\n", error, address); + } + } + + // proceed to the begining of the position of rotary encoders + keymapShift = get_keymap_shift(ch, ShiftType_RE_Start); + + // detect PCA9534A, rotary encoders + for (uint8_t address = PCA9534A_FROM_ADDR; address < PCA9534A_END_ADDR; address++) { + i2c_status_t error = i2c_ping_address(address << 1, MY_I2C_TIMEOUT); + if (error == I2C_STATUS_SUCCESS) { + dprintf("[PCA9534A_init] %d, 0x%X \n", ch, address); + Keys_Data data = init_PCA9534A(address); + + if (data.type == Type_Unknown) { + dprintf("[PCA9534A_init] Failed: %d, 0x%X, type: %d \n", ch, address, data.type); + continue; + } + + int shiftValue = 0; + if (data.type == Type_PCA9534A_RE_CLICKABLE) { + shiftValue = 1; // for click button + } else { + dprintf("[PCA9534A_init] type is not covered: %d \n", data.type); + } + + keymapShift = get_updated_keymap_shift(keymapShift, shiftValue); + deviceList[nDevices] = (DeviceList){.ch = ch, .address = address, .type = data.type, .keymapShift = keymapShift}; + keymapShift += shiftValue; + nDevices++; + } else { + dprintf(" Missing: (%u) at address 0x%02X\n", error, address); + } + } + } + + if (nDevices == 0) { + dprintf("No I2C devices found\n"); + } else { + dprintf("#devices: %d\n", nDevices); + for (uint16_t i = 0; i < nDevices; i++) { + dprintf("[I2C] %d, 0x%X \n", deviceList[i].ch, deviceList[i].address); + } + } +} diff --git a/keyboards/cue2keys/i2clib.h b/keyboards/cue2keys/i2clib.h new file mode 100644 index 00000000000..f03b05c6db4 --- /dev/null +++ b/keyboards/cue2keys/i2clib.h @@ -0,0 +1,67 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include "keycodes.h" +#include "debug.h" + +// # of System Key +#define SYSTEM_KEY_NUM 10 +// maximum number of modules per channel +#define MAX_KEY_PER_CH_NUM 8 +#define MAX_RE_PER_CH_NUM 4 +#define CH_BUFFER_NUM 16 // for future modules + +// 0x18 is the beginning of PCA9557 +#define PCA9557_FROM_ADDR 0x18 +#define PCA9557_END_ADDR (0x18 + MAX_KEY_PER_CH_NUM) + +// 0x20 is the beginning of XL9555/TCA9535 +#define XL9555_FROM_ADDR 0x20 +#define XL9555_END_ADDR (0x20 + MAX_KEY_PER_CH_NUM) + +// 0x38 is the beginning of PCA9534A +// NOTICE: OLED resides on 0x3C, thus MAX_RE_PER_CH_NUM is 4 to skip this address. +// Additionally, on the hardware side, the A2 pin needs to be low. +#define PCA9534A_FROM_ADDR 0x38 +#define PCA9534A_END_ADDR (PCA9534A_FROM_ADDR + MAX_RE_PER_CH_NUM) + +#define I2C_MULTIPX_ADDR 0x70 + +#define MY_I2C_TIMEOUT 1 + +#define MAX_MEX_CH 4 +#define MAX_MCP_NUM 60 + +typedef enum _Type { + Type_Unknown = 0, + + Type_PCA9557_Keys4 = 1, + Type_PCA9557_Keys5 = 2, + + Type_XL9555_Keys4 = 3, + Type_XL9555_Keys5 = 4, + + Type_PCA9534A_RE_CLICKABLE = 5, +} Type; + +typedef struct { + Type type; + uint8_t data[2]; // key input, joysticks, etc +} Keys_Data; + +typedef struct { + Type type; + uint8_t ch; + uint8_t address; + uint16_t keymapShift; +} DeviceList; + +bool change_channel(uint8_t channel); +Keys_Data read_PCA9557_register(uint8_t address); +Keys_Data read_XL9555_register(uint8_t address); +Keys_Data read_PCA9534A_register(uint8_t address); +void do_scan(void); diff --git a/keyboards/cue2keys/kb_config.c b/keyboards/cue2keys/kb_config.c new file mode 100644 index 00000000000..79e297c3376 --- /dev/null +++ b/keyboards/cue2keys/kb_config.c @@ -0,0 +1,392 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "kb_config.h" + +void my_kb_config_init(kb_config_t* kb_config) { + kb_config->mouse_layer_on = 1; + kb_config->mouse_layer_off_delay_ms = 13; + kb_config->angle_L = 0; + kb_config->angle_R = 0; + kb_config->pointer_speed_magnification = 4; + kb_config->invert_drag_scroll_x = 0; + kb_config->invert_drag_scroll_y = 0; + kb_config->drag_scroll_speed_magnification = 4; + kb_config->trackball_led_off_timeout = 1; + kb_config->all_keys_are_mouse_keys = 0; + kb_config->_dummy_tb = 0; + kb_config->re_resolution_1 = 2; + kb_config->re_resolution_2 = 2; + kb_config->re_resolution_3 = 2; + kb_config->re_resolution_4 = 2; + kb_config->re_resolution_5 = 2; + kb_config->re_resolution_6 = 2; + kb_config->re_resolution_7 = 2; + kb_config->re_resolution_8 = 2; + kb_config->re_resolution_9 = 2; + kb_config->re_resolution_10 = 2; + kb_config->re_resolution_11 = 2; + kb_config->re_resolution_12 = 2; + kb_config->re_resolution_13 = 2; + kb_config->re_resolution_14 = 2; + kb_config->re_resolution_15 = 2; + kb_config->re_resolution_16 = 2; +} + +void debug_output_kb_config(kb_config_t* kb_config) { +#ifdef CONSOLE_ENABLE + { + static uint32_t timer = 0; + if (timer_elapsed32(timer) > 1000) { + dprintf("=== kb_config ===\n"); + dprintf("%s = %" PRIu32 "\n", "mouse_layer_on", (uint32_t)kb_config->mouse_layer_on); + dprintf("%s = %" PRIu32 "\n", "mouse_layer_off_delay_ms", (uint32_t)kb_config->mouse_layer_off_delay_ms); + dprintf("%s = %" PRIu32 "\n", "angle_L", (uint32_t)kb_config->angle_L); + dprintf("%s = %" PRIu32 "\n", "angle_R", (uint32_t)kb_config->angle_R); + dprintf("%s = %" PRIu32 "\n", "pointer_speed_magnification", (uint32_t)kb_config->pointer_speed_magnification); + dprintf("%s = %" PRIu32 "\n", "invert_drag_scroll_x", (uint32_t)kb_config->invert_drag_scroll_x); + dprintf("%s = %" PRIu32 "\n", "invert_drag_scroll_y", (uint32_t)kb_config->invert_drag_scroll_y); + dprintf("%s = %" PRIu32 "\n", "drag_scroll_speed_magnification", (uint32_t)kb_config->drag_scroll_speed_magnification); + dprintf("%s = %" PRIu32 "\n", "trackball_led_off_timeout", (uint32_t)kb_config->trackball_led_off_timeout); + dprintf("%s = %" PRIu32 "\n", "all_keys_are_mouse_keys", (uint32_t)kb_config->all_keys_are_mouse_keys); + dprintf("%s = %" PRIu32 "\n", "_dummy_tb", (uint32_t)kb_config->_dummy_tb); + dprintf("%s = %" PRIu32 "\n", "re_resolution_1", (uint32_t)kb_config->re_resolution_1); + dprintf("%s = %" PRIu32 "\n", "re_resolution_2", (uint32_t)kb_config->re_resolution_2); + dprintf("%s = %" PRIu32 "\n", "re_resolution_3", (uint32_t)kb_config->re_resolution_3); + dprintf("%s = %" PRIu32 "\n", "re_resolution_4", (uint32_t)kb_config->re_resolution_4); + dprintf("%s = %" PRIu32 "\n", "re_resolution_5", (uint32_t)kb_config->re_resolution_5); + dprintf("%s = %" PRIu32 "\n", "re_resolution_6", (uint32_t)kb_config->re_resolution_6); + dprintf("%s = %" PRIu32 "\n", "re_resolution_7", (uint32_t)kb_config->re_resolution_7); + dprintf("%s = %" PRIu32 "\n", "re_resolution_8", (uint32_t)kb_config->re_resolution_8); + dprintf("%s = %" PRIu32 "\n", "re_resolution_9", (uint32_t)kb_config->re_resolution_9); + dprintf("%s = %" PRIu32 "\n", "re_resolution_10", (uint32_t)kb_config->re_resolution_10); + dprintf("%s = %" PRIu32 "\n", "re_resolution_11", (uint32_t)kb_config->re_resolution_11); + dprintf("%s = %" PRIu32 "\n", "re_resolution_12", (uint32_t)kb_config->re_resolution_12); + dprintf("%s = %" PRIu32 "\n", "re_resolution_13", (uint32_t)kb_config->re_resolution_13); + dprintf("%s = %" PRIu32 "\n", "re_resolution_14", (uint32_t)kb_config->re_resolution_14); + dprintf("%s = %" PRIu32 "\n", "re_resolution_15", (uint32_t)kb_config->re_resolution_15); + dprintf("%s = %" PRIu32 "\n", "re_resolution_16", (uint32_t)kb_config->re_resolution_16); + dprintf("=== the end of kb_config ===\n"); + timer = timer_read32(); + } + } +#endif +} + +bool process_kb_config_modification(kb_config_t* kb_config, uint16_t keycode, keyrecord_t* record) { + if (record->event.pressed) { + switch (keycode) { + case AUTO_MOUSE_LAYER_P1: + kb_config->mouse_layer_on = ((uint64_t)kb_config->mouse_layer_on + 2 + 1) % 2; + return false; + case AUTO_MOUSE_LAYER_OFF_DELAY_P1: + kb_config->mouse_layer_off_delay_ms = ((uint64_t)kb_config->mouse_layer_off_delay_ms + 64 + 1) % 64; + return false; + case AUTO_MOUSE_LAYER_OFF_DELAY_M1: + kb_config->mouse_layer_off_delay_ms = ((uint64_t)kb_config->mouse_layer_off_delay_ms + 64 - 1) % 64; + return false; + case ANGLE_L_ADJUSTMENT_P1: + kb_config->angle_L = ((uint64_t)kb_config->angle_L + 360 + 1) % 360; + return false; + case ANGLE_L_ADJUSTMENT_M1: + kb_config->angle_L = ((uint64_t)kb_config->angle_L + 360 - 1) % 360; + return false; + case ANGLE_L_ADJUSTMENT_P30: + kb_config->angle_L = ((uint64_t)kb_config->angle_L + 360 + 30) % 360; + return false; + case ANGLE_L_ADJUSTMENT_M30: + kb_config->angle_L = ((uint64_t)kb_config->angle_L + 360 - 30) % 360; + return false; + case ANGLE_R_ADJUSTMENT_P1: + kb_config->angle_R = ((uint64_t)kb_config->angle_R + 360 + 1) % 360; + return false; + case ANGLE_R_ADJUSTMENT_M1: + kb_config->angle_R = ((uint64_t)kb_config->angle_R + 360 - 1) % 360; + return false; + case ANGLE_R_ADJUSTMENT_P30: + kb_config->angle_R = ((uint64_t)kb_config->angle_R + 360 + 30) % 360; + return false; + case ANGLE_R_ADJUSTMENT_M30: + kb_config->angle_R = ((uint64_t)kb_config->angle_R + 360 - 30) % 360; + return false; + case POINTER_SPEED_MAGNIFICATION_P1: + kb_config->pointer_speed_magnification = ((uint64_t)kb_config->pointer_speed_magnification + 16 + 1) % 16; + return false; + case POINTER_SPEED_MAGNIFICATION_M1: + kb_config->pointer_speed_magnification = ((uint64_t)kb_config->pointer_speed_magnification + 16 - 1) % 16; + return false; + case INVERT_DRAG_SCROLL_X_P1: + kb_config->invert_drag_scroll_x = ((uint64_t)kb_config->invert_drag_scroll_x + 2 + 1) % 2; + return false; + case INVERT_DRAG_SCROLL_Y_P1: + kb_config->invert_drag_scroll_y = ((uint64_t)kb_config->invert_drag_scroll_y + 2 + 1) % 2; + return false; + case DRAG_SCROLL_SPEED_MAGNIFICATION_P1: + kb_config->drag_scroll_speed_magnification = ((uint64_t)kb_config->drag_scroll_speed_magnification + 16 + 1) % 16; + return false; + case DRAG_SCROLL_SPEED_MAGNIFICATION_M1: + kb_config->drag_scroll_speed_magnification = ((uint64_t)kb_config->drag_scroll_speed_magnification + 16 - 1) % 16; + return false; + case TRACKBALL_LED_OFF_TIMEOUT_P1: + kb_config->trackball_led_off_timeout = ((uint64_t)kb_config->trackball_led_off_timeout + 4 + 1) % 4; + return false; + case TRACKBALL_LED_OFF_TIMEOUT_M1: + kb_config->trackball_led_off_timeout = ((uint64_t)kb_config->trackball_led_off_timeout + 4 - 1) % 4; + return false; + case ALL_KEYS_ARE_MOUSE_KEYS_P1: + kb_config->all_keys_are_mouse_keys = ((uint64_t)kb_config->all_keys_are_mouse_keys + 2 + 1) % 2; + return false; + case ROTARY_ENCODER_1_RESOLUTION_P1: + kb_config->re_resolution_1 = ((uint64_t)kb_config->re_resolution_1 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_2_RESOLUTION_P1: + kb_config->re_resolution_2 = ((uint64_t)kb_config->re_resolution_2 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_3_RESOLUTION_P1: + kb_config->re_resolution_3 = ((uint64_t)kb_config->re_resolution_3 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_4_RESOLUTION_P1: + kb_config->re_resolution_4 = ((uint64_t)kb_config->re_resolution_4 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_5_RESOLUTION_P1: + kb_config->re_resolution_5 = ((uint64_t)kb_config->re_resolution_5 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_6_RESOLUTION_P1: + kb_config->re_resolution_6 = ((uint64_t)kb_config->re_resolution_6 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_7_RESOLUTION_P1: + kb_config->re_resolution_7 = ((uint64_t)kb_config->re_resolution_7 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_8_RESOLUTION_P1: + kb_config->re_resolution_8 = ((uint64_t)kb_config->re_resolution_8 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_9_RESOLUTION_P1: + kb_config->re_resolution_9 = ((uint64_t)kb_config->re_resolution_9 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_10_RESOLUTION_P1: + kb_config->re_resolution_10 = ((uint64_t)kb_config->re_resolution_10 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_11_RESOLUTION_P1: + kb_config->re_resolution_11 = ((uint64_t)kb_config->re_resolution_11 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_12_RESOLUTION_P1: + kb_config->re_resolution_12 = ((uint64_t)kb_config->re_resolution_12 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_13_RESOLUTION_P1: + kb_config->re_resolution_13 = ((uint64_t)kb_config->re_resolution_13 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_14_RESOLUTION_P1: + kb_config->re_resolution_14 = ((uint64_t)kb_config->re_resolution_14 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_15_RESOLUTION_P1: + kb_config->re_resolution_15 = ((uint64_t)kb_config->re_resolution_15 + 4 + 1) % 4; + return false; + case ROTARY_ENCODER_16_RESOLUTION_P1: + kb_config->re_resolution_16 = ((uint64_t)kb_config->re_resolution_16 + 4 + 1) % 4; + return false; + } + } + + return true; +} + +void oled_kb_config_output(kb_config_t* kb_config, uint8_t page) { + oled_write_P(PSTR("Config("), false); + static char page_str[4]; + itoa(page + 1, page_str, 10); + oled_write_P(page_str, false); + oled_write_P(PSTR(") -- "), false); + + switch (page) { + case 0: { + static char type_count_str[8]; + oled_write_P(PSTR("mlo:"), false); + itoa(kb_config->mouse_layer_on, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("mod:"), false); + itoa(kb_config->mouse_layer_off_delay_ms, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("agl:"), false); + itoa(kb_config->angle_L, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("agr:"), false); + itoa(kb_config->angle_R, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("psm:"), false); + itoa(kb_config->pointer_speed_magnification, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("idsX:"), false); + itoa(kb_config->invert_drag_scroll_x, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + break; + case 1: { + static char type_count_str[8]; + oled_write_P(PSTR("idsY:"), false); + itoa(kb_config->invert_drag_scroll_y, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("dsm:"), false); + itoa(kb_config->drag_scroll_speed_magnification, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("tlt:"), false); + itoa(kb_config->trackball_led_off_timeout, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("amk:"), false); + itoa(kb_config->all_keys_are_mouse_keys, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr1:"), false); + itoa(kb_config->re_resolution_1, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + break; + case 2: { + static char type_count_str[8]; + oled_write_P(PSTR("rr2:"), false); + itoa(kb_config->re_resolution_2, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr3:"), false); + itoa(kb_config->re_resolution_3, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr4:"), false); + itoa(kb_config->re_resolution_4, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr5:"), false); + itoa(kb_config->re_resolution_5, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr6:"), false); + itoa(kb_config->re_resolution_6, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr7:"), false); + itoa(kb_config->re_resolution_7, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + break; + case 3: { + static char type_count_str[8]; + oled_write_P(PSTR("rr8:"), false); + itoa(kb_config->re_resolution_8, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr9:"), false); + itoa(kb_config->re_resolution_9, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr10:"), false); + itoa(kb_config->re_resolution_10, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr11:"), false); + itoa(kb_config->re_resolution_11, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr12:"), false); + itoa(kb_config->re_resolution_12, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr13:"), false); + itoa(kb_config->re_resolution_13, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + break; + case 4: { + static char type_count_str[8]; + oled_write_P(PSTR("rr14:"), false); + itoa(kb_config->re_resolution_14, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr15:"), false); + itoa(kb_config->re_resolution_15, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + { + static char type_count_str[8]; + oled_write_P(PSTR("rr16:"), false); + itoa(kb_config->re_resolution_16, type_count_str, 10); + oled_write_P(type_count_str, false); + } + oled_write_P(PSTR(", "), false); + break; + default: + oled_write_ln_P(PSTR("no config"), false); + } + oled_write_ln_P("", false); +} diff --git a/keyboards/cue2keys/kb_config.h b/keyboards/cue2keys/kb_config.h new file mode 100644 index 00000000000..dbe5a4bbebd --- /dev/null +++ b/keyboards/cue2keys/kb_config.h @@ -0,0 +1,146 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include "quantum.h" + +enum my_keycodes { + // Next OLED Page + NEXT_OLED_PAGE = QK_KB_0, + // drag scroll feature for trackball + DRAG_SCROLL, + // kb_config modification + AUTO_MOUSE_LAYER_P1, + AUTO_MOUSE_LAYER_OFF_DELAY_P1, + AUTO_MOUSE_LAYER_OFF_DELAY_M1, + ANGLE_L_ADJUSTMENT_P1, + ANGLE_L_ADJUSTMENT_M1, + ANGLE_L_ADJUSTMENT_P30, + ANGLE_L_ADJUSTMENT_M30, + ANGLE_R_ADJUSTMENT_P1, + ANGLE_R_ADJUSTMENT_M1, + ANGLE_R_ADJUSTMENT_P30, + ANGLE_R_ADJUSTMENT_M30, + POINTER_SPEED_MAGNIFICATION_P1, + POINTER_SPEED_MAGNIFICATION_M1, + INVERT_DRAG_SCROLL_X_P1, + INVERT_DRAG_SCROLL_Y_P1, + DRAG_SCROLL_SPEED_MAGNIFICATION_P1, + DRAG_SCROLL_SPEED_MAGNIFICATION_M1, + TRACKBALL_LED_OFF_TIMEOUT_P1, + TRACKBALL_LED_OFF_TIMEOUT_M1, + ALL_KEYS_ARE_MOUSE_KEYS_P1, + ROTARY_ENCODER_1_RESOLUTION_P1, + ROTARY_ENCODER_2_RESOLUTION_P1, + ROTARY_ENCODER_3_RESOLUTION_P1, + ROTARY_ENCODER_4_RESOLUTION_P1, + ROTARY_ENCODER_5_RESOLUTION_P1, + ROTARY_ENCODER_6_RESOLUTION_P1, + ROTARY_ENCODER_7_RESOLUTION_P1, + ROTARY_ENCODER_8_RESOLUTION_P1, + ROTARY_ENCODER_9_RESOLUTION_P1, + ROTARY_ENCODER_10_RESOLUTION_P1, + ROTARY_ENCODER_11_RESOLUTION_P1, + ROTARY_ENCODER_12_RESOLUTION_P1, + ROTARY_ENCODER_13_RESOLUTION_P1, + ROTARY_ENCODER_14_RESOLUTION_P1, + ROTARY_ENCODER_15_RESOLUTION_P1, + ROTARY_ENCODER_16_RESOLUTION_P1, +}; + +typedef union { + uint8_t raw[EECONFIG_KB_DATA_SIZE]; // 1KB + struct { + // Auto mouse layer (true/false) + // 2^1=2, default: 1, max: 1 + uint32_t mouse_layer_on : 1; + // Auto mouse layer off delay time in ms (value * 100ms) + // 2^6=64, default: 13, max: 63 + uint32_t mouse_layer_off_delay_ms : 6; + // Angle adjustment for trackballs (left) + // 2^9=512, default: 0, max: 359 + uint32_t angle_L : 9; + // Angle adjustment for trackballs (right) + // 2^9=512, default: 0, max: 359 + uint32_t angle_R : 9; + // Pointer speed magnification (value * 0.25) + // 2^4=16, default: 4, max: 15 + uint32_t pointer_speed_magnification : 4; + // Invert drag scroll X-axis direction (true/false) + // 2^1=2, default: 0, max: 1 + uint32_t invert_drag_scroll_x : 1; + // Invert drag scroll Y-axis direction (true/false) + // 2^1=2, default: 0, max: 1 + uint32_t invert_drag_scroll_y : 1; + // Drag scroll speed magnification (value * 0.25) + // 2^4=16, default: 4, max: 15 + uint32_t drag_scroll_speed_magnification : 4; + // Trackball LED off timeout (never, 5min, 10min, 15 min) + // 2^2=4, default: 1, max: 3 + uint32_t trackball_led_off_timeout : 2; + // All keys are treated as mouse keys (true/false) + // 2^1=2, default: 0, max: 1 + uint32_t all_keys_are_mouse_keys : 1; + // Dummy value + // 2^32=4294967296, default: 0, max: 0 + uint32_t _dummy_tb : 32; + // Rotary encoder 1 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_1 : 2; + // Rotary encoder 2 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_2 : 2; + // Rotary encoder 3 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_3 : 2; + // Rotary encoder 4 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_4 : 2; + // Rotary encoder 5 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_5 : 2; + // Rotary encoder 6 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_6 : 2; + // Rotary encoder 7 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_7 : 2; + // Rotary encoder 8 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_8 : 2; + // Rotary encoder 9 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_9 : 2; + // Rotary encoder 10 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_10 : 2; + // Rotary encoder 11 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_11 : 2; + // Rotary encoder 12 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_12 : 2; + // Rotary encoder 13 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_13 : 2; + // Rotary encoder 14 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_14 : 2; + // Rotary encoder 15 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_15 : 2; + // Rotary encoder 16 resolution (restart needed to reflect) + // 2^2=4, default: 2, max: 3 + uint32_t re_resolution_16 : 2; + }; +} kb_config_t; + +extern kb_config_t kb_config; + +void my_kb_config_init(kb_config_t* kb_config); +void debug_output_kb_config(kb_config_t* kb_config); +bool process_kb_config_modification(kb_config_t* kb_config, uint16_t keycode, keyrecord_t* record); +void oled_kb_config_output(kb_config_t* kb_config, uint8_t page); diff --git a/keyboards/cue2keys/keyboard.json b/keyboards/cue2keys/keyboard.json new file mode 100644 index 00000000000..6bb844cd88d --- /dev/null +++ b/keyboards/cue2keys/keyboard.json @@ -0,0 +1,533 @@ +{ + "manufacturer": "cue2keys", + "keyboard_name": "cue2keys", + "maintainer": "esplo", + "board": "GENERIC_RP_RP2040", + "bootloader": "rp2040", + "customKeycodes": [ + { + "name": "NEXT_OLED_PAGE", + "shortName": "NEXT_OLED_PAGE", + "title": "Open next page on OLED display" + }, + { + "name": "DRAG_SCROLL", + "shortName": "DRAG_SCROLL", + "title": "Change the pointer device movement into the mouse scroll" + }, + { + "name": "AUTO_MOUSE_LAYER_P1", + "shortName": "mlo_P1", + "title": "Auto mouse layer (true/false)" + }, + { + "name": "AUTO_MOUSE_LAYER_OFF_DELAY_P1", + "shortName": "mod_P1", + "title": "Auto mouse layer off delay time in ms (value * 100ms)" + }, + { + "name": "AUTO_MOUSE_LAYER_OFF_DELAY_M1", + "shortName": "mod_M1", + "title": "Auto mouse layer off delay time in ms (value * 100ms)" + }, + { + "name": "ANGLE_L_ADJUSTMENT_P1", + "shortName": "agl_P1", + "title": "Angle adjustment for trackballs (left)" + }, + { + "name": "ANGLE_L_ADJUSTMENT_M1", + "shortName": "agl_M1", + "title": "Angle adjustment for trackballs (left)" + }, + { + "name": "ANGLE_L_ADJUSTMENT_P30", + "shortName": "agl_P30", + "title": "Angle adjustment for trackballs (left)" + }, + { + "name": "ANGLE_L_ADJUSTMENT_M30", + "shortName": "agl_M30", + "title": "Angle adjustment for trackballs (left)" + }, + { + "name": "ANGLE_R_ADJUSTMENT_P1", + "shortName": "agr_P1", + "title": "Angle adjustment for trackballs (right)" + }, + { + "name": "ANGLE_R_ADJUSTMENT_M1", + "shortName": "agr_M1", + "title": "Angle adjustment for trackballs (right)" + }, + { + "name": "ANGLE_R_ADJUSTMENT_P30", + "shortName": "agr_P30", + "title": "Angle adjustment for trackballs (right)" + }, + { + "name": "ANGLE_R_ADJUSTMENT_M30", + "shortName": "agr_M30", + "title": "Angle adjustment for trackballs (right)" + }, + { + "name": "POINTER_SPEED_MAGNIFICATION_P1", + "shortName": "psm_P1", + "title": "Pointer speed magnification (value * 0.25)" + }, + { + "name": "POINTER_SPEED_MAGNIFICATION_M1", + "shortName": "psm_M1", + "title": "Pointer speed magnification (value * 0.25)" + }, + { + "name": "INVERT_DRAG_SCROLL_X_P1", + "shortName": "idsX_P1", + "title": "Invert drag scroll X-axis direction (true/false)" + }, + { + "name": "INVERT_DRAG_SCROLL_Y_P1", + "shortName": "idsY_P1", + "title": "Invert drag scroll Y-axis direction (true/false)" + }, + { + "name": "DRAG_SCROLL_SPEED_MAGNIFICATION_P1", + "shortName": "dsm_P1", + "title": "Drag scroll speed magnification (value * 0.25)" + }, + { + "name": "DRAG_SCROLL_SPEED_MAGNIFICATION_M1", + "shortName": "dsm_M1", + "title": "Drag scroll speed magnification (value * 0.25)" + }, + { + "name": "TRACKBALL_LED_OFF_TIMEOUT_P1", + "shortName": "tlt_P1", + "title": "Trackball LED off timeout (never, 5min, 10min, 15 min)" + }, + { + "name": "TRACKBALL_LED_OFF_TIMEOUT_M1", + "shortName": "tlt_M1", + "title": "Trackball LED off timeout (never, 5min, 10min, 15 min)" + }, + { + "name": "ALL_KEYS_ARE_MOUSE_KEYS_P1", + "shortName": "amk_P1", + "title": "All keys are treated as mouse keys (true/false)" + }, + { + "name": "ROTARY_ENCODER_1_RESOLUTION_P1", + "shortName": "rr1_P1", + "title": "Rotary encoder 1 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_2_RESOLUTION_P1", + "shortName": "rr2_P1", + "title": "Rotary encoder 2 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_3_RESOLUTION_P1", + "shortName": "rr3_P1", + "title": "Rotary encoder 3 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_4_RESOLUTION_P1", + "shortName": "rr4_P1", + "title": "Rotary encoder 4 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_5_RESOLUTION_P1", + "shortName": "rr5_P1", + "title": "Rotary encoder 5 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_6_RESOLUTION_P1", + "shortName": "rr6_P1", + "title": "Rotary encoder 6 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_7_RESOLUTION_P1", + "shortName": "rr7_P1", + "title": "Rotary encoder 7 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_8_RESOLUTION_P1", + "shortName": "rr8_P1", + "title": "Rotary encoder 8 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_9_RESOLUTION_P1", + "shortName": "rr9_P1", + "title": "Rotary encoder 9 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_10_RESOLUTION_P1", + "shortName": "rr10_P1", + "title": "Rotary encoder 10 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_11_RESOLUTION_P1", + "shortName": "rr11_P1", + "title": "Rotary encoder 11 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_12_RESOLUTION_P1", + "shortName": "rr12_P1", + "title": "Rotary encoder 12 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_13_RESOLUTION_P1", + "shortName": "rr13_P1", + "title": "Rotary encoder 13 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_14_RESOLUTION_P1", + "shortName": "rr14_P1", + "title": "Rotary encoder 14 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_15_RESOLUTION_P1", + "shortName": "rr15_P1", + "title": "Rotary encoder 15 resolution (restart needed to reflect)" + }, + { + "name": "ROTARY_ENCODER_16_RESOLUTION_P1", + "shortName": "rr16_P1", + "title": "Rotary encoder 16 resolution (restart needed to reflect)" + } + ], + "dynamic_keymap": { + "layer_count": 8 + }, + "eeprom": { + "wear_leveling": { + "backing_size": 32768 + } + }, + "features": { + "bootmagic": true, + "command": false, + "console": true, + "encoder": true, + "extrakey": true, + "mousekey": true, + "nkro": true, + "oled": true + }, + "matrix_pins": { + "direct": [ + ["GP9", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"], + ["NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN", "NO_PIN"] + ] + }, + "processor": "RP2040", + "serial": { + "driver": "vendor" + }, + "url": "https://cue2keys.esplo.net/", + "usb": { + "device_version": "1.0.0", + "pid": "0xC2C2", + "vid": "0xFEFD" + }, + "layouts": { + "LAYOUT_5x4": { + "layout": [ + {"label": "ch1_key(0,1)", "matrix": [1, 0], "x": 0, "y": 0}, + {"label": "ch1_key(1,1)", "matrix": [1, 1], "x": 0, "y": 1}, + {"label": "ch1_key(2,1)", "matrix": [1, 2], "x": 0, "y": 2}, + {"label": "ch1_key(3,1)", "matrix": [1, 3], "x": 0, "y": 3}, + {"label": "ch1_key(4,1)", "matrix": [1, 4], "x": 0, "y": 4}, + {"label": "ch1_key(5,1)", "matrix": [1, 5], "x": 1, "y": 0}, + {"label": "ch1_key(6,1)", "matrix": [1, 6], "x": 1, "y": 1}, + {"label": "ch1_key(7,1)", "matrix": [1, 7], "x": 1, "y": 2}, + {"label": "ch1_key(8,1)", "matrix": [1, 8], "x": 1, "y": 3}, + {"label": "ch1_key(9,1)", "matrix": [1, 9], "x": 1, "y": 4}, + {"label": "ch1_key(0,2)", "matrix": [2, 0], "x": 2, "y": 0}, + {"label": "ch1_key(1,2)", "matrix": [2, 1], "x": 2, "y": 1}, + {"label": "ch1_key(2,2)", "matrix": [2, 2], "x": 2, "y": 2}, + {"label": "ch1_key(3,2)", "matrix": [2, 3], "x": 2, "y": 3}, + {"label": "ch1_key(4,2)", "matrix": [2, 4], "x": 2, "y": 4}, + {"label": "ch1_key(5,2)", "matrix": [2, 5], "x": 3, "y": 0}, + {"label": "ch1_key(6,2)", "matrix": [2, 6], "x": 3, "y": 1}, + {"label": "ch1_key(7,2)", "matrix": [2, 7], "x": 3, "y": 2}, + {"label": "ch1_key(8,2)", "matrix": [2, 8], "x": 3, "y": 3}, + {"label": "ch1_key(9,2)", "matrix": [2, 9], "x": 3, "y": 4} + ] + }, + "LAYOUT_all": { + "layout": [ + {"label": "ch1_key(0,1)", "matrix": [1, 0], "x": 0, "y": 0}, + {"label": "ch1_key(1,1)", "matrix": [1, 1], "x": 0, "y": 1}, + {"label": "ch1_key(2,1)", "matrix": [1, 2], "x": 0, "y": 2}, + {"label": "ch1_key(3,1)", "matrix": [1, 3], "x": 0, "y": 3}, + {"label": "ch1_key(4,1)", "matrix": [1, 4], "x": 0, "y": 4}, + {"label": "ch1_key(5,1)", "matrix": [1, 5], "x": 1, "y": 0}, + {"label": "ch1_key(6,1)", "matrix": [1, 6], "x": 1, "y": 1}, + {"label": "ch1_key(7,1)", "matrix": [1, 7], "x": 1, "y": 2}, + {"label": "ch1_key(8,1)", "matrix": [1, 8], "x": 1, "y": 3}, + {"label": "ch1_key(9,1)", "matrix": [1, 9], "x": 1, "y": 4}, + {"label": "ch1_key(0,2)", "matrix": [2, 0], "x": 2, "y": 0}, + {"label": "ch1_key(1,2)", "matrix": [2, 1], "x": 2, "y": 1}, + {"label": "ch1_key(2,2)", "matrix": [2, 2], "x": 2, "y": 2}, + {"label": "ch1_key(3,2)", "matrix": [2, 3], "x": 2, "y": 3}, + {"label": "ch1_key(4,2)", "matrix": [2, 4], "x": 2, "y": 4}, + {"label": "ch1_key(5,2)", "matrix": [2, 5], "x": 3, "y": 0}, + {"label": "ch1_key(6,2)", "matrix": [2, 6], "x": 3, "y": 1}, + {"label": "ch1_key(7,2)", "matrix": [2, 7], "x": 3, "y": 2}, + {"label": "ch1_key(8,2)", "matrix": [2, 8], "x": 3, "y": 3}, + {"label": "ch1_key(9,2)", "matrix": [2, 9], "x": 3, "y": 4}, + {"label": "ch1_key(0,3)", "matrix": [3, 0], "x": 4, "y": 0}, + {"label": "ch1_key(1,3)", "matrix": [3, 1], "x": 4, "y": 1}, + {"label": "ch1_key(2,3)", "matrix": [3, 2], "x": 4, "y": 2}, + {"label": "ch1_key(3,3)", "matrix": [3, 3], "x": 4, "y": 3}, + {"label": "ch1_key(4,3)", "matrix": [3, 4], "x": 4, "y": 4}, + {"label": "ch1_key(5,3)", "matrix": [3, 5], "x": 5, "y": 0}, + {"label": "ch1_key(6,3)", "matrix": [3, 6], "x": 5, "y": 1}, + {"label": "ch1_key(7,3)", "matrix": [3, 7], "x": 5, "y": 2}, + {"label": "ch1_key(8,3)", "matrix": [3, 8], "x": 5, "y": 3}, + {"label": "ch1_key(9,3)", "matrix": [3, 9], "x": 5, "y": 4}, + {"label": "ch1_key(0,4)", "matrix": [4, 0], "x": 6, "y": 0}, + {"label": "ch1_key(1,4)", "matrix": [4, 1], "x": 6, "y": 1}, + {"label": "ch1_key(2,4)", "matrix": [4, 2], "x": 6, "y": 2}, + {"label": "ch1_key(3,4)", "matrix": [4, 3], "x": 6, "y": 3}, + {"label": "ch1_key(4,4)", "matrix": [4, 4], "x": 6, "y": 4}, + {"label": "ch1_key(5,4)", "matrix": [4, 5], "x": 7, "y": 0}, + {"label": "ch1_key(6,4)", "matrix": [4, 6], "x": 7, "y": 1}, + {"label": "ch1_key(7,4)", "matrix": [4, 7], "x": 7, "y": 2}, + {"label": "ch1_key(8,4)", "matrix": [4, 8], "x": 7, "y": 3}, + {"label": "ch1_key(9,4)", "matrix": [4, 9], "x": 7, "y": 4}, + {"label": "e1", "matrix": [5, 0], "x": 8, "y": 0, "encoder": 0}, + {"label": "e2", "matrix": [5, 1], "x": 8, "y": 1, "encoder": 1}, + {"label": "e3", "matrix": [5, 2], "x": 8, "y": 2, "encoder": 2}, + {"label": "e4", "matrix": [5, 3], "x": 8, "y": 3, "encoder": 3}, + {"label": "ch2_key(0,7)", "matrix": [7, 0], "x": 12, "y": 0}, + {"label": "ch2_key(1,7)", "matrix": [7, 1], "x": 12, "y": 1}, + {"label": "ch2_key(2,7)", "matrix": [7, 2], "x": 12, "y": 2}, + {"label": "ch2_key(3,7)", "matrix": [7, 3], "x": 12, "y": 3}, + {"label": "ch2_key(4,7)", "matrix": [7, 4], "x": 12, "y": 4}, + {"label": "ch2_key(5,7)", "matrix": [7, 5], "x": 13, "y": 0}, + {"label": "ch2_key(6,7)", "matrix": [7, 6], "x": 13, "y": 1}, + {"label": "ch2_key(7,7)", "matrix": [7, 7], "x": 13, "y": 2}, + {"label": "ch2_key(8,7)", "matrix": [7, 8], "x": 13, "y": 3}, + {"label": "ch2_key(9,7)", "matrix": [7, 9], "x": 13, "y": 4}, + {"label": "ch2_key(0,8)", "matrix": [8, 0], "x": 14, "y": 0}, + {"label": "ch2_key(1,8)", "matrix": [8, 1], "x": 14, "y": 1}, + {"label": "ch2_key(2,8)", "matrix": [8, 2], "x": 14, "y": 2}, + {"label": "ch2_key(3,8)", "matrix": [8, 3], "x": 14, "y": 3}, + {"label": "ch2_key(4,8)", "matrix": [8, 4], "x": 14, "y": 4}, + {"label": "ch2_key(5,8)", "matrix": [8, 5], "x": 15, "y": 0}, + {"label": "ch2_key(6,8)", "matrix": [8, 6], "x": 15, "y": 1}, + {"label": "ch2_key(7,8)", "matrix": [8, 7], "x": 15, "y": 2}, + {"label": "ch2_key(8,8)", "matrix": [8, 8], "x": 15, "y": 3}, + {"label": "ch2_key(9,8)", "matrix": [8, 9], "x": 15, "y": 4}, + {"label": "ch2_key(0,9)", "matrix": [9, 0], "x": 16, "y": 0}, + {"label": "ch2_key(1,9)", "matrix": [9, 1], "x": 16, "y": 1}, + {"label": "ch2_key(2,9)", "matrix": [9, 2], "x": 16, "y": 2}, + {"label": "ch2_key(3,9)", "matrix": [9, 3], "x": 16, "y": 3}, + {"label": "ch2_key(4,9)", "matrix": [9, 4], "x": 16, "y": 4}, + {"label": "ch2_key(5,9)", "matrix": [9, 5], "x": 17, "y": 0}, + {"label": "ch2_key(6,9)", "matrix": [9, 6], "x": 17, "y": 1}, + {"label": "ch2_key(7,9)", "matrix": [9, 7], "x": 17, "y": 2}, + {"label": "ch2_key(8,9)", "matrix": [9, 8], "x": 17, "y": 3}, + {"label": "ch2_key(9,9)", "matrix": [9, 9], "x": 17, "y": 4}, + {"label": "ch2_key(0,10)", "matrix": [10, 0], "x": 18, "y": 0}, + {"label": "ch2_key(1,10)", "matrix": [10, 1], "x": 18, "y": 1}, + {"label": "ch2_key(2,10)", "matrix": [10, 2], "x": 18, "y": 2}, + {"label": "ch2_key(3,10)", "matrix": [10, 3], "x": 18, "y": 3}, + {"label": "ch2_key(4,10)", "matrix": [10, 4], "x": 18, "y": 4}, + {"label": "ch2_key(5,10)", "matrix": [10, 5], "x": 19, "y": 0}, + {"label": "ch2_key(6,10)", "matrix": [10, 6], "x": 19, "y": 1}, + {"label": "ch2_key(7,10)", "matrix": [10, 7], "x": 19, "y": 2}, + {"label": "ch2_key(8,10)", "matrix": [10, 8], "x": 19, "y": 3}, + {"label": "ch2_key(9,10)", "matrix": [10, 9], "x": 19, "y": 4}, + {"label": "e5", "matrix": [11, 0], "x": 20, "y": 0, "encoder": 4}, + {"label": "e6", "matrix": [11, 1], "x": 20, "y": 1, "encoder": 5}, + {"label": "e7", "matrix": [11, 2], "x": 20, "y": 2, "encoder": 6}, + {"label": "e8", "matrix": [11, 3], "x": 20, "y": 3, "encoder": 7}, + {"label": "ch3_key(0,13)", "matrix": [13, 0], "x": 24, "y": 0}, + {"label": "ch3_key(1,13)", "matrix": [13, 1], "x": 24, "y": 1}, + {"label": "ch3_key(2,13)", "matrix": [13, 2], "x": 24, "y": 2}, + {"label": "ch3_key(3,13)", "matrix": [13, 3], "x": 24, "y": 3}, + {"label": "ch3_key(4,13)", "matrix": [13, 4], "x": 24, "y": 4}, + {"label": "ch3_key(5,13)", "matrix": [13, 5], "x": 25, "y": 0}, + {"label": "ch3_key(6,13)", "matrix": [13, 6], "x": 25, "y": 1}, + {"label": "ch3_key(7,13)", "matrix": [13, 7], "x": 25, "y": 2}, + {"label": "ch3_key(8,13)", "matrix": [13, 8], "x": 25, "y": 3}, + {"label": "ch3_key(9,13)", "matrix": [13, 9], "x": 25, "y": 4}, + {"label": "ch3_key(0,14)", "matrix": [14, 0], "x": 26, "y": 0}, + {"label": "ch3_key(1,14)", "matrix": [14, 1], "x": 26, "y": 1}, + {"label": "ch3_key(2,14)", "matrix": [14, 2], "x": 26, "y": 2}, + {"label": "ch3_key(3,14)", "matrix": [14, 3], "x": 26, "y": 3}, + {"label": "ch3_key(4,14)", "matrix": [14, 4], "x": 26, "y": 4}, + {"label": "ch3_key(5,14)", "matrix": [14, 5], "x": 27, "y": 0}, + {"label": "ch3_key(6,14)", "matrix": [14, 6], "x": 27, "y": 1}, + {"label": "ch3_key(7,14)", "matrix": [14, 7], "x": 27, "y": 2}, + {"label": "ch3_key(8,14)", "matrix": [14, 8], "x": 27, "y": 3}, + {"label": "ch3_key(9,14)", "matrix": [14, 9], "x": 27, "y": 4}, + {"label": "ch3_key(0,15)", "matrix": [15, 0], "x": 28, "y": 0}, + {"label": "ch3_key(1,15)", "matrix": [15, 1], "x": 28, "y": 1}, + {"label": "ch3_key(2,15)", "matrix": [15, 2], "x": 28, "y": 2}, + {"label": "ch3_key(3,15)", "matrix": [15, 3], "x": 28, "y": 3}, + {"label": "ch3_key(4,15)", "matrix": [15, 4], "x": 28, "y": 4}, + {"label": "ch3_key(5,15)", "matrix": [15, 5], "x": 29, "y": 0}, + {"label": "ch3_key(6,15)", "matrix": [15, 6], "x": 29, "y": 1}, + {"label": "ch3_key(7,15)", "matrix": [15, 7], "x": 29, "y": 2}, + {"label": "ch3_key(8,15)", "matrix": [15, 8], "x": 29, "y": 3}, + {"label": "ch3_key(9,15)", "matrix": [15, 9], "x": 29, "y": 4}, + {"label": "ch3_key(0,16)", "matrix": [16, 0], "x": 30, "y": 0}, + {"label": "ch3_key(1,16)", "matrix": [16, 1], "x": 30, "y": 1}, + {"label": "ch3_key(2,16)", "matrix": [16, 2], "x": 30, "y": 2}, + {"label": "ch3_key(3,16)", "matrix": [16, 3], "x": 30, "y": 3}, + {"label": "ch3_key(4,16)", "matrix": [16, 4], "x": 30, "y": 4}, + {"label": "ch3_key(5,16)", "matrix": [16, 5], "x": 31, "y": 0}, + {"label": "ch3_key(6,16)", "matrix": [16, 6], "x": 31, "y": 1}, + {"label": "ch3_key(7,16)", "matrix": [16, 7], "x": 31, "y": 2}, + {"label": "ch3_key(8,16)", "matrix": [16, 8], "x": 31, "y": 3}, + {"label": "ch3_key(9,16)", "matrix": [16, 9], "x": 31, "y": 4}, + {"label": "e9", "matrix": [17, 0], "x": 32, "y": 0, "encoder": 8}, + {"label": "e10", "matrix": [17, 1], "x": 32, "y": 1, "encoder": 9}, + {"label": "e11", "matrix": [17, 2], "x": 32, "y": 2, "encoder": 10}, + {"label": "e12", "matrix": [17, 3], "x": 32, "y": 3, "encoder": 11}, + {"label": "ch4_key(0,19)", "matrix": [19, 0], "x": 36, "y": 0}, + {"label": "ch4_key(1,19)", "matrix": [19, 1], "x": 36, "y": 1}, + {"label": "ch4_key(2,19)", "matrix": [19, 2], "x": 36, "y": 2}, + {"label": "ch4_key(3,19)", "matrix": [19, 3], "x": 36, "y": 3}, + {"label": "ch4_key(4,19)", "matrix": [19, 4], "x": 36, "y": 4}, + {"label": "ch4_key(5,19)", "matrix": [19, 5], "x": 37, "y": 0}, + {"label": "ch4_key(6,19)", "matrix": [19, 6], "x": 37, "y": 1}, + {"label": "ch4_key(7,19)", "matrix": [19, 7], "x": 37, "y": 2}, + {"label": "ch4_key(8,19)", "matrix": [19, 8], "x": 37, "y": 3}, + {"label": "ch4_key(9,19)", "matrix": [19, 9], "x": 37, "y": 4}, + {"label": "ch4_key(0,20)", "matrix": [20, 0], "x": 38, "y": 0}, + {"label": "ch4_key(1,20)", "matrix": [20, 1], "x": 38, "y": 1}, + {"label": "ch4_key(2,20)", "matrix": [20, 2], "x": 38, "y": 2}, + {"label": "ch4_key(3,20)", "matrix": [20, 3], "x": 38, "y": 3}, + {"label": "ch4_key(4,20)", "matrix": [20, 4], "x": 38, "y": 4}, + {"label": "ch4_key(5,20)", "matrix": [20, 5], "x": 39, "y": 0}, + {"label": "ch4_key(6,20)", "matrix": [20, 6], "x": 39, "y": 1}, + {"label": "ch4_key(7,20)", "matrix": [20, 7], "x": 39, "y": 2}, + {"label": "ch4_key(8,20)", "matrix": [20, 8], "x": 39, "y": 3}, + {"label": "ch4_key(9,20)", "matrix": [20, 9], "x": 39, "y": 4}, + {"label": "ch4_key(0,21)", "matrix": [21, 0], "x": 40, "y": 0}, + {"label": "ch4_key(1,21)", "matrix": [21, 1], "x": 40, "y": 1}, + {"label": "ch4_key(2,21)", "matrix": [21, 2], "x": 40, "y": 2}, + {"label": "ch4_key(3,21)", "matrix": [21, 3], "x": 40, "y": 3}, + {"label": "ch4_key(4,21)", "matrix": [21, 4], "x": 40, "y": 4}, + {"label": "ch4_key(5,21)", "matrix": [21, 5], "x": 41, "y": 0}, + {"label": "ch4_key(6,21)", "matrix": [21, 6], "x": 41, "y": 1}, + {"label": "ch4_key(7,21)", "matrix": [21, 7], "x": 41, "y": 2}, + {"label": "ch4_key(8,21)", "matrix": [21, 8], "x": 41, "y": 3}, + {"label": "ch4_key(9,21)", "matrix": [21, 9], "x": 41, "y": 4}, + {"label": "ch4_key(0,22)", "matrix": [22, 0], "x": 42, "y": 0}, + {"label": "ch4_key(1,22)", "matrix": [22, 1], "x": 42, "y": 1}, + {"label": "ch4_key(2,22)", "matrix": [22, 2], "x": 42, "y": 2}, + {"label": "ch4_key(3,22)", "matrix": [22, 3], "x": 42, "y": 3}, + {"label": "ch4_key(4,22)", "matrix": [22, 4], "x": 42, "y": 4}, + {"label": "ch4_key(5,22)", "matrix": [22, 5], "x": 43, "y": 0}, + {"label": "ch4_key(6,22)", "matrix": [22, 6], "x": 43, "y": 1}, + {"label": "ch4_key(7,22)", "matrix": [22, 7], "x": 43, "y": 2}, + {"label": "ch4_key(8,22)", "matrix": [22, 8], "x": 43, "y": 3}, + {"label": "ch4_key(9,22)", "matrix": [22, 9], "x": 43, "y": 4}, + {"label": "e13", "matrix": [23, 0], "x": 44, "y": 0, "encoder": 12}, + {"label": "e14", "matrix": [23, 1], "x": 44, "y": 1, "encoder": 13}, + {"label": "e15", "matrix": [23, 2], "x": 44, "y": 2, "encoder": 14}, + {"label": "e16", "matrix": [23, 3], "x": 44, "y": 3, "encoder": 15} + ] + }, + "LAYOUT_basic": { + "layout": [ + {"label": "ch1_key(0,1)", "matrix": [1, 0], "x": 0, "y": 0}, + {"label": "ch1_key(1,1)", "matrix": [1, 1], "x": 0, "y": 1}, + {"label": "ch1_key(2,1)", "matrix": [1, 2], "x": 0, "y": 2}, + {"label": "ch1_key(3,1)", "matrix": [1, 3], "x": 0, "y": 3}, + {"label": "ch1_key(4,1)", "matrix": [1, 4], "x": 0, "y": 4}, + {"label": "ch1_key(5,1)", "matrix": [1, 5], "x": 1, "y": 0}, + {"label": "ch1_key(6,1)", "matrix": [1, 6], "x": 1, "y": 1}, + {"label": "ch1_key(7,1)", "matrix": [1, 7], "x": 1, "y": 2}, + {"label": "ch1_key(8,1)", "matrix": [1, 8], "x": 1, "y": 3}, + {"label": "ch1_key(9,1)", "matrix": [1, 9], "x": 1, "y": 4}, + {"label": "ch1_key(0,2)", "matrix": [2, 0], "x": 2, "y": 0}, + {"label": "ch1_key(1,2)", "matrix": [2, 1], "x": 2, "y": 1}, + {"label": "ch1_key(2,2)", "matrix": [2, 2], "x": 2, "y": 2}, + {"label": "ch1_key(3,2)", "matrix": [2, 3], "x": 2, "y": 3}, + {"label": "ch1_key(4,2)", "matrix": [2, 4], "x": 2, "y": 4}, + {"label": "ch1_key(5,2)", "matrix": [2, 5], "x": 3, "y": 0}, + {"label": "ch1_key(6,2)", "matrix": [2, 6], "x": 3, "y": 1}, + {"label": "ch1_key(7,2)", "matrix": [2, 7], "x": 3, "y": 2}, + {"label": "ch1_key(8,2)", "matrix": [2, 8], "x": 3, "y": 3}, + {"label": "ch1_key(9,2)", "matrix": [2, 9], "x": 3, "y": 4}, + {"label": "ch1_key(0,3)", "matrix": [3, 0], "x": 4, "y": 0}, + {"label": "ch1_key(1,3)", "matrix": [3, 1], "x": 4, "y": 1}, + {"label": "ch1_key(2,3)", "matrix": [3, 2], "x": 4, "y": 2}, + {"label": "ch1_key(3,3)", "matrix": [3, 3], "x": 4, "y": 3}, + {"label": "ch1_key(4,3)", "matrix": [3, 4], "x": 4, "y": 4}, + {"label": "ch1_key(5,3)", "matrix": [3, 5], "x": 5, "y": 0}, + {"label": "ch1_key(6,3)", "matrix": [3, 6], "x": 5, "y": 1}, + {"label": "ch1_key(7,3)", "matrix": [3, 7], "x": 5, "y": 2}, + {"label": "ch1_key(8,3)", "matrix": [3, 8], "x": 5, "y": 3}, + {"label": "ch1_key(0,4)", "matrix": [4, 0], "x": 6, "y": 0}, + {"label": "ch1_key(1,4)", "matrix": [4, 1], "x": 6, "y": 1}, + {"label": "ch1_key(2,4)", "matrix": [4, 2], "x": 6, "y": 2}, + {"label": "ch1_key(3,4)", "matrix": [4, 3], "x": 6, "y": 3}, + {"label": "e1", "matrix": [5, 0], "x": 8, "y": 0, "encoder": 0}, + {"label": "ch2_key(0,7)", "matrix": [7, 0], "x": 12, "y": 0}, + {"label": "ch2_key(1,7)", "matrix": [7, 1], "x": 12, "y": 1}, + {"label": "ch2_key(2,7)", "matrix": [7, 2], "x": 12, "y": 2}, + {"label": "ch2_key(3,7)", "matrix": [7, 3], "x": 12, "y": 3}, + {"label": "ch2_key(5,7)", "matrix": [7, 5], "x": 13, "y": 0}, + {"label": "ch2_key(6,7)", "matrix": [7, 6], "x": 13, "y": 1}, + {"label": "ch2_key(7,7)", "matrix": [7, 7], "x": 13, "y": 2}, + {"label": "ch2_key(8,7)", "matrix": [7, 8], "x": 13, "y": 3}, + {"label": "ch2_key(0,8)", "matrix": [8, 0], "x": 14, "y": 0}, + {"label": "ch2_key(1,8)", "matrix": [8, 1], "x": 14, "y": 1}, + {"label": "ch2_key(2,8)", "matrix": [8, 2], "x": 14, "y": 2}, + {"label": "ch2_key(3,8)", "matrix": [8, 3], "x": 14, "y": 3}, + {"label": "ch2_key(4,8)", "matrix": [8, 4], "x": 14, "y": 4}, + {"label": "ch2_key(5,8)", "matrix": [8, 5], "x": 15, "y": 0}, + {"label": "ch2_key(6,8)", "matrix": [8, 6], "x": 15, "y": 1}, + {"label": "ch2_key(7,8)", "matrix": [8, 7], "x": 15, "y": 2}, + {"label": "ch2_key(8,8)", "matrix": [8, 8], "x": 15, "y": 3}, + {"label": "ch2_key(9,8)", "matrix": [8, 9], "x": 15, "y": 4}, + {"label": "ch2_key(0,9)", "matrix": [9, 0], "x": 16, "y": 0}, + {"label": "ch2_key(1,9)", "matrix": [9, 1], "x": 16, "y": 1}, + {"label": "ch2_key(2,9)", "matrix": [9, 2], "x": 16, "y": 2}, + {"label": "ch2_key(3,9)", "matrix": [9, 3], "x": 16, "y": 3}, + {"label": "ch2_key(4,9)", "matrix": [9, 4], "x": 16, "y": 4}, + {"label": "ch2_key(5,9)", "matrix": [9, 5], "x": 17, "y": 0}, + {"label": "ch2_key(6,9)", "matrix": [9, 6], "x": 17, "y": 1}, + {"label": "ch2_key(7,9)", "matrix": [9, 7], "x": 17, "y": 2}, + {"label": "ch2_key(8,9)", "matrix": [9, 8], "x": 17, "y": 3}, + {"label": "ch2_key(9,9)", "matrix": [9, 9], "x": 17, "y": 4}, + {"label": "ch2_key(0,10)", "matrix": [10, 0], "x": 18, "y": 0}, + {"label": "ch2_key(1,10)", "matrix": [10, 1], "x": 18, "y": 1}, + {"label": "ch2_key(2,10)", "matrix": [10, 2], "x": 18, "y": 2}, + {"label": "ch2_key(3,10)", "matrix": [10, 3], "x": 18, "y": 3}, + {"label": "ch2_key(4,10)", "matrix": [10, 4], "x": 18, "y": 4} + ] + } + } +} diff --git a/keyboards/cue2keys/keymaps/default/keymap.c b/keyboards/cue2keys/keymaps/default/keymap.c new file mode 100644 index 00000000000..c999e1365f2 --- /dev/null +++ b/keyboards/cue2keys/keymaps/default/keymap.c @@ -0,0 +1,327 @@ +// Copyright 2022 QMK +// SPDX-License-Identifier: GPL-3.0-or-later + +#include QMK_KEYBOARD_H +#include + +enum layer_names { _BASE, _NUM, _FN, _MOUSE }; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_all( + // clang-format off + + // channel 1 + //// keys * 8 + KC_ESC, KC_TAB, KC_LEFT_CTRL, KC_LEFT_SHIFT, LT(_NUM, KC_GRAVE), + KC_1, KC_Q, KC_A, KC_Z, KC_LEFT_PAREN, + KC_2,KC_W, KC_S, KC_X, KC_RIGHT_PAREN, + KC_3, KC_E, KC_D, KC_C, KC_LEFT_ALT, + KC_4, KC_R, KC_F, KC_V, LGUI_T(KC_LANGUAGE_2), + KC_5, KC_T, KC_G, KC_B, KC_NO, + KC_SPACE, KC_BACKSPACE, _______, _______, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + //// rotary encoders * 4 + KC_TAB, KC_TAB, KC_TAB, KC_TAB, + + // channel 2 + //// keys * 8 + KC_ENTER, KC_TAB, _______,LCTL(KC_LEFT_BRACKET), KC_NO, + KC_6, KC_Y, KC_H, KC_N, KC_NO, + KC_7,KC_U, KC_J, KC_M, KC_LANGUAGE_1, + KC_8, KC_I, KC_K, KC_COMMA, _______, + KC_9, KC_O, KC_L, KC_DOT, KC_LEFT_BRACKET, + KC_0, KC_P, KC_SEMICOLON, KC_SLASH, KC_RIGHT_BRACKET, + KC_MINUS, KC_BACKSLASH, KC_QUOTE, _______, KC_EQUAL, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + //// rotary encoders * 4 + KC_TAB, KC_TAB, KC_TAB, KC_TAB, + + // channel 3 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, KC_7, KC_4, KC_1, _______, + _______, KC_8, KC_5, KC_2, KC_0, + _______, KC_9, KC_6, KC_3, _______, + _______, KC_MINUS, KC_PPLS, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 4 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, QK_MOUSE_WHEEL_UP, _______, _______, + _______, _______, QK_MOUSE_WHEEL_DOWN, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______ + // clang-format on + ), + [_NUM] = LAYOUT_all( + // clang-format off + + // channel 1 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, KC_EXCLAIM, KC_CIRCUMFLEX, MO(_FN), + _______, _______, KC_AT, KC_AMPERSAND, _______, + _______, _______, KC_HASH, KC_ASTERISK, _______, + _______, _______, KC_DOLLAR, _______, _______, + _______, _______, KC_PERCENT, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 2 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, KC_7, KC_4, KC_1, _______, + _______, KC_8, KC_5, KC_2, KC_0, + _______, KC_9, KC_6, KC_3, KC_LEFT, + _______, KC_MINUS, KC_PPLS, KC_UP, KC_DOWN, + _______, _______, _______, _______, KC_RIGHT, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 3 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 4 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______ + // clang-format on + + ), + [_FN] = LAYOUT_all( + // clang-format off + + // channel 1 + //// keys * 8 + QK_BOOT, QK_CLEAR_EEPROM, QK_REBOOT, _______, _______, + QK_KB_15, QK_KB_10, QK_KB_5, QK_KB_0, _______, + QK_KB_16, QK_KB_11, QK_KB_6, QK_KB_1, _______, + QK_KB_17, QK_KB_12, QK_KB_7, QK_KB_2, _______, + QK_KB_18, QK_KB_13, QK_KB_8, QK_KB_3, _______, + QK_KB_19, QK_KB_14, QK_KB_9, QK_KB_4, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 2 + //// keys * 8 + _______, _______, _______, _______, _______, + QK_KB_20, _______, _______, _______, _______, + QK_KB_21, KC_F7, KC_F4, KC_F1, _______, + QK_KB_22, KC_F8, KC_F5, KC_F2, KC_F10, + QK_KB_23, KC_F9, KC_F6, KC_F3, _______, + QK_KB_24, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 3 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 4 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______ + // clang-format on + + ), + [_MOUSE] = LAYOUT_all( + // clang-format off + + // channel 1 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, DRAG_SCROLL, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, QK_MOUSE_WHEEL_UP, _______, _______, + _______, _______, QK_MOUSE_WHEEL_DOWN, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 2 + //// keys * 8 + QK_MOUSE_BUTTON_4, QK_MOUSE_BUTTON_3, QK_MOUSE_BUTTON_2, QK_MOUSE_BUTTON_1, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 3 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______, + + // channel 4 + //// keys * 8 + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + //// rotary encoders * 4 + _______, _______, _______, _______ + // clang-format on + ), +}; + +#ifdef ENCODER_MAP_ENABLE +const uint16_t PROGMEM + encoder_map[][NUM_ENCODERS] + [NUM_DIRECTIONS] = { + + [_BASE] = + { + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + }, + [_NUM] = + { + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + }, + [_FN] = + { + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + }, + [_MOUSE] = + { + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + }, + +}; +#endif + +#ifdef POINTING_DEVICE_ENABLE +void pointing_device_init_user(void) { + set_auto_mouse_layer(_MOUSE); +} +#endif diff --git a/keyboards/cue2keys/keymaps/default/rules.mk b/keyboards/cue2keys/keymaps/default/rules.mk new file mode 100644 index 00000000000..ee325681483 --- /dev/null +++ b/keyboards/cue2keys/keymaps/default/rules.mk @@ -0,0 +1 @@ +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/cue2keys/keymaps/default_5x4/keymap.c b/keyboards/cue2keys/keymaps/default_5x4/keymap.c new file mode 100644 index 00000000000..3b662980f4e --- /dev/null +++ b/keyboards/cue2keys/keymaps/default_5x4/keymap.c @@ -0,0 +1,20 @@ +// Copyright 2022 QMK +// SPDX-License-Identifier: GPL-3.0-or-later + +#include QMK_KEYBOARD_H +#include + +enum layer_names { _BASE }; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {[_BASE] = LAYOUT_5x4( + // clang-format off + KC_MINUS, KC_PLUS, KC_PLUS, KC_ENTER, KC_ENTER, + KC_ASTERISK, KC_9, KC_6, KC_3, KC_0, + KC_SLASH, KC_8, KC_5, KC_2, KC_0, + KC_NUM_LOCK, KC_7, KC_4, KC_1, KC_DEL + // clang-format on + )}; + +#ifdef ENCODER_MAP_ENABLE +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {[_BASE] = {}}; +#endif diff --git a/keyboards/cue2keys/keymaps/default_5x4/rules.mk b/keyboards/cue2keys/keymaps/default_5x4/rules.mk new file mode 100644 index 00000000000..ee325681483 --- /dev/null +++ b/keyboards/cue2keys/keymaps/default_5x4/rules.mk @@ -0,0 +1 @@ +ENCODER_MAP_ENABLE = yes diff --git a/keyboards/cue2keys/keymaps/default_basic/keymap.c b/keyboards/cue2keys/keymaps/default_basic/keymap.c new file mode 100644 index 00000000000..19b1356d3f5 --- /dev/null +++ b/keyboards/cue2keys/keymaps/default_basic/keymap.c @@ -0,0 +1,211 @@ +// Copyright 2022 QMK +// SPDX-License-Identifier: GPL-3.0-or-later + +#include QMK_KEYBOARD_H +#include + +enum layer_names { _BASE, _NUM, _FN, _MOUSE }; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [_BASE] = LAYOUT_basic( + // clang-format off + + // channel 1 + //// key5 * 5, key4 * 2 + KC_ESC, KC_TAB, KC_LEFT_CTRL, KC_LEFT_SHIFT, LT(_NUM, KC_GRAVE), + KC_1, KC_Q, KC_A, KC_Z, KC_LEFT_PAREN, + KC_2,KC_W, KC_S, KC_X, KC_RIGHT_PAREN, + KC_3, KC_E, KC_D, KC_C, KC_LEFT_ALT, + KC_4, KC_R, KC_F, KC_V, LGUI_T(KC_LANGUAGE_2), + KC_5, KC_T, KC_G, KC_B, + KC_SPACE, KC_BACKSPACE, _______, _______, + //// rotary encoders * 1 + KC_TAB, + + // channel 2 + //// key4 * 2, key5 * 5 + KC_ENTER, KC_TAB, _______, LCTL(KC_LEFT_BRACKET), + KC_6, KC_Y, KC_H, KC_N, + KC_7, KC_U, KC_J, KC_M, KC_LANGUAGE_1, + KC_8, KC_I, KC_K, KC_COMMA, _______, + KC_9, KC_O, KC_L, KC_DOT, KC_LEFT_BRACKET, + KC_0, KC_P, KC_SEMICOLON, KC_SLASH, KC_RIGHT_BRACKET, + KC_MINUS, KC_BACKSLASH, KC_QUOTE, _______, KC_EQUAL + + // clang-format on + ), + [_NUM] = LAYOUT_basic( + // clang-format off + + // channel 1 + //// key5 * 5, key4 * 2 + _______, _______, _______, _______, _______, + _______, _______, KC_EXCLAIM, KC_CIRCUMFLEX, MO(_FN), + _______, _______, KC_AT, KC_AMPERSAND, _______, + _______, _______, KC_HASH, KC_ASTERISK, _______, + _______, _______, KC_DOLLAR, _______, _______, + _______, _______, KC_PERCENT, _______, + _______, _______, _______, _______, + //// rotary encoders * 1 + _______, + + // channel 2 + //// key4 * 2, key5 * 5 + _______, _______, _______, _______, + _______, _______, _______, _______, + _______, KC_7, KC_4, KC_1, _______, + _______, KC_8, KC_5, KC_2, KC_0, + _______, KC_9, KC_6, KC_3, KC_LEFT, + _______, KC_MINUS, KC_PPLS, KC_UP, KC_DOWN, + _______, _______, _______, _______, KC_RIGHT + + // clang-format on + ), + [_FN] = LAYOUT_basic( + // clang-format off + + // channel 1 + //// key5 * 5, key4 * 2 + QK_BOOT, QK_CLEAR_EEPROM, QK_REBOOT, _______, _______, + QK_KB_15, QK_KB_10, QK_KB_5, QK_KB_0, _______, + QK_KB_16, QK_KB_11, QK_KB_6, QK_KB_1, _______, + QK_KB_17, QK_KB_12, QK_KB_7, QK_KB_2, _______, + QK_KB_18, QK_KB_13, QK_KB_8, QK_KB_3, _______, + QK_KB_19, QK_KB_14, QK_KB_9, QK_KB_4, + _______, _______, _______, _______, + + //// rotary encoders * 1 + _______, + + // channel 2 + //// key4 * 2, key5 * 5 + _______, _______, _______, _______, + QK_KB_20, _______, _______, _______, + QK_KB_21, KC_F7, KC_F4, KC_F1, _______, + QK_KB_22, KC_F8, KC_F5, KC_F2, KC_F10, + QK_KB_23, KC_F9, KC_F6, KC_F3, _______, + QK_KB_24, _______, _______, _______, _______, + _______, _______, _______, _______, _______ + + // clang-format on + ), + [_MOUSE] = LAYOUT_basic( + // clang-format off + + // channel 1 + //// key5 * 5, key4 * 2 + _______, _______, _______, _______, _______, + _______, _______, DRAG_SCROLL, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, QK_MOUSE_WHEEL_UP, _______, _______, + _______, _______, QK_MOUSE_WHEEL_DOWN, _______, _______, + _______, _______, _______, _______, + _______, _______, _______, _______, + + //// rotary encoders * 1 + _______, + + // channel 2 + //// key4 * 2, key5 * 5 + QK_MOUSE_BUTTON_4, QK_MOUSE_BUTTON_3, QK_MOUSE_BUTTON_2, QK_MOUSE_BUTTON_1, + _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______ + + // clang-format on + ), +}; + +#ifdef ENCODER_MAP_ENABLE +const uint16_t PROGMEM + encoder_map[][NUM_ENCODERS] + [NUM_DIRECTIONS] = { + + [_BASE] = + { + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + ENCODER_CCW_CW(KC_PGDN, KC_PGUP), + }, + [_NUM] = + { + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + }, + [_FN] = + { + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + }, + [_MOUSE] = + { + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + ENCODER_CCW_CW(_______, _______), + }, + +}; +#endif + +#ifdef POINTING_DEVICE_ENABLE +void pointing_device_init_user(void) { + set_auto_mouse_layer(_MOUSE); +} +#endif diff --git a/keyboards/cue2keys/mcuconf.h b/keyboards/cue2keys/mcuconf.h new file mode 100644 index 00000000000..9802dd9762b --- /dev/null +++ b/keyboards/cue2keys/mcuconf.h @@ -0,0 +1,16 @@ +// Copyright 2025 esplo +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include_next + +#define RP2040_MCUCONF + +#undef RP_I2C_USE_I2C0 +#define RP_I2C_USE_I2C0 FALSE +#undef RP_I2C_USE_I2C1 +#define RP_I2C_USE_I2C1 TRUE + +#define RP_I2C_BUSY_TIMEOUT 50 +#define RP_I2C_ADDRESS_MODE_10BIT FALSE diff --git a/keyboards/cue2keys/readme.md b/keyboards/cue2keys/readme.md new file mode 100644 index 00000000000..2e91fb3352b --- /dev/null +++ b/keyboards/cue2keys/readme.md @@ -0,0 +1,27 @@ +# cue2keys + +![cue2keys](https://i.imgur.com/hUCVD23.jpeg) + +A keyboard that achieves flexible placement and configuration by combining modules as building blocks. + +- Keyboard Maintainer: [esplo](https://github.com/esplo) +- Hardware Supported: Cue2Keys PCB +- Hardware Availability: [official website](https://cue2keys.esplo.net/), [online store](https://c2k.booth.pm/items/6659174) + +Make example for this keyboard (after setting up your build environment): + + make cue2keys:default + +Flashing example for this keyboard: + + make cue2keys:default:flash + +See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). + +## Bootloader + +Enter the bootloader in 3 ways: + +- **Physical reset button (connected)**: Briefly double press the RST button on the PCB +- **Physical reset button (disconnected)**: press and hold the BS button on the PCB, then connect this to the PC +- **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available diff --git a/keyboards/cue2keys/rules.mk b/keyboards/cue2keys/rules.mk new file mode 100644 index 00000000000..4c2e1e365f7 --- /dev/null +++ b/keyboards/cue2keys/rules.mk @@ -0,0 +1,10 @@ +I2C_DRIVER_REQUIRED = yes +LIB_SRC += i2clib.c + +LIB_SRC += kb_config.c + +POINTING_DEVICE_ENABLE = yes +POINTING_DEVICE_DRIVER = custom +LIB_SRC += drivers/modular_adns5050.c + +LIB_SRC += drivers/encoder_dynamic_res.c