Added snap click, per-key/mixed rgb, custom debounce, wireless config feature
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/* 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 "rgb_matrix_kb_config.h"
|
||||
|
||||
#define OS_INDICATOR_CONFIG_SIZE 4 // sizeof(os_indicator_config_t)
|
||||
|
||||
//#define OS_INDICATOR_CONFIG_OFFSET (PER_KEY_RGB_LED_COLOR_LIST_SIZE + RGB_MATRIX_LED_COUNT)
|
||||
#define RETAIL_DEMO_SIZE 1 // sizeof(retail_demo_enable)
|
||||
|
||||
#define PER_KEY_RGB_TYPE_SIZE 1
|
||||
#define PER_KEY_RGB_LED_COLOR_LIST_SIZE (RGB_MATRIX_LED_COUNT * 3)
|
||||
|
||||
#define MIX_RGB_LAYER_FLAG_SIZE RGB_MATRIX_LED_COUNT
|
||||
#define EFFECT_CONFIG_SIZE 8 // sizeof(effect_config_t)
|
||||
#define EFFECT_LIST_SIZE (EFFECT_LAYERS * EFFECTS_PER_LAYER * EFFECT_CONFIG_SIZE)
|
||||
|
||||
#define EECONFIG_SIZE_CUSTOM_RGB ( \
|
||||
OS_INDICATOR_CONFIG_SIZE \
|
||||
+ RETAIL_DEMO_SIZE \
|
||||
+ PER_KEY_RGB_TYPE_SIZE \
|
||||
+ PER_KEY_RGB_LED_COLOR_LIST_SIZE \
|
||||
+ MIX_RGB_LAYER_FLAG_SIZE \
|
||||
+ EFFECT_LIST_SIZE)
|
||||
@@ -0,0 +1,494 @@
|
||||
/* 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 "raw_hid.h"
|
||||
#include "keychron_common.h"
|
||||
#include "keychron_rgb_type.h"
|
||||
#include "eeconfig_kb.h"
|
||||
#include "usb_main.h"
|
||||
#include "color.h"
|
||||
#ifdef LK_WIRELESS_ENABLE
|
||||
#include "transport.h"
|
||||
#endif
|
||||
#include <lib/lib8tion/lib8tion.h>
|
||||
|
||||
#if defined(KEYCHRON_RGB_ENABLE) && defined(EECONFIG_SIZE_CUSTOM_RGB)
|
||||
|
||||
# define PER_KEY_RGB_VER 0x0001
|
||||
|
||||
# define OFFSET_OS_INDICATOR ((uint8_t *)(EECONFIG_BASE_CUSTOM_RGB))
|
||||
# define OFFSET_RETAIL_DEMO (OFFSET_OS_INDICATOR + sizeof(os_indicator_config_t))
|
||||
# define OFFSET_PER_KEY_RGB_TYPE (OFFSET_RETAIL_DEMO + sizeof(retail_demo_enable))
|
||||
# define OFFSET_PER_KEY_RGBS (OFFSET_PER_KEY_RGB_TYPE + sizeof(per_key_rgb_type))
|
||||
# define OFFSET_LAYER_FLAGS (OFFSET_PER_KEY_RGBS + sizeof(per_key_led))
|
||||
# define OFFSET_EFFECT_LIST (OFFSET_LAYER_FLAGS + sizeof(regions))
|
||||
|
||||
enum {
|
||||
RGB_GET_PROTOCOL_VER = 0x01,
|
||||
RGB_SAVE,
|
||||
GET_INDICATORS_CONFIG,
|
||||
SET_INDICATORS_CONFIG,
|
||||
RGB_GET_LED_COUNT,
|
||||
RGB_GET_LED_IDX,
|
||||
PER_KEY_RGB_GET_TYPE,
|
||||
PER_KEY_RGB_SET_TYPE,
|
||||
PER_KEY_RGB_GET_COLOR,
|
||||
PER_KEY_RGB_SET_COLOR, //10
|
||||
MIXED_EFFECT_RGB_GET_INFO,
|
||||
MIXED_EFFECT_RGB_GET_REGIONS,
|
||||
MIXED_EFFECT_RGB_SET_REGIONS,
|
||||
MIXED_EFFECT_RGB_GET_EFFECT_LIST,
|
||||
MIXED_EFFECT_RGB_SET_EFFECT_LIST,
|
||||
};
|
||||
|
||||
extern uint8_t retail_demo_enable;
|
||||
extern uint8_t per_key_rgb_type;
|
||||
extern HSV per_key_led[RGB_MATRIX_LED_COUNT];
|
||||
extern HSV default_per_key_led[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
extern uint8_t regions[RGB_MATRIX_LED_COUNT];
|
||||
extern uint8_t rgb_regions[RGB_MATRIX_LED_COUNT];
|
||||
extern effect_config_t effect_list[EFFECT_LAYERS][EFFECTS_PER_LAYER];
|
||||
extern uint8_t default_region[RGB_MATRIX_LED_COUNT];
|
||||
|
||||
os_indicator_config_t os_ind_cfg;
|
||||
|
||||
extern void update_mixed_rgb_effect_count(void);
|
||||
|
||||
void eeconfig_reset_custom_rgb(void) {
|
||||
os_ind_cfg.disable.raw = 0;
|
||||
os_ind_cfg.hsv.s = 0;
|
||||
os_ind_cfg.hsv.h = os_ind_cfg.hsv.v = 0xFF;
|
||||
|
||||
eeprom_update_block(&os_ind_cfg, OFFSET_OS_INDICATOR, sizeof(os_ind_cfg));
|
||||
retail_demo_enable = 0;
|
||||
eeprom_read_block(&retail_demo_enable, (uint8_t *)(OFFSET_RETAIL_DEMO), sizeof(retail_demo_enable));
|
||||
per_key_rgb_type = 0;
|
||||
eeprom_update_block(&per_key_rgb_type, OFFSET_PER_KEY_RGB_TYPE, sizeof(per_key_rgb_type));
|
||||
|
||||
memcpy(per_key_led, default_per_key_led, sizeof(per_key_led));
|
||||
eeprom_update_block(per_key_led, OFFSET_PER_KEY_RGBS, sizeof(per_key_led));
|
||||
|
||||
memcpy(regions, default_region, RGB_MATRIX_LED_COUNT);
|
||||
eeprom_update_block(regions, OFFSET_LAYER_FLAGS, sizeof(regions));
|
||||
|
||||
memset(effect_list, 0, sizeof(effect_list));
|
||||
|
||||
effect_list[0][0].effect = 5;
|
||||
effect_list[0][0].sat = 255;
|
||||
effect_list[0][0].speed = 127;
|
||||
effect_list[0][0].time = 5000;
|
||||
|
||||
effect_list[1][0].effect = 2;
|
||||
effect_list[1][0].hue = 0;
|
||||
effect_list[1][0].sat = 255;
|
||||
effect_list[1][0].speed = 127;
|
||||
effect_list[1][0].time = 5000;
|
||||
|
||||
eeprom_update_block(effect_list, OFFSET_EFFECT_LIST, sizeof(effect_list));
|
||||
update_mixed_rgb_effect_count();
|
||||
}
|
||||
|
||||
void eeconfig_init_custom_rgb(void) {
|
||||
memcpy(per_key_led, default_per_key_led, sizeof(per_key_led));
|
||||
eeprom_update_dword(EECONFIG_KEYBOARD, (EECONFIG_KB_DATA_VERSION));
|
||||
|
||||
eeprom_read_block(&os_ind_cfg, OFFSET_OS_INDICATOR, sizeof(os_ind_cfg));
|
||||
eeprom_read_block(&retail_demo_enable, (uint8_t *)(OFFSET_RETAIL_DEMO), sizeof(retail_demo_enable));
|
||||
|
||||
if (os_ind_cfg.hsv.v < 128) os_ind_cfg.hsv.v = 128;
|
||||
// Load per key rgb led
|
||||
eeprom_read_block(&per_key_rgb_type, OFFSET_PER_KEY_RGB_TYPE, sizeof(per_key_rgb_type));
|
||||
eeprom_read_block(per_key_led, OFFSET_PER_KEY_RGBS, sizeof(per_key_led));
|
||||
// Load mixed rgb
|
||||
eeprom_read_block(regions, OFFSET_LAYER_FLAGS, sizeof(regions));
|
||||
eeprom_read_block(effect_list, OFFSET_EFFECT_LIST, sizeof(effect_list));
|
||||
update_mixed_rgb_effect_count();
|
||||
|
||||
}
|
||||
|
||||
void rgb_save_retail_demo(void) {
|
||||
eeprom_update_block(&retail_demo_enable, (uint8_t *)(OFFSET_RETAIL_DEMO), sizeof(retail_demo_enable));
|
||||
}
|
||||
|
||||
static bool rgb_get_version(uint8_t *data) {
|
||||
data[1] = PER_KEY_RGB_VER & 0xFF;
|
||||
data[2] = (PER_KEY_RGB_VER >> 8) & 0xFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rgb_get_led_count(uint8_t *data) {
|
||||
data[1] = RGB_MATRIX_LED_COUNT;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rgb_get_led_idx(uint8_t *data) {
|
||||
uint8_t row = data[0];
|
||||
if (row > MATRIX_ROWS) return false;
|
||||
|
||||
uint8_t led_idx[128];
|
||||
uint32_t row_mask = 0;
|
||||
memcpy(&row_mask, &data[1], 3);
|
||||
|
||||
for (uint8_t c = 0; c < MATRIX_COLS; c++) {
|
||||
led_idx[0] = 0xFF;
|
||||
if (row_mask & (0x01 << c)) {
|
||||
rgb_matrix_map_row_column_to_led(row, c, led_idx);
|
||||
}
|
||||
data[1 + c] = led_idx[0];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool per_key_rgb_get_type(uint8_t *data) {
|
||||
extern uint8_t per_key_rgb_type;
|
||||
data[1] = per_key_rgb_type;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool per_key_rgb_set_type(uint8_t *data) {
|
||||
uint8_t type = data[0];
|
||||
|
||||
if (type >= PER_KEY_RGB_MAX) return false;
|
||||
|
||||
per_key_rgb_type = data[0];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool per_key_rgb_get_led_color(uint8_t *data) {
|
||||
uint8_t start = data[0];
|
||||
uint8_t count = data[1];
|
||||
|
||||
if (count > 9) return false;
|
||||
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
data[1 + i * 3] = per_key_led[start + i].h;
|
||||
data[2 + i * 3] = per_key_led[start + i].s;
|
||||
data[3 + i * 3] = per_key_led[start + i].v;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool per_key_rgb_set_led_color(uint8_t *data) {
|
||||
uint8_t start = data[0];
|
||||
uint8_t count = data[1];
|
||||
|
||||
if (count > 9) return false;
|
||||
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
per_key_led[start + i].h = data[2 + i * 3];
|
||||
per_key_led[start + i].s = data[3 + i * 3];
|
||||
per_key_led[start + i].v = data[4 + i * 3];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mixed_rgb_get_effect_info(uint8_t *data) {
|
||||
data[1] = EFFECT_LAYERS;
|
||||
data[2] = EFFECTS_PER_LAYER;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mixed_rgb_get_regions(uint8_t *data) {
|
||||
uint8_t start = data[0];
|
||||
uint8_t count = data[1];
|
||||
|
||||
if (count > 29 || start + count > RGB_MATRIX_LED_COUNT) return false;
|
||||
memcpy(&data[1], ®ions[start], count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mixed_rgb_set_regions(uint8_t *data) {
|
||||
uint8_t start = data[0];
|
||||
uint8_t count = data[1];
|
||||
|
||||
if (count > 28 || start + count > RGB_MATRIX_LED_COUNT) return false;
|
||||
for (uint8_t i = 0; i < count; i++)
|
||||
if (data[2 + i] >= EFFECT_LAYERS) return false;
|
||||
|
||||
memcpy(®ions[start], &data[2], count);
|
||||
memcpy(&rgb_regions[start], &data[2], count);
|
||||
|
||||
return true;
|
||||
}
|
||||
#define EFFECT_DATA_LEN 8
|
||||
|
||||
static bool mixed_rgb_get_effect_list(uint8_t *data) {
|
||||
uint8_t region = data[0];
|
||||
uint8_t start = data[1];
|
||||
uint8_t count = data[2];
|
||||
|
||||
if (count > 3 || region > EFFECT_LAYERS || start + count > EFFECTS_PER_LAYER) return false;
|
||||
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
data[1 + i * EFFECT_DATA_LEN] = effect_list[region][start + i].effect;
|
||||
data[2 + i * EFFECT_DATA_LEN] = effect_list[region][start + i].hue;
|
||||
data[3 + i * EFFECT_DATA_LEN] = effect_list[region][start + i].sat;
|
||||
data[4 + i * EFFECT_DATA_LEN] = effect_list[region][start + i].speed;
|
||||
memcpy(&data[5 + i * EFFECT_DATA_LEN], &effect_list[region][start + i].time, 4);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mixed_rgb_set_effect_list(uint8_t *data) {
|
||||
uint8_t region = data[0];
|
||||
uint8_t start = data[1];
|
||||
uint8_t count = data[2];
|
||||
|
||||
if (count > 3 || region > EFFECT_LAYERS || start + count > EFFECTS_PER_LAYER) return false;
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
if (data[3 + i * EFFECT_DATA_LEN] >= RGB_MATRIX_CUSTOM_MIXED_RGB) return false;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < count; i++) {
|
||||
effect_list[region][start + i].effect = data[3 + i * EFFECT_DATA_LEN];
|
||||
effect_list[region][start + i].hue = data[4 + i * EFFECT_DATA_LEN];
|
||||
effect_list[region][start + i].sat = data[5 + i * EFFECT_DATA_LEN];
|
||||
effect_list[region][start + i].speed = data[6 + i * EFFECT_DATA_LEN];
|
||||
memcpy(&effect_list[region][start + i].time, &data[7 + i * EFFECT_DATA_LEN], 4);
|
||||
}
|
||||
update_mixed_rgb_effect_count();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool kc_rgb_save(void) {
|
||||
eeprom_update_block(&os_ind_cfg, OFFSET_OS_INDICATOR, sizeof(os_ind_cfg));
|
||||
eeprom_update_block(&per_key_rgb_type, OFFSET_PER_KEY_RGB_TYPE, sizeof(per_key_rgb_type));
|
||||
eeprom_update_block(per_key_led, OFFSET_PER_KEY_RGBS, RGB_MATRIX_LED_COUNT * sizeof(rgb_led_t));
|
||||
eeprom_update_block(regions, OFFSET_LAYER_FLAGS, RGB_MATRIX_LED_COUNT);
|
||||
eeprom_update_block(effect_list, OFFSET_EFFECT_LIST, sizeof(effect_list));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool get_indicators_config(uint8_t *data) {
|
||||
data[1] = 0
|
||||
#if defined(NUM_LOCK_INDEX) && !defined(DIM_NUM_LOCK)
|
||||
| (1 << 0x00)
|
||||
#endif
|
||||
#if defined(CAPS_LOCK_INDEX) && !defined(DIM_CAPS_LOCK)
|
||||
| (1 << 0x01)
|
||||
#endif
|
||||
#if defined(SCROLL_LOCK_INDEX)
|
||||
| (1 << 0x02)
|
||||
#endif
|
||||
#if defined(COMPOSE_LOCK_INDEX)
|
||||
| (1 << 0x03)
|
||||
#endif
|
||||
#if defined(KANA_LOCK_INDEX)
|
||||
| (1 << 0x04)
|
||||
#endif
|
||||
;
|
||||
data[2] = os_ind_cfg.disable.raw;
|
||||
data[3] = os_ind_cfg.hsv.h;
|
||||
data[4] = os_ind_cfg.hsv.s;
|
||||
data[5] = os_ind_cfg.hsv.v;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool set_indicators_config(uint8_t *data) {
|
||||
os_ind_cfg.disable.raw = data[0];
|
||||
os_ind_cfg.hsv.h = data[1];
|
||||
os_ind_cfg.hsv.s = data[2];
|
||||
os_ind_cfg.hsv.v = data[3];
|
||||
|
||||
if (os_ind_cfg.hsv.v < 128) os_ind_cfg.hsv.v = 128;
|
||||
led_update_kb(host_keyboard_led_state());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void kc_rgb_matrix_rx(uint8_t *data, uint8_t length) {
|
||||
uint8_t cmd = data[1];
|
||||
bool success = true;
|
||||
|
||||
switch (cmd) {
|
||||
case RGB_GET_PROTOCOL_VER:
|
||||
success = rgb_get_version(&data[2]);
|
||||
break;
|
||||
|
||||
case RGB_SAVE:
|
||||
success = kc_rgb_save();
|
||||
break;
|
||||
|
||||
case GET_INDICATORS_CONFIG:
|
||||
success = get_indicators_config(&data[2]);
|
||||
break;
|
||||
|
||||
case SET_INDICATORS_CONFIG:
|
||||
success = set_indicators_config(&data[2]);
|
||||
break;
|
||||
|
||||
case RGB_GET_LED_COUNT:
|
||||
success = rgb_get_led_count(&data[2]);
|
||||
break;
|
||||
|
||||
case RGB_GET_LED_IDX:
|
||||
success = rgb_get_led_idx(&data[2]);
|
||||
break;
|
||||
|
||||
case PER_KEY_RGB_GET_TYPE:
|
||||
success = per_key_rgb_get_type(&data[2]);
|
||||
break;
|
||||
|
||||
case PER_KEY_RGB_SET_TYPE:
|
||||
success = per_key_rgb_set_type(&data[2]);
|
||||
break;
|
||||
|
||||
case PER_KEY_RGB_GET_COLOR:
|
||||
success = per_key_rgb_get_led_color(&data[2]);
|
||||
break;
|
||||
|
||||
case PER_KEY_RGB_SET_COLOR:
|
||||
success = per_key_rgb_set_led_color(&data[2]);
|
||||
break;
|
||||
|
||||
case MIXED_EFFECT_RGB_GET_INFO:
|
||||
success = mixed_rgb_get_effect_info(&data[2]);
|
||||
break;
|
||||
|
||||
case MIXED_EFFECT_RGB_GET_REGIONS:
|
||||
success = mixed_rgb_get_regions(&data[2]);
|
||||
break;
|
||||
|
||||
case MIXED_EFFECT_RGB_SET_REGIONS:
|
||||
success = mixed_rgb_set_regions(&data[2]);
|
||||
break;
|
||||
|
||||
case MIXED_EFFECT_RGB_GET_EFFECT_LIST:
|
||||
success = mixed_rgb_get_effect_list(&data[2]);
|
||||
break;
|
||||
|
||||
case MIXED_EFFECT_RGB_SET_EFFECT_LIST:
|
||||
success = mixed_rgb_set_effect_list(&data[2]);
|
||||
break;
|
||||
|
||||
default:
|
||||
data[0] = 0xFF;
|
||||
break;
|
||||
}
|
||||
|
||||
data[2] = success ? 0 : 1;
|
||||
}
|
||||
|
||||
void os_state_indicate(void) {
|
||||
# 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
|
||||
|
||||
RGB rgb = hsv_to_rgb(os_ind_cfg.hsv);
|
||||
|
||||
# if defined(NUM_LOCK_INDEX)
|
||||
if (host_keyboard_led_state().num_lock && !os_ind_cfg.disable.num_lock) {
|
||||
rgb_matrix_set_color(NUM_LOCK_INDEX, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
# endif
|
||||
# if defined(CAPS_LOCK_INDEX)
|
||||
if (host_keyboard_led_state().caps_lock && !os_ind_cfg.disable.caps_lock) {
|
||||
rgb_matrix_set_color(CAPS_LOCK_INDEX, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
# endif
|
||||
# if defined(SCROLL_LOCK_INDEX)
|
||||
if (host_keyboard_led_state().compose && !os_ind_cfg.disable.scroll_lock) {
|
||||
rgb_matrix_set_color(SCROLL_LOCK_INDEX, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
# endif
|
||||
# if defined(COMPOSE_LOCK_INDEX)
|
||||
if (host_keyboard_led_state().compose && !os_ind_cfg.disable.compose) {
|
||||
rgb_matrix_set_color(COMPOSE_LOCK_INDEX, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
# endif
|
||||
# if defined(KANA_LOCK_INDEX)
|
||||
if (host_keyboard_led_state().kana && !os_ind_cfg.disable.kana) {
|
||||
rgb_matrix_set_color(KANA_LOCK_INDEX, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
# endif
|
||||
(void)rgb;
|
||||
}
|
||||
|
||||
bool process_record_keychron_rgb(uint16_t keycode, keyrecord_t *record) {
|
||||
if (rgb_matrix_get_mode() == RGB_MATRIX_CUSTOM_MIXED_RGB || rgb_matrix_get_mode() == RGB_MATRIX_CUSTOM_PER_KEY_RGB) {
|
||||
switch (keycode) {
|
||||
case RGB_HUI ... RGB_SAD:
|
||||
return false;
|
||||
|
||||
case RGB_SPI:
|
||||
if (rgb_matrix_get_mode() == RGB_MATRIX_CUSTOM_MIXED_RGB) {
|
||||
return false;
|
||||
} else {
|
||||
rgb_matrix_config.speed = qadd8(rgb_matrix_config.speed, RGB_MATRIX_SPD_STEP);
|
||||
eeprom_write_byte((uint8_t *)EECONFIG_RGB_MATRIX + offsetof(rgb_config_t, speed), rgb_matrix_config.speed);
|
||||
}
|
||||
break;
|
||||
case RGB_SPD:
|
||||
if (rgb_matrix_get_mode() == RGB_MATRIX_CUSTOM_MIXED_RGB) {
|
||||
return false;
|
||||
} else {
|
||||
rgb_matrix_config.speed = qsub8(rgb_matrix_config.speed, RGB_MATRIX_SPD_STEP);
|
||||
eeprom_write_byte((uint8_t *)EECONFIG_RGB_MATRIX + offsetof(rgb_config_t, speed), rgb_matrix_config.speed);
|
||||
}
|
||||
break;
|
||||
|
||||
case RGB_VAI:
|
||||
# ifdef RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL
|
||||
if (!rgb_matrix_config.enable) {
|
||||
rgb_matrix_toggle();
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
rgb_matrix_config.hsv.v = qadd8(rgb_matrix_config.hsv.v, RGB_MATRIX_VAL_STEP);
|
||||
# ifdef RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL
|
||||
while (rgb_matrix_config.hsv.v <= RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL)
|
||||
rgb_matrix_config.hsv.v = qadd8(rgb_matrix_config.hsv.v, RGB_MATRIX_VAL_STEP);
|
||||
# endif
|
||||
eeprom_write_byte((uint8_t *)EECONFIG_RGB_MATRIX + offsetof(rgb_config_t, hsv.v), rgb_matrix_config.hsv.v);
|
||||
return false;
|
||||
|
||||
case RGB_VAD:
|
||||
# ifdef RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL
|
||||
if (rgb_matrix_config.enable && rgb_matrix_config.hsv.v > RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL)
|
||||
# endif
|
||||
{
|
||||
rgb_matrix_config.hsv.v = qsub8(rgb_matrix_config.hsv.v, RGB_MATRIX_VAL_STEP);
|
||||
eeprom_write_byte((uint8_t *)EECONFIG_RGB_MATRIX + offsetof(rgb_config_t, hsv.v), rgb_matrix_config.hsv.v);
|
||||
}
|
||||
# ifdef RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL
|
||||
if (rgb_matrix_config.enable && rgb_matrix_config.hsv.v <= RGB_MATRIX_BRIGHTNESS_TURN_OFF_VAL) {
|
||||
rgb_matrix_toggle();
|
||||
}
|
||||
# endif
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* 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 "color.h"
|
||||
|
||||
enum {
|
||||
PER_KEY_RGB_SOLID,
|
||||
PER_KEY_RGB_BREATHING,
|
||||
PER_KEY_RGB_REATIVE_SIMPLE,
|
||||
PER_KEY_RGB_REATIVE_MULTI_WIDE,
|
||||
PER_KEY_RGB_REATIVE_SPLASH,
|
||||
PER_KEY_RGB_MAX,
|
||||
};
|
||||
|
||||
typedef struct PACKED {
|
||||
uint8_t effect;
|
||||
uint8_t hue;
|
||||
uint8_t sat;
|
||||
uint8_t speed;
|
||||
uint32_t time;
|
||||
} effect_config_t;
|
||||
|
||||
typedef union {
|
||||
uint8_t raw;
|
||||
struct {
|
||||
bool num_lock : 1;
|
||||
bool caps_lock : 1;
|
||||
bool scroll_lock : 1;
|
||||
bool compose : 1;
|
||||
bool kana : 1;
|
||||
uint8_t reserved : 3;
|
||||
};
|
||||
} os_led_t;
|
||||
|
||||
// TODO:
|
||||
// typedef struct PACKED HSV2 {
|
||||
// uint8_t h;
|
||||
// uint8_t s;
|
||||
// uint8_t v;
|
||||
// } HSV2;
|
||||
|
||||
typedef struct PACKED {
|
||||
os_led_t disable;
|
||||
HSV hsv;
|
||||
} os_indicator_config_t;
|
||||
@@ -0,0 +1,191 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#if defined(KEYCHRON_RGB_ENABLE) && defined(EECONFIG_SIZE_CUSTOM_RGB)
|
||||
|
||||
#include "quantum.h"
|
||||
#include "rgb_matrix.h"
|
||||
#include "keychron_rgb_type.h"
|
||||
|
||||
#define RGB_MATRIX_EFFECT(name, ...) \
|
||||
extern bool name(effect_params_t *params);
|
||||
#include "rgb_matrix_effects.inc"
|
||||
#include "rgb_matrix_kb.inc"
|
||||
#undef RGB_MATRIX_EFFECT
|
||||
|
||||
// PER_KEY_RGB data
|
||||
extern uint8_t per_key_rgb_type;
|
||||
|
||||
// MIXED_RGB data
|
||||
extern uint8_t rgb_regions[RGB_MATRIX_LED_COUNT];
|
||||
uint8_t regions[RGB_MATRIX_LED_COUNT] = {0}; //
|
||||
effect_config_t effect_list[EFFECT_LAYERS][EFFECTS_PER_LAYER];
|
||||
|
||||
uint8_t layer_effect_count[EFFECT_LAYERS] = {0};
|
||||
uint8_t layer_effect_index[EFFECT_LAYERS] = {0};
|
||||
uint32_t layer_effect_timer[EFFECT_LAYERS] = {0};
|
||||
|
||||
// Typing heatmap
|
||||
uint8_t typingHeatmap = 0;
|
||||
|
||||
static bool multiple_rgb_effect_runner(effect_params_t *params);
|
||||
|
||||
void mixed_rgb_reset(void) {
|
||||
typingHeatmap = 0;
|
||||
for (uint8_t i=0; i<EFFECT_LAYERS; i++) {
|
||||
layer_effect_index[i] = 0;
|
||||
layer_effect_timer[i] = timer_read32();
|
||||
|
||||
if (effect_list[i][0].effect == RGB_MATRIX_TYPING_HEATMAP) typingHeatmap |= 0x01 << i;
|
||||
}
|
||||
}
|
||||
|
||||
void update_mixed_rgb_effect_count(void) {
|
||||
for (int8_t layer=0; layer<EFFECT_LAYERS; layer++) {
|
||||
layer_effect_count[layer] = 0;
|
||||
for (uint8_t i=0; i<EFFECTS_PER_LAYER; i++) {
|
||||
if (effect_list[layer][i].effect != 0) ++layer_effect_count[layer];
|
||||
}
|
||||
}
|
||||
|
||||
mixed_rgb_reset();
|
||||
}
|
||||
|
||||
bool mixed_rgb(effect_params_t *params) {
|
||||
|
||||
bool ret;
|
||||
|
||||
extern uint8_t rgb_regions[RGB_MATRIX_LED_COUNT];
|
||||
if (params->init) {
|
||||
memcpy(rgb_regions, regions, RGB_MATRIX_LED_COUNT);
|
||||
memset(layer_effect_index, 0, sizeof(layer_effect_index));
|
||||
|
||||
mixed_rgb_reset();
|
||||
}
|
||||
|
||||
for (int8_t i=EFFECT_LAYERS-1; i>=0; i--) {
|
||||
params->region = i;
|
||||
ret = multiple_rgb_effect_runner(params);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define TRANSITION_TIME 1000
|
||||
|
||||
bool multiple_rgb_effect_runner(effect_params_t *params) {
|
||||
HSV hsv= rgb_matrix_get_hsv();
|
||||
uint8_t backup_value = hsv.v;
|
||||
|
||||
bool transation = false;
|
||||
bool rendering = false;
|
||||
uint8_t layer = params->region;
|
||||
|
||||
uint8_t effect_index = layer_effect_index[layer];
|
||||
|
||||
if (effect_list[layer][effect_index].effect == RGB_MATRIX_TYPING_HEATMAP)
|
||||
typingHeatmap |= 0x01 << layer;
|
||||
else
|
||||
typingHeatmap &= ~(0x01 << layer);
|
||||
|
||||
uint8_t last_effect = effect_list[layer][layer_effect_index[layer]].effect;
|
||||
|
||||
if (layer_effect_count[layer] > 1) {
|
||||
if (timer_elapsed32(layer_effect_timer[layer]) > effect_list[layer][effect_index].time) {
|
||||
layer_effect_timer[layer] = timer_read32();
|
||||
if (++layer_effect_index[layer] >= EFFECTS_PER_LAYER) layer_effect_index[layer] = 0;
|
||||
|
||||
effect_index = layer_effect_index[layer];
|
||||
|
||||
if (effect_list[layer][effect_index].time == 0) return true; //
|
||||
}
|
||||
else if (timer_elapsed32(layer_effect_timer[layer]) > effect_list[layer][effect_index].time - TRANSITION_TIME)
|
||||
{
|
||||
hsv.v = backup_value*(effect_list[layer][effect_index].time - timer_elapsed32(layer_effect_timer[layer]))/TRANSITION_TIME;
|
||||
transation = true;
|
||||
}
|
||||
|
||||
if (timer_elapsed32(layer_effect_timer[layer]) < TRANSITION_TIME)
|
||||
{
|
||||
hsv.v = backup_value*timer_elapsed32(layer_effect_timer[layer])/TRANSITION_TIME;
|
||||
transation = true;
|
||||
}
|
||||
} else if (layer_effect_count[layer] == 1 && effect_list[layer][effect_index].effect == 0) {
|
||||
for (uint8_t i=0; i<EFFECTS_PER_LAYER; i++) {
|
||||
if (effect_list[layer][i].effect != 0) {
|
||||
effect_index = layer_effect_index[params->region] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t effect = effect_list[layer][effect_index].effect;
|
||||
if (effect == 0) ++layer_effect_index[layer]; // Skip effect 0
|
||||
if (layer_effect_index[layer] >= EFFECTS_PER_LAYER) layer_effect_index[layer] = 0;
|
||||
|
||||
effect = effect_list[layer][effect_index].effect;
|
||||
hsv.h = effect_list[layer][effect_index].hue;
|
||||
hsv.s = effect_list[layer][effect_index].sat;
|
||||
rgb_matrix_sethsv_noeeprom(hsv.h, hsv.s, hsv.v);
|
||||
|
||||
rgb_matrix_set_speed_noeeprom(effect_list[layer][effect_index].speed);
|
||||
|
||||
params->init = last_effect != effect;
|
||||
|
||||
// each effect can opt to do calculations
|
||||
// and/or request PWM buffer updates.
|
||||
switch (effect) {
|
||||
// ---------------------------------------------
|
||||
// -----Begin rgb effect switch case macros-----
|
||||
#define RGB_MATRIX_EFFECT(name, ...) \
|
||||
case RGB_MATRIX_##name: \
|
||||
rendering = name(params); \
|
||||
break;
|
||||
#include "rgb_matrix_effects.inc"
|
||||
#undef RGB_MATRIX_EFFECT
|
||||
|
||||
#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
|
||||
# define RGB_MATRIX_EFFECT(name, ...) \
|
||||
case RGB_MATRIX_CUSTOM_##name: \
|
||||
rendering = name(params); \
|
||||
break;
|
||||
# ifdef RGB_MATRIX_CUSTOM_KB
|
||||
# include "rgb_matrix_kb.inc"
|
||||
# endif
|
||||
# undef RGB_MATRIX_EFFECT
|
||||
#endif
|
||||
// -----End rgb effect switch case macros-------
|
||||
// ---------------------------------------------
|
||||
}
|
||||
|
||||
if (transation) {
|
||||
rgb_matrix_sethsv_noeeprom(hsv.h, hsv.s, backup_value);
|
||||
}
|
||||
|
||||
return rendering;
|
||||
|
||||
}
|
||||
|
||||
void process_rgb_matrix_kb(uint8_t row, uint8_t col, bool pressed) {
|
||||
if (pressed)
|
||||
{
|
||||
if (rgb_matrix_config.mode == RGB_MATRIX_CUSTOM_MIXED_RGB) {
|
||||
extern void process_rgb_matrix_typing_heatmap(uint8_t row, uint8_t col);
|
||||
if (typingHeatmap) process_rgb_matrix_typing_heatmap(row, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,160 @@
|
||||
/* 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 "rgb_matrix.h"
|
||||
#include "keychron_rgb_type.h"
|
||||
#include <math.h>
|
||||
#include <lib/lib8tion/lib8tion.h>
|
||||
|
||||
#if defined(KEYCHRON_RGB_ENABLE)
|
||||
|
||||
// PER_KEY_RGB data
|
||||
uint8_t per_key_rgb_type;
|
||||
HSV per_key_led[RGB_MATRIX_LED_COUNT] = {0};
|
||||
|
||||
bool per_key_rgb_solid(effect_params_t *params) {
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
HSV hsv;
|
||||
|
||||
for (uint8_t i = led_min; i < led_max; i++) {
|
||||
hsv = per_key_led[i];
|
||||
hsv.v = rgb_matrix_config.hsv.v;
|
||||
RGB rgb = hsv_to_rgb(hsv);
|
||||
rgb_matrix_region_set_color(params->region, i, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
bool per_key_rgb_breahting(effect_params_t *params) {
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
HSV hsv;
|
||||
uint16_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 8);
|
||||
|
||||
for (uint8_t i = led_min; i < led_max; i++) {
|
||||
hsv = per_key_led[i];
|
||||
hsv.v = scale8(abs8(sin8(time) - 128) * 2, rgb_matrix_config.hsv.v);
|
||||
RGB rgb = hsv_to_rgb(hsv);
|
||||
RGB_MATRIX_TEST_LED_FLAGS();
|
||||
rgb_matrix_region_set_color(params->region, i, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
bool per_key_rgb_reactive_simple(effect_params_t *params) {
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
|
||||
uint16_t max_tick = 65535 / qadd8(rgb_matrix_config.speed, 1);
|
||||
for (uint8_t i = led_min; i < led_max; i++) {
|
||||
RGB_MATRIX_TEST_LED_FLAGS();
|
||||
uint16_t tick = max_tick;
|
||||
// Reverse search to find most recent key hit
|
||||
for (int8_t j = g_last_hit_tracker.count - 1; j >= 0; j--) {
|
||||
if (g_last_hit_tracker.index[j] == i && g_last_hit_tracker.tick[j] < tick) {
|
||||
tick = g_last_hit_tracker.tick[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t offset = scale16by8(tick, qadd8(rgb_matrix_config.speed, 1));
|
||||
HSV hsv = per_key_led[i];
|
||||
|
||||
hsv.v = scale8(255 - offset, rgb_matrix_config.hsv.v);
|
||||
if (per_key_led[i].v < hsv.v)
|
||||
hsv.v = per_key_led[i].v;
|
||||
|
||||
RGB rgb = hsv_to_rgb(hsv);
|
||||
rgb_matrix_region_set_color(params->region, i, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
|
||||
}
|
||||
|
||||
typedef HSV (*reactive_splash_f)(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick);
|
||||
|
||||
bool per_key_rgb_effect_runner_reactive_splash(uint8_t start, effect_params_t* params, reactive_splash_f effect_func) {
|
||||
RGB_MATRIX_USE_LIMITS(led_min, led_max);
|
||||
|
||||
uint8_t count = g_last_hit_tracker.count;
|
||||
for (uint8_t i = led_min; i < led_max; i++) {
|
||||
RGB_MATRIX_TEST_LED_FLAGS();
|
||||
HSV hsv = rgb_matrix_config.hsv;
|
||||
hsv.v = 0;
|
||||
for (uint8_t j = start; j < count; j++) {
|
||||
int16_t dx = g_led_config.point[i].x - g_last_hit_tracker.x[j];
|
||||
int16_t dy = g_led_config.point[i].y - g_last_hit_tracker.y[j];
|
||||
uint8_t dist = sqrt16(dx * dx + dy * dy);
|
||||
uint16_t tick = scale16by8(g_last_hit_tracker.tick[j], qadd8(rgb_matrix_config.speed, 1));
|
||||
hsv = effect_func(hsv, dx, dy, dist, tick);
|
||||
}
|
||||
hsv.h = per_key_led[i].h;
|
||||
hsv.s = per_key_led[i].s;
|
||||
hsv.v = scale8(hsv.v, rgb_matrix_config.hsv.v);
|
||||
if (per_key_led[i].v < hsv.v)
|
||||
hsv.v = per_key_led[i].v;
|
||||
RGB rgb = hsv_to_rgb(hsv);
|
||||
rgb_matrix_region_set_color(params->region, i, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
return rgb_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
static HSV solid_reactive_wide_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
|
||||
uint16_t effect = tick + dist * 5;
|
||||
if (effect > 255) effect = 255;
|
||||
# ifdef RGB_MATRIX_SOLID_REACTIVE_GRADIENT_MODE
|
||||
hsv.h = scale16by8(g_rgb_timer, qadd8(rgb_matrix_config.speed, 8) >> 4);
|
||||
# endif
|
||||
hsv.v = qadd8(hsv.v, 255 - effect);
|
||||
return hsv;
|
||||
}
|
||||
|
||||
bool per_key_rgb_reactive_multi_wide(effect_params_t *params) {
|
||||
return per_key_rgb_effect_runner_reactive_splash(0, params, &solid_reactive_wide_math);
|
||||
}
|
||||
|
||||
static HSV SPLASH_math(HSV hsv, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) {
|
||||
uint16_t effect = tick - dist;
|
||||
if (effect > 255) effect = 255;
|
||||
hsv.h += effect;
|
||||
hsv.v = qadd8(hsv.v, 255 - effect);
|
||||
return hsv;
|
||||
}
|
||||
|
||||
bool per_key_rgb_reactive_splash(effect_params_t *params) {
|
||||
return per_key_rgb_effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SPLASH_math);
|
||||
}
|
||||
|
||||
bool per_key_rgb(effect_params_t *params) {
|
||||
switch (per_key_rgb_type) {
|
||||
case PER_KEY_RGB_BREATHING:
|
||||
return per_key_rgb_breahting(params);
|
||||
|
||||
case PER_KEY_RGB_REATIVE_SIMPLE:
|
||||
return per_key_rgb_reactive_simple(params);
|
||||
|
||||
case PER_KEY_RGB_REATIVE_MULTI_WIDE:
|
||||
return per_key_rgb_reactive_multi_wide(params);
|
||||
|
||||
case PER_KEY_RGB_REATIVE_SPLASH:
|
||||
return per_key_rgb_reactive_splash(params);
|
||||
|
||||
default:
|
||||
return per_key_rgb_solid(params);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,185 @@
|
||||
/* 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 <string.h>
|
||||
#include "eeconfig_kb.h"
|
||||
#include "retail_demo.h"
|
||||
#include "eeconfig.h"
|
||||
#include "matrix.h"
|
||||
#include "quantum.h"
|
||||
#ifdef LK_WIRELESS_ENABLE
|
||||
# include "transport.h"
|
||||
#endif
|
||||
|
||||
#if defined(RETAIL_DEMO_ENABLE) && defined(KEYCHRON_RGB_ENABLE) && defined(EECONFIG_SIZE_CUSTOM_RGB)
|
||||
|
||||
# ifndef RETAIL_DEMO_KEY_1
|
||||
# ifdef RGB_MATRIX_ENABLE
|
||||
# define RETAIL_DEMO_KEY_1 RGB_HUI
|
||||
# else
|
||||
# define RETAIL_DEMO_KEY_1 KC_D
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef RETAIL_DEMO_KEY_2
|
||||
# ifdef RGB_MATRIX_ENABLE
|
||||
# define RETAIL_DEMO_KEY_2 RGB_HUD
|
||||
# else
|
||||
# define RETAIL_DEMO_KEY_2 KC_E
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef EFFECT_DURATION
|
||||
# define EFFECT_DURATION 10000
|
||||
# endif
|
||||
|
||||
enum {
|
||||
KEY_PRESS_FN = 0x01 << 0,
|
||||
KEY_PRESS_D = 0x01 << 1,
|
||||
KEY_PRESS_E = 0x01 << 2,
|
||||
KEY_PRESS_RETAIL_DEMO = KEY_PRESS_FN | KEY_PRESS_D | KEY_PRESS_E,
|
||||
};
|
||||
|
||||
uint8_t retail_demo_enable = 0;
|
||||
static uint8_t retail_demo_combo = 0;
|
||||
static uint32_t retail_demo_timer = 0;
|
||||
|
||||
extern void rgb_save_retail_demo(void);
|
||||
|
||||
bool process_record_retail_demo(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case MO(0)... MO(15):
|
||||
if (record->event.pressed)
|
||||
retail_demo_combo |= KEY_PRESS_FN;
|
||||
else
|
||||
retail_demo_combo &= ~KEY_PRESS_FN;
|
||||
break;
|
||||
|
||||
case RETAIL_DEMO_KEY_1:
|
||||
if (record->event.pressed) {
|
||||
retail_demo_combo |= KEY_PRESS_D;
|
||||
if (retail_demo_combo == KEY_PRESS_RETAIL_DEMO) retail_demo_timer = timer_read32();
|
||||
} else {
|
||||
retail_demo_combo &= ~KEY_PRESS_D;
|
||||
retail_demo_timer = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case RETAIL_DEMO_KEY_2:
|
||||
if (record->event.pressed) {
|
||||
retail_demo_combo |= KEY_PRESS_E;
|
||||
if (retail_demo_combo == KEY_PRESS_RETAIL_DEMO) retail_demo_timer = timer_read32();
|
||||
} else {
|
||||
retail_demo_combo &= ~KEY_PRESS_E;
|
||||
retail_demo_timer = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (retail_demo_enable && keycode >= RGB_TOG && keycode <= RGB_SPD) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void retail_demo_start(void) {
|
||||
extern bool mixed_rgb_set_regions(uint8_t * data);
|
||||
extern bool mixed_rgb_set_effect_list(uint8_t * data);
|
||||
|
||||
uint8_t index = 0;
|
||||
uint8_t this_count = 28;
|
||||
uint8_t data[31] = {0};
|
||||
|
||||
// Set all LED to region 0
|
||||
while (index < RGB_MATRIX_LED_COUNT - 1) {
|
||||
memset(data, 0, 31);
|
||||
|
||||
if ((index + this_count) >= RGB_MATRIX_LED_COUNT)
|
||||
this_count = RGB_MATRIX_LED_COUNT - 1 - index;
|
||||
else
|
||||
this_count = 28;
|
||||
|
||||
data[0] = index;
|
||||
data[1] = this_count;
|
||||
mixed_rgb_set_regions(data);
|
||||
|
||||
index += this_count;
|
||||
}
|
||||
|
||||
uint8_t effect_list[5] = {4, 7, 8, 11, 14};
|
||||
// Set effect list
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
data[0] = 0; // regsion
|
||||
data[1] = i; // start
|
||||
data[2] = 1; // count
|
||||
data[3] = effect_list[i]; // effect
|
||||
data[4] = 0; // hue
|
||||
data[5] = 255; // sat
|
||||
data[6] = 127; // speed;
|
||||
data[7] = EFFECT_DURATION & 0xFF;
|
||||
data[8] = (EFFECT_DURATION >> 8) & 0xFF;
|
||||
data[9] = (EFFECT_DURATION >> 16) & 0xFF;
|
||||
data[10] = (EFFECT_DURATION >> 24) & 0xFF;
|
||||
|
||||
mixed_rgb_set_effect_list(data);
|
||||
}
|
||||
|
||||
HSV hsv = rgb_matrix_get_hsv();
|
||||
hsv.v = hsv.s = UINT8_MAX;
|
||||
rgb_matrix_sethsv_noeeprom(hsv.h, hsv.s, hsv.v);
|
||||
rgb_matrix_set_speed_noeeprom(RGB_MATRIX_DEFAULT_SPD);
|
||||
rgb_matrix_mode_noeeprom(RGB_MATRIX_CUSTOM_MIXED_RGB);
|
||||
}
|
||||
|
||||
void retail_demo_stop(void) {
|
||||
retail_demo_enable = false;
|
||||
rgb_save_retail_demo();
|
||||
eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config));
|
||||
}
|
||||
|
||||
static inline void retail_demo_timer_check(void) {
|
||||
if (timer_elapsed32(retail_demo_timer) > 5000) {
|
||||
retail_demo_timer = 0;
|
||||
|
||||
if (retail_demo_combo == KEY_PRESS_RETAIL_DEMO) {
|
||||
retail_demo_combo = 0;
|
||||
retail_demo_enable = !retail_demo_enable;
|
||||
|
||||
if (retail_demo_enable) {
|
||||
# ifdef LK_WIRELESS_ENABLE
|
||||
// Retail demo is allowed only in wireless mode
|
||||
if (get_transport() != TRANSPORT_USB) {
|
||||
retail_demo_enable = false;
|
||||
return;
|
||||
}
|
||||
# endif
|
||||
} else {
|
||||
eeprom_read_block(&rgb_matrix_config, EECONFIG_RGB_MATRIX, sizeof(rgb_matrix_config));
|
||||
}
|
||||
rgb_save_retail_demo();
|
||||
|
||||
if (!retail_demo_enable) {
|
||||
extern void eeconfig_init_custom_rgb(void);
|
||||
eeconfig_init_custom_rgb();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void retail_demo_task(void) {
|
||||
if (retail_demo_timer) retail_demo_timer_check();
|
||||
if (retail_demo_enable && rgb_matrix_get_mode() != RGB_MATRIX_CUSTOM_MIXED_RGB) retail_demo_start();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/* 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 "stdint.h"
|
||||
#include "action.h"
|
||||
|
||||
void retail_demo_start(void);
|
||||
void retail_demo_stop(void);
|
||||
|
||||
bool process_record_retail_demo(uint16_t keycode, keyrecord_t * record);
|
||||
void retail_demo_task(void);
|
||||
@@ -0,0 +1,14 @@
|
||||
OPT_DEFS += -DKEYCHRON_RGB_ENABLE -DRETAIL_DEMO_ENABLE
|
||||
|
||||
RGB_MATRIX_CUSTOM_KB = yes
|
||||
RGB_MATRIX_DIR = common/rgb
|
||||
|
||||
SRC += \
|
||||
$(RGB_MATRIX_DIR)/keychron_rgb.c \
|
||||
$(RGB_MATRIX_DIR)/per_key_rgb.c \
|
||||
$(RGB_MATRIX_DIR)/mixed_rgb.c \
|
||||
$(RGB_MATRIX_DIR)/retail_demo.c
|
||||
|
||||
VPATH += $(TOP_DIR)/keyboards/keychron/$(RGB_MATRIX_DIR)
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/* 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 "rgb_matrix_kb_config.h"
|
||||
|
||||
#if defined(KEYCHRON_RGB_ENABLE) && defined(EECONFIG_SIZE_CUSTOM_RGB)
|
||||
//extern bool MIXED_RGB(effect_params_t *params);
|
||||
|
||||
RGB_MATRIX_EFFECT(PER_KEY_RGB)
|
||||
RGB_MATRIX_EFFECT(MIXED_RGB)
|
||||
|
||||
# ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
bool PER_KEY_RGB(effect_params_t *params) {
|
||||
extern bool per_key_rgb(effect_params_t *params);
|
||||
return per_key_rgb(params);
|
||||
}
|
||||
|
||||
bool MIXED_RGB(effect_params_t *params) {
|
||||
extern bool mixed_rgb(effect_params_t *params);
|
||||
return mixed_rgb(params);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
/* 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 "config.h"
|
||||
|
||||
#ifndef EFFECT_LAYERS
|
||||
#define EFFECT_LAYERS 2
|
||||
#endif
|
||||
|
||||
#ifndef EFFECTS_PER_LAYER
|
||||
#define EFFECTS_PER_LAYER 5
|
||||
#endif
|
||||
Reference in New Issue
Block a user