Added Lemokey P1 Pro

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

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,10 +1,11 @@
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)/factory_test.c
$(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
@ -35,7 +49,7 @@ enum {
BAT_LVL_ANI_BLINK_ON,
};
static uint8_t animation_state = 0;
static uint8_t animation_state = 0;
static uint32_t bat_lvl_ani_timer_buffer = 0;
static uint8_t bat_percentage;
static uint8_t cur_percentage;
@ -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
bat_percentage = percentage;
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;
}
@ -71,7 +128,7 @@ bool bat_level_animiation_actived(void) {
void bat_level_animiation_indicate(void) {
#ifdef LED_MATRIX_ENABLE
uint8_t bat_lvl_led_list[10] = BAT_LEVEL_LED_LIST;
uint8_t bat_lvl_led_list[10] = BAT_LEVEL_LED_LIST;
for (uint8_t i = 0; i <= LED_MATRIX_LED_COUNT; i++) {
led_matrix_set_value(i, 0);
@ -83,7 +140,7 @@ void bat_level_animiation_indicate(void) {
#endif
#ifdef RGB_MATRIX_ENABLE
uint8_t bat_lvl_led_list[10] = BAT_LEVEL_LED_LIST;
uint8_t bat_lvl_led_list[10] = BAT_LEVEL_LED_LIST;
for (uint8_t i = 0; i <= RGB_MATRIX_LED_COUNT; i++) {
rgb_matrix_set_color(i, 0, 0, 0);
@ -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
}
}
#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
# 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;
}
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) {
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);
}
#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,14 +463,19 @@ 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;
default:
@ -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(NUM_LOCK_INDEX) || defined(CAPS_LOCK_INDEX) || defined(SCROLL_LOCK_INDEX) || defined(COMPOSE_LOCK_INDEX) || defined(KANA_LOCK_INDEX)
if (LED_DRIVER_ALLOW_SHUTDOWN())
# 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,9 +655,8 @@ 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 defined(LOW_BAT_IND_INDEX)
if (bat_low_ind_state && (bat_low_ind_state & 0x0F) <= LOW_BAT_LED_BLINK_TIMES) {
uint8_t idx_list[] = LOW_BAT_IND_INDEX;
for (uint8_t i = 0; i < sizeof(idx_list); i++) {
@ -615,8 +667,8 @@ 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
#ifndef LOW_BAT_LED_BLINK_PERIOD
# define LOW_BAT_LED_BLINK_PERIOD 1000
#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 5
#endif
# ifndef LOW_BAT_LED_BLINK_TIMES
# define LOW_BAT_LED_BLINK_TIMES 3
# endif
#ifndef LOW_BAT_LED_TRIG_INTERVAL
# define LOW_BAT_LED_TRIG_INTERVAL 30000
#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
@ -25,9 +25,9 @@
extern void factory_test_send(uint8_t* payload, uint8_t length);
# ifndef RAW_EPSIZE
# define RAW_EPSIZE 32
# endif
#ifndef RAW_EPSIZE
# define RAW_EPSIZE 32
#endif
#ifndef SPI_SCK_PIN
# define SPI_SCK_PIN A5
@ -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)
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) {
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 (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) {
@ -610,9 +622,9 @@ void lkbt51_write_customize_data(uint8_t* data, uint8_t len) {
}
#ifdef RAW_ENABLE
void lkbt51_dfu_tx(uint8_t rsp, uint8_t* data, uint8_t len, uint8_t sn) {
uint16_t checksum = 0;
uint8_t buf[RAW_EPSIZE] = {0};
uint8_t i = 0;
uint16_t checksum = 0;
uint8_t buf[RAW_EPSIZE] = {0};
uint8_t i = 0;
buf[i++] = 0x03;
buf[i++] = 0xAA;
@ -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,44 +77,62 @@ 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
}
__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;
#ifdef LED_MATRIX_ENABLE
led_matrix_set_value_all(0);
led_matrix_driver.flush();
led_matrix_driver_shutdown();
#endif
if (!lpm_set(mode)) return false;
#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
}
#if defined(KEEP_USB_CONNECTION_IN_WIRELESS_MODE)
/* Usb unit is actived and running, stop and disconnect first */
@ -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())
# endif
# ifdef RGB_MATRIX_ENABLE
!rgb_matrix_is_enabled() ||
(rgb_matrix_is_enabled() && rgb_matrix_is_driver_shutdown())
# endif
)
#ifdef LED_MATRIX_ENABLE
!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
{
) {
if (!lpm_any_matrix_action()) {
if (pre_enter_low_power_mode(LOW_POWER_MODE)) {
enter_power_mode(LOW_POWER_MODE);
lpm_wakeup();
lpm_timer_reset();
report_buffer_init();
lpm_set(PM_RUN);
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;
@ -51,20 +72,21 @@ bool lpm_set(pm_t mode) {
else {
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
PWR->CR |=
#if STOP_MODE_MAIN_REGULATOR_LOW_VOLTAGE
# if STOP_MODE_MAIN_REGULATOR_LOW_VOLTAGE
PWR_CR_MRLVDS |
#endif
#if STOP_MODE_LOW_POWER_REGULATOR_LOW_VOLTAG
# endif
# if STOP_MODE_LOW_POWER_REGULATOR_LOW_VOLTAG
PWR_CR_LPLVDS |
#endif
#if STOP_MODE_FLASH_POWER_DOWN
# endif
# if STOP_MODE_FLASH_POWER_DOWN
PWR_CR_FPDS |
#endif
#if STOP_MODE_LOW_POWER_DEEPSLEEP
# endif
# if STOP_MODE_LOW_POWER_DEEPSLEEP
PWR_CR_LPDS |
#endif
# 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,51 +234,50 @@ 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;
led_update_kb((led_t)led_state);
if (get_transport() & TRANSPORT_WIRELESS)
led_update_kb((led_t)led_state);
wireless_state = WT_DISCONNECTED;
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,25 +15,25 @@
*/
#include QMK_KEYBOARD_H
#ifdef LK_WIRELESS_ENABLE
# include "lkbt51.h"
# include "wireless.h"
# include "indicator.h"
# include "transport.h"
# include "battery.h"
# include "bat_level_animation.h"
# include "lpm.h"
# include "lemokey_wireless_common.h"
# include "lemokey_task.h"
#endif
#include "lkbt51.h"
#include "wireless.h"
#include "indicator.h"
#include "transport.h"
#include "battery.h"
#include "bat_level_animation.h"
#include "lpm.h"
#include "wireless_common.h"
#include "lemokey_task.h"
#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 uint32_t time = 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);
time = timer_read32();
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,8 +151,8 @@ void wireless_pre_task(void) {
break;
}
} else {
mode = readPin(BT_MODE_SELECT_PIN) << 1 | readPin(P2P4_MODE_SELECT_PIN);
time = timer_read32();
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) {}