Added snap click, per-key/mixed rgb, custom debounce, wireless config feature

This commit is contained in:
lokher
2025-05-30 23:55:10 +08:00
parent b507ea2216
commit c9049679ac
81 changed files with 3696 additions and 251 deletions
@@ -1,4 +1,20 @@
/* Copyright 2023~2025 @ Keychron (https://www.keychron.com)
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "quantum.h"
#include "wireless.h"
#include "indicator.h"
@@ -1,4 +1,4 @@
/* Copyright 2022 @ lokher (https://www.keychron.com)
/* Copyright 2023~2025 @ lokher (https://www.keychron.com)
*
* 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
@@ -0,0 +1,20 @@
/* Copyright 2024 @ Keychron (https://www.keychron.com)
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#define EECONFIG_SIZE_WIRELESS_CONFIG 4 //sizeof(backlit_disable_time) + sizeof (connected_idle_time)
+14 -7
View File
@@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2023~2025 @ lokher (https://www.keychron.com)
*
* 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
@@ -60,6 +60,8 @@ enum {
BACKLIGHT_ON_UNCONNECTED = 0x02,
};
extern uint16_t backlit_disable_time;
static indicator_config_t pairing_config = INDICATOR_CONFIG_PARING;
static indicator_config_t connected_config = INDICATOR_CONFIG_CONNECTD;
static indicator_config_t reconnecting_config = INDICATOR_CONFIG_RECONNECTING;
@@ -201,12 +203,13 @@ inline void indicator_disable(void) {
LED_DRIVER_DISABLE_NOEEPROM();
}
void indicator_set_backlit_timeout(uint32_t time) {
LED_DRIVER_DISABLE_TIMEOUT_SET(time);
void indicator_reset_backlit_time(void) {
LED_DRIVER_DISABLE_TIME_RESET();
}
static inline void indicator_reset_backlit_time(void) {
LED_DRIVER_DISABLE_TIME_RESET();
void indicator_set_backlit_timeout(uint32_t time) {
LED_DRIVER_DISABLE_TIMEOUT_SET(time);
indicator_reset_backlit_time();
}
bool indicator_is_enabled(void) {
@@ -443,7 +446,7 @@ void indicator_set(wt_state_t state, uint8_t host_index) {
indicator_timer_cb((void *)&indicator_config.type);
}
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
indicator_set_backlit_timeout(DECIDE_TIME(CONNECTED_BACKLIGHT_DISABLE_TIMEOUT * 1000, indicator_config.duration));
indicator_set_backlit_timeout(DECIDE_TIME(backlit_disable_time * 1000, indicator_config.duration));
#endif
break;
@@ -541,6 +544,9 @@ void indicator_battery_low_enable(bool enable) {
} else {
rtc_time = 0;
bat_low_ind_state = 0;
# if defined(BAT_LOW_LED_PIN)
writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
# endif
# if defined(SPACE_KEY_LOW_BAT_IND)
indicator_eeconfig_reload();
if (!LED_DRIVER_IS_ENABLED()) indicator_disable();
@@ -552,7 +558,8 @@ void indicator_battery_low_enable(bool enable) {
void indicator_battery_low(void) {
#if defined(BAT_LOW_LED_PIN) || defined(SPACE_KEY_LOW_BAT_IND)
if (bat_low_ind_state) {
if ((bat_low_ind_state & 0x0F) <= (LOW_BAT_LED_BLINK_TIMES) && timer_elapsed32(bat_low_backlit_indicator) > (LOW_BAT_LED_BLINK_PERIOD)) {
if ((bat_low_ind_state & 0x0F) <= (LOW_BAT_LED_BLINK_TIMES) &&
timer_elapsed32(bat_low_backlit_indicator) > (LOW_BAT_LED_BLINK_PERIOD)) {
if (bat_low_ind_state & 0x80) {
bat_low_ind_state &= 0x7F;
bat_low_ind_state++;
@@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2023~2025 @ lokher (https://www.keychron.com)
*
* 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
@@ -101,7 +101,7 @@ typedef struct {
void indicator_init(void);
void indicator_set(wt_state_t state, uint8_t host_index);
void indicator_set_backlit_timeout(uint32_t time);
void indicator_backlight_timer_reset(bool enable);
void indicator_reset_backlit_time(void);
bool indicator_hook_key(uint16_t keycode);
void indicator_enable(void);
void indicator_disable(void);
@@ -1,4 +1,4 @@
/* Copyright 2022 @ Keychron (https://www.keychron.com)
/* Copyright 2022~2025 @ Keychron (https://www.keychron.com)
*
* 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
@@ -32,6 +32,7 @@ bool firstDisconnect = true;
static uint32_t pairing_key_timer;
static uint8_t host_idx = 0;
extern uint32_t connected_idle_time;
bool process_record_keychron_wireless(uint16_t keycode, keyrecord_t *record) {
static uint8_t host_idx;
@@ -84,7 +85,7 @@ void lkbt51_param_init(void) {
// clang-format off
/* Set bluetooth parameters */
module_param_t param = {.event_mode = 0x02,
.connected_idle_timeout = 7200,
.connected_idle_timeout = connected_idle_time,
.pairing_timeout = 180,
.pairing_mode = 0,
.reconnect_timeout = 5,
+24 -4
View File
@@ -194,6 +194,11 @@ static inline void lpm_wakeup(void) {
halInit();
#if defined(DIP_SWITCH_PINS)
/* Init dip switch as early as possible, and read it later. */
dip_switch_init();
#endif
#ifdef ENCODER_ENABLE
encoder_cb_init();
#endif
@@ -227,15 +232,30 @@ static inline void lpm_wakeup(void) {
#endif
#if defined(DIP_SWITCH_PINS)
dip_switch_init();
dip_switch_read(true);
#endif
/* Call debounce_free() to avoiding memory leak of debounce_counters as debounce_init()
invoked in matrix_init() alloc new memory to debounce_counters */
debounce_free();
matrix_init();
#ifdef ENABLE_RGB_MATRIX_PIXEL_RAIN
extern void PIXEL_RAIN_init(void);
PIXEL_RAIN_init();
#endif
#ifdef ENABLE_RGB_MATRIX_PIXEL_FLOW
extern void PIXEL_FLOW_init(void);
PIXEL_FLOW_init();
#endif
#ifdef ENABLE_RGB_MATRIX_PIXEL_FRACTAL
extern void PIXEL_FRACTAL_init(void);
PIXEL_FRACTAL_init();
#endif
#if defined(DIP_SWITCH_PINS)
dip_switch_read(true);
#endif
}
void lpm_task(void) {
+118 -2
View File
@@ -24,6 +24,8 @@
#include "rtc_timer.h"
#include "keychron_wireless_common.h"
#include "keychron_task.h"
#include "wireless_config.h"
#include "keychron_raw_hid.h"
extern uint8_t pairing_indication;
extern host_driver_t chibios_driver;
@@ -39,6 +41,9 @@ static wt_state_t wireless_state = WT_RESET;
static bool pincodeEntry = false;
uint8_t wireless_report_protocol = true;
uint16_t backlit_disable_time = CONNECTED_BACKLIGHT_DISABLE_TIMEOUT;
uint16_t connected_idle_time = CONNECTED_IDLE_TIME;
/* declarations */
uint8_t wreless_keyboard_leds(void);
void wireless_send_keyboard(report_keyboard_t *report);
@@ -55,6 +60,8 @@ wireless_event_t wireless_event_queue[WT_EVENT_QUEUE_SIZE];
uint8_t wireless_event_queue_head;
uint8_t wireless_event_queue_tail;
bool wireless_lpm_set(uint8_t *data);
void wireless_event_queue_init(void) {
// Initialise the event queue
memset(&wireless_event_queue, 0, sizeof(wireless_event_queue));
@@ -82,6 +89,41 @@ static inline bool wireless_event_dequeue(wireless_event_t *event) {
return true;
}
#if defined(EECONFIG_BASE_WIRELESS_CONFIG)
void wireless_config_reset(void) {
uint8_t data[4] = { 0 };
uint16_t backlit_disable_time = CONNECTED_BACKLIGHT_DISABLE_TIMEOUT;
uint16_t connected_idle_time = CONNECTED_IDLE_TIME;
memcpy(&data[0], &backlit_disable_time, sizeof(backlit_disable_time));
memcpy(&data[2], &connected_idle_time, sizeof(connected_idle_time));
wireless_lpm_set(data);
}
void wireless_config_load(void) {
uint8_t offset = 0;
eeprom_read_block(&backlit_disable_time, (uint8_t *)(EECONFIG_BASE_WIRELESS_CONFIG+offset), sizeof(backlit_disable_time));
offset += sizeof(backlit_disable_time);
eeprom_read_block(&connected_idle_time, (uint8_t *)(EECONFIG_BASE_WIRELESS_CONFIG+offset), sizeof(connected_idle_time));
if (backlit_disable_time == 0)
backlit_disable_time = CONNECTED_BACKLIGHT_DISABLE_TIMEOUT;
else if (backlit_disable_time < 5 ) backlit_disable_time = 5;
if (connected_idle_time == 0)
connected_idle_time = CONNECTED_IDLE_TIME;
else if (connected_idle_time < 30 ) connected_idle_time = 30;
}
void wireless_config_save(void) {
uint8_t offset = 0;
eeprom_update_block(&backlit_disable_time, (uint8_t *)(EECONFIG_BASE_WIRELESS_CONFIG+offset), sizeof(backlit_disable_time));
offset += sizeof(backlit_disable_time);
eeprom_update_block(&connected_idle_time, (uint8_t *)(EECONFIG_BASE_WIRELESS_CONFIG+offset), sizeof(connected_idle_time));
}
#endif
/*
* Bluetooth init.
*/
@@ -102,6 +144,10 @@ void wireless_init(void) {
#if HAL_USE_RTC
rtc_timer_init();
#endif
#if defined(EECONFIG_BASE_WIRELESS_CONFIG)
wireless_config_load();
#endif
}
/*
@@ -253,9 +299,10 @@ static void wireless_enter_disconnected(uint8_t host_idx, uint8_t reason) {
indicator_set(WT_SUSPEND, host_idx);
} else {
indicator_set(wireless_state, host_idx);
#if defined(RGB_MATRIX) || defined(LED_MATRIX)
if (reason && (get_transport() & TRANSPORT_WIRELESS))
#if defined(RGB_MATRIX_ENABLE) || defined(LED_MATRIX_ENABLE)
if (reason && (get_transport() & TRANSPORT_WIRELESS)) {
indicator_set_backlit_timeout(DISCONNECTED_BACKLIGHT_DISABLE_TIMEOUT*1000);
}
#endif
}
@@ -539,3 +586,72 @@ bool process_record_wireless(uint16_t keycode, keyrecord_t *record) {
return true;
}
#if defined(EECONFIG_BASE_WIRELESS_CONFIG)
bool wireless_lpm_get(uint8_t *data) {
uint8_t index = 1;
memcpy(&data[index], &backlit_disable_time, sizeof(backlit_disable_time));
index += sizeof(backlit_disable_time);
memcpy(&data[index], &connected_idle_time, sizeof(connected_idle_time));
return true;
}
bool wireless_lpm_set(uint8_t *data) {
uint8_t index = 0;
memcpy(&backlit_disable_time, &data[index], sizeof(backlit_disable_time));
index += sizeof(backlit_disable_time);
memcpy(&connected_idle_time, &data[index], sizeof(connected_idle_time));
if (backlit_disable_time < 5 || connected_idle_time < 60) {
wireless_config_load();
return false;
}
wireless_config_save();
// Reset backlight timeout
if ((get_transport() & TRANSPORT_WIRELESS) && wireless_state == WT_CONNECTED)
{
indicator_set_backlit_timeout(backlit_disable_time*1000);
indicator_reset_backlit_time();
// Wiggle mouse to reset bluetooth module timer
mousekey_on(KC_MS_LEFT);
mousekey_send();
wait_ms(10);
mousekey_on(KC_MS_RIGHT);
mousekey_send();
wait_ms(10);
mousekey_off((KC_MS_RIGHT));
mousekey_send();
wait_ms(10);
}
// Update bluetooth module param
lkbt51_param_init();
return true;
}
void wireless_raw_hid_rx(uint8_t *data, uint8_t length) {
uint8_t cmd = data[1];
bool success = true;
switch (cmd) {
case WIRELESS_LPM_GET:
success = wireless_lpm_get(&data[2]);
break;
case WIRELESS_LPM_SET:
success = wireless_lpm_set(&data[2]);
break;
default:
data[0] = 0xFF;
break;
}
data[2] = success ? 0 : 1;
}
#endif
@@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2023~2025 @ lokher (https://www.keychron.com)
*
* 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
@@ -67,6 +67,8 @@ typedef struct {
extern void register_wt_tasks(void);
void wireless_init(void);
void wireless_config_reset(void);
void wireless_set_transport(wt_func_t *transport);
void wireless(void);
@@ -99,3 +101,6 @@ wt_state_t wireless_get_state(void);
void wireless_low_battery_shutdown(void);
bool process_record_wireless(uint16_t keycode, keyrecord_t *record);
void wireless_raw_hid_rx(uint8_t *data, uint8_t length);
@@ -1,4 +1,4 @@
OPT_DEFS += -DLK_WIRELESS_ENABLE
OPT_DEFS += -DLK_WIRELESS_ENABLE -DWIRELESS_CONFIG_ENABLE
OPT_DEFS += -DNO_USB_STARTUP_CHECK
OPT_DEFS += -DCORTEX_ENABLE_WFI_IDLE=TRUE
@@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2023~2025 @ lokher (https://www.keychron.com)
*
* 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
@@ -25,12 +25,7 @@
#define P2P4G_HOST_DEVICES_COUNT 1
// Uint: Second
#ifndef DISCONNECTED_BACKLIGHT_OFF_DELAY_TIME
# define DISCONNECTED_BACKLIGHT_OFF_DELAY_TIME 40
#endif
// Uint: Second, the timer restarts on key activities.
#ifndef CONNECTED_BACKLIGHT_OFF_DELAY_TIME
# define CONNECTED_BACKLIGHT_OFF_DELAY_TIME 600
#ifndef CONNECTED_IDLE_TIME
# define CONNECTED_IDLE_TIME 7200
#endif
@@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2023~2025 @ lokher (https://www.keychron.com)
*
* 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