Added Lemokey P1 Pro

This commit is contained in:
lokher 2024-08-21 11:20:44 +08:00
parent b71b83f882
commit 62030ee6bb
72 changed files with 2876 additions and 507 deletions

2
.gitmodules vendored
View File

@ -4,7 +4,7 @@
branch = master
[submodule "lib/chibios-contrib"]
path = lib/chibios-contrib
url = https://github.com/qmk/ChibiOS-Contrib
url = https://github.com/Keychron/ChibiOS-Contrib
branch = master
[submodule "lib/googletest"]
path = lib/googletest

View File

@ -1,4 +1,4 @@
/* Copyright 2021 @ Keychron (https://www.keychron.com)
/* Copyright 2022~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
@ -176,6 +176,7 @@ bool process_record_factory_test(uint16_t keycode, keyrecord_t *record) {
factory_reset_timer = 0;
}
break;
case KC_Z:
#if defined(FN_Z_KEY)
case FN_Z_KEY:
@ -195,6 +196,7 @@ bool process_record_factory_test(uint16_t keycode, keyrecord_t *record) {
}
}
break;
#if defined(BL_CYCLE_KEY) || defined(BL_CYCLE_KEY_2)
# if defined(BL_CYCLE_KEY)
case BL_CYCLE_KEY:

View File

@ -1,4 +1,4 @@
/* Copyright 2022 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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,7 +25,6 @@ void factory_test_init(void);
bool factory_test_indicator(void);
#endif
//void process_record_factory_test(uint16_t keycode, keyrecord_t *record);
bool factory_reset_indicating(void);
void factory_test_task(void);
void factory_test_rx(uint8_t *data, uint8_t length);

View File

@ -1,4 +1,4 @@
/* Copyright 2022 @ Keychron (https://www.keychron.com)
/* Copyright 2022~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
@ -34,6 +34,16 @@ static key_combination_t key_comb_list[3] = {
{2, {KC_LWIN, KC_L}},
};
#if defined(WIN_LOCK_HOLD_TIME)
static uint32_t winlock_timer = 0;
#endif
void gui_toggle(void) {
keymap_config.no_gui = !keymap_config.no_gui;
eeconfig_update_keymap(keymap_config.raw);
led_update_kb(host_keyboard_led_state());
}
bool process_record_lemokey_common(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_TASK_VIEW:
@ -49,6 +59,7 @@ bool process_record_lemokey_common(uint16_t keycode, keyrecord_t *record) {
}
}
return false; // Skip all further processing of this key
case KC_MCTRL:
if (record->event.pressed) {
register_code(KC_MISSION_CONTROL);
@ -56,13 +67,15 @@ bool process_record_lemokey_common(uint16_t keycode, keyrecord_t *record) {
unregister_code(KC_MISSION_CONTROL);
}
return false; // Skip all further processing of this key
case KC_LANCH:
case KC_LNPAD:
if (record->event.pressed) {
register_code(KC_LAUNCHPAD);
} else {
unregister_code(KC_LAUNCHPAD);
}
return false; // Skip all further processing of this key
case KC_LOPTN:
case KC_ROPTN:
case KC_LCMMD:
@ -73,59 +86,73 @@ bool process_record_lemokey_common(uint16_t keycode, keyrecord_t *record) {
unregister_code(mac_keycode[keycode - KC_LOPTN]);
}
return false; // Skip all further processing of this key
#if defined(WIN_LOCK_HOLD_TIME) || defined(WIN_LOCK_LED_PIN) || defined(WINLOCK_LED_LIST)
case GU_TOGG:
# if defined(WIN_LOCK_HOLD_TIME)
if (record->event.pressed) {
winlock_timer = timer_read32();
} else {
winlock_timer = 0;
}
# else
if (record->event.pressed) gui_toggle();
# endif
return false;
#endif
default:
return true; // Process all other keycodes normally
}
}
void lemokey_common_task(void) {}
void lemokey_common_task(void) {
#if defined(WIN_LOCK_HOLD_TIME)
if (winlock_timer) {
if (keymap_config.no_gui) {
winlock_timer = 0;
gui_toggle();
} else if (timer_elapsed32(winlock_timer) > WIN_LOCK_HOLD_TIME) {
winlock_timer = 0;
gui_toggle();
}
}
#endif
}
#ifdef ENCODER_ENABLE
static void encoder0_pad_cb(void *param) {
(void)param;
encoder_inerrupt_read(0);
static void encoder_pad_cb(void *param) {
uint8_t index = (uint32_t)param;
encoder_inerrupt_read(index);
}
void encoder_cb_init(void) {
pin_t encoders_pad_a[] = ENCODERS_PAD_A;
pin_t encoders_pad_b[] = ENCODERS_PAD_B;
palEnableLineEvent(encoders_pad_a[0], PAL_EVENT_MODE_BOTH_EDGES);
palEnableLineEvent(encoders_pad_b[0], PAL_EVENT_MODE_BOTH_EDGES);
palSetLineCallback(encoders_pad_a[0], encoder0_pad_cb, NULL);
palSetLineCallback(encoders_pad_b[0], encoder0_pad_cb, NULL);
}
#endif
//__attribute__((weak)) bool raw_hid_receive_lemokey(uint8_t *data, uint8_t length) { return true; }
bool via_command_kb(uint8_t *data, uint8_t length) {
// if (!raw_hid_receive_lemokey(data, length))
// return false;
switch (data[0]) {
#ifdef LK_WIRELESS_ENABLE
case 0xAA:
lkbt51_dfu_rx(data, length);
break;
#endif
#ifdef FACTORY_TEST_ENABLE
case 0xAB:
factory_test_rx(data, length);
break;
#endif
default:
return false;
}
return true;
}
#if !defined(VIA_ENABLE)
void raw_hid_receive(uint8_t *data, uint8_t length) {
switch (data[0]) {
case RAW_HID_CMD:
via_command_kb(data, length);
break;
for (uint32_t i=0; i<NUM_ENCODERS; i++)
{
palEnableLineEvent(encoders_pad_a[i], PAL_EVENT_MODE_BOTH_EDGES);
palEnableLineEvent(encoders_pad_b[i], PAL_EVENT_MODE_BOTH_EDGES);
palSetLineCallback(encoders_pad_a[i], encoder_pad_cb, (void*)i);
palSetLineCallback(encoders_pad_b[i], encoder_pad_cb, (void*)i);
}
}
#endif
__attribute__((weak)) void suspend_power_down_lemokey(void) {}
__attribute__((weak)) void suspend_wakeup_init_lemokey(void) {}
void suspend_power_down_kb(void) {
#ifdef WIN_LOCK_LED_PIN
writePin(WIN_LOCK_LED_PIN, !WIN_LOCK_LED_ON_LEVEL);
#endif
suspend_power_down_lemokey();
suspend_power_down_user();
}
void suspend_wakeup_init_kb(void) {
#ifdef WIN_LOCK_LED_PIN
if (keymap_config.no_gui) writePin(WIN_LOCK_LED_PIN, !WIN_LOCK_LED_ON_LEVEL);
#endif
suspend_wakeup_init_lemokey();
suspend_wakeup_init_user();
}

View File

@ -1,4 +1,4 @@
/* Copyright 2022 @ Keychron (https://www.lemokey.com)
/* Copyright 2022~2024 @ Keychron (https://www.lemokey.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
@ -24,7 +24,7 @@ enum {
KC_FILE_EXPLORER,
KC_LOCK_SCREEN, // Lock screen
KC_MCTRL,
KC_LANCH,
KC_LNPAD,
KC_LOPTN,
KC_ROPTN,
KC_LCMMD,
@ -35,15 +35,16 @@ enum {
BT_HST3,
P2P4G,
BAT_LVL,
__LK_WIRELESS_ENABLE_END = BAT_LVL,
#else
BT_HST1 = _______,
BT_HST2 = _______,
BT_HST3 = _______,
P2P4G = _______,
BAT_LVL = _______,
__LK_WIRELESS_ENABLE_END = KC_LOCK_SCREEN,
#endif
NEW_SAFE_RANGE,
NEW_SAFE_RANGE = __LK_WIRELESS_ENABLE_END + 1,
};
#define KC_TASK KC_TASK_VIEW

View File

@ -1,9 +1,10 @@
OPT_DEFS += -DFACTORY_TEST_ENABLE
OPT_DEFS += -DFACTORY_TEST_ENABLE -DAPDAPTIVE_NKRO_ENABLE
LEMOKEY_COMMON_DIR = common
SRC += \
$(LEMOKEY_COMMON_DIR)/lemokey_task.c \
$(LEMOKEY_COMMON_DIR)/lemokey_common.c \
$(LEMOKEY_COMMON_DIR)/lemokey_raw_hid.c \
$(LEMOKEY_COMMON_DIR)/factory_test.c
VPATH += $(TOP_DIR)/keyboards/lemokey/$(LEMOKEY_COMMON_DIR)

View File

@ -0,0 +1,120 @@
/* 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/>.
*/
#include QMK_KEYBOARD_H
#include "lemokey_common.h"
#include "raw_hid.h"
#include "version.h"
#ifdef FACTORY_TEST_ENABLE
# include "factory_test.h"
#endif
#ifdef LK_WIRELESS_ENABLE
# include "lkbt51.h"
#endif
#ifdef ANANLOG_MATRIX
# include "analog_matrix.h"
#endif
#define PROTOCOL_VERSION 0x02
enum {
KC_GET_PROTOCOL_VERSION = 0xA0,
KC_GET_FIRMWARE_VERSION = 0xA1,
KC_GET_SUPPORT_FEATURE = 0xA2,
KC_GET_DEFAULT_LAYER = 0xA3,
};
enum {
FEATURE_DEFAULT_LAYER = 0x01 << 0,
FEATURE_BLUETOOTH = 0x01 << 1,
FEATURE_P2P4G = 0x01 << 2,
FEATURE_ANALOG_MATRIX = 0x01 << 3,
};
void get_support_feature(uint8_t *data) {
data[1] = FEATURE_DEFAULT_LAYER
#ifdef KC_BLUETOOTH_ENABLE
| FEATURE_BLUETOOTH
#endif
#ifdef LK_WIRELESS_ENABLE
| FEATURE_BLUETOOTH | FEATURE_P2P4G
#endif
#ifdef ANANLOG_MATRIX
| FEATURE_ANALOG_MATRIX
#endif
;
}
bool lemokey_raw_hid_rx(uint8_t *data, uint8_t length) {
switch (data[0]) {
case KC_GET_PROTOCOL_VERSION:
data[1] = PROTOCOL_VERSION;
break;
case KC_GET_FIRMWARE_VERSION: {
uint8_t i = 1;
data[i++] = 'v';
if ((DEVICE_VER & 0xF000) != 0) itoa((DEVICE_VER >> 12), (char *)&data[i++], 16);
itoa((DEVICE_VER >> 8) & 0xF, (char *)&data[i++], 16);
data[i++] = '.';
itoa((DEVICE_VER >> 4) & 0xF, (char *)&data[i++], 16);
data[i++] = '.';
itoa(DEVICE_VER & 0xF, (char *)&data[i++], 16);
data[i++] = ' ';
memcpy(&data[i], QMK_BUILDDATE, sizeof(QMK_BUILDDATE));
i += sizeof(QMK_BUILDDATE);
} break;
case KC_GET_SUPPORT_FEATURE:
get_support_feature(&data[1]);
break;
case KC_GET_DEFAULT_LAYER:
data[1] = get_highest_layer(default_layer_state);
break;
#ifdef ANANLOG_MATRIX
case 0xA9:
analog_matrix_rx(data, length);
return true;
#endif
#ifdef LK_WIRELESS_ENABLE
case 0xAA:
lkbt51_dfu_rx(data, length);
return true;
#endif
#ifdef FACTORY_TEST_ENABLE
case 0xAB:
factory_test_rx(data, length);
return true;
#endif
default:
return false;
}
raw_hid_send(data, length);
return true;
}
#if defined(VIA_ENABLE)
bool via_command_kb(uint8_t *data, uint8_t length) {
return lemokey_raw_hid_rx(data, length);
}
#else
void raw_hid_receive(uint8_t *data, uint8_t length) {
lemokey_raw_hid_rx(data, length);
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ Keychron (https://www.keychron.com)
/* Copyright 2022~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
@ -34,7 +34,6 @@ bool process_record_lemokey(uint16_t keycode, keyrecord_t *record) {
#ifdef FACTORY_TEST_ENABLE
if (!process_record_factory_test(keycode, record)) return false;
#endif
// extern bool process_record_lemokey_kb(uint16_t keycode, keyrecord_t *record);
if (!process_record_lemokey_kb(keycode, record)) return false;

View File

@ -1,4 +1,4 @@
/* Copyright 2022 @ Keychron (https://www.lemokey.com)
/* Copyright 2022~2024 @ Keychron (https://www.lemokey.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

View File

@ -1,4 +1,20 @@
/* Copyright 2022~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/>.
*/
#include "quantum.h"
#include "wireless.h"
#include "indicator.h"
@ -10,8 +26,6 @@
#endif
#include "eeprom.h"
#if (defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)) && defined(BAT_LEVEL_LED_LIST)
#ifndef BAT_LEVEL_GROWING_INTERVAL
# define BAT_LEVEL_GROWING_INTERVAL 150
#endif
@ -47,21 +61,64 @@ static uint8_t r, g, b;
extern indicator_config_t indicator_config;
extern backlight_state_t original_backlight_state;
#ifdef INDICATOR_LED_PINS
void bat_level_stop(void) {
pin_t bat_lvl_led_pin_list[] = INDICATOR_LED_PINS;
for (uint8_t i = 0; i < INDICATOR_LED_COUNT; i++) {
writePin(bat_lvl_led_pin_list[i], !LED_PIN_ON_STATE);
}
animation_state = BAT_LVL_ANI_NONE;
}
__attribute__((weak)) void bat_level_indication(uint8_t percentage) {
pin_t bat_lvl_led_pin_list[] = INDICATOR_LED_PINS;
uint8_t led_cnt = sizeof(bat_lvl_led_pin_list) / sizeof(bat_lvl_led_pin_list[0]);
bat_level_stop();
animation_state = BAT_LVL_ANI_BLINK_ON;
cur_percentage = 0;
time_interval = 3000;
if ((percentage / 10) >= 8)
cur_percentage = 4;
else if ((percentage / 10) >= 6)
cur_percentage = 3;
else if ((percentage / 10) >= 3)
cur_percentage = 2;
else
cur_percentage = 1;
for (uint8_t i = 0; i < cur_percentage && i < led_cnt; i++) {
writePin(bat_lvl_led_pin_list[i], LED_PIN_ON_STATE);
}
}
#endif
void bat_level_animiation_start(uint8_t percentage) {
/* Turn on backlight mode for indicator */
animation_state = BAT_LVL_ANI_GROWING;
bat_lvl_ani_timer_buffer = timer_read32();
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
indicator_enable();
animation_state = BAT_LVL_ANI_GROWING;
bat_percentage = percentage;
bat_lvl_ani_timer_buffer = timer_read32();
cur_percentage = 0;
time_interval = BAT_LEVEL_GROWING_INTERVAL;
# ifdef RGB_MATRIX_ENABLE
r = g = b = 255;
# endif
#else
bat_level_indication(percentage);
#endif
}
void bat_level_animiation_stop(void) {
#if !defined(LED_MATRIX_ENABLE) && !defined(RGB_MATRIX_ENABLE)
pin_t bat_lvl_led_pin_list[INDICATOR_LED_COUNT] = INDICATOR_LED_PINS;
for (uint8_t i = 0; i < INDICATOR_LED_COUNT; i++) {
writePin(bat_lvl_led_pin_list[i], !INDICATORS_LED_PIN_ON_STATE);
}
#endif
animation_state = BAT_LVL_ANI_NONE;
}
@ -124,10 +181,12 @@ void bat_level_animiation_update(void) {
case BAT_LVL_ANI_BLINK_ON:
animation_state = BAT_LVL_ANI_NONE;
#if defined(RGB_MATRIX_ENABLE) || defined(LED_MATRIX_ENABLE)
indicator_eeconfig_reload();
if (indicator_config.value == 0 && !LED_DRIVER_IS_ENABLED()) {
indicator_disable();
}
#endif
lpm_timer_reset();
break;
@ -140,8 +199,10 @@ void bat_level_animiation_update(void) {
void bat_level_animiation_task(void) {
if (animation_state && sync_timer_elapsed32(bat_lvl_ani_timer_buffer) > time_interval) {
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
bat_level_animiation_update();
}
}
#else
bat_level_stop();
#endif
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2022 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -21,3 +21,4 @@ void bat_level_animiation_stop(void);
bool bat_level_animiation_actived(void);
void bat_level_animiation_indicate(void);
void bat_level_animiation_task(void);
void bat_level_indication(uint8_t percentage);

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.lemokey.com)
/* Copyright 2022~2024 @ 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
@ -167,12 +167,7 @@ void battery_check_empty(void) {
if (voltage < EMPTY_VOLTAGE_VALUE) {
if (bat_empty <= BATTERY_EMPTY_COUNT) {
if (++bat_empty > BATTERY_EMPTY_COUNT) {
#ifdef BAT_LOW_LED_PIN
indicator_battery_low_enable(true);
#endif
#if defined(LOW_BAT_IND_INDEX)
indicator_battery_low_backlit_enable(true);
#endif
power_on_sample = VOLTAGE_POWER_ON_MEASURE_COUNT;
}
}
@ -229,11 +224,6 @@ void battery_task(void) {
if ((bat_empty || critical_low) && usb_power_connected()) {
bat_empty = false;
critical_low = false;
#ifdef BAT_LOW_LED_PIN
indicator_battery_low_enable(false);
#endif
#if defined(LOW_BAT_IND_INDEX)
indicator_battery_low_backlit_enable(false);
#endif
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.lemokey.com)
/* Copyright 2022~2024 @ 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
@ -15,6 +15,7 @@
*/
#pragma once
#include "config.h"
enum {
BAT_NOT_CHARGING = 0,
@ -54,7 +55,6 @@ void battery_calculate_voltage(bool vol_src_bt, uint16_t value);
void battery_set_voltage(uint16_t value);
uint16_t battery_get_voltage(void);
uint8_t battery_get_percentage(void);
void indicator_battery_low_enable(bool enable);
bool battery_is_empty(void);
bool battery_is_critical_low(void);
bool battery_power_on_sample(void);

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -28,7 +28,6 @@
# include "factory_test.h"
#endif
#include "lpm.h"
#include "lemokey_task.h"
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
# ifdef LED_MATRIX_ENABLE
@ -37,15 +36,16 @@
# ifdef RGB_MATRIX_ENABLE
# include "rgb_matrix.h"
# endif
# include "bat_level_animation.h"
# include "eeprom.h"
#endif
#include "bat_level_animation.h"
#define HOST_INDEX_MASK 0x0F
#define HOST_P2P4G 0x10
#define INDEX_MASK 0x0F
#define P24G_IND_MASK 0x10
#define USB_IND_MASK 0x20
#define LED_ON 0x80
// #define RGB_MATRIX_TIMEOUT_INFINITE 0xFFFFFFFF
#define IND_VAL_MASK (USB_IND_MASK | P24G_IND_MASK | INDEX_MASK)
#ifdef LED_MATRIX_ENABLE
# define DECIDE_TIME(t, duration) (duration == 0 ? LED_MATRIX_TIMEOUT_INFINITE : ((t > duration) ? t : duration))
#endif
@ -71,12 +71,7 @@ static uint16_t next_period;
static indicator_type_t type;
static uint32_t indicator_timer_buffer = 0;
#if defined(BAT_LOW_LED_PIN)
static uint32_t bat_low_pin_indicator = 0;
static uint32_t bat_low_blink_duration = 0;
#endif
#if defined(LOW_BAT_IND_INDEX)
#if defined(BAT_LOW_LED_PIN) || defined(SPACE_KEY_LOW_BAT_IND)
static uint32_t bat_low_backlit_indicator = 0;
static uint8_t bat_low_ind_state = 0;
static uint32_t rtc_time = 0;
@ -85,22 +80,13 @@ static uint32_t rtc_time = 0;
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
backlight_state_t original_backlight_state;
# ifdef BT_HOST_LED_MATRIX_LIST
static uint8_t bt_host_led_matrix_list[BT_HOST_DEVICES_COUNT] = BT_HOST_LED_MATRIX_LIST;
# ifdef BT_INDICATION_LED_LIST
static uint8_t bt_host_led_matrix_list[BT_HOST_DEVICES_COUNT] = BT_INDICATION_LED_LIST;
# endif
#endif
# ifdef P2P4G_HOST_LED_MATRIX_LIST
static uint8_t p2p4g_host_led_matrix_list[P2P4G_HOST_DEVICES_COUNT] = P2P4G_HOST_LED_MATRIX_LIST;
# endif
#endif
#ifdef BT_HOST_LED_PIN_LIST
static pin_t bt_led_pin_list[BT_HOST_DEVICES_COUNT] = BT_HOST_LED_PIN_LIST;
#endif
#ifdef P24G_HOST_LED_PIN_LIST
static pin_t p24g_led_pin_list[P24G_HOST_DEVICES_COUNT] = P24G_HOST_LED_PIN_LIST;
#ifdef BT_INDICATION_LED_PIN_LIST
static pin_t bt_led_pin_list[BT_HOST_DEVICES_COUNT] = BT_INDICATION_LED_PIN_LIST;
#endif
#ifdef LED_MATRIX_ENABLE
@ -111,9 +97,9 @@ static pin_t p24g_led_pin_list[P24G_HOST_DEVICES_COUNT] = P24G_HOST_LED_PIN_LIST
# define SET_ALL_LED_OFF() led_matrix_set_value_all(0)
# define SET_LED_OFF(idx) led_matrix_set_value(idx, 0)
# define SET_LED_ON(idx) led_matrix_set_value(idx, 255)
# define SET_LED_BT(idx) led_matrix_set_value(idx, 255)
# define SET_LED_P24G(idx) led_matrix_set_value(idx, 255)
# define SET_LED_LOW_BAT(idx) led_matrix_set_value(idx, 255)
# define SET_LED_BT SET_LED_ON
# define SET_LED_P24G SET_LED_ON
# define SET_LED_LOW_BAT SET_LED_ON
# define LED_DRIVER_IS_ENABLED led_matrix_is_enabled
# define LED_DRIVER_EECONFIG_RELOAD() \
eeprom_read_block(&led_matrix_eeconfig, EECONFIG_LED_MATRIX, sizeof(led_matrix_eeconfig)); \
@ -157,29 +143,41 @@ static pin_t p24g_led_pin_list[P24G_HOST_DEVICES_COUNT] = P24G_HOST_LED_PIN_LIST
# define LED_DRIVER_TIMEOUTED rgb_matrix_timeouted
#endif
#ifdef WINLOCK_LED_LIST
# define SET_LED_WINLOCK(idx) rgb_matrix_set_color(idx, 255, 0, 0)
#endif
bool LED_INDICATORS_KB(void);
void indicator_init(void) {
memset(&indicator_config, 0, sizeof(indicator_config));
#ifdef BT_HOST_LED_PIN_LIST
#ifdef BT_INDICATION_LED_PIN_LIST
for (uint8_t i = 0; i < BT_HOST_DEVICES_COUNT; i++) {
setPinOutput(bt_led_pin_list[i]);
writePin(bt_led_pin_list[i], !HOST_LED_PIN_ON_STATE);
writePin(bt_led_pin_list[i], !BT_INDICATION_LED_ON_STATE);
}
#endif
#ifdef P24G_HOST_LED_PIN_LIST
for (uint8_t i = 0; i < P24G_HOST_DEVICES_COUNT; i++) {
setPinOutput(p24g_led_pin_list[i]);
writePin(p24g_led_pin_list[i], !HOST_LED_PIN_ON_STATE);
}
#ifdef COMMON_BT_LED_PIN
setPinOutput(COMMON_BT_LED_PIN);
writePin(COMMON_BT_LED_PIN, !COMMON_BT_LED_PIN_ON_STATE);
#endif
#ifdef P24G_INDICATION_LED_PIN
setPinOutput(P24G_INDICATION_LED_PIN);
writePin(P24G_INDICATION_LED_PIN, !BT_INDICATION_LED_ON_STATE);
#endif
#ifdef BAT_LOW_LED_PIN
setPinOutput(BAT_LOW_LED_PIN);
writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
#endif
#ifdef WIN_LOCK_LED_PIN
setPinOutput(WIN_LOCK_LED_PIN);
writePin(WIN_LOCK_LED_PIN, keymap_config.no_gui);
#endif
}
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
@ -213,10 +211,7 @@ void indicator_eeconfig_reload(void) {
bool indicator_is_running(void) {
return
#if defined(BAT_LOW_LED_PIN)
bat_low_blink_duration ||
#endif
#if defined(LOW_BAT_IND_INDEX)
#if defined(BAT_LOW_LED_PIN) || defined(SPACE_KEY_LOW_BAT_IND)
bat_low_ind_state ||
#endif
!!indicator_config.value;
@ -253,7 +248,7 @@ static void indicator_timer_cb(void *arg) {
indicator_config.value |= LED_ON;
next_period = indicator_config.on_time;
} else {
indicator_config.value = indicator_config.value & 0x1F;
indicator_config.value = indicator_config.value & IND_VAL_MASK;
next_period = indicator_config.duration - indicator_config.on_time;
}
@ -268,7 +263,7 @@ static void indicator_timer_cb(void *arg) {
case INDICATOR_BLINK:
if (indicator_config.value) {
if (indicator_config.value & LED_ON) {
indicator_config.value = indicator_config.value & 0x1F;
indicator_config.value = indicator_config.value & IND_VAL_MASK;
next_period = indicator_config.off_time;
} else {
indicator_config.value |= LED_ON;
@ -289,32 +284,38 @@ static void indicator_timer_cb(void *arg) {
break;
}
#if defined(BT_HOST_LED_PIN_LIST) || defined(P24G_HOST_LED_PIN_LIST)
#if defined(BT_INDICATION_LED_PIN_LIST) || defined(P24G_INDICATION_LED_PIN) || defined(COMMON_BT_LED_PIN)
if (indicator_config.value) {
uint8_t idx = (indicator_config.value & HOST_INDEX_MASK) - 1;
pin_t *led_lin_list = NULL;
uint8_t led_count;
# if defined(P24G_HOST_LED_PIN_LIST)
if (indicator_config.value & HOST_P2P4G) {
if (idx < P24G_HOST_DEVICES_COUNT) led_lin_list = p24g_led_pin_list;
led_count = P24G_HOST_DEVICES_COUNT;
# if defined(P24G_INDICATION_LED_PIN)
if (indicator_config.value & P24G_IND_MASK) {
if ((indicator_config.value & LED_ON) && !time_up) {
writePin(P24G_INDICATION_LED_PIN, BT_INDICATION_LED_ON_STATE);
} else {
writePin(P24G_INDICATION_LED_PIN, !BT_INDICATION_LED_ON_STATE);
}
} else
# endif
{
if (idx < BT_HOST_DEVICES_COUNT) led_lin_list = bt_led_pin_list;
led_count = BT_HOST_DEVICES_COUNT;
uint8_t idx = (indicator_config.value & INDEX_MASK) - 1;
#ifdef BT_INDICATION_LED_PIN_LIST
for (uint8_t i = 0; i < BT_HOST_DEVICES_COUNT; i++) {
if (i != idx) writePin(bt_led_pin_list[idx], !BT_INDICATION_LED_ON_STATE);
}
for (uint8_t i = 0; i < led_count; i++) {
if (i != idx) writePin(led_lin_list[idx], !HOST_LED_PIN_ON_STATE);
}
if (led_lin_list) {
#endif
if ((indicator_config.value & LED_ON) && !time_up) {
writePin(led_lin_list[idx], HOST_LED_PIN_ON_STATE);
#ifdef BT_INDICATION_LED_PIN_LIST
writePin(bt_led_pin_list[idx], BT_INDICATION_LED_ON_STATE);
#endif
#ifdef COMMON_BT_LED_PIN
writePin(COMMON_BT_LED_PIN, COMMON_BT_LED_PIN_ON_STATE);
#endif
} else {
writePin(led_lin_list[idx], !HOST_LED_PIN_ON_STATE);
#ifdef BT_INDICATION_LED_PIN_LIST
writePin(bt_led_pin_list[idx], !BT_INDICATION_LED_ON_STATE);
#endif
#ifdef COMMON_BT_LED_PIN
writePin(COMMON_BT_LED_PIN, !COMMON_BT_LED_PIN_ON_STATE);
#endif
}
}
}
@ -322,7 +323,7 @@ static void indicator_timer_cb(void *arg) {
if (time_up) {
/* Set indicator to off on timeup, avoid keeping light up until next update in raindrop effect */
indicator_config.value = indicator_config.value & 0x1F;
indicator_config.value = indicator_config.value & IND_VAL_MASK;
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
LED_INDICATORS_KB();
#endif
@ -342,11 +343,18 @@ static void indicator_timer_cb(void *arg) {
void indicator_set(wt_state_t state, uint8_t host_index) {
if (get_transport() == TRANSPORT_USB) return;
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
static uint8_t pre_state = 0;
#endif
static uint8_t current_state = 0;
static uint8_t current_host = 0;
bool host_index_changed = false;
if (host_index == 24) host_index = HOST_P2P4G | 0x01;
if (host_index == P24G_HOST_INDEX)
host_index = P24G_IND_MASK | 0x01;
else if (host_index == USB_HOST_INDEX)
host_index = USB_IND_MASK | 0x01;
if (current_host != host_index && state != WT_DISCONNECTED) {
host_index_changed = true;
@ -354,6 +362,11 @@ void indicator_set(wt_state_t state, uint8_t host_index) {
}
if (current_state != state || host_index_changed || state == WT_RECONNECTING) {
// Some BT chips need to reset to enter sleep mode, ignore it.
if (current_state == WT_SUSPEND && state == WT_DISCONNECTED) return;
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
pre_state = current_state;
#endif
current_state = state;
} else {
return;
@ -366,15 +379,25 @@ void indicator_set(wt_state_t state, uint8_t host_index) {
indicator_enable();
indicator_reset_backlit_time();
#endif
#if defined(BT_INDICATION_LED_PIN_LIST)
for (uint8_t i = 0; i < BT_HOST_DEVICES_COUNT; i++)
writePin(bt_led_pin_list[i], !BT_INDICATION_LED_ON_STATE);
#endif
#if defined(P24G_INDICATION_LED_PIN)
writePin(P24G_INDICATION_LED_PIN, !BT_INDICATION_LED_ON_STATE);
#endif
#ifdef COMMON_BT_LED_PIN
writePin(COMMON_BT_LED_PIN, !COMMON_BT_LED_PIN_ON_STATE);
#endif
switch (state) {
case WT_DISCONNECTED:
#if defined(BT_HOST_LED_PIN_LIST)
if ((host_index & HOST_P2P4G) != HOST_P2P4G) writePin(bt_led_pin_list[(host_index & HOST_INDEX_MASK) - 1], !HOST_LED_PIN_ON_STATE);
#if defined(BT_INDICATION_LED_PIN_LIST)
if ((host_index & P24G_IND_MASK) != P24G_IND_MASK) writePin(bt_led_pin_list[(host_index & INDEX_MASK) - 1], !BT_INDICATION_LED_ON_STATE);
#endif
#if defined(P24G_HOST_LED_PIN_LIST)
if (host_index & HOST_P2P4G) writePin(p24g_led_pin_list[(host_index & HOST_INDEX_MASK) - 1], !HOST_LED_PIN_ON_STATE);
#if defined(P24G_INDICATION_LED_PIN)
writePin(P24G_INDICATION_LED_PIN, !BT_INDICATION_LED_ON_STATE);
#endif
INDICATOR_SET(disconnected);
@ -385,6 +408,11 @@ void indicator_set(wt_state_t state, uint8_t host_index) {
indicator_set_backlit_timeout(1000);
} else {
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
if (pre_state == WT_CONNECTED)
indicator_set_backlit_timeout(1000);
else
#endif
/* Set timer so that user has chance to turn on the backlight when is off */
indicator_set_backlit_timeout(DECIDE_TIME(DISCONNECTED_BACKLIGHT_DISABLE_TIMEOUT * 1000, indicator_config.duration));
}
@ -435,13 +463,18 @@ void indicator_set(wt_state_t state, uint8_t host_index) {
}
#endif
#if defined(BT_HOST_LED_PIN_LIST)
#if defined(BT_INDICATION_LED_PIN_LIST)
for (uint8_t i = 0; i < BT_HOST_DEVICES_COUNT; i++)
writePin(bt_led_pin_list[i], !HOST_LED_PIN_ON_STATE);
writePin(bt_led_pin_list[i], !BT_INDICATION_LED_ON_STATE);
#endif
#if defined(P24G_HOST_LED_PIN_LIST)
for (uint8_t i = 0; i < P24G_HOST_DEVICES_COUNT; i++)
writePin(p24g_led_pin_list[i], !HOST_LED_PIN_ON_STATE);
#if defined(P24G_INDICATION_LED_PIN)
writePin(P24G_INDICATION_LED_PIN, !BT_INDICATION_LED_ON_STATE);
#endif
#ifdef COMMON_BT_LED_PIN
writePin(COMMON_BT_LED_PIN, !COMMON_BT_LED_PIN_ON_STATE);
#endif
# if defined(BAT_LOW_LED_PIN)
writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
# endif
break;
@ -465,22 +498,11 @@ void indicator_stop(void) {
#endif
}
#ifdef BAT_LOW_LED_PIN
void indicator_battery_low_enable(bool enable) {
if (enable) {
if (bat_low_blink_duration == 0) {
bat_low_blink_duration = bat_low_pin_indicator = timer_read32();
} else
bat_low_blink_duration = timer_read32();
} else
writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
}
#endif
#if defined(LOW_BAT_IND_INDEX)
void indicator_battery_low_backlit_enable(bool enable) {
#if defined(BAT_LOW_LED_PIN) || defined(SPACE_KEY_LOW_BAT_IND)
if (enable) {
uint32_t t = rtc_timer_read_ms();
/* Check overflow */
if (rtc_time > t) {
if (bat_low_ind_state == 0)
@ -489,55 +511,62 @@ void indicator_battery_low_backlit_enable(bool enable) {
rtc_time += t;
}
}
/* Indicating at first time or after the interval */
if ((rtc_time == 0 || t - rtc_time > LOW_BAT_LED_TRIG_INTERVAL) && bat_low_ind_state == 0) {
bat_low_backlit_indicator = enable ? timer_read32() : 0;
rtc_time = rtc_timer_read_ms();
bat_low_ind_state = 1;
# if defined(SPACE_KEY_LOW_BAT_IND)
indicator_enable();
# endif
}
} else {
rtc_time = 0;
bat_low_ind_state = 0;
# if defined(SPACE_KEY_LOW_BAT_IND)
indicator_eeconfig_reload();
if (!LED_DRIVER_IS_ENABLED()) indicator_disable();
}
# endif
}
#endif
}
void indicator_battery_low(void) {
#ifdef BAT_LOW_LED_PIN
if (bat_low_pin_indicator && timer_elapsed32(bat_low_pin_indicator) > (LOW_BAT_LED_BLINK_PERIOD)) {
togglePin(BAT_LOW_LED_PIN);
bat_low_pin_indicator = timer_read32();
// Turn off low battery indication if we reach the duration
if (timer_elapsed32(bat_low_blink_duration) > LOW_BAT_LED_BLINK_DURATION && palReadLine(BAT_LOW_LED_PIN) != BAT_LOW_LED_PIN_ON_STATE) {
bat_low_blink_duration = bat_low_pin_indicator = 0;
}
}
#endif
#if defined(LOW_BAT_IND_INDEX)
#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 & 0x80) {
bat_low_ind_state &= 0x7F;
bat_low_ind_state++;
# if defined(BAT_LOW_LED_PIN)
writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
# endif
} else {
bat_low_ind_state |= 0x80;
# if defined(BAT_LOW_LED_PIN)
writePin(BAT_LOW_LED_PIN, BAT_LOW_LED_PIN_ON_STATE);
# endif
}
bat_low_backlit_indicator = timer_read32();
/* Restore backligth state */
if ((bat_low_ind_state & 0x0F) > (LOW_BAT_LED_BLINK_TIMES)) {
# 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)
# if defined(NUM_LOCK_INDEX) || defined(CAPS_LOCK_INDEX) || defined(SCROLL_LOCK_INDEX) || defined(COMPOSE_LOCK_INDEX) || defined(KANA_LOCK_INDEX)
if (LED_DRIVER_ALLOW_SHUTDOWN())
# endif
indicator_disable();
# endif
}
} else if ((bat_low_ind_state & 0x0F) > (LOW_BAT_LED_BLINK_TIMES)) {
# if defined(BAT_LOW_LED_PIN)
writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
# endif
bat_low_ind_state = 0;
lpm_timer_reset();
}
@ -546,9 +575,7 @@ void indicator_battery_low(void) {
}
void indicator_task(void) {
#if (defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)) && defined(BAT_LEVEL_LED_LIST)
bat_level_animiation_task();
#endif
if (indicator_config.value && timer_elapsed32(indicator_timer_buffer) >= next_period) {
indicator_timer_cb((void *)&type);
indicator_timer_buffer = timer_read32();
@ -592,6 +619,32 @@ __attribute__((weak)) void os_state_indicate(void) {
SET_LED_ON(KANA_LOCK_INDEX);
}
# endif
# if defined(WIN_LOCK_LED_PIN) || defined(WINLOCK_LED_LIST)
/* TODO: move to common.c */
if (keymap_config.no_gui && (((get_transport() & TRANSPORT_WIRELESS) && wireless_get_state() == WT_CONNECTED) || (get_transport() == TRANSPORT_USB && USBD1.state == USB_ACTIVE))) {
# ifdef WINLOCK_LED_LIST
if (keymap_config.no_gui) {
uint8_t led_list[] = WINLOCK_LED_LIST;
uint8_t led_cnt = ARRAY_SIZE(led_list);
for (uint8_t i = 0; i < led_cnt; i++) {
# if defined(DIM_WIN_LOCK)
SET_LED_OFF(led_list[i]);
# else
SET_LED_WINLOCK(led_list[i]);
# endif
}
}
# endif
# ifdef WIN_LOCK_LED_PIN
writePin(WIN_LOCK_LED_PIN, WIN_LOCK_LED_ON_LEVEL);
# endif
} else {
# ifdef WIN_LOCK_LED_PIN
writePin(WIN_LOCK_LED_PIN, !WIN_LOCK_LED_ON_LEVEL);
# endif
}
# endif
}
bool LED_INDICATORS_KB(void) {
@ -602,7 +655,6 @@ bool LED_INDICATORS_KB(void) {
return true;
}
# if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
if (battery_is_empty()) SET_ALL_LED_OFF();
# if defined(LOW_BAT_IND_INDEX)
if (bat_low_ind_state && (bat_low_ind_state & 0x0F) <= LOW_BAT_LED_BLINK_TIMES) {
@ -616,7 +668,7 @@ bool LED_INDICATORS_KB(void) {
}
}
# endif
# endif
# if (defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)) && defined(BAT_LEVEL_LED_LIST)
if (bat_level_animiation_actived()) {
bat_level_animiation_indicate();
@ -625,39 +677,40 @@ bool LED_INDICATORS_KB(void) {
static uint8_t last_host_index = 0xFF;
if (indicator_config.value) {
uint8_t host_index = indicator_config.value & HOST_INDEX_MASK;
uint8_t host_index = indicator_config.value & INDEX_MASK;
if (indicator_config.highlight) {
SET_ALL_LED_OFF();
} else if (last_host_index != host_index) {
if (indicator_config.value & HOST_P2P4G)
SET_LED_OFF(p2p4g_host_led_matrix_list[host_index - 1]);
# ifdef P24G_INDICATION_LED_INDEX
if (indicator_config.value & P24G_IND_MASK)
SET_LED_OFF(P24G_INDICATION_LED_INDEX);
else
# endif
SET_LED_OFF(bt_host_led_matrix_list[host_index - 1]);
last_host_index = host_index;
}
if (indicator_config.value & LED_ON) {
# ifdef P2P4G_HOST_LED_MATRIX_LIST
if (indicator_config.value & HOST_P2P4G)
SET_LED_P24G(p2p4g_host_led_matrix_list[host_index - 1]);
# ifdef P24G_INDICATION_LED_INDEX
if (indicator_config.value & P24G_IND_MASK)
SET_LED_P24G(P24G_INDICATION_LED_INDEX);
else
# endif
SET_LED_BT(bt_host_led_matrix_list[host_index - 1]);
} else {
# ifdef P2P4G_HOST_LED_MATRIX_LIST
if (indicator_config.value & HOST_P2P4G)
SET_LED_OFF(p2p4g_host_led_matrix_list[host_index - 1]);
# ifdef P24G_INDICATION_LED_INDEX
if (indicator_config.value & P24G_IND_MASK)
SET_LED_OFF(P24G_INDICATION_LED_INDEX);
else
# endif
SET_LED_OFF(bt_host_led_matrix_list[host_index - 1]);
}
} else
os_state_indicate();
} else
os_state_indicate();
}
if (get_transport() == TRANSPORT_USB) os_state_indicate();
if (!LED_INDICATORS_USER()) return true;
@ -686,10 +739,7 @@ bool led_update_kb(led_t led_state) {
}
void LED_NONE_INDICATORS_KB(void) {
# if defined(RGB_DISABLE_WHEN_USB_SUSPENDED)
if (get_transport() == TRANSPORT_USB && USB_DRIVER.state == USB_SUSPENDED) return;
# endif
# if defined(LED_DISABLE_WHEN_USB_SUSPENDED)
# if defined(RGB_DISABLE_WHEN_USB_SUSPENDED) || defined(LED_DISABLE_WHEN_USB_SUSPENDED)
if (get_transport() == TRANSPORT_USB && USB_DRIVER.state == USB_SUSPENDED) return;
# endif
@ -713,8 +763,11 @@ bool LED_DRIVER_ALLOW_SHUTDOWN(void) {
# if defined(KANA_LOCK_INDEX)
if (host_keyboard_led_state().kana) return false;
# endif
# if defined(WINLOCK_LED_LIST) && !defined(WIN_LOCK_LED_PIN)
if (keymap_config.no_gui && (wireless_get_state() == WT_CONNECTED || get_transport()==TRANSPORT_USB)) return false;
# endif
return true;
}
# endif
#endif

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -19,6 +19,9 @@
#include "config.h"
#include "wireless.h"
#define P24G_HOST_INDEX 24
#define USB_HOST_INDEX 34
/* Indication of pairing */
#ifndef INDICATOR_CONFIG_PARING
# define INDICATOR_CONFIG_PARING {INDICATOR_BLINK, 1000, 1000, 0, true, 0};
@ -41,45 +44,43 @@
/* Uint: Second */
#ifndef DISCONNECTED_BACKLIGHT_DISABLE_TIMEOUT
# define DISCONNECTED_BACKLIGHT_OFF_DELAY_TIME 40
# define DISCONNECTED_BACKLIGHT_DISABLE_TIMEOUT 40
#endif
/* Uint: Second, the timer restarts on key activities. */
#ifndef CONNECTED_BACKLIGHT_DISABLE_TIMEOUT
# define CONNECTED_BACKLIGHT_OFF_DELAY_TIME 600
# define CONNECTED_BACKLIGHT_DISABLE_TIMEOUT 600
#endif
#ifdef BAT_LOW_LED_PIN
/* Uint: ms */
#ifndef LOW_BAT_LED_BLINK_PERIOD
# define LOW_BAT_LED_BLINK_PERIOD 1000
#endif
# ifndef LOW_BAT_LED_BLINK_DURATION
# define LOW_BAT_LED_BLINK_DURATION 10000
# endif
#endif
#ifdef LOW_BAT_IND_INDEX
/* Uint: ms */
# ifndef LOW_BAT_LED_BLINK_PERIOD
# define LOW_BAT_LED_BLINK_PERIOD 500
# endif
#ifndef LOW_BAT_LED_BLINK_TIMES
# define LOW_BAT_LED_BLINK_TIMES 3
# define LOW_BAT_LED_BLINK_TIMES 5
#endif
#ifndef LOW_BAT_LED_TRIG_INTERVAL
# define LOW_BAT_LED_TRIG_INTERVAL 30000
#endif
#if ((defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)) && defined(LOW_BAT_IND_INDEX))
# define SPACE_KEY_LOW_BAT_IND
#endif
#if BT_HOST_MAX_COUNT > 6
# pragma error("HOST_COUNT max value is 6")
#endif
typedef enum { INDICATOR_NONE, INDICATOR_OFF, INDICATOR_ON, INDICATOR_ON_OFF, INDICATOR_BLINK, INDICATOR_LAST } indicator_type_t;
typedef enum {
INDICATOR_NONE,
INDICATOR_OFF,
INDICATOR_ON,
INDICATOR_ON_OFF,
INDICATOR_BLINK,
INDICATOR_LAST,
} indicator_type_t;
typedef struct PACKED {
indicator_type_t type;
@ -98,6 +99,7 @@ typedef struct PACKED {
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);
bool indicator_hook_key(uint16_t keycode);
void indicator_enable(void);
@ -106,12 +108,6 @@ void indicator_stop(void);
void indicator_eeconfig_reload(void);
bool indicator_is_enabled(void);
bool indicator_is_running(void);
#ifdef BAT_LOW_LED_PIN
void indicator_battery_low_enable(bool enable);
#endif
#if defined(LOW_BAT_IND_INDEX)
void indicator_battery_low_backlit_enable(bool enable);
#endif
void indicator_task(void);

View File

@ -1,4 +1,4 @@
/* Copyright 2021 @ Keychron (https://www.keychron.com)
/* Copyright 2022~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
@ -141,12 +141,12 @@ enum{
};
// clang-format on
static uint8_t payload[PACKET_MAX_LEN];
static uint8_t reg_offset = 0xFF;
static uint8_t expect_len = 22;
static uint16_t connection_interval = 1;
static uint32_t wake_time;
static uint32_t factory_reset = 0;
// clang-format off
wt_func_t wireless_transport = {
@ -164,6 +164,7 @@ wt_func_t wireless_transport = {
};
// clang-format on
#if defined(MCU_STM32)
/* Init SPI */
const SPIConfig spicfg = {
.circular = false,
@ -175,6 +176,18 @@ const SPIConfig spicfg = {
.cr1 = SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_BR_0,
.cr2 = 0U,
};
#endif
#if defined(WB32F3G71xx)
/* Init SPI */
const SPIConfig spicfg = {
.ssport = PAL_PORT(BLUETOOTH_INT_OUTPUT_PIN),
.sspad = PAL_PAD(BLUETOOTH_INT_OUTPUT_PIN),
.SPI_CPOL = 0U,
.SPI_CPHA = 0U,
.SPI_BaudRatePrescaler = 32U,
};
#endif
void lkbt51_init(bool wakeup_from_low_power_mode) {
#ifdef LKBT51_RESET_PIN
@ -187,14 +200,11 @@ void lkbt51_init(bool wakeup_from_low_power_mode) {
#endif
#if (HAL_USE_SPI == TRUE)
if (WT_DRIVER.state == SPI_UNINIT) {
setPinOutput(SPI_SCK_PIN);
writePinHigh(SPI_SCK_PIN);
palSetLineMode(SPI_SCK_PIN, PAL_MODE_ALTERNATE(SPI_CLK_PAL_MODE));
palSetLineMode(SPI_MISO_PIN, PAL_MODE_ALTERNATE(SPI_MISO_PAL_MODE));
palSetLineMode(SPI_MOSI_PIN, PAL_MODE_ALTERNATE(SPI_MOSI_PAL_MODE));
if (WT_DRIVER.state == SPI_UNINIT) {
if (wakeup_from_low_power_mode) {
spiInit();
return;
@ -367,9 +377,9 @@ void lkbt51_send_mouse(uint8_t* report) {
payload[i++] = LKBT51_CMD_SEND_MOUSE; // Cmd type
payload[i++] = report[1]; // Button
payload[i++] = report[2]; // X
payload[i++] = (report[2] & 0x80) ? 0xff : 0x00; // ckbt51 use 16bit report, set high byte
payload[i++] = (report[2] & 0x80) ? 0xff : 0x00; // lkbt51 use 16bit report, set high byte
payload[i++] = report[3]; // Y
payload[i++] = (report[3] & 0x80) ? 0xff : 0x00; // ckbt51 use 16bit report, set high byte
payload[i++] = (report[3] & 0x80) ? 0xff : 0x00; // lkbt51 use 16bit report, set high byte
payload[i++] = report[4]; // V wheel
payload[i++] = report[5]; // H wheel
@ -434,7 +444,8 @@ void lkbt51_disconnect(void) {
payload[i++] = LKBT51_CMD_DISCONNECT;
payload[i++] = 0; // Sleep mode
spiSelect(&SPID1);
if (WT_DRIVER.state != SPI_READY) spiStart(&WT_DRIVER, &spicfg);
wait_ms(30);
// spiUnselect(&SPID1);
wait_ms(70);
@ -539,6 +550,7 @@ void lkbt51_factory_reset(uint8_t p2p4g_clr_msk) {
lkbt51_wake();
lkbt51_send_cmd(payload, i, false, false);
factory_reset = timer_read32();
}
void lkbt51_int_pin_test(bool enable) {
@ -791,6 +803,10 @@ void lkbt51_task(void) {
break;
case LKBT51_DISCONNECTED:
event.evt_type = EVT_DISCONNECTED;
if (factory_reset && timer_elapsed32(factory_reset) < 3000) {
factory_reset = 0;
event.data = 1;
}
break;
case LKBT51_PINCODE_ENTRY:
event.evt_type = EVT_BT_PINCODE_ENTRY;

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ Keychron (https://www.keychron.com)
/* Copyright 2022~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
@ -18,18 +18,23 @@
#include "stdint.h"
#include "hal.h"
#ifndef WT_DRIVER
# define WT_DRIVER SPID1
#endif
#include "config.h"
// Error checking
#if HAL_USE_SPI == FALSE
# error "Please enable SPI to use LKBT51"
#endif
#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3
# error "WT driver activated but no SPI peripheral assigned"
#if defined(WB32F3G71xx)
# ifndef WT_DRIVER
# define WT_DRIVER SPIDQ
# endif
#endif
#if defined(MCU_STM32)
# ifndef WT_DRIVER
# define WT_DRIVER SPID1
# endif
#endif
#define PACKECT_HEADER_LEN 5

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -32,6 +32,7 @@
#include "lpm.h"
#include "transport.h"
#include "battery.h"
#include "bat_level_animation.h"
#include "report_buffer.h"
#include "lemokey_common.h"
@ -46,7 +47,6 @@ static matrix_row_t empty_matrix[MATRIX_ROWS] = {0};
pin_t pins_row[MATRIX_ROWS] = MATRIX_ROW_PINS;
pin_t pins_col[MATRIX_COLS] = MATRIX_COL_PINS;
;
__attribute__((weak)) void select_all_cols(void) {
for (uint8_t i = 0; i < MATRIX_COLS; i++) {
@ -77,45 +77,63 @@ void lpm_timer_stop(void) {
}
static inline bool lpm_any_matrix_action(void) {
#ifdef OPTICAL_SWITCH
bool any_key = false;
for (uint8_t i = 0; i < MATRIX_ROWS; i++)
if (matrix_get_row(i) != 0) {
any_key = true;
}
return any_key;
#else
return memcmp(matrix, empty_matrix, sizeof(empty_matrix));
#endif
}
__attribute__((weak)) void matrix_enter_low_power(void) {
/* Enable key matrix wake up */
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
if (pins_row[x] != NO_PIN) {
palEnableLineEvent(pins_row[x], PAL_EVENT_MODE_BOTH_EDGES);
}
}
select_all_cols();
}
__attribute__((weak)) void matrix_exit_low_power(void) {
/* Disable all wake up pins */
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
if (pins_row[x] != NO_PIN) {
palDisableLineEvent(pins_row[x]);
}
}
}
/* Implement of entering low power mode and wakeup varies per mcu or platform */
__attribute__((weak)) void enter_power_mode(pm_t mode) {}
__attribute__((weak)) bool usb_power_connected(void) {
#ifdef USB_POWER_SENSE_PIN
return readPin(USB_POWER_SENSE_PIN) == USB_POWER_CONNECTED_LEVEL;
#else
return true;
__attribute__((weak)) void lpm_pre_enter_low_power(void) {}
__attribute__((weak)) void lpm_enter_low_power_kb(void) {}
__attribute__((weak)) void lpm_enter_low_power(void) {
if (get_transport() == TRANSPORT_USB && !usb_power_connected()) {
#ifdef RGB_MATRIX_ENABLE
rgb_matrix_set_color_all(0, 0, 0);
rgb_matrix_driver.flush();
rgb_matrix_driver_shutdown();
#endif
#ifdef LED_MATRIX_ENABLE
led_matrix_set_value_all(0);
led_matrix_driver.flush();
led_matrix_driver_shutdown();
#endif
#ifdef LED_NUM_LOCK_PIN
writePin(LED_NUM_LOCK_PIN, !LED_PIN_ON_STATE);
#endif
#ifdef LED_CAPS_LOCK_PIN
writePin(LED_CAPS_LOCK_PIN, !LED_PIN_ON_STATE);
#endif
#ifdef BAT_LOW_LED_PIN
writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
#endif
#ifdef BT_INDICATION_LED_PIN_LIST
pin_t bt_led_pins[] = BT_INDICATION_LED_PIN_LIST;
for (uint8_t i = 0; i < sizeof(bt_led_pins) / sizeof(pin_t); i++)
writePin(bt_led_pins[i], !BT_INDICATION_LED_ON_STATE);
#endif
}
__attribute__((weak)) bool lpm_is_kb_idle(void) {
return true;
}
__attribute__((weak)) bool lpm_set(pm_t mode) {
return false;
}
bool pre_enter_low_power_mode(pm_t mode) {
#if defined(KEEP_USB_CONNECTION_IN_WIRELESS_MODE)
/* Don't enter low power mode if attached to the host */
if (mode > PM_SLEEP && usb_power_connected()) return false;
#endif
if (!lpm_set(mode)) return false;
#if defined(KEEP_USB_CONNECTION_IN_WIRELESS_MODE)
/* Usb unit is actived and running, stop and disconnect first */
usbStop(&USBD1);
@ -125,6 +143,13 @@ bool pre_enter_low_power_mode(pm_t mode) {
// PWR->CR2 &= ~PWR_CR2_USV; /*PWR_CR2_USV is available on STM32L4x2xx and STM32L4x3xx devices only. */
#endif
#if (HAL_USE_SPI == TRUE)
spiStop(&SPI_DRIVER);
palSetLineMode(SPI_SCK_PIN, PAL_MODE_INPUT_PULLDOWN);
palSetLineMode(SPI_MISO_PIN, PAL_MODE_INPUT_PULLDOWN);
palSetLineMode(SPI_MOSI_PIN, PAL_MODE_INPUT_PULLDOWN);
#endif
palEnableLineEvent(LKBT51_INT_INPUT_PIN, PAL_EVENT_MODE_FALLING_EDGE);
#ifdef USB_POWER_SENSE_PIN
palEnableLineEvent(USB_POWER_SENSE_PIN, PAL_EVENT_MODE_BOTH_EDGES);
@ -135,38 +160,7 @@ bool pre_enter_low_power_mode(pm_t mode) {
#ifdef BT_MODE_SELECT_PIN
palEnableLineEvent(BT_MODE_SELECT_PIN, PAL_EVENT_MODE_BOTH_EDGES);
#endif
#ifdef OPTICAL_SWITCH
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
if (pins_row[x] != NO_PIN) {
writePinLow(pins_row[x]);
}
}
for (uint8_t x = 0; x < MATRIX_COLS; x++) {
if (pins_col[x] != NO_PIN) {
setPinInputLow(pins_col[x]);
}
}
#else
/* Enable key matrix wake up */
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
if (pins_row[x] != NO_PIN) {
palEnableLineEvent(pins_row[x], PAL_EVENT_MODE_BOTH_EDGES);
}
}
#endif
select_all_cols();
#if (HAL_USE_SPI == TRUE)
palSetLineMode(SPI_SCK_PIN, PAL_MODE_INPUT_PULLDOWN);
palSetLineMode(SPI_MISO_PIN, PAL_MODE_INPUT_PULLDOWN);
palSetLineMode(SPI_MOSI_PIN, PAL_MODE_INPUT_PULLDOWN);
#endif
palSetLineMode(A12, PAL_MODE_INPUT_PULLDOWN);
palSetLineMode(A11, PAL_MODE_INPUT_PULLDOWN);
matrix_enter_low_power();
#if defined(DIP_SWITCH_PINS)
# define NUMBER_OF_DIP_SWITCHES (sizeof(dip_switch_pad) / sizeof(pin_t))
@ -177,19 +171,25 @@ bool pre_enter_low_power_mode(pm_t mode) {
}
#endif
battery_stop();
return true;
lpm_enter_low_power_kb();
}
static inline void lpm_wakeup(void) {
palSetLineMode(A11, PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING | PAL_MODE_ALTERNATE(10U));
palSetLineMode(A12, PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING | PAL_MODE_ALTERNATE(10U));
__attribute__((weak)) void lpm_post_enter_low_power(void) {}
#if (HAL_USE_SPI == TRUE)
palSetLineMode(SPI_SCK_PIN, PAL_MODE_ALTERNATE(5));
palSetLineMode(SPI_MISO_PIN, PAL_MODE_ALTERNATE(5));
palSetLineMode(SPI_MOSI_PIN, PAL_MODE_ALTERNATE(5));
#endif
__attribute__((weak)) void lpm_standby(pm_t mode) {}
__attribute__((weak)) void lpm_early_wakeup(void) {
writePinLow(BLUETOOTH_INT_OUTPUT_PIN);
}
__attribute__((weak)) void lpm_wakeup_init(void) {}
__attribute__((weak)) void lpm_pre_wakeup(void) {
writePinHigh(BLUETOOTH_INT_OUTPUT_PIN);
}
__attribute__((weak)) void lpm_wakeup(void) {
matrix_exit_low_power();
halInit();
@ -200,13 +200,6 @@ static inline void lpm_wakeup(void) {
if (wireless_transport.init) wireless_transport.init(true);
battery_init();
/* Disable all wake up pins */
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
if (pins_row[x] != NO_PIN) {
palDisableLineEvent(pins_row[x]);
}
}
palDisableLineEvent(LKBT51_INT_INPUT_PIN);
#ifdef P2P4_MODE_SELECT_PIN
palDisableLineEvent(P2P4_MODE_SELECT_PIN);
@ -218,7 +211,11 @@ static inline void lpm_wakeup(void) {
palDisableLineEvent(USB_POWER_SENSE_PIN);
# if defined(KEEP_USB_CONNECTION_IN_WIRELESS_MODE)
if (usb_power_connected()) {
if (usb_power_connected()
# ifndef BT_MODE_SELECT_PIN
&& (get_transport() == TRANSPORT_USB)
# endif
) {
usb_event_queue_init();
init_usb_driver(&USB_DRIVER);
}
@ -236,8 +233,41 @@ static inline void lpm_wakeup(void) {
debounce_free();
matrix_init();
}
__attribute__((weak)) void lpm_post_wakeup(void) {}
__attribute__((weak)) bool usb_power_connected(void) {
#ifdef USB_POWER_SENSE_PIN
return readPin(USB_POWER_SENSE_PIN) == USB_POWER_CONNECTED_LEVEL;
#else
return true;
#endif
}
__attribute__((weak)) bool lpm_is_kb_idle(void) {
return true;
}
__attribute__((weak)) bool lpm_set(pm_t mode) {
return false;
}
__attribute__((weak)) void lpm_peripheral_enter_low_power(void) {}
__attribute__((weak)) void lpm_peripheral_exit_low_power(void) {}
bool allow_low_power_mode(pm_t mode) {
#if defined(KEEP_USB_CONNECTION_IN_WIRELESS_MODE)
/* Don't enter low power mode if attached to the host */
if (mode > PM_SLEEP && usb_power_connected()) return false;
#endif
if (!lpm_set(mode)) return false;
return true;
}
void lpm_task(void) {
bool lpm = false;
if (!lpm_time_up && sync_timer_elapsed32(lpm_timer_buffer) > RUN_MODE_PROCESS_TIME) {
lpm_time_up = true;
lpm_timer_buffer = 0;
@ -248,30 +278,39 @@ void lpm_task(void) {
init_usb_driver(&USB_DRIVER);
}
if ((get_transport() == TRANSPORT_BLUETOOTH || get_transport() == TRANSPORT_P2P4) && lpm_time_up && !indicator_is_running() && lpm_is_kb_idle()) {
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
if ((get_transport() & TRANSPORT_WIRELESS) && lpm_time_up && !indicator_is_running() && lpm_is_kb_idle()) {
if (
#ifdef LED_MATRIX_ENABLE
!led_matrix_is_enabled() ||
(led_matrix_is_enabled() && led_matrix_is_driver_shutdown())
!led_matrix_is_enabled() || (led_matrix_is_enabled() && led_matrix_is_driver_shutdown())
#elif defined(RGB_MATRIX_ENABLE)
!rgb_matrix_is_enabled() || (rgb_matrix_is_enabled() && rgb_matrix_is_driver_shutdown())
#else
!bat_level_animiation_actived()
#endif
# ifdef RGB_MATRIX_ENABLE
!rgb_matrix_is_enabled() ||
(rgb_matrix_is_enabled() && rgb_matrix_is_driver_shutdown())
# endif
)
#endif
{
) {
if (!lpm_any_matrix_action()) {
if (pre_enter_low_power_mode(LOW_POWER_MODE)) {
enter_power_mode(LOW_POWER_MODE);
if (allow_low_power_mode(LOW_POWER_MODE)) {
lpm = true;
}
}
}
}
if (lpm) {
lpm_pre_enter_low_power();
lpm_enter_low_power();
lpm_post_enter_low_power();
lpm_standby(LOW_POWER_MODE);
lpm_early_wakeup();
lpm_wakeup_init();
lpm_pre_wakeup();
lpm_wakeup();
lpm_post_wakeup();
lpm_timer_reset();
report_buffer_init();
lpm_set(PM_RUN);
}
}
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -30,6 +30,19 @@ typedef enum {
void lpm_init(void);
void lpm_timer_reset(void);
void lpm_timer_stop(void);
void select_all_cols(void);
void matrix_enter_low_power(void);
void matrix_exit_low_power(void);
void lpm_pre_enter_low_power(void);
void lpm_enter_low_power(void);
void lpm_enter_low_power_kb(void);
void lpm_post_enter_low_power(void) ;
void lpm_standby(pm_t mode);
void lpm_early_wakeup(void);
void lpm_wakeup_init(void);
void lpm_pre_wakeup(void);
void lpm_wakeup(void);
void lpm_post_wakeup(void);
bool usb_power_connected(void);
bool lpm_is_kb_idle(void);
void enter_power_mode(pm_t mode);

View File

@ -1,4 +1,4 @@
/* Copyright 2022 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -29,8 +29,29 @@
#include "lpm_stm32f401.h"
#include "config.h"
#include "hal.h"
static pm_t power_mode = PM_RUN;
void lpm_post_enter_low_power(void) {
/* USB D+/D- */
palSetLineMode(A12, PAL_MODE_INPUT_PULLDOWN);
palSetLineMode(A11, PAL_MODE_INPUT_PULLDOWN);
}
void lpm_pre_wakeup(void) {
/* USB D+/D- */
palSetLineMode(A11, PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING | PAL_MODE_ALTERNATE(10U));
palSetLineMode(A12, PAL_STM32_OTYPE_PUSHPULL | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUPDR_FLOATING | PAL_MODE_ALTERNATE(10U));
/* SPI */
#if (HAL_USE_SPI == TRUE)
palSetLineMode(SPI_SCK_PIN, PAL_MODE_ALTERNATE(5));
palSetLineMode(SPI_MISO_PIN, PAL_MODE_ALTERNATE(5));
palSetLineMode(SPI_MOSI_PIN, PAL_MODE_ALTERNATE(5));
#endif
}
bool lpm_set(pm_t mode) {
bool ret = true;
@ -65,6 +86,7 @@ bool lpm_set(pm_t mode) {
# endif
0;
}
break;
case PM_STANDBY:
@ -83,7 +105,7 @@ bool lpm_set(pm_t mode) {
return ret;
}
void enter_power_mode(pm_t mode) {
void lpm_standby(pm_t mode) {
#if STM32_HSE_ENABLED
/* Switch to HSI */
RCC->CFGR = (RCC->CFGR & (~STM32_SW_MASK)) | STM32_SW_HSI;
@ -103,10 +125,10 @@ void enter_power_mode(pm_t mode) {
__WFI();
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
}
writePinLow(BLUETOOTH_INT_OUTPUT_PIN);
void lpm_wakeup_init(void) {
stm32_clock_init();
writePinHigh(BLUETOOTH_INT_OUTPUT_PIN);
}
void usb_power_connect(void) {}

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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

View File

@ -0,0 +1,135 @@
/* Copyright 2024 @ 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
* 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 "lpm.h"
bool wakeup_from_lpm;
static pm_t power_mode = PM_RUN;
static const uint32_t pre_lp_code[] = {553863175u, 554459777u, 1208378049u, 4026624001u, 688390415u, 554227969u, 3204472833u, 1198571264u, 1073807360u, 1073808388u,};
#define PRE_LP() ((void (*)(void))((unsigned int)(pre_lp_code) | 0x01))()
static const uint32_t post_lp_code[] = {553863177u, 554459777u, 1208509121u, 51443856u, 4026550535u, 1745485839u, 3489677954u, 536895496u, 673389632u, 1198578684u, 1073807360u, 536866816u, 1073808388u,};
#define POST_LP() ((void (*)(void))((unsigned int)(post_lp_code) | 0x01))()
extern void __early_init(void);
extern void matrix_init_pins(void);
void stop_mode_entry(void);
void lpm_post_enter_low_power(void) {
/* USB D+/D- */
palSetLineMode(A12, PAL_MODE_INPUT_PULLUP); // why PAL_MODE_INPUT_PULLUP
palSetLineMode(A11, PAL_MODE_INPUT_PULLDOWN);
palSetLineMode(DP_PULLUP_CONTROL_PIN, PAL_MODE_INPUT_PULLDOWN);
}
void lpm_pre_wakeup(void) {
/* USB D+/D- */
palSetLineMode(A11, PAL_WB32_OTYPE_PUSHPULL | PAL_WB32_OSPEED_HIGH | PAL_WB32_PUPDR_FLOATING | PAL_MODE_ALTERNATE(10U));
palSetLineMode(A12, PAL_WB32_OTYPE_PUSHPULL | PAL_WB32_OSPEED_HIGH | PAL_WB32_PUPDR_FLOATING | PAL_MODE_ALTERNATE(10U));
/* SPI */
#if (HAL_USE_SPI == TRUE)
palSetLineMode(SPI_SCK_PIN, PAL_MODE_ALTERNATE(5));
palSetLineMode(SPI_MISO_PIN, PAL_MODE_ALTERNATE(5));
palSetLineMode(SPI_MOSI_PIN, PAL_MODE_ALTERNATE(5));
#endif
}
bool lpm_set(pm_t mode) {
bool ret = true;
switch (mode) {
case PM_SLEEP:
/* Wake source: Any interrupt or event */
if (power_mode != PM_RUN)
ret = false;
else
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
break;
case PM_STOP:
if (power_mode != PM_RUN) ret = false;
break;
case PM_STANDBY:
if (power_mode != PM_RUN)
ret = false;
else {
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
}
break;
default:
break;
}
power_mode = mode;
return ret;
}
void lpm_standby(pm_t mode) {
chSysDisable();
wb32_set_main_clock_to_mhsi();
rtclp_lld_init();
stop_mode_entry();
chSysEnable();
}
void lpm_wakeup_init(void) {
wakeup_from_lpm = true;
__early_init();
wakeup_from_lpm = false;
}
void stop_mode_entry(void) {
EXTI->PR = 0x7FFFF;
for (uint8_t i = 0; i < 8; i++) {
for (uint8_t j = 0; j < 32; j++) {
if (NVIC->ISPR[i] & (0x01UL < j)) {
NVIC->ICPR[i] = (0x01UL < j);
}
}
}
SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk; // Clear Systick IRQ Pending
/* Clear all bits except DBP and FCLKSD bit */
PWR->CR0 &= 0x09U;
/* STOP LP4 MODE S32KON */
PWR->CR0 |= 0x3B004U;
PWR->CFGR = 0x3B3;
PRE_LP();
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
/* Request Wait For Interrupt */
__WFI();
POST_LP();
/* Clear SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR &= (~SCB_SCR_SLEEPDEEP_Msk);
lpm_early_wakeup();
}

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -95,7 +95,6 @@ bool report_buffer_next_inverval(void) {
}
void report_buffer_set_inverval(uint8_t interval) {
// OG_TRACE("report_buffer_set_inverval: %d\n\r", interval);
report_interval = interval;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2022 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -17,7 +17,6 @@
#include "hal.h"
#if (HAL_USE_RTC)
# include "rtc_timer.h"
void rtc_timer_init(void) {
@ -39,5 +38,4 @@ uint32_t rtc_timer_read_ms(void) {
uint32_t rtc_timer_elapsed_ms(uint32_t last) {
return TIMER_DIFF_32(rtc_timer_read_ms(), last);
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -55,7 +55,7 @@ __attribute__((weak)) void bt_transport_enable(bool enable) {
wireless_disconnect();
uint32_t t = timer_read32();
while (timer_elapsed32(t) < 50) {
while (timer_elapsed32(t) < 100) {
wireless_transport.task();
}
// wireless_connect();
@ -83,7 +83,7 @@ __attribute__((weak)) void p24g_transport_enable(bool enable) {
wireless_disconnect();
uint32_t t = timer_read32();
while (timer_elapsed32(t) < 50) {
while (timer_elapsed32(t) < 100) {
wireless_transport.task();
}
wireless_connect_ex(P24G_INDEX, 0);
@ -125,9 +125,10 @@ __attribute__((weak)) void usb_transport_enable(bool enable) {
#endif
}
}
void set_transport(transport_t new_transport) {
if (transport != new_transport) {
indicator_init();
if (transport == TRANSPORT_USB || ((transport != TRANSPORT_USB) && wireless_get_state() == WT_CONNECTED)) clear_keyboard();
transport = new_transport;
@ -212,10 +213,7 @@ static void reinit_led_drvier(void) {
#endif
void transport_changed(transport_t new_transport) {
kc_printf("transport_changed %d\n\r", new_transport);
indicator_init();
#if (REINIT_LED_DRIVER)
#if (REINIT_LED_DRIVER) && !defined(TRANSPORT_SOFT_SWITCH_ENABLE)
reinit_led_drvier();
#endif
@ -235,6 +233,10 @@ void transport_changed(transport_t new_transport) {
void usb_remote_wakeup(void) {
if (USB_DRIVER.state == USB_SUSPENDED) {
#if defined(WB32F3G71xx)
wait_ms(300);
if (!usb_power_connected()) return;
#endif
while (USB_DRIVER.state == USB_SUSPENDED) {
wireless_pre_task();
if (get_transport() != TRANSPORT_USB) {
@ -244,7 +246,11 @@ void usb_remote_wakeup(void) {
/* Do this in the suspended state */
suspend_power_down(); // on AVR this deep sleeps for 15ms
/* Remote wakeup */
if (suspend_wakeup_condition()) {
if (suspend_wakeup_condition()
#ifdef ENCODER_ENABLE
|| encoder_read()
#endif
) {
usbWakeupHost(&USB_DRIVER);
wait_ms(300);
#ifdef MOUSEKEY_ENABLE

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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

View File

@ -22,7 +22,7 @@
#include "indicator.h"
#include "transport.h"
#include "rtc_timer.h"
#include "lemokey_wireless_common.h"
#include "wireless_common.h"
#include "lemokey_task.h"
extern uint8_t pairing_indication;
@ -90,6 +90,7 @@ static inline bool wireless_event_dequeue(wireless_event_t *event) {
* Bluetooth init.
*/
void wireless_init(void) {
kc_printf("wireless_init\r\n");
wireless_state = WT_INITIALIZED;
wireless_event_queue_init();
@ -233,30 +234,28 @@ static void wireless_enter_connected(uint8_t host_idx) {
clear_keyboard();
/* Enable NKRO since it may be disabled in pin code entry */
#if defined(NKRO_ENABLE) && defined(WIRELESS_NKRO_ENABLE)
keymap_config.nkro = nkro.bluetooth;
#else
#if defined(NKRO_ENABLE) && !defined(WIRELESS_NKRO_ENABLE)
keymap_config.nkro = false;
#endif
wireless_enter_connected_kb(host_idx);
#ifdef BAT_LOW_LED_PIN
if (battery_is_empty()) {
indicator_battery_low_enable(true);
}
#endif
if (wireless_transport.update_bat_level) wireless_transport.update_bat_level(battery_get_percentage());
lpm_timer_reset();
}
/* Enters disconnected state. Upon entering this state we perform the following actions:
* - change state to DISCONNECTED
* - set disconnected indication
*/
static void wireless_enter_disconnected(uint8_t host_idx) {
kc_printf("wireless_disconnected %d\n\r", host_idx);
static void wireless_enter_disconnected(uint8_t host_idx, uint8_t reason) {
kc_printf("wireless_disconnected %d, %d\n\r", host_idx, reason);
uint8_t previous_state = wireless_state;
led_state = 0;
if (get_transport() & TRANSPORT_WIRELESS)
led_update_kb((led_t)led_state);
wireless_state = WT_DISCONNECTED;
@ -264,20 +263,21 @@ static void wireless_enter_disconnected(uint8_t host_idx) {
if (previous_state == WT_CONNECTED) {
lpm_timer_reset();
indicator_set(WT_SUSPEND, host_idx);
} else
} else {
indicator_set(wireless_state, host_idx);
#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
}
#ifndef DISABLE_REPORT_BUFFER
report_buffer_init();
#endif
retry = 0;
wireless_enter_disconnected_kb(host_idx);
#ifdef BAT_LOW_LED_PIN
wireless_enter_disconnected_kb(host_idx, reason);
indicator_battery_low_enable(false);
#endif
#if defined(LOW_BAT_IND_INDEX)
indicator_battery_low_backlit_enable(false);
#endif
}
/* Enter pin code entry state. */
@ -291,8 +291,8 @@ static void wireless_enter_bluetooth_pin_code_entry(void) {
/* Exit pin code entry state. */
static void wireless_exit_bluetooth_pin_code_entry(void) {
#if defined(NKRO_ENABLE)
keymap_config.nkro = true;
#if defined(NKRO_ENABLE) || defined(WIRELESS_NKRO_ENABLE)
keymap_config.raw = eeconfig_read_keymap();
#endif
pincodeEntry = false;
wireless_exit_bluetooth_pin_code_entry_kb();
@ -306,26 +306,24 @@ static void wireless_enter_sleep(void) {
kc_printf("wireless_enter_sleep %d\n\r", wireless_state);
led_state = 0;
if (wireless_state == WT_PARING) {
wireless_state = WT_SUSPEND;
#if defined(RGB_MATRIX_ENABLE) || defined(LED_MATRIX_ENABLE)
if (wireless_state == WT_CONNECTED || wireless_state == WT_PARING)
#endif
{
kc_printf("WT_SUSPEND\n\r");
lpm_timer_reset();
wireless_enter_sleep_kb();
indicator_set(wireless_state, 0);
#ifdef BAT_LOW_LED_PIN
indicator_set(WT_SUSPEND, 0);
indicator_battery_low_enable(false);
#endif
#if defined(LOW_BAT_IND_INDEX)
indicator_battery_low_backlit_enable(false);
#endif
}
wireless_state = WT_SUSPEND;
}
__attribute__((weak)) void wireless_enter_reset_kb(uint8_t reason) {}
__attribute__((weak)) void wireless_enter_discoverable_kb(uint8_t host_idx) {}
__attribute__((weak)) void wireless_enter_reconnecting_kb(uint8_t host_idx) {}
__attribute__((weak)) void wireless_enter_connected_kb(uint8_t host_idx) {}
__attribute__((weak)) void wireless_enter_disconnected_kb(uint8_t host_idx) {}
__attribute__((weak)) void wireless_enter_disconnected_kb(uint8_t host_idx, uint8_t reason) {}
__attribute__((weak)) void wireless_enter_bluetooth_pin_code_entry_kb(void) {}
__attribute__((weak)) void wireless_exit_bluetooth_pin_code_entry_kb(void) {}
__attribute__((weak)) void wireless_enter_sleep_kb(void) {}
@ -436,13 +434,7 @@ void wireless_send_extra(report_extra_t *report) {
}
void wireless_low_battery_shutdown(void) {
#ifdef BAT_LOW_LED_PIN
indicator_battery_low_enable(false);
#endif
#if defined(LOW_BAT_IND_INDEX)
indicator_battery_low_backlit_enable(false);
#endif
report_buffer_init();
clear_keyboard(); //
wait_ms(50); // wait a while for bt module to free buffer by sending report
@ -485,7 +477,7 @@ void wireless_event_task(void) {
wireless_enter_reconnecting(event.params.hostIndex);
break;
case EVT_DISCONNECTED:
wireless_enter_disconnected(event.params.hostIndex);
wireless_enter_disconnected(event.params.hostIndex, event.data);
break;
case EVT_BT_PINCODE_ENTRY:
wireless_enter_bluetooth_pin_code_entry();
@ -518,7 +510,7 @@ void wireless_task(void) {
report_buffer_task();
#endif
indicator_task();
lemokey_wireless_common_task();
wireless_common_task();
battery_task();
lpm_task();
}
@ -540,19 +532,12 @@ bool process_record_wireless(uint16_t keycode, keyrecord_t *record) {
if (get_transport() & TRANSPORT_WIRELESS) {
lpm_timer_reset();
#if defined(BAT_LOW_LED_PIN) || defined(LOW_BAT_IND_INDEX)
if (battery_is_empty() && wireless_get_state() == WT_CONNECTED && record->event.pressed) {
# if defined(BAT_LOW_LED_PIN)
indicator_battery_low_enable(true);
# endif
# if defined(LOW_BAT_IND_INDEX)
indicator_battery_low_backlit_enable(true);
# endif
}
#endif
}
if (!process_record_lemokey_wireless(keycode, record)) return false;
if (!process_record_wireless_common(keycode, record)) return false;
return true;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -84,7 +84,7 @@ void wireless_enter_reset_kb(uint8_t reason);
void wireless_enter_discoverable_kb(uint8_t host_idx);
void wireless_enter_reconnecting_kb(uint8_t host_idx);
void wireless_enter_connected_kb(uint8_t host_idx);
void wireless_enter_disconnected_kb(uint8_t host_idx);
void wireless_enter_disconnected_kb(uint8_t host_idx, uint8_t reason);
void wireless_enter_bluetooth_pin_code_entry_kb(void);
void wireless_exit_bluetooth_pin_code_entry_kb(void);
void wireless_enter_sleep_kb(void);
@ -98,4 +98,4 @@ wt_state_t wireless_get_state(void);
void wireless_low_battery_shutdown(void);
bool process_record_wireless(uint16_t keycode, keyrecord_t *record);
bool process_record_wireless_common(uint16_t keycode, keyrecord_t *record);

View File

@ -11,11 +11,18 @@ SRC += \
$(WIRELESS_DIR)/wireless_main.c \
$(WIRELESS_DIR)/transport.c \
$(WIRELESS_DIR)/lpm.c \
$(WIRELESS_DIR)/lpm_stm32f401.c \
$(WIRELESS_DIR)/battery.c \
$(WIRELESS_DIR)/bat_level_animation.c \
$(WIRELESS_DIR)/rtc_timer.c \
$(WIRELESS_DIR)/lemokey_wireless_common.c
$(WIRELESS_DIR)/wireless_common.c
ifeq ($(strip $(MCU_SERIES)), STM32F4xx)
SRC += $(WIRELESS_DIR)/lpm_stm32f401.c
endif
ifeq ($(strip $(MCU_SERIES)), WB32F3G71xx)
SRC += $(WIRELESS_DIR)/lpm_wb32f3g71.c
endif
VPATH += $(TOP_DIR)/keyboards/lemokey/$(WIRELESS_DIR)

View File

@ -1,4 +1,4 @@
/* Copyright 2022 @ Keychron (https://www.keychron.com)
/* Copyright 2022~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
@ -15,7 +15,7 @@
*/
#include QMK_KEYBOARD_H
#ifdef LK_WIRELESS_ENABLE
#include "lkbt51.h"
#include "wireless.h"
#include "indicator.h"
@ -23,17 +23,17 @@
#include "battery.h"
#include "bat_level_animation.h"
#include "lpm.h"
# include "lemokey_wireless_common.h"
#include "wireless_common.h"
#include "lemokey_task.h"
#endif
#include "lemokey_common.h"
#include "config.h"
bool firstDisconnect = true;
static uint32_t pairing_key_timer;
static uint8_t host_idx = 0;
bool process_record_lemokey_wireless(uint16_t keycode, keyrecord_t *record) {
bool process_record_wireless_common(uint16_t keycode, keyrecord_t *record) {
static uint8_t host_idx;
switch (keycode) {
@ -100,7 +100,7 @@ void wireless_enter_reset_kb(uint8_t reason) {
lkbt51_param_init();
}
void wireless_enter_disconnected_kb(uint8_t host_idx) {
void wireless_enter_disconnected_kb(uint8_t host_idx, uint8_t reason) {
/* CKBT51 bluetooth module boot time is slower, it enters disconnected after boot,
so we place initialization here. */
if (firstDisconnect && timer_read32() < 1000) {
@ -110,7 +110,7 @@ void wireless_enter_disconnected_kb(uint8_t host_idx) {
}
}
void lemokey_wireless_common_task(void) {
void wireless_common_task(void) {
if (pairing_key_timer) {
if (timer_elapsed32(pairing_key_timer) > 2000) {
pairing_key_timer = 0;
@ -120,21 +120,24 @@ void lemokey_wireless_common_task(void) {
}
void wireless_pre_task(void) {
static uint8_t mode = 0;
static uint8_t dip_switch_state = 0;
static uint32_t time = 0;
if (time == 0) {
if ((readPin(BT_MODE_SELECT_PIN) << 1 | readPin(P2P4_MODE_SELECT_PIN)) != mode) {
mode = readPin(BT_MODE_SELECT_PIN) << 1 | readPin(P2P4_MODE_SELECT_PIN);
uint8_t pins_state = (readPin(BT_MODE_SELECT_PIN) << 1) | readPin(P2P4_MODE_SELECT_PIN);
if (pins_state != dip_switch_state) {
dip_switch_state = pins_state;
time = timer_read32();
}
}
if ((time && timer_elapsed32(time) > 100) || get_transport() == TRANSPORT_NONE) {
if ((readPin(BT_MODE_SELECT_PIN) << 1 | readPin(P2P4_MODE_SELECT_PIN)) == mode) {
uint8_t pins_state = (readPin(BT_MODE_SELECT_PIN) << 1) | readPin(P2P4_MODE_SELECT_PIN);
if (pins_state == dip_switch_state) {
time = 0;
switch (mode) {
switch (dip_switch_state) {
case 0x01:
set_transport(TRANSPORT_BLUETOOTH);
break;
@ -148,7 +151,7 @@ void wireless_pre_task(void) {
break;
}
} else {
mode = readPin(BT_MODE_SELECT_PIN) << 1 | readPin(P2P4_MODE_SELECT_PIN);
dip_switch_state = pins_state;
time = timer_read32();
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ Keychron (https://www.lemokey.com)
/* Copyright 2022~2024 @ Keychron (https://www.lemokey.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
@ -14,13 +14,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdint.h"
#ifdef VIA_ENABLE
# include "via.h"
#endif
#pragma once
#include "quantum_keycodes.h"
void lkbt51_param_init(void);
bool process_record_lemokey_wireless(uint16_t keycode, keyrecord_t *record);
void lemokey_wireless_common_task(void);
bool process_record_wireless(uint16_t keycode, keyrecord_t *record);
void wireless_common_task(void);
void wireless_pre_task(void);

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -18,19 +18,6 @@
#include "config.h"
//
#ifndef BT_HOST_DEVICES_COUNT
# define BT_HOST_DEVICES_COUNT 3
#endif
#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
#endif

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -41,4 +41,5 @@ typedef struct {
uint8_t protocol; /* Parameters to EVT_HID_SET_PROTOCOL event */
uint8_t interval; /* Parameters to EVT_CONECTION_INTERVAL event */
} params;
uint8_t data;
} wireless_event_t;

View File

@ -1,4 +1,4 @@
/* Copyright 2023 @ lokher (https://www.keychron.com)
/* Copyright 2022~2024 @ 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
@ -20,6 +20,7 @@
#include "factory_test.h"
#include "lemokey_task.h"
__attribute__((weak)) bool wireless_pre_task_kb(void) { return true; }
__attribute__((weak)) void wireless_pre_task(void) {}
__attribute__((weak)) void wireless_post_task(void) {}

View File

@ -47,7 +47,7 @@
/* Indications */
# define CAPS_LOCK_INDEX 47
# define LOW_BAT_IND_INDEX \
# define SPACE_KEY_LOW_BAT_IND \
{ 79 }
# define RGB_MATRIX_KEYPRESSES

View File

@ -20,6 +20,8 @@
#define ENCODER_DEFAULT_POS 0x3
#define ENCODER_MAP_KEY_DELAY 2
# define LED_DRIVER_SHUTDOWN_PIN B7
#ifdef LK_WIRELESS_ENABLE
/* Hardware configuration */
# define P2P4_MODE_SELECT_PIN A9
@ -39,13 +41,10 @@
# if defined(RGB_MATRIX_ENABLE) || defined(LED_MATRIX_ENABLE)
# define LED_DRIVER_SHUTDOWN_PIN B7
# define BT_HOST_LED_MATRIX_LIST \
# define BT_INDICATION_LED_LIST \
{ 16, 17, 18 }
# define P2P4G_HOST_LED_MATRIX_LIST \
{ 19 }
# define P24G_INDICATION_LED_INDEX 19
# define BAT_LEVEL_LED_LIST \
{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 }

View File

@ -23,7 +23,7 @@
#ifdef LK_WIRELESS_ENABLE
# include "lkbt51.h"
# include "wireless.h"
# include "lemokey_wireless_common.h"
# include "wireless_common.h"
# include "battery.h"
# include "transport.h"
#endif

View File

@ -0,0 +1,2 @@
include keyboards/lemokey/common/wireless/wireless.mk

View File

@ -1,4 +1,3 @@
include keyboards/lemokey/common/wireless/wireless.mk
include keyboards/lemokey/common/lemokey_common.mk
VPATH += $(TOP_DIR)/keyboards/lemokey

View File

@ -54,11 +54,10 @@
# define LED_DRIVER_SHUTDOWN_PIN B7
# define BT_HOST_LED_MATRIX_LIST \
# define BT_INDICATION_LED_LIST \
{ 17, 18, 19 }
# define P2P4G_HOST_LED_MATRIX_LIST \
{ 20 }
# define P24G_INDICATION_LED_INDEX 20
# define BAT_LEVEL_LED_LIST \
{ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }

View File

@ -23,7 +23,7 @@
#ifdef LK_WIRELESS_ENABLE
# include "lkbt51.h"
# include "wireless.h"
# include "lemokey_wireless_common.h"
# include "wireless_common.h"
# include "battery.h"
# include "transport.h"
#endif

View File

@ -0,0 +1,2 @@
include keyboards/lemokey/common/wireless/wireless.mk

View File

@ -1,4 +1,3 @@
include keyboards/lemokey/common/wireless/wireless.mk
include keyboards/lemokey/common/lemokey_common.mk
VPATH += $(TOP_DIR)/keyboards/lemokey

View File

@ -0,0 +1,148 @@
/* 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/>.
*/
#include "quantum.h"
// clang-format off
#ifdef RGB_MATRIX_ENABLE
const snled27351_led_t PROGMEM g_snled27351_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to snled27351manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{0, A_15, C_15, B_15},
{0, A_14, C_14, B_14},
{0, A_13, C_13, B_13},
{0, A_12, C_12, B_12},
{0, A_11, C_11, B_11},
{0, A_10, C_10, B_10},
{0, A_9, C_9, B_9},
{0, A_8, C_8, B_8},
{0, A_7, C_7, B_7},
{0, A_6, C_6, B_6},
{0, A_5, C_5, B_5},
{0, A_4, C_4, B_4},
{0, A_3, C_3, B_3},
{0, A_2, C_2, B_2},
{0, G_15, I_15, H_15},
{0, G_14, I_14, H_14},
{0, G_13, I_13, H_13},
{0, G_12, I_12, H_12},
{0, G_11, I_11, H_11},
{0, G_10, I_10, H_10},
{0, G_9, I_9, H_9},
{0, G_8, I_8, H_8},
{0, G_7, I_7, H_7},
{0, G_6, I_6, H_6},
{0, G_5, I_5, H_5},
{0, G_4, I_4, H_4},
{0, G_3, I_3, H_3},
{0, G_2, I_2, H_2},
{0, G_1, I_1, H_1},
{0, D_15, F_15, E_15},
{0, D_14, F_14, E_14},
{0, D_13, F_13, E_13},
{0, D_12, F_12, E_12},
{0, D_11, F_11, E_11},
{0, D_10, F_10, E_10},
{0, D_9, F_9, E_9},
{0, D_8, F_8, E_8},
{0, D_7, F_7, E_7},
{0, D_6, F_6, E_6},
{0, D_5, F_5, E_5},
{0, D_4, F_4, E_4},
{0, D_3, F_3, E_3},
{0, D_2, F_2, E_2},
{0, D_1, F_1, E_1},
{1, A_15, C_15, B_15},
{1, A_14, C_14, B_14},
{1, A_13, C_13, B_13},
{1, A_12, C_12, B_12},
{1, A_11, C_11, B_11},
{1, A_10, C_10, B_10},
{1, A_9, C_9, B_9},
{1, A_8, C_8, B_8},
{1, A_7, C_7, B_7},
{1, A_6, C_6, B_6},
{1, A_5, C_5, B_5},
{1, A_4, C_4, B_4},
{1, A_2, C_2, B_2},
{1, A_1, C_1, B_1},
{1, G_15, I_15, H_15},
{1, G_13, I_13, H_13},
{1, G_12, I_12, H_12},
{1, G_11, I_11, H_11},
{1, G_10, I_10, H_10},
{1, G_9, I_9, H_9},
{1, G_8, I_8, H_8},
{1, G_7, I_7, H_7},
{1, G_6, I_6, H_6},
{1, G_5, I_5, H_5},
{1, G_4, I_4, H_4},
{1, G_3, I_3, H_3},
{1, G_2, I_2, H_2},
{1, D_15, F_15, E_15},
{1, D_14, F_14, E_14},
{1, D_13, F_13, E_13},
{1, D_9, F_9, E_9},
{1, D_6, F_6, E_6},
{1, D_5, F_5, E_5},
{1, D_4, F_4, E_4},
{1, D_3, F_3, E_3},
{1, D_2, F_2, E_2},
{1, D_1, F_1, E_1},
};
#define __ NO_LED
led_config_t g_led_config = {
{
// Key Matrix to LED Index
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, __ },
{ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 },
{ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43 },
{ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, __, 56, 57 },
{ 58, __, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, __},
{ 71, 72, 73, __, __, __, 74, __, __, 75, 76, 77, 78, 79, 80 },
},
{
// LED Index to Physical Position
{0, 0}, {18, 0}, {33, 0}, {48, 0}, {62, 0}, {81, 0}, {95, 0}, {110, 0}, {125, 0}, {143, 0}, {158, 0}, {172, 0}, {187, 0}, {205, 0},
{0,15}, {15,15}, {29,15}, {44,15}, {59,15}, {73,15}, {88,15}, {103,15}, {117,15}, {132,15}, {146,15}, {161,15}, {176,15}, {198,15}, {224,15},
{4,26}, {22,26}, {37,26}, {51,26}, {66,26}, {81,26}, {95,26}, {110,26}, {125,26}, {139,26}, {154,26}, {168,26}, {183,26}, {201,26}, {224,26},
{6,38}, {26,38}, {40,38}, {55,38}, {70,38}, {84,38}, {99,38}, {114,38}, {128,38}, {143,38}, {158,38}, {172,38}, {196,38}, {224,38},
{8,49}, {33,49}, {48,49}, {62,49}, {77,49}, {92,49}, {106,49}, {121,49}, {136,49}, {150,49}, {165,49}, {185,49}, {209,52},
{2,61}, {20,61}, {38,61}, {94,61}, {147,61}, {161,61}, {176,61}, {195,64}, {209,64}, {224,64},
},
{
// RGB LED Index to Flag
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
}
};
#endif

View File

@ -0,0 +1,57 @@
/* 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
#ifdef RGB_MATRIX_ENABLE
/* RGB Matrix driver configuration */
# define DRIVER_COUNT 2
# define RGB_MATRIX_LED_COUNT 81
# define SPI_SCK_PIN A5
# define SPI_MISO_PIN A6
# define SPI_MOSI_PIN A7
# define DRIVER_CS_PINS \
{ B15, C6 }
# define SNLED23751_SPI_DIVISOR 16
# define SPI_DRIVER SPIDQ
/* Scan phase of led driver set as MSKPHASE_9CHANNEL(defined as 0x03 in CKLED2001.h) */
# define SNLED27351_PHASE_CHANNEL MSKPHASE_9CHANNEL
/* Set LED driver current */
# define SNLED27351_CURRENT_TUNE \
{ 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C }
/* Set to infinit, which is use in USB mode by default */
# define RGB_MATRIX_TIMEOUT RGB_MATRIX_TIMEOUT_INFINITE
/* Allow shutdown of led driver to save power */
# define RGB_MATRIX_DRIVER_SHUTDOWN_ENABLE
/* Turn off backlight on low brightness to save power */
# define RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL 32
/* Caps lock indicating led */
# define CAPS_LOCK_INDEX 44
# define DIM_CAPS_LOCK
# define SPACE_KEY_LOW_BAT_IND { 74 }
# define WINLOCK_LED_LIST { 72 }
# define RGB_MATRIX_KEYPRESSES
# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#endif

View File

@ -0,0 +1,99 @@
{
"usb": {
"pid": "0x0303",
"device_version": "1.0.1"
},
"layouts": {
"LAYOUT_ansi_82": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1.25, "y": 0},
{"matrix": [0, 2], "x": 2.25, "y": 0},
{"matrix": [0, 3], "x": 3.25, "y": 0},
{"matrix": [0, 4], "x": 4.25, "y": 0},
{"matrix": [0, 5], "x": 5.5, "y": 0},
{"matrix": [0, 6], "x": 6.5, "y": 0},
{"matrix": [0, 7], "x": 7.5, "y": 0},
{"matrix": [0, 8], "x": 8.5, "y": 0},
{"matrix": [0, 9], "x": 9.75, "y": 0},
{"matrix": [0, 10], "x": 10.75, "y": 0},
{"matrix": [0, 11], "x": 11.75, "y": 0},
{"matrix": [0, 12], "x": 12.75, "y": 0},
{"matrix": [0, 13], "x": 14, "y": 0},
{"matrix": [0, 14], "x": 15.25, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1.25},
{"matrix": [1, 1], "x": 1, "y": 1.25},
{"matrix": [1, 2], "x": 2, "y": 1.25},
{"matrix": [1, 3], "x": 3, "y": 1.25},
{"matrix": [1, 4], "x": 4, "y": 1.25},
{"matrix": [1, 5], "x": 5, "y": 1.25},
{"matrix": [1, 6], "x": 6, "y": 1.25},
{"matrix": [1, 7], "x": 7, "y": 1.25},
{"matrix": [1, 8], "x": 8, "y": 1.25},
{"matrix": [1, 9], "x": 9, "y": 1.25},
{"matrix": [1, 10], "x": 10, "y": 1.25},
{"matrix": [1, 11], "x": 11, "y": 1.25},
{"matrix": [1, 12], "x": 12, "y": 1.25},
{"matrix": [1, 13], "x": 13, "y": 1.25, "w": 2},
{"matrix": [1, 14], "x": 15.25, "y": 1.25},
{"matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5},
{"matrix": [2, 1], "x": 1.5, "y": 2.25},
{"matrix": [2, 2], "x": 2.5, "y": 2.25},
{"matrix": [2, 3], "x": 3.5, "y": 2.25},
{"matrix": [2, 4], "x": 4.5, "y": 2.25},
{"matrix": [2, 5], "x": 5.5, "y": 2.25},
{"matrix": [2, 6], "x": 6.5, "y": 2.25},
{"matrix": [2, 7], "x": 7.5, "y": 2.25},
{"matrix": [2, 8], "x": 8.5, "y": 2.25},
{"matrix": [2, 9], "x": 9.5, "y": 2.25},
{"matrix": [2, 10], "x": 10.5, "y": 2.25},
{"matrix": [2, 11], "x": 11.5, "y": 2.25},
{"matrix": [2, 12], "x": 12.5, "y": 2.25},
{"matrix": [2, 13], "x": 13.5, "y": 2.25, "w": 1.5},
{"matrix": [2, 14], "x": 15.25, "y": 2.25},
{"matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75},
{"matrix": [3, 1], "x": 1.75, "y": 3.25},
{"matrix": [3, 2], "x": 2.75, "y": 3.25},
{"matrix": [3, 3], "x": 3.75, "y": 3.25},
{"matrix": [3, 4], "x": 4.75, "y": 3.25},
{"matrix": [3, 5], "x": 5.75, "y": 3.25},
{"matrix": [3, 6], "x": 6.75, "y": 3.25},
{"matrix": [3, 7], "x": 7.75, "y": 3.25},
{"matrix": [3, 8], "x": 8.75, "y": 3.25},
{"matrix": [3, 9], "x": 9.75, "y": 3.25},
{"matrix": [3, 10], "x": 10.75, "y": 3.25},
{"matrix": [3, 11], "x": 11.75, "y": 3.25},
{"matrix": [3, 13], "x": 12.75, "y": 3.25, "w": 2.25},
{"matrix": [3, 14], "x": 15.25, "y": 3.25},
{"matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25},
{"matrix": [4, 2], "x": 2.25, "y": 4.25},
{"matrix": [4, 3], "x": 3.25, "y": 4.25},
{"matrix": [4, 4], "x": 4.25, "y": 4.25},
{"matrix": [4, 5], "x": 5.25, "y": 4.25},
{"matrix": [4, 6], "x": 6.25, "y": 4.25},
{"matrix": [4, 7], "x": 7.25, "y": 4.25},
{"matrix": [4, 8], "x": 8.25, "y": 4.25},
{"matrix": [4, 9], "x": 9.25, "y": 4.25},
{"matrix": [4, 10], "x": 10.25, "y": 4.25},
{"matrix": [4, 11], "x": 11.25, "y": 4.25},
{"matrix": [4, 12], "x": 12.25, "y": 4.25, "w": 1.75},
{"matrix": [4, 13], "x": 14.25, "y": 4.5},
{"matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.25},
{"matrix": [5, 1], "x": 1.25, "y": 5.25, "w": 1.25},
{"matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.25},
{"matrix": [5, 6], "x": 3.75, "y": 5.25, "w": 6.25},
{"matrix": [5, 9], "x": 10, "y": 5.25},
{"matrix": [5, 10], "x": 11, "y": 5.25},
{"matrix": [5, 11], "x": 12, "y": 5.25},
{"matrix": [5, 12], "x": 13.25, "y": 5.5},
{"matrix": [5, 13], "x": 14.25, "y": 5.5},
{"matrix": [5, 14], "x": 15.25, "y": 5.5}
]
}
}
}

View File

@ -0,0 +1,77 @@
/* 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/>.
*/
#include QMK_KEYBOARD_H
#include "lemokey_common.h"
// clang-format off
enum layers {
BASE,
FN,
L2,
L3,
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[BASE] = LAYOUT_ansi_82(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_MUTE,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_HOME,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(FN),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
[FN] = LAYOUT_ansi_82(
_______, KC_BRID, KC_BRIU, KC_TASK, KC_FILE, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, RGB_TOG,
_______, BT_HST1, BT_HST2, BT_HST3, P2P4G, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_END,
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, BAT_LVL, NK_TOGG, _______, _______, _______, _______, _______, _______,
_______, GU_TOGG, _______, _______, _______, _______, _______, _______, _______, _______),
[L2] = LAYOUT_ansi_82(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
[L3] = LAYOUT_ansi_82(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
[FN] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
[L2] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
[L3] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)}
};
#endif
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if(!process_record_lemokey_common(keycode, record)) {
return false;
}
return true;
}

View File

@ -0,0 +1,77 @@
/* 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/>.
*/
#include QMK_KEYBOARD_H
#include "lemokey_common.h"
// clang-format off
enum layers {
BASE,
FN,
L2,
L3,
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[BASE] = LAYOUT_ansi_82(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_MUTE,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_HOME,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(FN),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
[FN] = LAYOUT_ansi_82(
_______, KC_BRID, KC_BRIU, KC_TASK, KC_FILE, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, RGB_TOG,
_______, BT_HST1, BT_HST2, BT_HST3, P2P4G, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_END,
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, BAT_LVL, NK_TOGG, _______, _______, _______, _______, _______, _______,
_______, GU_TOGG, _______, _______, _______, _______, _______, _______, _______, _______),
[L2] = LAYOUT_ansi_82(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
[L3] = LAYOUT_ansi_82(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
[FN] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
[L2] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
[L3] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)}
};
#endif
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if(!process_record_lemokey_common(keycode, record)) {
return false;
}
return true;
}

View File

@ -0,0 +1 @@
VIA_ENABLE = yes

View File

@ -0,0 +1 @@
# This file intentionally left blank

View File

@ -0,0 +1,110 @@
/* 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
/* Encoder Configuration */
#define ENCODER_DEFAULT_POS 0x3
#define ENCODER_MAP_KEY_DELAY 2
/* I2C Driver Configuration */
#define I2C1_SCL_PIN B8
#define I2C1_SDA_PIN B9
#define I2C1_CLOCK_SPEED 400000
#define I2C1_DUTY_CYCLE FAST_DUTY_CYCLE_2
/* EEPROM Driver Configuration */
#define EXTERNAL_EEPROM_BYTE_COUNT 2048
#define EXTERNAL_EEPROM_PAGE_SIZE 32
#define EXTERNAL_EEPROM_WRITE_TIME 3
/* User used eeprom */
#define I2C1_OPMODE OPMODE_I2C
#define EXTERNAL_EEPROM_I2C_BASE_ADDRESS 0b10100010
#define KEYCODE_BUFFER_ENABLE
#define LED_DRIVER_SHUTDOWN_PIN B14
/* Hold Fn+Win to lock Win key */
#define WIN_LOCK_HOLD_TIME 3000
/* Firmware Version for Via */
#define VIA_FIRMWARE_VERSION 0x00000001
#ifdef LK_WIRELESS_ENABLE
/* Hardware configuration */
# define WT_DRIVER SPIDQ
# define P2P4_MODE_SELECT_PIN C11
# define BT_MODE_SELECT_PIN C13
# define LKBT51_RESET_PIN C4
# define LKBT51_INT_INPUT_PIN B1
# define BLUETOOTH_INT_OUTPUT_PIN A4
# define USB_POWER_SENSE_PIN B0
# define USB_POWER_CONNECTED_LEVEL 0
# define BAT_CHARGING_PIN C10
# define BAT_CHARGING_LEVEL 0
# define BAT_LOW_LED_PIN C5
# define BAT_LOW_LED_PIN_ON_STATE 1
# define DP_PULLUP_CONTROL_PIN C6
# define BT_HOST_DEVICES_COUNT 3
# if defined(RGB_MATRIX_ENABLE) || defined(LED_MATRIX_ENABLE)
# define BT_INDICATION_LED_LIST \
{ 15, 16, 17 }
# define P24G_INDICATION_LED_INDEX 18
# define BAT_LEVEL_LED_LIST \
{ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }
/* Backlit disable timeout when keyboard is disconnected(unit: second) */
# define DISCONNECTED_BACKLIGHT_DISABLE_TIMEOUT 40
/* Backlit disable timeout when keyboard is connected(unit: second) */
# define CONNECTED_BACKLIGHT_DISABLE_TIMEOUT 600
/* Reinit LED driver on tranport changed */
# define REINIT_LED_DRIVER 1
# endif
/* Keep USB connection in blueooth mode */
# define KEEP_USB_CONNECTION_IN_WIRELESS_MODE
/* Enable bluetooth NKRO */
# define WIRELESS_NKRO_ENABLE
/* Raw hid command for factory test and bluetooth DFU */
# define RAW_HID_CMD 0xAA ... 0xAB
#else
/* Raw hid command for factory test */
# define RAW_HID_CMD 0xAB
#endif
/* Factory test keys */
#define FN_KEY_1 MO(1)
#define FN_KEY_2 MO(3)
#define FN_BL_TRIG_KEY KC_END
#define MATRIX_IO_DELAY 10

View File

@ -0,0 +1,32 @@
/* 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 _CHIBIOS_HAL_CONF_VER_8_0_
#define HAL_USE_SPI TRUE
#define HAL_USE_I2C TRUE
#ifdef LK_WIRELESS_ENABLE
# define HAL_USE_RTC TRUE
#endif
#if defined(LK_WIRELESS_ENABLE) || defined(ENCODER_ENABLE)
# define PAL_USE_CALLBACKS TRUE
#endif
#include_next <halconf.h>

View File

@ -0,0 +1,73 @@
{
"keyboard_name": "Lemokey P1 Pro",
"manufacturer": "Keychron",
"url": "https://github.com/Keychron",
"maintainer": "Keychron",
"processor": "WB32F3G71",
"bootloader": "wb32-dfu",
"usb": {
"vid": "0x362D"
},
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"encoder": true,
"encoder_map": true,
"nkro": true,
"rgb_matrix": true,
"raw": true,
"send_string": true
},
"matrix_pins": {
"cols": ["C14", "C15", "C2", "C3", "A0", "A1", "A2", "A3", "B10", "B12", "B13", "C7", "C8", "C9", "A10"],
"rows": ["C12", "D2", "B3", "B4", "B5", "B6"]
},
"diode_direction": "ROW2COL",
"encoder": {
"rotary": [
{"pin_a": "A8", "pin_b": "A9"}
]
},
"indicators": {
"caps_lock": "C1",
"on_state": 1
},
"rgb_matrix": {
"driver": "snled27351_spi",
"sleep": true,
"animations": {
"band_spiral_val": true,
"breathing": true,
"cycle_all": true,
"cycle_left_right": true,
"cycle_out_in": true,
"cycle_out_in_dual": true,
"cycle_pinwheel": true,
"cycle_spiral": true,
"cycle_up_down": true,
"digital_rain": true,
"dual_beacon": true,
"jellybean_raindrops": true,
"pixel_rain": true,
"rainbow_beacon": true,
"rainbow_moving_chevron": true,
"solid_reactive_multinexus": true,
"solid_reactive_multiwide": true,
"solid_reactive_simple": true,
"solid_splash": true,
"splash": true,
"typing_heatmap": true
}
},
"dynamic_keymap": {
"layer_count": 4
},
"eeprom": {
"driver": "i2c"
},
"build": {
"debounce_type": "sym_eager_pk"
},
"debounce": 20
}

View File

@ -0,0 +1,57 @@
/* 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
#ifdef RGB_MATRIX_ENABLE
/* RGB Matrix driver configuration */
# define DRIVER_COUNT 2
# define RGB_MATRIX_LED_COUNT 82
# define SPI_SCK_PIN A5
# define SPI_MISO_PIN A6
# define SPI_MOSI_PIN A7
# define DRIVER_CS_PINS \
{ B15, C6 }
# define SNLED23751_SPI_DIVISOR 16
# define SPI_DRIVER SPIDQ
/* Scan phase of led driver set as MSKPHASE_9CHANNEL(defined as 0x03 in CKLED2001.h) */
# define SNLED27351_PHASE_CHANNEL MSKPHASE_9CHANNEL
/* Set LED driver current */
# define SNLED27351_CURRENT_TUNE \
{ 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C }
/* Set to infinit, which is use in USB mode by default */
# define RGB_MATRIX_TIMEOUT RGB_MATRIX_TIMEOUT_INFINITE
/* Allow shutdown of led driver to save power */
# define RGB_MATRIX_DRIVER_SHUTDOWN_ENABLE
/* Turn off backlight on low brightness to save power */
# define RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL 32
/* Caps lock indicating led */
# define CAPS_LOCK_INDEX 44
# define DIM_CAPS_LOCK
# define SPACE_KEY_LOW_BAT_IND { 75 }
# define WINLOCK_LED_LIST { 73 }
# define RGB_MATRIX_KEYPRESSES
# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#endif

View File

@ -0,0 +1,100 @@
{
"usb": {
"pid": "0x0304",
"device_version": "1.0.2"
},
"layouts": {
"LAYOUT_iso_83": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1.25, "y": 0},
{"matrix": [0, 2], "x": 2.25, "y": 0},
{"matrix": [0, 3], "x": 3.25, "y": 0},
{"matrix": [0, 4], "x": 4.25, "y": 0},
{"matrix": [0, 5], "x": 5.5, "y": 0},
{"matrix": [0, 6], "x": 6.5, "y": 0},
{"matrix": [0, 7], "x": 7.5, "y": 0},
{"matrix": [0, 8], "x": 8.5, "y": 0},
{"matrix": [0, 9], "x": 9.75, "y": 0},
{"matrix": [0, 10], "x": 10.75, "y": 0},
{"matrix": [0, 11], "x": 11.75, "y": 0},
{"matrix": [0, 12], "x": 12.75, "y": 0},
{"matrix": [0, 13], "x": 14, "y": 0},
{"matrix": [0, 14], "x": 15.25, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1.25},
{"matrix": [1, 1], "x": 1, "y": 1.25},
{"matrix": [1, 2], "x": 2, "y": 1.25},
{"matrix": [1, 3], "x": 3, "y": 1.25},
{"matrix": [1, 4], "x": 4, "y": 1.25},
{"matrix": [1, 5], "x": 5, "y": 1.25},
{"matrix": [1, 6], "x": 6, "y": 1.25},
{"matrix": [1, 7], "x": 7, "y": 1.25},
{"matrix": [1, 8], "x": 8, "y": 1.25},
{"matrix": [1, 9], "x": 9, "y": 1.25},
{"matrix": [1, 10], "x": 10, "y": 1.25},
{"matrix": [1, 11], "x": 11, "y": 1.25},
{"matrix": [1, 12], "x": 12, "y": 1.25},
{"matrix": [1, 13], "x": 13, "y": 1.25, "w": 2},
{"matrix": [1, 14], "x": 15.25, "y": 1.25},
{"matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5},
{"matrix": [2, 1], "x": 1.5, "y": 2.25},
{"matrix": [2, 2], "x": 2.5, "y": 2.25},
{"matrix": [2, 3], "x": 3.5, "y": 2.25},
{"matrix": [2, 4], "x": 4.5, "y": 2.25},
{"matrix": [2, 5], "x": 5.5, "y": 2.25},
{"matrix": [2, 6], "x": 6.5, "y": 2.25},
{"matrix": [2, 7], "x": 7.5, "y": 2.25},
{"matrix": [2, 8], "x": 8.5, "y": 2.25},
{"matrix": [2, 9], "x": 9.5, "y": 2.25},
{"matrix": [2, 10], "x": 10.5, "y": 2.25},
{"matrix": [2, 11], "x": 11.5, "y": 2.25},
{"matrix": [2, 12], "x": 12.5, "y": 2.25},
{"matrix": [2, 14], "x": 15.25, "y": 2.25},
{"matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75},
{"matrix": [3, 1], "x": 1.75, "y": 3.25},
{"matrix": [3, 2], "x": 2.75, "y": 3.25},
{"matrix": [3, 3], "x": 3.75, "y": 3.25},
{"matrix": [3, 4], "x": 4.75, "y": 3.25},
{"matrix": [3, 5], "x": 5.75, "y": 3.25},
{"matrix": [3, 6], "x": 6.75, "y": 3.25},
{"matrix": [3, 7], "x": 7.75, "y": 3.25},
{"matrix": [3, 8], "x": 8.75, "y": 3.25},
{"matrix": [3, 9], "x": 9.75, "y": 3.25},
{"matrix": [3, 10], "x": 10.75, "y": 3.25},
{"matrix": [3, 11], "x": 11.75, "y": 3.25},
{"matrix": [3, 13], "x": 12.75, "y": 3.25},
{"matrix": [2, 13], "x": 13.75, "y": 2.25, "w": 1.25, "h": 2},
{"matrix": [3, 14], "x": 15.25, "y": 3.25},
{"matrix": [4, 0], "x": 0, "y": 4.25, "w": 1.25},
{"matrix": [4, 1], "x": 1.25, "y": 4.25},
{"matrix": [4, 2], "x": 2.25, "y": 4.25},
{"matrix": [4, 3], "x": 3.25, "y": 4.25},
{"matrix": [4, 4], "x": 4.25, "y": 4.25},
{"matrix": [4, 5], "x": 5.25, "y": 4.25},
{"matrix": [4, 6], "x": 6.25, "y": 4.25},
{"matrix": [4, 7], "x": 7.25, "y": 4.25},
{"matrix": [4, 8], "x": 8.25, "y": 4.25},
{"matrix": [4, 9], "x": 9.25, "y": 4.25},
{"matrix": [4, 10], "x": 10.25, "y": 4.25},
{"matrix": [4, 11], "x": 11.25, "y": 4.25},
{"matrix": [4, 12], "x": 12.25, "y": 4.25, "w": 1.75},
{"matrix": [4, 13], "x": 14.25, "y": 4.5},
{"matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.25},
{"matrix": [5, 1], "x": 1.25, "y": 5.25, "w": 1.25},
{"matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.25},
{"matrix": [5, 6], "x": 3.75, "y": 5.25, "w": 6.25},
{"matrix": [5, 9], "x": 10, "y": 5.25},
{"matrix": [5, 10], "x": 11, "y": 5.25},
{"matrix": [5, 11], "x": 12, "y": 5.25},
{"matrix": [5, 12], "x": 13.25, "y": 5.5},
{"matrix": [5, 13], "x": 14.25, "y": 5.5},
{"matrix": [5, 14], "x": 15.25, "y": 5.5}
]
}
}
}

View File

@ -0,0 +1,149 @@
/* 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/>.
*/
#include "quantum.h"
// clang-format off
#ifdef RGB_MATRIX_ENABLE
const snled27351_led_t PROGMEM g_snled27351_leds[RGB_MATRIX_LED_COUNT] = {
/* Refer to snled27351manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{0, A_15, C_15, B_15},
{0, A_14, C_14, B_14},
{0, A_13, C_13, B_13},
{0, A_12, C_12, B_12},
{0, A_11, C_11, B_11},
{0, A_10, C_10, B_10},
{0, A_9, C_9, B_9},
{0, A_8, C_8, B_8},
{0, A_7, C_7, B_7},
{0, A_6, C_6, B_6},
{0, A_5, C_5, B_5},
{0, A_4, C_4, B_4},
{0, A_3, C_3, B_3},
{0, A_2, C_2, B_2},
{0, G_15, I_15, H_15},
{0, G_14, I_14, H_14},
{0, G_13, I_13, H_13},
{0, G_12, I_12, H_12},
{0, G_11, I_11, H_11},
{0, G_10, I_10, H_10},
{0, G_9, I_9, H_9},
{0, G_8, I_8, H_8},
{0, G_7, I_7, H_7},
{0, G_6, I_6, H_6},
{0, G_5, I_5, H_5},
{0, G_4, I_4, H_4},
{0, G_3, I_3, H_3},
{0, G_2, I_2, H_2},
{0, G_1, I_1, H_1},
{0, D_15, F_15, E_15},
{0, D_14, F_14, E_14},
{0, D_13, F_13, E_13},
{0, D_12, F_12, E_12},
{0, D_11, F_11, E_11},
{0, D_10, F_10, E_10},
{0, D_9, F_9, E_9},
{0, D_8, F_8, E_8},
{0, D_7, F_7, E_7},
{0, D_6, F_6, E_6},
{0, D_5, F_5, E_5},
{0, D_4, F_4, E_4},
{0, D_3, F_3, E_3},
{0, D_2, F_2, E_2},
{0, D_1, F_1, E_1},
{1, A_15, C_15, B_15},
{1, A_14, C_14, B_14},
{1, A_13, C_13, B_13},
{1, A_12, C_12, B_12},
{1, A_11, C_11, B_11},
{1, A_10, C_10, B_10},
{1, A_9, C_9, B_9},
{1, A_8, C_8, B_8},
{1, A_7, C_7, B_7},
{1, A_6, C_6, B_6},
{1, A_5, C_5, B_5},
{1, A_4, C_4, B_4},
{1, A_2, C_2, B_2},
{1, A_1, C_1, B_1},
{1, G_15, I_15, H_15},
{1, G_14, I_14, H_14},
{1, G_13, I_13, H_13},
{1, G_12, I_12, H_12},
{1, G_11, I_11, H_11},
{1, G_10, I_10, H_10},
{1, G_9, I_9, H_9},
{1, G_8, I_8, H_8},
{1, G_7, I_7, H_7},
{1, G_6, I_6, H_6},
{1, G_5, I_5, H_5},
{1, G_4, I_4, H_4},
{1, G_3, I_3, H_3},
{1, G_2, I_2, H_2},
{1, D_15, F_15, E_15},
{1, D_14, F_14, E_14},
{1, D_13, F_13, E_13},
{1, D_9, F_9, E_9},
{1, D_6, F_6, E_6},
{1, D_5, F_5, E_5},
{1, D_4, F_4, E_4},
{1, D_3, F_3, E_3},
{1, D_2, F_2, E_2},
{1, D_1, F_1, E_1},
};
#define __ NO_LED
led_config_t g_led_config = {
{
// Key Matrix to LED Index
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, __ },
{ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 },
{ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43 },
{ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, __, 56, 57 },
{ 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, __ },
{ 72, 73, 74, __, __, __, 75, __, __, 76, 77, 78, 79, 80, 81 },
},
{
// LED Index to Physical Position
{0, 0}, {18, 0}, {33, 0}, {48, 0}, {62, 0}, {81, 0}, {95, 0}, {110, 0}, {125, 0}, {143, 0}, {158, 0}, {172, 0}, {187, 0}, {205, 0},
{0,15}, {15,15}, {29,15}, {44,15}, {59,15}, {73,15}, {88,15}, {103,15}, {117,15}, {132,15}, {146,15}, {161,15}, {176,15}, {201,15}, {224,15},
{4,26}, {22,26}, {37,26}, {51,26}, {66,26}, {81,26}, {95,26}, {110,26}, {125,26}, {139,26}, {154,26}, {168,26}, {183,26}, {201,30}, {224,26},
{6,38}, {26,38}, {40,38}, {55,38}, {70,38}, {84,38}, {99,38}, {114,38}, {128,38}, {143,38}, {158,38}, {172,38}, {190,38}, {224,38},
{2,49}, {18,49}, {33,49}, {48,49}, {62,49}, {77,49}, {92,49}, {106,49}, {121,49}, {136,49}, {150,49}, {165,49}, {190,49}, {209,52},
{2,61}, {20,61}, {38,61}, {94,61}, {147,61}, {161,61}, {176,61}, {195,64}, {209,64}, {224,64},
},
{
// RGB LED Index to Flag
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
}
};
#endif

View File

@ -0,0 +1,77 @@
/* 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/>.
*/
#include QMK_KEYBOARD_H
#include "lemokey_common.h"
// clang-format off
enum layers {
BASE,
FN,
L2,
L3,
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[BASE] = LAYOUT_iso_83(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_MUTE,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_HOME,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(FN), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
[FN] = LAYOUT_iso_83(
_______, KC_BRID, KC_BRIU, KC_TASK, KC_FILE, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, RGB_TOG,
_______, BT_HST1, BT_HST2, BT_HST3, P2P4G, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_END,
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, _______, _______, _______, _______, _______, _______, _______, _______,
_______, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, BAT_LVL, NK_TOGG, _______, _______, _______, _______, _______, _______,
_______, GU_TOGG, _______, _______, _______, _______, _______, _______, _______, _______),
[L2] = LAYOUT_iso_83(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
[L3] = LAYOUT_iso_83(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
[FN] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
[L2] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
[L3] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)}
};
#endif
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if(!process_record_lemokey_common(keycode, record)) {
return false;
}
return true;
}

View File

@ -0,0 +1,77 @@
/* 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/>.
*/
#include QMK_KEYBOARD_H
#include "lemokey_common.h"
// clang-format off
enum layers {
BASE,
FN,
L2,
L3,
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[BASE] = LAYOUT_iso_83(
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_MUTE,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_HOME,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(FN), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
[FN] = LAYOUT_iso_83(
_______, KC_BRID, KC_BRIU, KC_TASK, KC_FILE, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, RGB_TOG,
_______, BT_HST1, BT_HST2, BT_HST3, P2P4G, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_END,
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, _______, _______, _______, _______, _______, _______, _______, _______,
_______, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, BAT_LVL, NK_TOGG, _______, _______, _______, _______, _______, _______,
_______, GU_TOGG, _______, _______, _______, _______, _______, _______, _______, _______),
[L2] = LAYOUT_iso_83(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
[L3] = LAYOUT_iso_83(
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
[FN] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
[L2] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
[L3] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)}
};
#endif
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if(!process_record_lemokey_common(keycode, record)) {
return false;
}
return true;
}

View File

@ -0,0 +1 @@
VIA_ENABLE = yes

View File

@ -0,0 +1 @@
# This file intentionally left blank

View File

@ -0,0 +1,29 @@
/* 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
#include_next <mcuconf.h>
#undef WB32_I2C_USE_I2C1
#define WB32_I2C_USE_I2C1 TRUE
#undef WB32_SPI_USE_QSPI
#define WB32_SPI_USE_QSPI TRUE
#undef WB32_LSI_ENABLED
#define WB32_LSI_ENABLED TRUE
#define WB32_EXTI_REQUIRED

View File

@ -0,0 +1,81 @@
/* 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/>.
*/
#include "quantum.h"
#include "lemokey_task.h"
#ifdef FACTORY_TEST_ENABLE
# include "factory_test.h"
# include "lemokey_common.h"
#endif
#ifdef LK_WIRELESS_ENABLE
# include "lkbt51.h"
# include "wireless.h"
# include "wireless_common.h"
# include "battery.h"
#endif
#define POWER_ON_LED_DURATION 3000
static uint32_t power_on_indicator_timer_buffer;
void keyboard_post_init_kb(void) {
#ifdef LK_WIRELESS_ENABLE
# ifdef BT_MODE_SELECT_PIN
palSetLineMode(BT_MODE_SELECT_PIN, PAL_MODE_INPUT);
# endif
# ifdef P2P4_MODE_SELECT_PIN
palSetLineMode(P2P4_MODE_SELECT_PIN, PAL_MODE_INPUT);
# endif
palSetLineMode(B2, PAL_MODE_INPUT);
palSetLineMode(C5, PAL_MODE_INPUT);
writePin(BAT_LOW_LED_PIN, BAT_LOW_LED_PIN_ON_STATE);
lkbt51_init(false);
wireless_init();
#endif
power_on_indicator_timer_buffer = timer_read32();
#ifdef ENCODER_ENABLE
encoder_cb_init();
#endif
keyboard_post_init_user();
}
bool lemokey_task_kb(void) {
if (power_on_indicator_timer_buffer) {
if (timer_elapsed32(power_on_indicator_timer_buffer) > POWER_ON_LED_DURATION) {
power_on_indicator_timer_buffer = 0;
#ifdef LK_WIRELESS_ENABLE
writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
#endif
} else {
#ifdef LK_WIRELESS_ENABLE
writePin(BAT_LOW_LED_PIN, BAT_LOW_LED_PIN_ON_STATE);
#endif
}
}
return true;
}
#ifdef LK_WIRELESS_ENABLE
bool lpm_is_kb_idle(void) {
return power_on_indicator_timer_buffer == 0 && !factory_reset_indicating();
}
#endif

View File

@ -0,0 +1,2 @@
include keyboards/lemokey/common/wireless/wireless.mk

View File

@ -0,0 +1,21 @@
# Lemokey P1 Pro
![Lemokey P1 Pro]
A customizable 75% keyboard.
* Keyboard Maintainer: [Keychron](https://github.com/keychron)
* Hardware Supported: Lemokey P1 Pro
* Hardware Availability: [Lemokey P1 Pro QMK/VIA Wireless Custom Mechanical Keyboard]
Make example for this keyboard (after setting up your build environment):
make lemokey/p1_pro/ansi_encoder:default
Flashing example for this keyboard:
make lemokey/p1_pro/ansi_encoder:default:flash
**Reset Key**: Disconnect the USB cable, toggle mode switch to "Cable", hold down the *Esc* key or reset button underneath space bar, then connect the USB cable.
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).

View File

@ -0,0 +1,4 @@
include keyboards/lemokey/common/lemokey_common.mk
VPATH += $(TOP_DIR)/keyboards/lemokey

View File

@ -0,0 +1,287 @@
{
"name": "Lemokey P1 Pro ANSI Knob",
"vendorId": "0x362D",
"productId": "0x0303",
"firmwareVersion": 1,
"keycodes": ["qmk_lighting"],
"menus": [
{
"label": "Lighting",
"content": [
{
"label": "Backlight",
"content": [
{
"label": "Brightness",
"type": "range",
"options": [0, 255],
"content": ["id_qmk_rgb_matrix_brightness", 3, 1]
},
{
"label": "Effect",
"type": "dropdown",
"content": ["id_qmk_rgb_matrix_effect", 3, 2],
"options": [
["None", 0],
["Solid Color", 1],
["Breathing", 2],
["Band Spiral Val", 3],
["Cycle All", 4],
["Cycle Left Right", 5],
["Cycle Up Down", 6],
["Rainbow Moving Chevron", 7],
["Cycle Out In", 8],
["Cycle Out In Dual", 9],
["Cycle Pinwheel", 10],
["Cycle Spiral", 11],
["Dual Beacon", 12],
["Rainbow Beacon", 13],
["Jellybean Raindrops", 14],
["Pixel Rain", 15],
["Typing Heatmap", 16],
["Digital Rain", 17],
["Reactive Simple", 18],
["Reactive Multiwide", 19],
["Reactive Multinexus", 20],
["Splash", 21],
["Solid Splash", 22]
]
},
{
"showIf": "{id_qmk_rgb_matrix_effect} > 1",
"label": "Effect Speed",
"type": "range",
"options": [0, 255],
"content": ["id_qmk_rgb_matrix_effect_speed", 3, 3]
},
{
"showIf": "{id_qmk_rgb_matrix_effect} != 0 && ( {id_qmk_rgb_matrix_effect} < 4 || {id_qmk_rgb_matrix_effect} == 18 || ({id_qmk_rgb_matrix_effect} > 17 && {id_qmk_rgb_matrix_effect} != 21) ) ",
"label": "Color",
"type": "color",
"content": ["id_qmk_rgb_matrix_color", 3, 4]
}
]
}
]
}
],
"customKeycodes": [
{"name": "Task View", "title": "Task View in Windows", "shortName": "Task"},
{"name": "File Explorer", "title": "File Explorer in Windows", "shortName": "File"},
{"name": "Lock Screen", "title": "Lock Screen in Windows", "shortName": "Lock"},
{"name": "Misson Control", "title": "Misson Control in Mac", "shortName": "MCtl"},
{"name": "Launch Pad", "title": "Lanuch Pad in Windows", "shortName": "LPad"},
{"name": "Left Option", "title": "Left Option", "shortName": "LOpt"},
{"name": "Right Option", "title": "Right Option", "shortName": "ROpt"},
{"name": "Left Cmd", "title": "Left Command", "shortName": "LCmd"},
{"name": "Right Cmd", "title": "Right Command", "shortName": "RCmd"},
{"name": "Bluetooth Host 1", "title": "Bluetooth Host 1", "shortName": "BTH1"},
{"name": "Bluetooth Host 2", "title": "Bluetooth Host 2", "shortName": "BTH2"},
{"name": "Bluetooth Host 3", "title": "Bluetooth Host 3", "shortName": "BTH3"},
{"name": "2.4G", "title": "2.4G", "shortName": "2.4G"},
{"name": "Battery Level", "title": "Show battery level", "shortName": "Batt"}
],
"matrix": {"rows": 6, "cols" : 15},
"layouts": {
"keymap": [
[
{
"c": "#777777"
},
"0, 0",
{
"x": 0.25,
"c": "#cccccc"
},
"0, 1",
"0, 2",
"0, 3",
"0, 4",
{
"x": 0.25,
"c": "#aaaaaa"
},
"0, 5",
"0, 6",
"0, 7",
"0, 8",
{
"x": 0.25,
"c": "#cccccc"
},
"0, 9",
"0, 10",
"0, 11",
"0, 12",
{
"x": 0.25,
"c": "#aaaaaa"
},
"0, 13",
{
"x": 0.25
},
"0, 14\n\n\n\n\n\n\n\n\ne0"
],
[
{
"y": 0.25,
"c": "#aaaaaa"
},
"1, 0",
{
"c": "#cccccc"
},
"1, 1",
"1, 2",
"1, 3",
"1, 4",
"1, 5",
"1, 6",
"1, 7",
"1, 8",
"1, 9",
"1, 10",
"1, 11",
"1, 12",
{
"w": 2,
"c": "#aaaaaa"
},
"1, 13",
{
"x": 0.25
},
"1, 14"
],
[
{
"w": 1.5,
"c": "#aaaaaa"
},
"2, 0",
{
"c": "#cccccc"
},
"2, 1",
"2, 2",
"2, 3",
"2, 4",
"2, 5",
"2, 6",
"2, 7",
"2, 8",
"2, 9",
"2, 10",
"2, 11",
"2, 12",
{
"w": 1.5,
"c": "#aaaaaa"
},
"2, 13",
{
"x": 0.25
},
"2, 14"
],
[
{
"w": 1.75,
"c": "#aaaaaa"
},
"3, 0",
{
"c": "#cccccc"
},
"3, 1",
"3, 2",
"3, 3",
"3, 4",
"3, 5",
"3, 6",
"3, 7",
"3, 8",
"3, 9",
"3, 10",
"3, 11",
{
"w": 2.25,
"c": "#777777"
},
"3, 13",
{
"x": 0.25,
"c": "#aaaaaa"
},
"3, 14"
],
[
{
"w": 2.25,
"c": "#aaaaaa"
},
"4, 0",
{
"c": "#cccccc"
},
"4, 2",
"4, 3",
"4, 4",
"4, 5",
"4, 6",
"4, 7",
"4, 8",
"4, 9",
"4, 10",
"4, 11",
{
"w": 1.75,
"c": "#aaaaaa"
},
"4, 12",
{
"x": 0.25,
"y": 0.25,
"c": "#cccccc"
},
"4, 13"
],
[
{
"y": -0.25,
"w": 1.25,
"c": "#aaaaaa"
},
"5, 0",
{
"w": 1.25
},
"5, 1",
{
"w": 1.25
},
"5, 2",
{
"w": 6.25,
"c": "#cccccc"
},
"5, 6",
{
"c": "#aaaaaa"
},
"5, 9",
"5, 10",
"5, 11",
{
"x": 0.25,
"y": 0.25,
"c": "#cccccc"
},
"5, 12",
"5, 13",
"5, 14"
]
]
}
}

View File

@ -0,0 +1,290 @@
{
"name": "Lemokey P1 Pro ISO Knob",
"vendorId": "0x362D",
"productId": "0x0304",
"firmwareVersion": 1,
"keycodes": ["qmk_lighting"],
"menus": [
{
"label": "Lighting",
"content": [
{
"label": "Backlight",
"content": [
{
"label": "Brightness",
"type": "range",
"options": [0, 255],
"content": ["id_qmk_rgb_matrix_brightness", 3, 1]
},
{
"label": "Effect",
"type": "dropdown",
"content": ["id_qmk_rgb_matrix_effect", 3, 2],
"options": [
["None", 0],
["Solid Color", 1],
["Breathing", 2],
["Band Spiral Val", 3],
["Cycle All", 4],
["Cycle Left Right", 5],
["Cycle Up Down", 6],
["Rainbow Moving Chevron", 7],
["Cycle Out In", 8],
["Cycle Out In Dual", 9],
["Cycle Pinwheel", 10],
["Cycle Spiral", 11],
["Dual Beacon", 12],
["Rainbow Beacon", 13],
["Jellybean Raindrops", 14],
["Pixel Rain", 15],
["Typing Heatmap", 16],
["Digital Rain", 17],
["Reactive Simple", 18],
["Reactive Multiwide", 19],
["Reactive Multinexus", 20],
["Splash", 21],
["Solid Splash", 22]
]
},
{
"showIf": "{id_qmk_rgb_matrix_effect} > 1",
"label": "Effect Speed",
"type": "range",
"options": [0, 255],
"content": ["id_qmk_rgb_matrix_effect_speed", 3, 3]
},
{
"showIf": "{id_qmk_rgb_matrix_effect} != 0 && ( {id_qmk_rgb_matrix_effect} < 4 || {id_qmk_rgb_matrix_effect} == 18 || ({id_qmk_rgb_matrix_effect} > 17 && {id_qmk_rgb_matrix_effect} != 21) ) ",
"label": "Color",
"type": "color",
"content": ["id_qmk_rgb_matrix_color", 3, 4]
}
]
}
]
}
],
"customKeycodes": [
{"name": "Task View", "title": "Task View in Windows", "shortName": "Task"},
{"name": "File Explorer", "title": "File Explorer in Windows", "shortName": "File"},
{"name": "Lock Screen", "title": "Lock Screen in Windows", "shortName": "Lock"},
{"name": "Misson Control", "title": "Misson Control in Mac", "shortName": "MCtl"},
{"name": "Launch Pad", "title": "Lanuch Pad in Windows", "shortName": "LPad"},
{"name": "Left Option", "title": "Left Option", "shortName": "LOpt"},
{"name": "Right Option", "title": "Right Option", "shortName": "ROpt"},
{"name": "Left Cmd", "title": "Left Command", "shortName": "LCmd"},
{"name": "Right Cmd", "title": "Right Command", "shortName": "RCmd"},
{"name": "Bluetooth Host 1", "title": "Bluetooth Host 1", "shortName": "BTH1"},
{"name": "Bluetooth Host 2", "title": "Bluetooth Host 2", "shortName": "BTH2"},
{"name": "Bluetooth Host 3", "title": "Bluetooth Host 3", "shortName": "BTH3"},
{"name": "2.4G", "title": "2.4G", "shortName": "2.4G"},
{"name": "Battery Level", "title": "Show battery level", "shortName": "Batt"}
],
"matrix": {"rows": 6, "cols" : 15},
"layouts": {
"keymap": [
[
{
"c": "#777777"
},
"0, 0",
{
"x": 0.25,
"c": "#cccccc"
},
"0, 1",
"0, 2",
"0, 3",
"0, 4",
{
"x": 0.25,
"c": "#aaaaaa"
},
"0, 5",
"0, 6",
"0, 7",
"0, 8",
{
"x": 0.25,
"c": "#cccccc"
},
"0, 9",
"0, 10",
"0, 11",
"0, 12",
{
"x": 0.25,
"c": "#aaaaaa"
},
"0, 13",
{
"x": 0.25
},
"0, 14\n\n\n\n\n\n\n\n\ne0"
],
[
{
"y": 0.25,
"c": "#aaaaaa"
},
"1, 0",
{
"c": "#cccccc"
},
"1, 1",
"1, 2",
"1, 3",
"1, 4",
"1, 5",
"1, 6",
"1, 7",
"1, 8",
"1, 9",
"1, 10",
"1, 11",
"1, 12",
{
"w": 2,
"c": "#aaaaaa"
},
"1, 13",
{
"x": 0.25
},
"1, 14"
],
[
{
"w": 1.5,
"c": "#aaaaaa"
},
"2, 0",
{
"c": "#cccccc"
},
"2, 1",
"2, 2",
"2, 3",
"2, 4",
"2, 5",
"2, 6",
"2, 7",
"2, 8",
"2, 9",
"2, 10",
"2, 11",
"2, 12",
{
"x": 0.25,
"c": "#777777",
"w": 1.25,
"h": 2,
"w2": 1.5,
"h2": 1,
"x2": -0.25
},
"2, 13",
{
"x": 0.25,
"c": "#aaaaaa"
},
"2, 14"
],
[
{
"w": 1.75,
"c": "#aaaaaa"
},
"3, 0",
{
"c": "#cccccc"
},
"3, 1",
"3, 2",
"3, 3",
"3, 4",
"3, 5",
"3, 6",
"3, 7",
"3, 8",
"3, 9",
"3, 10",
"3, 11",
"3, 13",
{
"x": 1.5,
"c": "#aaaaaa"
},
"3, 14"
],
[
{
"w": 1.25,
"c": "#aaaaaa"
},
"4, 0",
"4, 1",
{
"c": "#cccccc"
},
"4, 2",
"4, 3",
"4, 4",
"4, 5",
"4, 6",
"4, 7",
"4, 8",
"4, 9",
"4, 10",
"4, 11",
{
"w": 1.75,
"c": "#aaaaaa"
},
"4, 12",
{
"x": 0.25,
"y": 0.25,
"c": "#cccccc"
},
"4, 13"
],
[
{
"y": -0.25,
"w": 1.25,
"c": "#aaaaaa"
},
"5, 0",
{
"w": 1.25
},
"5, 1",
{
"w": 1.25
},
"5, 2",
{
"w": 6.25,
"c": "#cccccc"
},
"5, 6",
{
"c": "#aaaaaa"
},
"5, 9",
"5, 10",
"5, 11",
{
"x": 0.25,
"y": 0.25,
"c": "#cccccc"
},
"5, 12",
"5, 13",
"5, 14"
]
]
}
}

@ -1 +1 @@
Subproject commit da78eb3759b8d1779b237657c7667baa4aa95ca1
Subproject commit 5dbc2a078f5f10a10af053e1255dcc34fda333f8

View File

@ -56,6 +56,8 @@
#define WB32_PPRE1 1
#define WB32_PPRE2 1
#define WB32_USBPRE WB32_USBPRE_DIV1P5
#define WB32_RTCSEL WB32_RTCSEL_HSEDIV
#define WB32_RTCLP_SEL WB32_RTCSEL_LSI
/*
* EXTI driver system settings.
@ -84,6 +86,11 @@
#define WB32_GPT_TIM2_IRQ_PRIORITY 7
#define WB32_GPT_TIM3_IRQ_PRIORITY 7
#define WB32_GPT_TIM4_IRQ_PRIORITY 7
/*
* RTC driver system settings.
*/
#define WB32_RTCAlarm_IRQ_PRIORITY 14
#define WB32_RTC_IRQ_PRIORITY 15
/*
* ICU driver system settings.

View File

@ -101,6 +101,13 @@ _Static_assert((DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) - (DYNAMIC_KEYMAP_MACRO_EEPROM_A
# define DYNAMIC_KEYMAP_MACRO_DELAY TAP_CODE_DELAY
#endif
#ifdef KEYCODE_BUFFER_ENABLE
static uint8_t layer_buffer = 0xFF;
static uint8_t row_buffer = 0xFF;
static uint8_t col_buffer = 0xFF;
static uint16_t keycode_buffer = 0;
#endif
uint8_t dynamic_keymap_get_layer_count(void) {
return DYNAMIC_KEYMAP_LAYER_COUNT;
}
@ -113,18 +120,33 @@ void *dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t c
uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column) {
if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || row >= MATRIX_ROWS || column >= MATRIX_COLS) return KC_NO;
void *address = dynamic_keymap_key_to_eeprom_address(layer, row, column);
#ifdef KEYCODE_BUFFER_ENABLE
uint16_t keycode = eeprom_read_word(address);
keycode=__builtin_bswap16(keycode);
#else
// Big endian, so we can read/write EEPROM directly from host if we want
uint16_t keycode = eeprom_read_byte(address) << 8;
keycode |= eeprom_read_byte(address + 1);
#endif
return keycode;
}
void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode) {
if (layer >= DYNAMIC_KEYMAP_LAYER_COUNT || row >= MATRIX_ROWS || column >= MATRIX_COLS) return;
#ifdef KEYCODE_BUFFER_ENABLE
if (layer == layer_buffer && row == row_buffer && column == col_buffer)
layer_buffer = row_buffer = col_buffer = 0xFF;
#endif
void *address = dynamic_keymap_key_to_eeprom_address(layer, row, column);
#ifdef KEYCODE_BUFFER_ENABLE
keycode = __builtin_bswap16(keycode);
eeprom_update_word(address, keycode);
#else
// Big endian, so we can read/write EEPROM directly from host if we want
eeprom_update_byte(address, (uint8_t)(keycode >> 8));
eeprom_update_byte(address + 1, (uint8_t)(keycode & 0xFF));
#endif
}
#ifdef ENCODER_MAP_ENABLE
@ -151,13 +173,26 @@ void dynamic_keymap_set_encoder(uint8_t layer, uint8_t encoder_id, bool clockwis
#endif // ENCODER_MAP_ENABLE
void dynamic_keymap_reset(void) {
#ifdef KEYCODE_BUFFER_ENABLE
uint16_t keymap_buffer[MATRIX_ROWS][MATRIX_COLS];
layer_buffer = row_buffer = col_buffer = 0xFF;
#endif
// Reset the keymaps in EEPROM to what is in flash.
for (int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++) {
for (int row = 0; row < MATRIX_ROWS; row++) {
for (int column = 0; column < MATRIX_COLS; column++) {
#ifdef KEYCODE_BUFFER_ENABLE
keymap_buffer[row][column] = keycode_at_keymap_location_raw(layer, row, column);
keymap_buffer[row][column] = __builtin_bswap16(keymap_buffer[row][column]);
#else
dynamic_keymap_set_keycode(layer, row, column, keycode_at_keymap_location_raw(layer, row, column));
#endif
}
}
#ifdef KEYCODE_BUFFER_ENABLE
eeprom_update_block(keymap_buffer, dynamic_keymap_key_to_eeprom_address(layer, 0, 0),sizeof(keymap_buffer));
#endif
#ifdef ENCODER_MAP_ENABLE
for (int encoder = 0; encoder < NUM_ENCODERS; encoder++) {
dynamic_keymap_set_encoder(layer, encoder, true, keycode_at_encodermap_location_raw(layer, encoder, true));
@ -197,7 +232,18 @@ void dynamic_keymap_set_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
uint16_t keycode_at_keymap_location(uint8_t layer_num, uint8_t row, uint8_t column) {
if (layer_num < DYNAMIC_KEYMAP_LAYER_COUNT && row < MATRIX_ROWS && column < MATRIX_COLS) {
#ifdef KEYCODE_BUFFER_ENABLE
if( (layer_num != layer_buffer) || (row != row_buffer) || (column != col_buffer))
{
layer_buffer = layer_num;
row_buffer = row;
col_buffer = column;
keycode_buffer = dynamic_keymap_get_keycode(layer_num, row, column);
}
return keycode_buffer;
#else
return dynamic_keymap_get_keycode(layer_num, row, column);
#endif
}
return KC_NO;
}