forked from mirrors/qmk_userspace
		
	Added shutdown fucntion to snled driver
This commit is contained in:
		
					parent
					
						
							
								4ae5990fcc
							
						
					
				
			
			
				commit
				
					
						cca8df6939
					
				
			
		
					 51 changed files with 81 additions and 2256 deletions
				
			
		| 
						 | 
				
			
			@ -16,6 +16,7 @@
 | 
			
		|||
 | 
			
		||||
#include "snled27351-simple.h"
 | 
			
		||||
#include "i2c_master.h"
 | 
			
		||||
#include "gpio.h"
 | 
			
		||||
 | 
			
		||||
#define SNLED27351_PWM_REGISTER_COUNT 192
 | 
			
		||||
#define SNLED27351_LED_CONTROL_REGISTER_COUNT 24
 | 
			
		||||
| 
						 | 
				
			
			@ -249,6 +250,24 @@ void snled27351_flush(void) {
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void snled27351_shutdown(void) {
 | 
			
		||||
#    if defined(LED_DRIVER_SHUTDOWN_PIN)
 | 
			
		||||
    writePinLow(LED_DRIVER_SHUTDOWN_PIN);
 | 
			
		||||
#    else
 | 
			
		||||
    for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
 | 
			
		||||
        snled27351_sw_shutdown(i);
 | 
			
		||||
#    endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void snled27351_exit_shutdown(void) {
 | 
			
		||||
#    if defined(LED_DRIVER_SHUTDOWN_PIN)
 | 
			
		||||
    writePinHigh(LED_DRIVER_SHUTDOWN_PIN);
 | 
			
		||||
#    else
 | 
			
		||||
    for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
 | 
			
		||||
        snled27351_sw_return_normal(i);
 | 
			
		||||
#    endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void snled27351_sw_return_normal(uint8_t addr) {
 | 
			
		||||
    // Select to function page
 | 
			
		||||
    snled27351_write_register(addr, SNLED27351_REG_COMMAND, SNLED27351_COMMAND_FUNCTION);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -171,7 +171,8 @@ void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index);
 | 
			
		|||
void snled27351_update_led_control_registers(uint8_t addr, uint8_t index);
 | 
			
		||||
 | 
			
		||||
void snled27351_flush(void);
 | 
			
		||||
 | 
			
		||||
void snled27351_shutdown(void);
 | 
			
		||||
void snled27351_exit_shutdown(void);
 | 
			
		||||
void snled27351_sw_return_normal(uint8_t addr);
 | 
			
		||||
void snled27351_sw_shutdown(uint8_t addr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@
 | 
			
		|||
 | 
			
		||||
#include "snled27351.h"
 | 
			
		||||
#include "i2c_master.h"
 | 
			
		||||
#include "gpio.h"
 | 
			
		||||
 | 
			
		||||
#define SNLED27351_PWM_REGISTER_COUNT 192
 | 
			
		||||
#define SNLED27351_LED_CONTROL_REGISTER_COUNT 24
 | 
			
		||||
| 
						 | 
				
			
			@ -264,6 +265,24 @@ void snled27351_flush(void) {
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void snled27351_shutdown(void) {
 | 
			
		||||
#    if defined(LED_DRIVER_SHUTDOWN_PIN)
 | 
			
		||||
    writePinLow(LED_DRIVER_SHUTDOWN_PIN);
 | 
			
		||||
#    else
 | 
			
		||||
    for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
 | 
			
		||||
        snled27351_sw_shutdown(i);
 | 
			
		||||
#    endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void snled27351_exit_shutdown(void) {
 | 
			
		||||
#    if defined(LED_DRIVER_SHUTDOWN_PIN)
 | 
			
		||||
    writePinHigh(LED_DRIVER_SHUTDOWN_PIN);
 | 
			
		||||
#    else
 | 
			
		||||
    for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
 | 
			
		||||
        snled27351_sw_return_normal(i);
 | 
			
		||||
#    endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void snled27351_sw_return_normal(uint8_t addr) {
 | 
			
		||||
    // Select to function page
 | 
			
		||||
    snled27351_write_register(addr, SNLED27351_REG_COMMAND, SNLED27351_COMMAND_FUNCTION);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -185,7 +185,8 @@ void snled27351_update_pwm_buffers(uint8_t addr, uint8_t index);
 | 
			
		|||
void snled27351_update_led_control_registers(uint8_t addr, uint8_t index);
 | 
			
		||||
 | 
			
		||||
void snled27351_flush(void);
 | 
			
		||||
 | 
			
		||||
void snled27351_shutdown(void);
 | 
			
		||||
void snled27351_exit_shutdown(void);
 | 
			
		||||
void snled27351_sw_return_normal(uint8_t addr);
 | 
			
		||||
void snled27351_sw_shutdown(uint8_t addr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,445 +0,0 @@
 | 
			
		|||
/* Copyright 2021 @ 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 "raw_hid.h"
 | 
			
		||||
#include "via.h"
 | 
			
		||||
 | 
			
		||||
#include "keychron_task.h"
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
#    include "transport.h"
 | 
			
		||||
#    include "battery.h"
 | 
			
		||||
#    include "lpm.h"
 | 
			
		||||
#    include "lkbt51.h"
 | 
			
		||||
#    include "indicator.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "version.h"
 | 
			
		||||
 | 
			
		||||
#ifndef RAW_EPSIZE
 | 
			
		||||
#    define RAW_EPSIZE 32
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BL_CYCLE_KEY
 | 
			
		||||
#    define BL_CYCLE_KEY KC_RIGHT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BL_TRIG_KEY
 | 
			
		||||
#    define BL_TRIG_KEY KC_HOME
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef P2P4G_CELAR_MASK
 | 
			
		||||
#    define P2P4G_CELAR_MASK P2P4G_CLEAR_PAIRING_TYPE_C
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    BACKLIGHT_TEST_OFF = 0,
 | 
			
		||||
    BACKLIGHT_TEST_WHITE,
 | 
			
		||||
    BACKLIGHT_TEST_RED,
 | 
			
		||||
    BACKLIGHT_TEST_GREEN,
 | 
			
		||||
    BACKLIGHT_TEST_BLUE,
 | 
			
		||||
    BACKLIGHT_TEST_MAX,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    KEY_PRESS_FN             = 0x01 << 0,
 | 
			
		||||
    KEY_PRESS_J              = 0x01 << 1,
 | 
			
		||||
    KEY_PRESS_Z              = 0x01 << 2,
 | 
			
		||||
    KEY_PRESS_BL_KEY1        = 0x01 << 3,
 | 
			
		||||
    KEY_PRESS_BL_KEY2        = 0x01 << 4,
 | 
			
		||||
    KEY_PRESS_FACTORY_RESET  = KEY_PRESS_FN | KEY_PRESS_J | KEY_PRESS_Z,
 | 
			
		||||
    KEY_PRESS_BACKLIGTH_TEST = KEY_PRESS_FN | KEY_PRESS_BL_KEY1 | KEY_PRESS_BL_KEY2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    FACTORY_TEST_CMD_BACKLIGHT = 0x01,
 | 
			
		||||
    FACTORY_TEST_CMD_OS_SWITCH,
 | 
			
		||||
    FACTORY_TEST_CMD_JUMP_TO_BL,
 | 
			
		||||
    FACTORY_TEST_CMD_INT_PIN,
 | 
			
		||||
    FACTORY_TEST_CMD_GET_TRANSPORT,
 | 
			
		||||
    FACTORY_TEST_CMD_CHARGING_ADC,
 | 
			
		||||
    FACTORY_TEST_CMD_RADIO_CARRIER,
 | 
			
		||||
    FACTORY_TEST_CMD_GET_BUILD_TIME,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    P2P4G_CLEAR_PAIRING_TYPE_A = 0x01 << 0,
 | 
			
		||||
    P2P4G_CLEAR_PAIRING_TYPE_C = 0x01 << 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    OS_SWITCH = 0x01,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static uint32_t factory_reset_timer = 0;
 | 
			
		||||
static uint8_t  factory_reset_state = 0;
 | 
			
		||||
static uint8_t  backlight_test_mode = BACKLIGHT_TEST_OFF;
 | 
			
		||||
 | 
			
		||||
static uint32_t factory_reset_ind_timer = 0;
 | 
			
		||||
static uint8_t  factory_reset_ind_state = 0;
 | 
			
		||||
static bool     report_os_sw_state      = false;
 | 
			
		||||
static bool     keys_released           = true;
 | 
			
		||||
 | 
			
		||||
void factory_timer_start(void) {
 | 
			
		||||
    factory_reset_timer = timer_read32();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void factory_timer_check(void) {
 | 
			
		||||
    if (timer_elapsed32(factory_reset_timer) > 3000) {
 | 
			
		||||
        factory_reset_timer = 0;
 | 
			
		||||
 | 
			
		||||
        if (factory_reset_state == KEY_PRESS_FACTORY_RESET) {
 | 
			
		||||
            factory_reset_ind_timer = timer_read32();
 | 
			
		||||
            factory_reset_ind_state++;
 | 
			
		||||
            keys_released = false;
 | 
			
		||||
 | 
			
		||||
            clear_keyboard(); // Avoid key being pressed after NKRO state changed
 | 
			
		||||
            layer_state_t default_layer_tmp = default_layer_state;
 | 
			
		||||
            eeconfig_init();
 | 
			
		||||
            keymap_config.raw = eeconfig_read_keymap();
 | 
			
		||||
            default_layer_set(default_layer_tmp);
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
            if (!led_matrix_is_enabled()) led_matrix_enable();
 | 
			
		||||
            led_matrix_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
            if (!rgb_matrix_is_enabled()) rgb_matrix_enable();
 | 
			
		||||
            rgb_matrix_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            lkbt51_factory_reset(P2P4G_CELAR_MASK);
 | 
			
		||||
#endif
 | 
			
		||||
        } else if (factory_reset_state == KEY_PRESS_BACKLIGTH_TEST) {
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
            if (!led_matrix_is_enabled()) led_matrix_enable();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
            if (!rgb_matrix_is_enabled()) rgb_matrix_enable();
 | 
			
		||||
#endif
 | 
			
		||||
            backlight_test_mode = BACKLIGHT_TEST_WHITE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        factory_reset_state = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void factory_reset_ind_timer_check(void) {
 | 
			
		||||
    if (factory_reset_ind_timer && timer_elapsed32(factory_reset_ind_timer) > 250) {
 | 
			
		||||
        if (factory_reset_ind_state++ > 6) {
 | 
			
		||||
            factory_reset_ind_timer = factory_reset_ind_state = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            factory_reset_ind_timer = timer_read32();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool process_record_factory_test(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    switch (keycode) {
 | 
			
		||||
#if defined(FN_KEY_1) || defined(FN_KEY_2)
 | 
			
		||||
#    if defined(FN_KEY_1)
 | 
			
		||||
        case FN_KEY_1: /* fall through */
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(FN_KEY_2)
 | 
			
		||||
        case FN_KEY_2:
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(FN_KEY_3)
 | 
			
		||||
        case FN_KEY_3:
 | 
			
		||||
#    endif
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                factory_reset_state |= KEY_PRESS_FN;
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_FN;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
        case KC_J:
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                factory_reset_state |= KEY_PRESS_J;
 | 
			
		||||
                if (factory_reset_state == 0x07) factory_timer_start();
 | 
			
		||||
                if (factory_reset_state & KEY_PRESS_FN) return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_J;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_Z:
 | 
			
		||||
#if defined(FN_Z_KEY)
 | 
			
		||||
        case FN_Z_KEY:
 | 
			
		||||
#endif
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                factory_reset_state |= KEY_PRESS_Z;
 | 
			
		||||
                if (factory_reset_state == 0x07) factory_timer_start();
 | 
			
		||||
                if ((factory_reset_state & KEY_PRESS_FN) && keycode == KC_Z) return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_Z;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
                /* Avoid changing backlight effect on key released if FN_Z_KEY is mode*/
 | 
			
		||||
 | 
			
		||||
                if (!keys_released && keycode >= QK_BACKLIGHT_ON && keycode <= RGB_MODE_TWINKLE) {
 | 
			
		||||
                    keys_released = true;
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#if defined(BL_CYCLE_KEY) || defined(BL_CYCLE_KEY_2)
 | 
			
		||||
#    if defined(BL_CYCLE_KEY)
 | 
			
		||||
        case BL_CYCLE_KEY:
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(FN_BL_CYCLE_KEY)
 | 
			
		||||
        case FN_BL_CYCLE_KEY:
 | 
			
		||||
#    endif
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                if (backlight_test_mode) {
 | 
			
		||||
                    if (++backlight_test_mode >= BACKLIGHT_TEST_MAX) {
 | 
			
		||||
                        backlight_test_mode = BACKLIGHT_TEST_WHITE;
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    factory_reset_state |= KEY_PRESS_BL_KEY1;
 | 
			
		||||
                    if (factory_reset_state == 0x19) {
 | 
			
		||||
                        factory_timer_start();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_BL_KEY1;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(BL_TRIG_KEY) || defined(BL_TRIG_KEY_2)
 | 
			
		||||
#    if defined(BL_TRIG_KEY)
 | 
			
		||||
        case BL_TRIG_KEY:
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(FN_BL_TRIG_KEY)
 | 
			
		||||
        case FN_BL_TRIG_KEY:
 | 
			
		||||
#    endif
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                if (backlight_test_mode) {
 | 
			
		||||
                    backlight_test_mode = BACKLIGHT_TEST_OFF;
 | 
			
		||||
                } else {
 | 
			
		||||
                    factory_reset_state |= KEY_PRESS_BL_KEY2;
 | 
			
		||||
                    if (factory_reset_state == 0x19) {
 | 
			
		||||
                        factory_timer_start();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_BL_KEY2;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
bool factory_test_indicator(void) {
 | 
			
		||||
    if (factory_reset_ind_state) {
 | 
			
		||||
        led_matrix_set_value_all(factory_reset_ind_state % 2 ? 0 : 255);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
bool factory_test_indicator(void) {
 | 
			
		||||
    if (factory_reset_ind_state) {
 | 
			
		||||
        backlight_test_mode = BACKLIGHT_TEST_OFF;
 | 
			
		||||
        rgb_matrix_set_color_all(factory_reset_ind_state % 2 ? 0 : 255, 0, 0);
 | 
			
		||||
        return false;
 | 
			
		||||
    } else if (backlight_test_mode) {
 | 
			
		||||
        switch (backlight_test_mode) {
 | 
			
		||||
            case BACKLIGHT_TEST_WHITE:
 | 
			
		||||
                rgb_matrix_set_color_all(255, 255, 255);
 | 
			
		||||
                break;
 | 
			
		||||
            case BACKLIGHT_TEST_RED:
 | 
			
		||||
                rgb_matrix_set_color_all(255, 0, 0);
 | 
			
		||||
                break;
 | 
			
		||||
            case BACKLIGHT_TEST_GREEN:
 | 
			
		||||
                rgb_matrix_set_color_all(0, 255, 0);
 | 
			
		||||
                break;
 | 
			
		||||
            case BACKLIGHT_TEST_BLUE:
 | 
			
		||||
                rgb_matrix_set_color_all(0, 0, 255);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool factory_reset_indicating(void) {
 | 
			
		||||
    return factory_reset_ind_timer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool factory_test_task(void) {
 | 
			
		||||
    if (factory_reset_timer) factory_timer_check();
 | 
			
		||||
    if (factory_reset_ind_timer) factory_reset_ind_timer_check();
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
void factory_test_init(void) {
 | 
			
		||||
    register_lemokey_task(factory_test_task, false);
 | 
			
		||||
    register_record_process(process_record_factory_test, false);
 | 
			
		||||
    register_led_indicator_task(factory_test_indicator, false);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void factory_test_send(uint8_t *payload, uint8_t length) {
 | 
			
		||||
#ifdef RAW_ENABLE
 | 
			
		||||
    uint16_t checksum         = 0;
 | 
			
		||||
    uint8_t  data[RAW_EPSIZE] = {0};
 | 
			
		||||
 | 
			
		||||
    uint8_t i = 0;
 | 
			
		||||
    data[i++] = 0xAB;
 | 
			
		||||
 | 
			
		||||
    memcpy(&data[i], payload, length);
 | 
			
		||||
    i += length;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = 1; i < RAW_EPSIZE - 3; i++)
 | 
			
		||||
        checksum += data[i];
 | 
			
		||||
    data[RAW_EPSIZE - 2] = checksum & 0xFF;
 | 
			
		||||
    data[RAW_EPSIZE - 1] = (checksum >> 8) & 0xFF;
 | 
			
		||||
 | 
			
		||||
    raw_hid_send(data, RAW_EPSIZE);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factory_test_rx(uint8_t *data, uint8_t length) {
 | 
			
		||||
    if (data[0] == 0xAB) {
 | 
			
		||||
        uint16_t checksum = 0;
 | 
			
		||||
 | 
			
		||||
        for (uint8_t i = 1; i < RAW_EPSIZE - 3; i++) {
 | 
			
		||||
            checksum += data[i];
 | 
			
		||||
        }
 | 
			
		||||
        /* Verify checksum */
 | 
			
		||||
        if ((checksum & 0xFF) != data[RAW_EPSIZE - 2] || checksum >> 8 != data[RAW_EPSIZE - 1]) return;
 | 
			
		||||
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
        uint8_t payload[32];
 | 
			
		||||
        uint8_t len = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        switch (data[1]) {
 | 
			
		||||
            case FACTORY_TEST_CMD_BACKLIGHT:
 | 
			
		||||
                backlight_test_mode = data[2];
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case FACTORY_TEST_CMD_OS_SWITCH:
 | 
			
		||||
                report_os_sw_state = data[2];
 | 
			
		||||
                if (report_os_sw_state) {
 | 
			
		||||
                    // dip_switch_read(true);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case FACTORY_TEST_CMD_JUMP_TO_BL:
 | 
			
		||||
                // if (memcmp(&data[2], "JumpToBootloader", strlen("JumpToBootloader")) == 0) bootloader_jump();
 | 
			
		||||
                break;
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            case FACTORY_TEST_CMD_INT_PIN:
 | 
			
		||||
                switch (data[2]) {
 | 
			
		||||
                    /* Enalbe/disable test */
 | 
			
		||||
                    case 0xA1:
 | 
			
		||||
                        lkbt51_int_pin_test(data[3]);
 | 
			
		||||
                        break;
 | 
			
		||||
                    /* Set INT state */
 | 
			
		||||
                    case 0xA2:
 | 
			
		||||
                        kc_printf("pin %d\n\r", data[3]);
 | 
			
		||||
                        writePin(BLUETOOTH_INT_OUTPUT_PIN, data[3]);
 | 
			
		||||
                        break;
 | 
			
		||||
                        /* Report INT state */
 | 
			
		||||
                        //                    case 0xA3:
 | 
			
		||||
                        //                        payload[len++] = FACTORY_TEST_CMD_INT_PIN;
 | 
			
		||||
                        //                        payload[len++] = 0xA3;
 | 
			
		||||
                        //                        payload[len++] = readPin(LKBT51_INT_INPUT_PIN);
 | 
			
		||||
                        //                        factory_test_send(payload, len);
 | 
			
		||||
                        //                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case FACTORY_TEST_CMD_GET_TRANSPORT:
 | 
			
		||||
                payload[len++] = FACTORY_TEST_CMD_GET_TRANSPORT;
 | 
			
		||||
                payload[len++] = get_transport();
 | 
			
		||||
                payload[len++] = readPin(USB_POWER_SENSE_PIN);
 | 
			
		||||
                factory_test_send(payload, len);
 | 
			
		||||
                break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef BATTERY_CHARGE_DONE_DETECT_ADC
 | 
			
		||||
            case FACTORY_TEST_CMD_CHARGING_ADC:
 | 
			
		||||
            case 0xA1:
 | 
			
		||||
                battery_charging_monitor(data[3]);
 | 
			
		||||
                break;
 | 
			
		||||
            case 0xA2:
 | 
			
		||||
                payload[len++] = FACTORY_TEST_CMD_CHARGING_ADC;
 | 
			
		||||
                payload[len++] = battery_adc_read_charging_pin();
 | 
			
		||||
                factory_test_send(payload, len);
 | 
			
		||||
                break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            case FACTORY_TEST_CMD_RADIO_CARRIER:
 | 
			
		||||
                if (data[2] < 79) lkbt51_radio_test(data[2]);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
#    ifdef WERELESS_PRESSURE_TEST
 | 
			
		||||
            case 0x70:
 | 
			
		||||
                switch (data[2]) {
 | 
			
		||||
                    /* Enalbe/disable test */
 | 
			
		||||
                    case 0xB1:
 | 
			
		||||
                        SEND_STRING("abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890\n");
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 0xB2:
 | 
			
		||||
                        payload[len++] = 0x70;
 | 
			
		||||
                        payload[len++] = 0xB2;
 | 
			
		||||
                        payload[len++] = wireless_get_state();
 | 
			
		||||
                        factory_test_send(payload, len);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
            case FACTORY_TEST_CMD_GET_BUILD_TIME: {
 | 
			
		||||
                payload[len++] = FACTORY_TEST_CMD_GET_BUILD_TIME;
 | 
			
		||||
                payload[len++] = 'v';
 | 
			
		||||
                if ((DEVICE_VER & 0xF000) != 0) itoa((DEVICE_VER >> 12), (char *)&payload[len++], 16);
 | 
			
		||||
                itoa((DEVICE_VER >> 8) & 0xF, (char *)&payload[len++], 16);
 | 
			
		||||
                payload[len++] = '.';
 | 
			
		||||
                itoa((DEVICE_VER >> 4) & 0xF, (char *)&payload[len++], 16);
 | 
			
		||||
                payload[len++] = '.';
 | 
			
		||||
                itoa((DEVICE_VER >> 4) & 0xF, (char *)&payload[len++], 16);
 | 
			
		||||
                payload[len++] = ' ';
 | 
			
		||||
                memcpy(&payload[len], QMK_BUILDDATE, sizeof(QMK_BUILDDATE));
 | 
			
		||||
                len += sizeof(QMK_BUILDDATE);
 | 
			
		||||
                factory_test_send(payload, len);
 | 
			
		||||
            } break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool dip_switch_update_user(uint8_t index, bool active) {
 | 
			
		||||
    if (report_os_sw_state) {
 | 
			
		||||
#ifdef INVERT_OS_SWITCH_STATE
 | 
			
		||||
        active = !active;
 | 
			
		||||
#endif
 | 
			
		||||
        uint8_t payload[3] = {FACTORY_TEST_CMD_OS_SWITCH, OS_SWITCH, active};
 | 
			
		||||
        factory_test_send(payload, 3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,210 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 "keychron_common.h"
 | 
			
		||||
#include "raw_hid.h"
 | 
			
		||||
#include "version.h"
 | 
			
		||||
 | 
			
		||||
#ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
#    include "factory_test.h"
 | 
			
		||||
#    include "keychron_common.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
#    include "lkbt51.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool     is_siri_active = false;
 | 
			
		||||
uint32_t siri_timer     = 0;
 | 
			
		||||
 | 
			
		||||
static uint8_t mac_keycode[4] = {KC_LOPT, KC_ROPT, KC_LCMD, KC_RCMD};
 | 
			
		||||
 | 
			
		||||
static key_combination_t key_comb_list[4] = {{2, {KC_LWIN, KC_TAB}}, {2, {KC_LWIN, KC_E}}, {3, {KC_LSFT, KC_LCMD, KC_4}}, {2, {KC_LWIN, KC_C}}};
 | 
			
		||||
 | 
			
		||||
bool process_record_lemokey_common(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    switch (keycode) {
 | 
			
		||||
        case KC_MCTRL:
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                register_code(KC_MISSION_CONTROL);
 | 
			
		||||
            } else {
 | 
			
		||||
                unregister_code(KC_MISSION_CONTROL);
 | 
			
		||||
            }
 | 
			
		||||
            return false; // Skip all further processing of this key
 | 
			
		||||
        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:
 | 
			
		||||
        case KC_RCMMD:
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                register_code(mac_keycode[keycode - KC_LOPTN]);
 | 
			
		||||
            } else {
 | 
			
		||||
                unregister_code(mac_keycode[keycode - KC_LOPTN]);
 | 
			
		||||
            }
 | 
			
		||||
            return false; // Skip all further processing of this key
 | 
			
		||||
        case KC_SIRI:
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                if (!is_siri_active) {
 | 
			
		||||
                    is_siri_active = true;
 | 
			
		||||
                    register_code(KC_LCMD);
 | 
			
		||||
                    register_code(KC_SPACE);
 | 
			
		||||
                }
 | 
			
		||||
                siri_timer = timer_read32();
 | 
			
		||||
            } else {
 | 
			
		||||
                // Do something else when release
 | 
			
		||||
            }
 | 
			
		||||
            return false; // Skip all further processing of this key
 | 
			
		||||
        case KC_TASK:
 | 
			
		||||
        case KC_FILE:
 | 
			
		||||
        case KC_SNAP:
 | 
			
		||||
        case KC_CTANA:
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                for (uint8_t i = 0; i < key_comb_list[keycode - KC_TASK].len; i++) {
 | 
			
		||||
                    register_code(key_comb_list[keycode - KC_TASK].keycode[i]);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                for (uint8_t i = 0; i < key_comb_list[keycode - KC_TASK].len; i++) {
 | 
			
		||||
                    unregister_code(key_comb_list[keycode - KC_TASK].keycode[i]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false; // Skip all further processing of this key
 | 
			
		||||
        default:
 | 
			
		||||
            return true; // Process all other keycodes normally
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lemokey_common_task(void) {
 | 
			
		||||
    if (is_siri_active && timer_elapsed32(siri_timer) > 500) {
 | 
			
		||||
        unregister_code(KC_LCMD);
 | 
			
		||||
        unregister_code(KC_SPACE);
 | 
			
		||||
        is_siri_active = false;
 | 
			
		||||
        siri_timer     = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef ENCODER_ENABLE
 | 
			
		||||
static void encoder0_pad_cb(void *param) {
 | 
			
		||||
    (void)param;
 | 
			
		||||
    encoder_inerrupt_read(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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; }
 | 
			
		||||
#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 via_command_kb(uint8_t *data, uint8_t length) {
 | 
			
		||||
    // if (!raw_hid_receive_lemokey(data, length))
 | 
			
		||||
    //     return false;
 | 
			
		||||
    switch (data[0]) {
 | 
			
		||||
        case kc_get_protocol_version:
 | 
			
		||||
            data[1] = PROTOCOL_VERSION;
 | 
			
		||||
            raw_hid_send(data, length);
 | 
			
		||||
            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 >> 4) & 0xF, (char *)&data[i++], 16);
 | 
			
		||||
            data[i++] = ' ';
 | 
			
		||||
            memcpy(&data[i], QMK_BUILDDATE, sizeof(QMK_BUILDDATE));
 | 
			
		||||
            i += sizeof(QMK_BUILDDATE);
 | 
			
		||||
            raw_hid_send(data, length);
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case kc_get_support_feature:
 | 
			
		||||
            get_support_feature(&data[1]);
 | 
			
		||||
            raw_hid_send(data, length);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case kc_get_default_layer:
 | 
			
		||||
            data[1] = get_highest_layer(default_layer_state);
 | 
			
		||||
            raw_hid_send(data, length);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
#ifdef ANANLOG_MATRIX
 | 
			
		||||
        case 0xA9:
 | 
			
		||||
            analog_matrix_rx(data, length);
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,75 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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
 | 
			
		||||
 * 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"
 | 
			
		||||
 | 
			
		||||
// clang-format off
 | 
			
		||||
enum {
 | 
			
		||||
    KC_LOPTN = QK_KB_0,
 | 
			
		||||
    KC_ROPTN,
 | 
			
		||||
    KC_LCMMD,
 | 
			
		||||
    KC_RCMMD,
 | 
			
		||||
    KC_MCTRL,
 | 
			
		||||
    KC_LNPAD,
 | 
			
		||||
    KC_TASK_VIEW,
 | 
			
		||||
    KC_FILE_EXPLORER,
 | 
			
		||||
    KC_SCREEN_SHOT,
 | 
			
		||||
    KC_CORTANA,
 | 
			
		||||
    KC_SIRI,
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    BT_HST1,
 | 
			
		||||
    BT_HST2,
 | 
			
		||||
    BT_HST3,
 | 
			
		||||
    P2P4G,
 | 
			
		||||
    BAT_LVL,
 | 
			
		||||
#else
 | 
			
		||||
    BT_HST1 = _______,
 | 
			
		||||
    BT_HST2 = _______,
 | 
			
		||||
    BT_HST3 = _______,
 | 
			
		||||
    P2P4G   = _______,
 | 
			
		||||
    BAT_LVL = _______,
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef DANANLOG_MATRIX
 | 
			
		||||
    PROF1,
 | 
			
		||||
    PROF2,
 | 
			
		||||
    PROF3,
 | 
			
		||||
#else
 | 
			
		||||
    PROF1 = _______,
 | 
			
		||||
    PROF2 = _______,
 | 
			
		||||
    PROF3 = _______,
 | 
			
		||||
#endif
 | 
			
		||||
    NEW_SAFE_RANGE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KC_TASK KC_TASK_VIEW
 | 
			
		||||
#define KC_FILE KC_FILE_EXPLORER
 | 
			
		||||
#define KC_SNAP KC_SCREEN_SHOT
 | 
			
		||||
#define KC_CTANA KC_CORTANA
 | 
			
		||||
 | 
			
		||||
typedef struct PACKED {
 | 
			
		||||
    uint8_t len;
 | 
			
		||||
    uint8_t keycode[3];
 | 
			
		||||
} key_combination_t;
 | 
			
		||||
 | 
			
		||||
bool process_record_lemokey_common(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
void lemokey_common_task(void);
 | 
			
		||||
 | 
			
		||||
#ifdef ENCODER_ENABLE
 | 
			
		||||
void encoder_cb_init(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,239 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 <stdlib.h>
 | 
			
		||||
#include "keychron_task.h"
 | 
			
		||||
#include "quantum.h"
 | 
			
		||||
#include "keychron_common.h"
 | 
			
		||||
#ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
#    include "factory_test.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
 | 
			
		||||
typedef struct lk_node {
 | 
			
		||||
    lemokey_cb      lk_cb;
 | 
			
		||||
    struct lk_node *next;
 | 
			
		||||
} lk_Node;
 | 
			
		||||
 | 
			
		||||
typedef struct lk_process_node {
 | 
			
		||||
    lemokey_record_process_cb process_cb;
 | 
			
		||||
    struct lk_process_node   *next;
 | 
			
		||||
} lk_process_Node;
 | 
			
		||||
 | 
			
		||||
lk_Node         *p;
 | 
			
		||||
lk_Node         *lk_task_list = NULL;
 | 
			
		||||
lk_process_Node *p_process;
 | 
			
		||||
lk_process_Node *lk_record_process_list = NULL;
 | 
			
		||||
 | 
			
		||||
#    if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
lk_Node *led_indicator_task_list = NULL;
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
void register_lemokey_cb(lk_Node **head, lemokey_cb cb, bool priority) {
 | 
			
		||||
    /* Create task node */
 | 
			
		||||
    lk_Node *task = (lk_Node *)malloc(sizeof(lk_Node));
 | 
			
		||||
    task->lk_cb   = cb;
 | 
			
		||||
    task->next    = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Add to the list*/
 | 
			
		||||
    if (*head) {
 | 
			
		||||
        if (priority) {
 | 
			
		||||
            task->next = *head;
 | 
			
		||||
            *head      = task;
 | 
			
		||||
        } else {
 | 
			
		||||
            p = *head;
 | 
			
		||||
            while (p->next)
 | 
			
		||||
                p = p->next;
 | 
			
		||||
            p->next = task;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        *head = task;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void deregister_lemokey_cb(lk_Node **head, lemokey_cb cb) {
 | 
			
		||||
    p = *head;
 | 
			
		||||
    while (p) {
 | 
			
		||||
        if (p->lk_cb == cb) {
 | 
			
		||||
            // lk_Node* temp = p;
 | 
			
		||||
            // if
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void register_lemokey_task(lemokey_cb cb, bool priority) {
 | 
			
		||||
    register_lemokey_cb(&lk_task_list, cb, priority);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void register_led_indicator_task(lemokey_cb cb, bool priority) {
 | 
			
		||||
    register_lemokey_cb(&led_indicator_task_list, cb, priority);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void register_record_process(lemokey_record_process_cb cb, bool priority) {
 | 
			
		||||
    lk_process_Node *process = (lk_process_Node *)malloc(sizeof(lk_process_Node));
 | 
			
		||||
    process->process_cb      = cb;
 | 
			
		||||
    process->next            = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Add to the list*/
 | 
			
		||||
    if (lk_record_process_list) {
 | 
			
		||||
        if (priority) {
 | 
			
		||||
            process->next          = lk_record_process_list;
 | 
			
		||||
            lk_record_process_list = process;
 | 
			
		||||
        } else {
 | 
			
		||||
            p_process = lk_record_process_list;
 | 
			
		||||
            while (p_process->next)
 | 
			
		||||
                p_process = p_process->next;
 | 
			
		||||
            p_process->next = process;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        lk_record_process_list = process;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void lemokey_task(void) {
 | 
			
		||||
    p = lk_task_list;
 | 
			
		||||
    while (p) {
 | 
			
		||||
        p->lk_cb();
 | 
			
		||||
        p = p->next;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool process_record_lemokey(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    p_process = lk_record_process_list;
 | 
			
		||||
    while (p_process) {
 | 
			
		||||
        if (!p_process->process_cb(keycode, record)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        p_process = p_process->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
#        if defined(LED_MATRIX_ENABLE)
 | 
			
		||||
inline bool led_matrix_indicators_lemokey(void) {
 | 
			
		||||
#        else
 | 
			
		||||
inline bool rgb_matrix_indicators_lemokey(void) {
 | 
			
		||||
#        endif
 | 
			
		||||
 | 
			
		||||
    p = led_indicator_task_list;
 | 
			
		||||
    while (p) {
 | 
			
		||||
        p->lk_cb();
 | 
			
		||||
        p = p->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) bool process_record_lemokey_kb(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool process_record_lemokey(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
#    ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    extern bool process_record_wireless(uint16_t keycode, keyrecord_t * record);
 | 
			
		||||
    if (!process_record_wireless(keycode, record)) return false;
 | 
			
		||||
#    endif
 | 
			
		||||
#    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;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    if defined(LED_MATRIX_ENABLE)
 | 
			
		||||
bool led_matrix_indicators_lemokey(void) {
 | 
			
		||||
#        ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    extern bool led_matrix_indicators_bt(void);
 | 
			
		||||
    led_matrix_indicators_bt();
 | 
			
		||||
#        endif
 | 
			
		||||
#        ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
    factory_test_indicator();
 | 
			
		||||
#        endif
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    if defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
bool rgb_matrix_indicators_lemokey(void) {
 | 
			
		||||
#        ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    extern bool rgb_matrix_indicators_bt(void);
 | 
			
		||||
    rgb_matrix_indicators_bt();
 | 
			
		||||
#        endif
 | 
			
		||||
#        ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
    factory_test_indicator();
 | 
			
		||||
#        endif
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) bool lemokey_task_kb(void) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lemokey_task(void) {
 | 
			
		||||
#    ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    extern void wireless_tasks(void);
 | 
			
		||||
    wireless_tasks();
 | 
			
		||||
#    endif
 | 
			
		||||
#    ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
    factory_test_task();
 | 
			
		||||
#    endif
 | 
			
		||||
    lemokey_common_task();
 | 
			
		||||
 | 
			
		||||
    lemokey_task_kb();
 | 
			
		||||
}
 | 
			
		||||
#endif // #ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
 | 
			
		||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    if (!process_record_user(keycode, record)) return false;
 | 
			
		||||
 | 
			
		||||
    if (!process_record_lemokey(keycode, record)) return false;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
bool rgb_matrix_indicators_kb(void) {
 | 
			
		||||
    if (!rgb_matrix_indicators_user()) return false;
 | 
			
		||||
 | 
			
		||||
    rgb_matrix_indicators_lemokey();
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
bool led_matrix_indicators_kb(void) {
 | 
			
		||||
    if (!led_matrix_indicators_user()) return false;
 | 
			
		||||
 | 
			
		||||
    led_matrix_indicators_lemokey();
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void housekeeping_task_kb(void) {
 | 
			
		||||
    lemokey_task();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,41 +0,0 @@
 | 
			
		|||
/* Copyright 2022 @ 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
 | 
			
		||||
 * 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"
 | 
			
		||||
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
typedef bool (*lemokey_cb)(void);
 | 
			
		||||
typedef bool (*lemokey_record_process_cb)(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool process_record_lemokey(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
 | 
			
		||||
void register_lemokey_task(lemokey_cb cb, bool priority);
 | 
			
		||||
void register_record_process(lemokey_record_process_cb cb, bool priority);
 | 
			
		||||
#if defined(LED_MATRIX_ENABLE) ||  defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
void register_led_indicator_task(lemokey_cb cb, bool priority);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
bool lemokey_task_kb(void);
 | 
			
		||||
bool process_record_lemokey_kb(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
void lemokey_task(void);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,445 +0,0 @@
 | 
			
		|||
/* Copyright 2021 @ 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 "raw_hid.h"
 | 
			
		||||
#include "via.h"
 | 
			
		||||
 | 
			
		||||
#include "keychron_task.h"
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
#    include "transport.h"
 | 
			
		||||
#    include "battery.h"
 | 
			
		||||
#    include "lpm.h"
 | 
			
		||||
#    include "lkbt51.h"
 | 
			
		||||
#    include "indicator.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "version.h"
 | 
			
		||||
 | 
			
		||||
#ifndef RAW_EPSIZE
 | 
			
		||||
#    define RAW_EPSIZE 32
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BL_CYCLE_KEY
 | 
			
		||||
#    define BL_CYCLE_KEY KC_RIGHT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BL_TRIG_KEY
 | 
			
		||||
#    define BL_TRIG_KEY KC_HOME
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef P2P4G_CELAR_MASK
 | 
			
		||||
#    define P2P4G_CELAR_MASK P2P4G_CLEAR_PAIRING_TYPE_C
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    BACKLIGHT_TEST_OFF = 0,
 | 
			
		||||
    BACKLIGHT_TEST_WHITE,
 | 
			
		||||
    BACKLIGHT_TEST_RED,
 | 
			
		||||
    BACKLIGHT_TEST_GREEN,
 | 
			
		||||
    BACKLIGHT_TEST_BLUE,
 | 
			
		||||
    BACKLIGHT_TEST_MAX,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    KEY_PRESS_FN             = 0x01 << 0,
 | 
			
		||||
    KEY_PRESS_J              = 0x01 << 1,
 | 
			
		||||
    KEY_PRESS_Z              = 0x01 << 2,
 | 
			
		||||
    KEY_PRESS_BL_KEY1        = 0x01 << 3,
 | 
			
		||||
    KEY_PRESS_BL_KEY2        = 0x01 << 4,
 | 
			
		||||
    KEY_PRESS_FACTORY_RESET  = KEY_PRESS_FN | KEY_PRESS_J | KEY_PRESS_Z,
 | 
			
		||||
    KEY_PRESS_BACKLIGTH_TEST = KEY_PRESS_FN | KEY_PRESS_BL_KEY1 | KEY_PRESS_BL_KEY2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    FACTORY_TEST_CMD_BACKLIGHT = 0x01,
 | 
			
		||||
    FACTORY_TEST_CMD_OS_SWITCH,
 | 
			
		||||
    FACTORY_TEST_CMD_JUMP_TO_BL,
 | 
			
		||||
    FACTORY_TEST_CMD_INT_PIN,
 | 
			
		||||
    FACTORY_TEST_CMD_GET_TRANSPORT,
 | 
			
		||||
    FACTORY_TEST_CMD_CHARGING_ADC,
 | 
			
		||||
    FACTORY_TEST_CMD_RADIO_CARRIER,
 | 
			
		||||
    FACTORY_TEST_CMD_GET_BUILD_TIME,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    P2P4G_CLEAR_PAIRING_TYPE_A = 0x01 << 0,
 | 
			
		||||
    P2P4G_CLEAR_PAIRING_TYPE_C = 0x01 << 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    OS_SWITCH = 0x01,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static uint32_t factory_reset_timer = 0;
 | 
			
		||||
static uint8_t  factory_reset_state = 0;
 | 
			
		||||
static uint8_t  backlight_test_mode = BACKLIGHT_TEST_OFF;
 | 
			
		||||
 | 
			
		||||
static uint32_t factory_reset_ind_timer = 0;
 | 
			
		||||
static uint8_t  factory_reset_ind_state = 0;
 | 
			
		||||
static bool     report_os_sw_state      = false;
 | 
			
		||||
static bool     keys_released           = true;
 | 
			
		||||
 | 
			
		||||
void factory_timer_start(void) {
 | 
			
		||||
    factory_reset_timer = timer_read32();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void factory_timer_check(void) {
 | 
			
		||||
    if (timer_elapsed32(factory_reset_timer) > 3000) {
 | 
			
		||||
        factory_reset_timer = 0;
 | 
			
		||||
 | 
			
		||||
        if (factory_reset_state == KEY_PRESS_FACTORY_RESET) {
 | 
			
		||||
            factory_reset_ind_timer = timer_read32();
 | 
			
		||||
            factory_reset_ind_state++;
 | 
			
		||||
            keys_released = false;
 | 
			
		||||
 | 
			
		||||
            clear_keyboard(); // Avoid key being pressed after NKRO state changed
 | 
			
		||||
            layer_state_t default_layer_tmp = default_layer_state;
 | 
			
		||||
            eeconfig_init();
 | 
			
		||||
            keymap_config.raw = eeconfig_read_keymap();
 | 
			
		||||
            default_layer_set(default_layer_tmp);
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
            if (!led_matrix_is_enabled()) led_matrix_enable();
 | 
			
		||||
            led_matrix_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
            if (!rgb_matrix_is_enabled()) rgb_matrix_enable();
 | 
			
		||||
            rgb_matrix_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            lkbt51_factory_reset(P2P4G_CELAR_MASK);
 | 
			
		||||
#endif
 | 
			
		||||
        } else if (factory_reset_state == KEY_PRESS_BACKLIGTH_TEST) {
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
            if (!led_matrix_is_enabled()) led_matrix_enable();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
            if (!rgb_matrix_is_enabled()) rgb_matrix_enable();
 | 
			
		||||
#endif
 | 
			
		||||
            backlight_test_mode = BACKLIGHT_TEST_WHITE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        factory_reset_state = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void factory_reset_ind_timer_check(void) {
 | 
			
		||||
    if (factory_reset_ind_timer && timer_elapsed32(factory_reset_ind_timer) > 250) {
 | 
			
		||||
        if (factory_reset_ind_state++ > 6) {
 | 
			
		||||
            factory_reset_ind_timer = factory_reset_ind_state = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            factory_reset_ind_timer = timer_read32();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool process_record_factory_test(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    switch (keycode) {
 | 
			
		||||
#if defined(FN_KEY_1) || defined(FN_KEY_2)
 | 
			
		||||
#    if defined(FN_KEY_1)
 | 
			
		||||
        case FN_KEY_1: /* fall through */
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(FN_KEY_2)
 | 
			
		||||
        case FN_KEY_2:
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(FN_KEY_3)
 | 
			
		||||
        case FN_KEY_3:
 | 
			
		||||
#    endif
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                factory_reset_state |= KEY_PRESS_FN;
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_FN;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
        case KC_J:
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                factory_reset_state |= KEY_PRESS_J;
 | 
			
		||||
                if (factory_reset_state == 0x07) factory_timer_start();
 | 
			
		||||
                if (factory_reset_state & KEY_PRESS_FN) return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_J;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_Z:
 | 
			
		||||
#if defined(FN_Z_KEY)
 | 
			
		||||
        case FN_Z_KEY:
 | 
			
		||||
#endif
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                factory_reset_state |= KEY_PRESS_Z;
 | 
			
		||||
                if (factory_reset_state == 0x07) factory_timer_start();
 | 
			
		||||
                if ((factory_reset_state & KEY_PRESS_FN) && keycode == KC_Z) return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_Z;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
                /* Avoid changing backlight effect on key released if FN_Z_KEY is mode*/
 | 
			
		||||
 | 
			
		||||
                if (!keys_released && keycode >= QK_BACKLIGHT_ON && keycode <= RGB_MODE_TWINKLE) {
 | 
			
		||||
                    keys_released = true;
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#if defined(BL_CYCLE_KEY) || defined(BL_CYCLE_KEY_2)
 | 
			
		||||
#    if defined(BL_CYCLE_KEY)
 | 
			
		||||
        case BL_CYCLE_KEY:
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(FN_BL_CYCLE_KEY)
 | 
			
		||||
        case FN_BL_CYCLE_KEY:
 | 
			
		||||
#    endif
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                if (backlight_test_mode) {
 | 
			
		||||
                    if (++backlight_test_mode >= BACKLIGHT_TEST_MAX) {
 | 
			
		||||
                        backlight_test_mode = BACKLIGHT_TEST_WHITE;
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    factory_reset_state |= KEY_PRESS_BL_KEY1;
 | 
			
		||||
                    if (factory_reset_state == 0x19) {
 | 
			
		||||
                        factory_timer_start();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_BL_KEY1;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(BL_TRIG_KEY) || defined(BL_TRIG_KEY_2)
 | 
			
		||||
#    if defined(BL_TRIG_KEY)
 | 
			
		||||
        case BL_TRIG_KEY:
 | 
			
		||||
#    endif
 | 
			
		||||
#    if defined(FN_BL_TRIG_KEY)
 | 
			
		||||
        case FN_BL_TRIG_KEY:
 | 
			
		||||
#    endif
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                if (backlight_test_mode) {
 | 
			
		||||
                    backlight_test_mode = BACKLIGHT_TEST_OFF;
 | 
			
		||||
                } else {
 | 
			
		||||
                    factory_reset_state |= KEY_PRESS_BL_KEY2;
 | 
			
		||||
                    if (factory_reset_state == 0x19) {
 | 
			
		||||
                        factory_timer_start();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                factory_reset_state &= ~KEY_PRESS_BL_KEY2;
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
bool factory_test_indicator(void) {
 | 
			
		||||
    if (factory_reset_ind_state) {
 | 
			
		||||
        led_matrix_set_value_all(factory_reset_ind_state % 2 ? 0 : 255);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
bool factory_test_indicator(void) {
 | 
			
		||||
    if (factory_reset_ind_state) {
 | 
			
		||||
        backlight_test_mode = BACKLIGHT_TEST_OFF;
 | 
			
		||||
        rgb_matrix_set_color_all(factory_reset_ind_state % 2 ? 0 : 255, 0, 0);
 | 
			
		||||
        return false;
 | 
			
		||||
    } else if (backlight_test_mode) {
 | 
			
		||||
        switch (backlight_test_mode) {
 | 
			
		||||
            case BACKLIGHT_TEST_WHITE:
 | 
			
		||||
                rgb_matrix_set_color_all(255, 255, 255);
 | 
			
		||||
                break;
 | 
			
		||||
            case BACKLIGHT_TEST_RED:
 | 
			
		||||
                rgb_matrix_set_color_all(255, 0, 0);
 | 
			
		||||
                break;
 | 
			
		||||
            case BACKLIGHT_TEST_GREEN:
 | 
			
		||||
                rgb_matrix_set_color_all(0, 255, 0);
 | 
			
		||||
                break;
 | 
			
		||||
            case BACKLIGHT_TEST_BLUE:
 | 
			
		||||
                rgb_matrix_set_color_all(0, 0, 255);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool factory_reset_indicating(void) {
 | 
			
		||||
    return factory_reset_ind_timer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool factory_test_task(void) {
 | 
			
		||||
    if (factory_reset_timer) factory_timer_check();
 | 
			
		||||
    if (factory_reset_ind_timer) factory_reset_ind_timer_check();
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
void factory_test_init(void) {
 | 
			
		||||
    register_keychron_task(factory_test_task, false);
 | 
			
		||||
    register_record_process(process_record_factory_test, false);
 | 
			
		||||
    register_led_indicator_task(factory_test_indicator, false);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void factory_test_send(uint8_t *payload, uint8_t length) {
 | 
			
		||||
#ifdef RAW_ENABLE
 | 
			
		||||
    uint16_t checksum         = 0;
 | 
			
		||||
    uint8_t  data[RAW_EPSIZE] = {0};
 | 
			
		||||
 | 
			
		||||
    uint8_t i = 0;
 | 
			
		||||
    data[i++] = 0xAB;
 | 
			
		||||
 | 
			
		||||
    memcpy(&data[i], payload, length);
 | 
			
		||||
    i += length;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = 1; i < RAW_EPSIZE - 3; i++)
 | 
			
		||||
        checksum += data[i];
 | 
			
		||||
    data[RAW_EPSIZE - 2] = checksum & 0xFF;
 | 
			
		||||
    data[RAW_EPSIZE - 1] = (checksum >> 8) & 0xFF;
 | 
			
		||||
 | 
			
		||||
    raw_hid_send(data, RAW_EPSIZE);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factory_test_rx(uint8_t *data, uint8_t length) {
 | 
			
		||||
    if (data[0] == 0xAB) {
 | 
			
		||||
        uint16_t checksum = 0;
 | 
			
		||||
 | 
			
		||||
        for (uint8_t i = 1; i < RAW_EPSIZE - 3; i++) {
 | 
			
		||||
            checksum += data[i];
 | 
			
		||||
        }
 | 
			
		||||
        /* Verify checksum */
 | 
			
		||||
        if ((checksum & 0xFF) != data[RAW_EPSIZE - 2] || checksum >> 8 != data[RAW_EPSIZE - 1]) return;
 | 
			
		||||
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
        uint8_t payload[32];
 | 
			
		||||
        uint8_t len = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        switch (data[1]) {
 | 
			
		||||
            case FACTORY_TEST_CMD_BACKLIGHT:
 | 
			
		||||
                backlight_test_mode = data[2];
 | 
			
		||||
                factory_reset_timer = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case FACTORY_TEST_CMD_OS_SWITCH:
 | 
			
		||||
                report_os_sw_state = data[2];
 | 
			
		||||
                if (report_os_sw_state) {
 | 
			
		||||
                    // dip_switch_read(true);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case FACTORY_TEST_CMD_JUMP_TO_BL:
 | 
			
		||||
                // if (memcmp(&data[2], "JumpToBootloader", strlen("JumpToBootloader")) == 0) bootloader_jump();
 | 
			
		||||
                break;
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            case FACTORY_TEST_CMD_INT_PIN:
 | 
			
		||||
                switch (data[2]) {
 | 
			
		||||
                    /* Enalbe/disable test */
 | 
			
		||||
                    case 0xA1:
 | 
			
		||||
                        lkbt51_int_pin_test(data[3]);
 | 
			
		||||
                        break;
 | 
			
		||||
                    /* Set INT state */
 | 
			
		||||
                    case 0xA2:
 | 
			
		||||
                        kc_printf("pin %d\n\r", data[3]);
 | 
			
		||||
                        writePin(BLUETOOTH_INT_OUTPUT_PIN, data[3]);
 | 
			
		||||
                        break;
 | 
			
		||||
                        /* Report INT state */
 | 
			
		||||
                        //                    case 0xA3:
 | 
			
		||||
                        //                        payload[len++] = FACTORY_TEST_CMD_INT_PIN;
 | 
			
		||||
                        //                        payload[len++] = 0xA3;
 | 
			
		||||
                        //                        payload[len++] = readPin(LKBT51_INT_INPUT_PIN);
 | 
			
		||||
                        //                        factory_test_send(payload, len);
 | 
			
		||||
                        //                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case FACTORY_TEST_CMD_GET_TRANSPORT:
 | 
			
		||||
                payload[len++] = FACTORY_TEST_CMD_GET_TRANSPORT;
 | 
			
		||||
                payload[len++] = get_transport();
 | 
			
		||||
                payload[len++] = readPin(USB_POWER_SENSE_PIN);
 | 
			
		||||
                factory_test_send(payload, len);
 | 
			
		||||
                break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef BATTERY_CHARGE_DONE_DETECT_ADC
 | 
			
		||||
            case FACTORY_TEST_CMD_CHARGING_ADC:
 | 
			
		||||
            case 0xA1:
 | 
			
		||||
                battery_charging_monitor(data[3]);
 | 
			
		||||
                break;
 | 
			
		||||
            case 0xA2:
 | 
			
		||||
                payload[len++] = FACTORY_TEST_CMD_CHARGING_ADC;
 | 
			
		||||
                payload[len++] = battery_adc_read_charging_pin();
 | 
			
		||||
                factory_test_send(payload, len);
 | 
			
		||||
                break;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            case FACTORY_TEST_CMD_RADIO_CARRIER:
 | 
			
		||||
                if (data[2] < 79) lkbt51_radio_test(data[2]);
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
#    ifdef WERELESS_PRESSURE_TEST
 | 
			
		||||
            case 0x70:
 | 
			
		||||
                switch (data[2]) {
 | 
			
		||||
                    /* Enalbe/disable test */
 | 
			
		||||
                    case 0xB1:
 | 
			
		||||
                        SEND_STRING("abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890\n");
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 0xB2:
 | 
			
		||||
                        payload[len++] = 0x70;
 | 
			
		||||
                        payload[len++] = 0xB2;
 | 
			
		||||
                        payload[len++] = wireless_get_state();
 | 
			
		||||
                        factory_test_send(payload, len);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
            case FACTORY_TEST_CMD_GET_BUILD_TIME: {
 | 
			
		||||
                payload[len++] = FACTORY_TEST_CMD_GET_BUILD_TIME;
 | 
			
		||||
                payload[len++] = 'v';
 | 
			
		||||
                if ((DEVICE_VER & 0xF000) != 0) itoa((DEVICE_VER >> 12), (char *)&payload[len++], 16);
 | 
			
		||||
                itoa((DEVICE_VER >> 8) & 0xF, (char *)&payload[len++], 16);
 | 
			
		||||
                payload[len++] = '.';
 | 
			
		||||
                itoa((DEVICE_VER >> 4) & 0xF, (char *)&payload[len++], 16);
 | 
			
		||||
                payload[len++] = '.';
 | 
			
		||||
                itoa((DEVICE_VER >> 4) & 0xF, (char *)&payload[len++], 16);
 | 
			
		||||
                payload[len++] = ' ';
 | 
			
		||||
                memcpy(&payload[len], QMK_BUILDDATE, sizeof(QMK_BUILDDATE));
 | 
			
		||||
                len += sizeof(QMK_BUILDDATE);
 | 
			
		||||
                factory_test_send(payload, len);
 | 
			
		||||
            } break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool dip_switch_update_user(uint8_t index, bool active) {
 | 
			
		||||
    if (report_os_sw_state) {
 | 
			
		||||
#ifdef INVERT_OS_SWITCH_STATE
 | 
			
		||||
        active = !active;
 | 
			
		||||
#endif
 | 
			
		||||
        uint8_t payload[3] = {FACTORY_TEST_CMD_OS_SWITCH, OS_SWITCH, active};
 | 
			
		||||
        factory_test_send(payload, 3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,239 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 <stdlib.h>
 | 
			
		||||
#include "keychron_task.h"
 | 
			
		||||
#include "quantum.h"
 | 
			
		||||
#include "keychron_common.h"
 | 
			
		||||
#ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
#    include "factory_test.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
 | 
			
		||||
typedef struct lk_node {
 | 
			
		||||
    keychron_cb      lk_cb;
 | 
			
		||||
    struct lk_node *next;
 | 
			
		||||
} lk_Node;
 | 
			
		||||
 | 
			
		||||
typedef struct lk_process_node {
 | 
			
		||||
    keychron_record_process_cb process_cb;
 | 
			
		||||
    struct lk_process_node   *next;
 | 
			
		||||
} lk_process_Node;
 | 
			
		||||
 | 
			
		||||
lk_Node         *p;
 | 
			
		||||
lk_Node         *lk_task_list = NULL;
 | 
			
		||||
lk_process_Node *p_process;
 | 
			
		||||
lk_process_Node *lk_record_process_list = NULL;
 | 
			
		||||
 | 
			
		||||
#    if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
lk_Node *led_indicator_task_list = NULL;
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
void register_keychron_cb(lk_Node **head, keychron_cb cb, bool priority) {
 | 
			
		||||
    /* Create task node */
 | 
			
		||||
    lk_Node *task = (lk_Node *)malloc(sizeof(lk_Node));
 | 
			
		||||
    task->lk_cb   = cb;
 | 
			
		||||
    task->next    = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Add to the list*/
 | 
			
		||||
    if (*head) {
 | 
			
		||||
        if (priority) {
 | 
			
		||||
            task->next = *head;
 | 
			
		||||
            *head      = task;
 | 
			
		||||
        } else {
 | 
			
		||||
            p = *head;
 | 
			
		||||
            while (p->next)
 | 
			
		||||
                p = p->next;
 | 
			
		||||
            p->next = task;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        *head = task;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void deregister_keychron_cb(lk_Node **head, keychron_cb cb) {
 | 
			
		||||
    p = *head;
 | 
			
		||||
    while (p) {
 | 
			
		||||
        if (p->lk_cb == cb) {
 | 
			
		||||
            // lk_Node* temp = p;
 | 
			
		||||
            // if
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void register_keychron_task(keychron_cb cb, bool priority) {
 | 
			
		||||
    register_keychron_cb(&lk_task_list, cb, priority);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void register_led_indicator_task(keychron_cb cb, bool priority) {
 | 
			
		||||
    register_keychron_cb(&led_indicator_task_list, cb, priority);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void register_record_process(keychron_record_process_cb cb, bool priority) {
 | 
			
		||||
    lk_process_Node *process = (lk_process_Node *)malloc(sizeof(lk_process_Node));
 | 
			
		||||
    process->process_cb      = cb;
 | 
			
		||||
    process->next            = NULL;
 | 
			
		||||
 | 
			
		||||
    /* Add to the list*/
 | 
			
		||||
    if (lk_record_process_list) {
 | 
			
		||||
        if (priority) {
 | 
			
		||||
            process->next          = lk_record_process_list;
 | 
			
		||||
            lk_record_process_list = process;
 | 
			
		||||
        } else {
 | 
			
		||||
            p_process = lk_record_process_list;
 | 
			
		||||
            while (p_process->next)
 | 
			
		||||
                p_process = p_process->next;
 | 
			
		||||
            p_process->next = process;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        lk_record_process_list = process;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void keychron_task(void) {
 | 
			
		||||
    p = lk_task_list;
 | 
			
		||||
    while (p) {
 | 
			
		||||
        p->lk_cb();
 | 
			
		||||
        p = p->next;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool process_record_keychron(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    p_process = lk_record_process_list;
 | 
			
		||||
    while (p_process) {
 | 
			
		||||
        if (!p_process->process_cb(keycode, record)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        p_process = p_process->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
#        if defined(LED_MATRIX_ENABLE)
 | 
			
		||||
inline bool led_matrix_indicators_keychron(void) {
 | 
			
		||||
#        else
 | 
			
		||||
inline bool rgb_matrix_indicators_keychron(void) {
 | 
			
		||||
#        endif
 | 
			
		||||
 | 
			
		||||
    p = led_indicator_task_list;
 | 
			
		||||
    while (p) {
 | 
			
		||||
        p->lk_cb();
 | 
			
		||||
        p = p->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) bool process_record_keychron_kb(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool process_record_keychron(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
#    ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    extern bool process_record_wireless(uint16_t keycode, keyrecord_t * record);
 | 
			
		||||
    if (!process_record_wireless(keycode, record)) return false;
 | 
			
		||||
#    endif
 | 
			
		||||
#    ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
    if (!process_record_factory_test(keycode, record)) return false;
 | 
			
		||||
#    endif
 | 
			
		||||
    // extern bool process_record_keychron_kb(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
 | 
			
		||||
    if (!process_record_keychron_kb(keycode, record)) return false;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    if defined(LED_MATRIX_ENABLE)
 | 
			
		||||
bool led_matrix_indicators_keychron(void) {
 | 
			
		||||
#        ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    extern bool led_matrix_indicators_bt(void);
 | 
			
		||||
    led_matrix_indicators_bt();
 | 
			
		||||
#        endif
 | 
			
		||||
#        ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
    factory_test_indicator();
 | 
			
		||||
#        endif
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    if defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
bool rgb_matrix_indicators_keychron(void) {
 | 
			
		||||
#        ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    extern bool rgb_matrix_indicators_bt(void);
 | 
			
		||||
    rgb_matrix_indicators_bt();
 | 
			
		||||
#        endif
 | 
			
		||||
#        ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
    factory_test_indicator();
 | 
			
		||||
#        endif
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) bool keychron_task_kb(void) {
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keychron_task(void) {
 | 
			
		||||
#    ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    extern void wireless_tasks(void);
 | 
			
		||||
    wireless_tasks();
 | 
			
		||||
#    endif
 | 
			
		||||
#    ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
    factory_test_task();
 | 
			
		||||
#    endif
 | 
			
		||||
    keychron_common_task();
 | 
			
		||||
 | 
			
		||||
    keychron_task_kb();
 | 
			
		||||
}
 | 
			
		||||
#endif // #ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
 | 
			
		||||
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    if (!process_record_user(keycode, record)) return false;
 | 
			
		||||
 | 
			
		||||
    if (!process_record_keychron(keycode, record)) return false;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
bool rgb_matrix_indicators_kb(void) {
 | 
			
		||||
    if (!rgb_matrix_indicators_user()) return false;
 | 
			
		||||
 | 
			
		||||
    rgb_matrix_indicators_keychron();
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
bool led_matrix_indicators_kb(void) {
 | 
			
		||||
    if (!led_matrix_indicators_user()) return false;
 | 
			
		||||
 | 
			
		||||
    led_matrix_indicators_keychron();
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void housekeeping_task_kb(void) {
 | 
			
		||||
    keychron_task();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,41 +0,0 @@
 | 
			
		|||
/* Copyright 2022 @ 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"
 | 
			
		||||
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
typedef bool (*keychron_cb)(void);
 | 
			
		||||
typedef bool (*keychron_record_process_cb)(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool process_record_keychron(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
 | 
			
		||||
void register_keychron_task(keychron_cb cb, bool priority);
 | 
			
		||||
void register_record_process(keychron_record_process_cb cb, bool priority);
 | 
			
		||||
#if defined(LED_MATRIX_ENABLE) ||  defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
void register_led_indicator_task(keychron_cb cb, bool priority);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
bool keychron_task_kb(void);
 | 
			
		||||
bool process_record_keychron_kb(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
void keychron_task(void);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED matrix configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 108
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 109
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 112
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 69
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 69
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 61
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define DRIVER_1_LED_TOTAL 90
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT DRIVER_1_LED_TOTAL
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 72
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 87
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 88
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 84
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 85
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define DRIVER_1_LED_COUNT 87
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT DRIVER_1_LED_COUNT
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 84
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 85
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 87
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 100
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define DRIVER_1_LED_COUNT 101
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT DRIVER_1_LED_COUNT
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 108
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 109
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 112
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 68
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 69
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 68
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 69
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 88
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED matrix driver configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 88
 | 
			
		||||
 | 
			
		||||
/* Set to infinit, which is use in USB mode by default */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 91
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 61
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 62
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@
 | 
			
		|||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
/* LED Matrix Driver Configuration */
 | 
			
		||||
#    define DRIVER_COUNT 1
 | 
			
		||||
#    define DRIVER_ADDR_1 0b1110100
 | 
			
		||||
#    define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
 | 
			
		||||
 | 
			
		||||
/* LED Matrix Configuration */
 | 
			
		||||
#    define LED_MATRIX_LED_COUNT 65
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,91 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 "keychron_task.h"
 | 
			
		||||
#ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
#    include "factory_test.h"
 | 
			
		||||
#    include "keychron_common.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
#    include "lkbt51.h"
 | 
			
		||||
#    include "wireless.h"
 | 
			
		||||
#    include "lemokey_wireless_common.h"
 | 
			
		||||
#    include "battery.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define POWER_ON_LED_DURATION 3000
 | 
			
		||||
static uint32_t power_on_indicator_timer_buffer;
 | 
			
		||||
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
bool lemokey_task_kb(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool dip_switch_update_kb(uint8_t index, bool active) {
 | 
			
		||||
    if (index == 0) {
 | 
			
		||||
        default_layer_set(1UL << (active ? 0 : 2));
 | 
			
		||||
    }
 | 
			
		||||
    dip_switch_update_user(index, active);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_post_init_kb(void) {
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    palSetLineMode(P2P4_MODE_SELECT_PIN, PAL_MODE_INPUT);
 | 
			
		||||
    palSetLineMode(BT_MODE_SELECT_PIN, PAL_MODE_INPUT);
 | 
			
		||||
 | 
			
		||||
    writePin(BAT_LOW_LED_PIN, BAT_LOW_LED_PIN_ON_STATE);
 | 
			
		||||
 | 
			
		||||
    lkbt51_init(false);
 | 
			
		||||
    wireless_init();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    power_on_indicator_timer_buffer = timer_read32();
 | 
			
		||||
#ifdef ENCODER_ENABLE
 | 
			
		||||
    encoder_cb_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
    factory_test_init();
 | 
			
		||||
    register_record_process(process_record_lemokey_kb, false);
 | 
			
		||||
    register_lemokey_task(lemokey_task_kb, false);
 | 
			
		||||
#endif
 | 
			
		||||
    keyboard_post_init_user();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool lemokey_task_kb(void) {
 | 
			
		||||
    if (power_on_indicator_timer_buffer) {
 | 
			
		||||
        if (timer_elapsed32(power_on_indicator_timer_buffer) > POWER_ON_LED_DURATION) {
 | 
			
		||||
            power_on_indicator_timer_buffer = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            writePin(BAT_LOW_LED_PIN, BAT_LOW_LED_PIN_ON_STATE);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
bool lpm_is_kb_idle(void) {
 | 
			
		||||
    return power_on_indicator_timer_buffer == 0 && !factory_reset_indicating();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,91 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 "keychron_task.h"
 | 
			
		||||
#ifdef FACTORY_TEST_ENABLE
 | 
			
		||||
#    include "factory_test.h"
 | 
			
		||||
#    include "keychron_common.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
#    include "lkbt51.h"
 | 
			
		||||
#    include "wireless.h"
 | 
			
		||||
#    include "keychron_wireless_common.h"
 | 
			
		||||
#    include "battery.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define POWER_ON_LED_DURATION 3000
 | 
			
		||||
static uint32_t power_on_indicator_timer_buffer;
 | 
			
		||||
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
bool keychron_task_kb(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool dip_switch_update_kb(uint8_t index, bool active) {
 | 
			
		||||
    if (index == 0) {
 | 
			
		||||
        default_layer_set(1UL << (active ? 0 : 2));
 | 
			
		||||
    }
 | 
			
		||||
    dip_switch_update_user(index, active);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_post_init_kb(void) {
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
    palSetLineMode(P2P4_MODE_SELECT_PIN, PAL_MODE_INPUT);
 | 
			
		||||
    palSetLineMode(BT_MODE_SELECT_PIN, PAL_MODE_INPUT);
 | 
			
		||||
 | 
			
		||||
    writePin(BAT_LOW_LED_PIN, BAT_LOW_LED_PIN_ON_STATE);
 | 
			
		||||
 | 
			
		||||
    lkbt51_init(false);
 | 
			
		||||
    wireless_init();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    power_on_indicator_timer_buffer = timer_read32();
 | 
			
		||||
#ifdef ENCODER_ENABLE
 | 
			
		||||
    encoder_cb_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LEMOKEY_CALLBACK_ENABLE
 | 
			
		||||
    factory_test_init();
 | 
			
		||||
    register_record_process(process_record_keychron_kb, false);
 | 
			
		||||
    register_keychron_task(keychron_task_kb, false);
 | 
			
		||||
#endif
 | 
			
		||||
    keyboard_post_init_user();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool keychron_task_kb(void) {
 | 
			
		||||
    if (power_on_indicator_timer_buffer) {
 | 
			
		||||
        if (timer_elapsed32(power_on_indicator_timer_buffer) > POWER_ON_LED_DURATION) {
 | 
			
		||||
            power_on_indicator_timer_buffer = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            writePin(BAT_LOW_LED_PIN, !BAT_LOW_LED_PIN_ON_STATE);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
            writePin(BAT_LOW_LED_PIN, BAT_LOW_LED_PIN_ON_STATE);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef LK_WIRELESS_ENABLE
 | 
			
		||||
bool lpm_is_kb_idle(void) {
 | 
			
		||||
    return power_on_indicator_timer_buffer == 0 && !factory_reset_indicating();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,76 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 "keychron_common.h"
 | 
			
		||||
 | 
			
		||||
enum layers {
 | 
			
		||||
    MAC_BASE,
 | 
			
		||||
    MAC_FN,
 | 
			
		||||
    WIN_BASE,
 | 
			
		||||
    WIN_FN,
 | 
			
		||||
};
 | 
			
		||||
// clang-format off
 | 
			
		||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
			
		||||
 [MAC_BASE] = LAYOUT_ansi_82(
 | 
			
		||||
        KC_ESC,   KC_BRID,  KC_BRIU,  KC_MCTRL, KC_LNPAD, RGB_VAD,  RGB_VAI,  KC_MPRV,  KC_MPLY,  KC_MNXT,  KC_MUTE,  KC_VOLD,  KC_VOLU,  KC_DEL,             KC_MUTE,
 | 
			
		||||
        KC_GRV,   KC_1,     KC_2,     KC_3,     KC_4,     KC_5,     KC_6,     KC_7,     KC_8,     KC_9,     KC_0,     KC_MINS,  KC_EQL,   KC_BSPC,            KC_PGUP,
 | 
			
		||||
        KC_TAB,   KC_Q,     KC_W,     KC_E,     KC_R,     KC_T,     KC_Y,     KC_U,     KC_I,     KC_O,     KC_P,     KC_LBRC,  KC_RBRC,  KC_BSLS,            KC_PGDN,
 | 
			
		||||
        KC_CAPS,  KC_A,     KC_S,     KC_D,     KC_F,     KC_G,     KC_H,     KC_J,     KC_K,     KC_L,     KC_SCLN,  KC_QUOT,            KC_ENT,             KC_HOME,
 | 
			
		||||
        KC_LSFT,            KC_Z,     KC_X,     KC_C,     KC_V,     KC_B,     KC_N,     KC_M,     KC_COMM,  KC_DOT,   KC_SLSH,            KC_RSFT,  KC_UP,
 | 
			
		||||
        KC_LCTL,  KC_LOPTN, KC_LCMMD,                               KC_SPC,                                 KC_RCMMD,MO(MAC_FN),KC_RCTL,  KC_LEFT,  KC_DOWN,  KC_RGHT),
 | 
			
		||||
 | 
			
		||||
    [MAC_FN] = LAYOUT_ansi_82(
 | 
			
		||||
        KC_TRNS,  KC_F1,    KC_F2,    KC_F3,    KC_F4,    KC_F5,    KC_F6,    KC_F7,    KC_F8,    KC_F9,    KC_F10,   KC_F11,   KC_F12,   KC_TRNS,            RGB_TOG,
 | 
			
		||||
        KC_TRNS,  BT_HST1,  BT_HST2,  BT_HST3,  P2P4G,    KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,
 | 
			
		||||
        RGB_TOG,  RGB_MOD,  RGB_VAI,  RGB_HUI,  RGB_SAI,  RGB_SPI,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,
 | 
			
		||||
        KC_TRNS,  RGB_RMOD, RGB_VAD,  RGB_HUD,  RGB_SAD,  RGB_SPD,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,            KC_END,
 | 
			
		||||
        KC_TRNS,            KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  BAT_LVL,  NK_TOGG,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,  KC_TRNS,
 | 
			
		||||
        KC_TRNS,  KC_TRNS,  KC_TRNS,                                KC_TRNS,                                KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS),
 | 
			
		||||
 | 
			
		||||
    [WIN_BASE] = LAYOUT_ansi_82(
 | 
			
		||||
        KC_ESC,   KC_F1,    KC_F2,    KC_F3,    KC_F4,    KC_F5,    KC_F6,    KC_F7,    KC_F8,    KC_F9,    KC_F10,   KC_F11,   KC_F12,   KC_DEL,             KC_MUTE,
 | 
			
		||||
        KC_GRV,   KC_1,     KC_2,     KC_3,     KC_4,     KC_5,     KC_6,     KC_7,     KC_8,     KC_9,     KC_0,     KC_MINS,  KC_EQL,   KC_BSPC,            KC_PGUP,
 | 
			
		||||
        KC_TAB,   KC_Q,     KC_W,     KC_E,     KC_R,     KC_T,     KC_Y,     KC_U,     KC_I,     KC_O,     KC_P,     KC_LBRC,  KC_RBRC,  KC_BSLS,            KC_PGDN,
 | 
			
		||||
        KC_CAPS,  KC_A,     KC_S,     KC_D,     KC_F,     KC_G,     KC_H,     KC_J,     KC_K,     KC_L,     KC_SCLN,  KC_QUOT,            KC_ENT,             KC_HOME,
 | 
			
		||||
        KC_LSFT,            KC_Z,     KC_X,     KC_C,     KC_V,     KC_B,     KC_N,     KC_M,     KC_COMM,  KC_DOT,   KC_SLSH,            KC_RSFT,  KC_UP,
 | 
			
		||||
        KC_LCTL,  KC_LGUI,  KC_LALT,                                KC_SPC,                                 KC_RALT, MO(WIN_FN),KC_RCTL,  KC_LEFT,  KC_DOWN,  KC_RGHT),
 | 
			
		||||
 | 
			
		||||
    [WIN_FN] = LAYOUT_ansi_82(
 | 
			
		||||
        KC_TRNS,  KC_BRID,  KC_BRIU,  KC_TASK,  KC_FILE,  RGB_VAD,  RGB_VAI,  KC_MPRV,  KC_MPLY,  KC_MNXT,  KC_MUTE,  KC_VOLD,  KC_VOLU,  KC_TRNS,            RGB_TOG,
 | 
			
		||||
        KC_TRNS,  BT_HST1,  BT_HST2,  BT_HST3,  P2P4G,    KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,
 | 
			
		||||
        RGB_TOG,  RGB_MOD,  RGB_VAI,  RGB_HUI,  RGB_SAI,  RGB_SPI,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,
 | 
			
		||||
        KC_TRNS,  RGB_RMOD, RGB_VAD,  RGB_HUD,  RGB_SAD,  RGB_SPD,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,            KC_END,
 | 
			
		||||
        KC_TRNS,            KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  BAT_LVL,  NK_TOGG,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,  KC_TRNS,
 | 
			
		||||
        KC_TRNS,  KC_TRNS,  KC_TRNS,                                KC_TRNS,                                KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// clang-format on
 | 
			
		||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    if (!process_record_lemokey_common(keycode, record)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(ENCODER_MAP_ENABLE)
 | 
			
		||||
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
 | 
			
		||||
    [MAC_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
 | 
			
		||||
    [MAC_FN]   = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
 | 
			
		||||
    [WIN_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
 | 
			
		||||
    [WIN_FN]   = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
 | 
			
		||||
};
 | 
			
		||||
#endif // ENCODER_MAP_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -1,76 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 "keychron_common.h"
 | 
			
		||||
 | 
			
		||||
enum layers {
 | 
			
		||||
    MAC_BASE,
 | 
			
		||||
    MAC_FN,
 | 
			
		||||
    WIN_BASE,
 | 
			
		||||
    WIN_FN,
 | 
			
		||||
};
 | 
			
		||||
// clang-format off
 | 
			
		||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
			
		||||
 [MAC_BASE] = LAYOUT_ansi_82(
 | 
			
		||||
        KC_ESC,   KC_BRID,  KC_BRIU,  KC_MCTRL, KC_LNPAD, RGB_VAD,  RGB_VAI,  KC_MPRV,  KC_MPLY,  KC_MNXT,  KC_MUTE,  KC_VOLD,  KC_VOLU,  KC_DEL,             KC_MUTE,
 | 
			
		||||
        KC_GRV,   KC_1,     KC_2,     KC_3,     KC_4,     KC_5,     KC_6,     KC_7,     KC_8,     KC_9,     KC_0,     KC_MINS,  KC_EQL,   KC_BSPC,            KC_PGUP,
 | 
			
		||||
        KC_TAB,   KC_Q,     KC_W,     KC_E,     KC_R,     KC_T,     KC_Y,     KC_U,     KC_I,     KC_O,     KC_P,     KC_LBRC,  KC_RBRC,  KC_BSLS,            KC_PGDN,
 | 
			
		||||
        KC_CAPS,  KC_A,     KC_S,     KC_D,     KC_F,     KC_G,     KC_H,     KC_J,     KC_K,     KC_L,     KC_SCLN,  KC_QUOT,            KC_ENT,             KC_HOME,
 | 
			
		||||
        KC_LSFT,            KC_Z,     KC_X,     KC_C,     KC_V,     KC_B,     KC_N,     KC_M,     KC_COMM,  KC_DOT,   KC_SLSH,            KC_RSFT,  KC_UP,
 | 
			
		||||
        KC_LCTL,  KC_LOPTN, KC_LCMMD,                               KC_SPC,                                 KC_RCMMD,MO(MAC_FN),KC_RCTL,  KC_LEFT,  KC_DOWN,  KC_RGHT),
 | 
			
		||||
 | 
			
		||||
    [MAC_FN] = LAYOUT_ansi_82(
 | 
			
		||||
        KC_TRNS,  KC_F1,    KC_F2,    KC_F3,    KC_F4,    KC_F5,    KC_F6,    KC_F7,    KC_F8,    KC_F9,    KC_F10,   KC_F11,   KC_F12,   KC_TRNS,            RGB_TOG,
 | 
			
		||||
        KC_TRNS,  BT_HST1,  BT_HST2,  BT_HST3,  P2P4G,    KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,
 | 
			
		||||
        RGB_TOG,  RGB_MOD,  RGB_VAI,  RGB_HUI,  RGB_SAI,  RGB_SPI,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,
 | 
			
		||||
        KC_TRNS,  RGB_RMOD, RGB_VAD,  RGB_HUD,  RGB_SAD,  RGB_SPD,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,            KC_END,
 | 
			
		||||
        KC_TRNS,            KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  BAT_LVL,  NK_TOGG,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,  KC_TRNS,
 | 
			
		||||
        KC_TRNS,  KC_TRNS,  KC_TRNS,                                KC_TRNS,                                KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS),
 | 
			
		||||
 | 
			
		||||
    [WIN_BASE] = LAYOUT_ansi_82(
 | 
			
		||||
        KC_ESC,   KC_F1,    KC_F2,    KC_F3,    KC_F4,    KC_F5,    KC_F6,    KC_F7,    KC_F8,    KC_F9,    KC_F10,   KC_F11,   KC_F12,   KC_DEL,             KC_MUTE,
 | 
			
		||||
        KC_GRV,   KC_1,     KC_2,     KC_3,     KC_4,     KC_5,     KC_6,     KC_7,     KC_8,     KC_9,     KC_0,     KC_MINS,  KC_EQL,   KC_BSPC,            KC_PGUP,
 | 
			
		||||
        KC_TAB,   KC_Q,     KC_W,     KC_E,     KC_R,     KC_T,     KC_Y,     KC_U,     KC_I,     KC_O,     KC_P,     KC_LBRC,  KC_RBRC,  KC_BSLS,            KC_PGDN,
 | 
			
		||||
        KC_CAPS,  KC_A,     KC_S,     KC_D,     KC_F,     KC_G,     KC_H,     KC_J,     KC_K,     KC_L,     KC_SCLN,  KC_QUOT,            KC_ENT,             KC_HOME,
 | 
			
		||||
        KC_LSFT,            KC_Z,     KC_X,     KC_C,     KC_V,     KC_B,     KC_N,     KC_M,     KC_COMM,  KC_DOT,   KC_SLSH,            KC_RSFT,  KC_UP,
 | 
			
		||||
        KC_LCTL,  KC_LGUI,  KC_LALT,                                KC_SPC,                                 KC_RALT, MO(WIN_FN),KC_RCTL,  KC_LEFT,  KC_DOWN,  KC_RGHT),
 | 
			
		||||
 | 
			
		||||
    [WIN_FN] = LAYOUT_ansi_82(
 | 
			
		||||
        KC_TRNS,  KC_BRID,  KC_BRIU,  KC_TASK,  KC_FILE,  RGB_VAD,  RGB_VAI,  KC_MPRV,  KC_MPLY,  KC_MNXT,  KC_MUTE,  KC_VOLD,  KC_VOLU,  KC_TRNS,            RGB_TOG,
 | 
			
		||||
        KC_TRNS,  BT_HST1,  BT_HST2,  BT_HST3,  P2P4G,    KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,
 | 
			
		||||
        RGB_TOG,  RGB_MOD,  RGB_VAI,  RGB_HUI,  RGB_SAI,  RGB_SPI,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,
 | 
			
		||||
        KC_TRNS,  RGB_RMOD, RGB_VAD,  RGB_HUD,  RGB_SAD,  RGB_SPD,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,            KC_END,
 | 
			
		||||
        KC_TRNS,            KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  BAT_LVL,  NK_TOGG,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,            KC_TRNS,  KC_TRNS,
 | 
			
		||||
        KC_TRNS,  KC_TRNS,  KC_TRNS,                                KC_TRNS,                                KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// clang-format on
 | 
			
		||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    if (!process_record_lemokey_common(keycode, record)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(ENCODER_MAP_ENABLE)
 | 
			
		||||
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
 | 
			
		||||
    [MAC_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
 | 
			
		||||
    [MAC_FN]   = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
 | 
			
		||||
    [WIN_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
 | 
			
		||||
    [WIN_FN]   = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
 | 
			
		||||
};
 | 
			
		||||
#endif // ENCODER_MAP_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -1,77 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 "keychron_common.h"
 | 
			
		||||
 | 
			
		||||
enum layers {
 | 
			
		||||
    MAC_BASE,
 | 
			
		||||
    MAC_FN,
 | 
			
		||||
    WIN_BASE,
 | 
			
		||||
    WIN_FN,
 | 
			
		||||
};
 | 
			
		||||
// clang-format off
 | 
			
		||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
			
		||||
 [MAC_BASE] = LAYOUT_ansi_83(
 | 
			
		||||
        KC_ESC,   KC_BRID,  KC_BRIU,  KC_MCTRL, KC_LNPAD, RGB_VAD,  RGB_VAI,  KC_MPRV,  KC_MPLY,  KC_MNXT,  KC_MUTE,  KC_VOLD,  KC_VOLU,  KC_DEL,             KC_MUTE,
 | 
			
		||||
        KC_GRV,   KC_1,     KC_2,     KC_3,     KC_4,     KC_5,     KC_6,     KC_7,     KC_8,     KC_9,     KC_0,     KC_MINS,  KC_EQL,   KC_BSPC,            KC_PGUP,
 | 
			
		||||
        KC_TAB,   KC_Q,     KC_W,     KC_E,     KC_R,     KC_T,     KC_Y,     KC_U,     KC_I,     KC_O,     KC_P,     KC_LBRC,  KC_RBRC,                      KC_PGDN,
 | 
			
		||||
        KC_CAPS,  KC_A,     KC_S,     KC_D,     KC_F,     KC_G,     KC_H,     KC_J,     KC_K,     KC_L,     KC_SCLN,  KC_QUOT,  KC_NUHS,  KC_ENT,             KC_HOME,
 | 
			
		||||
        KC_LSFT,  KC_NUBS,  KC_Z,     KC_X,     KC_C,     KC_V,     KC_B,     KC_N,     KC_M,     KC_COMM,  KC_DOT,   KC_SLSH,            KC_RSFT,  KC_UP,
 | 
			
		||||
        KC_LCTL,  KC_LOPTN, KC_LCMMD,                               KC_SPC,                                 KC_RCMMD,MO(MAC_FN),KC_RCTL,  KC_LEFT,  KC_DOWN,  KC_RGHT),
 | 
			
		||||
 | 
			
		||||
    [MAC_FN] = LAYOUT_ansi_83(
 | 
			
		||||
        _______,  KC_F1,    KC_F2,    KC_F3,    KC_F4,    KC_F5,    KC_F6,    KC_F7,    KC_F8,    KC_F9,    KC_F10,   KC_F11,   KC_F12,   _______,            RGB_TOG,
 | 
			
		||||
        _______,  BT_HST1,  BT_HST2,  BT_HST3,  P2P4G,    _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,            _______,
 | 
			
		||||
        RGB_TOG,  RGB_MOD,  RGB_VAI,  RGB_HUI,  RGB_SAI,  RGB_SPI,  _______,  _______,  _______,  _______,  _______,  _______,  _______,                      _______,
 | 
			
		||||
        _______,  RGB_RMOD, RGB_VAD,  RGB_HUD,  RGB_SAD,  RGB_SPD,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,            KC_END,
 | 
			
		||||
        _______,  _______,  _______,  _______,  _______,  _______,  BAT_LVL,  NK_TOGG,  _______,  _______,  _______,  _______,            _______,  _______,
 | 
			
		||||
        _______,  _______,  _______,                                _______,                                _______,  _______,  _______,  _______,  _______,  _______),
 | 
			
		||||
 | 
			
		||||
    [WIN_BASE] = LAYOUT_ansi_83(
 | 
			
		||||
        KC_ESC,   KC_F1,    KC_F2,    KC_F3,    KC_F4,    KC_F5,    KC_F6,    KC_F7,    KC_F8,    KC_F9,    KC_F10,   KC_F11,   KC_F12,   KC_DEL,             KC_MUTE,
 | 
			
		||||
        KC_GRV,   KC_1,     KC_2,     KC_3,     KC_4,     KC_5,     KC_6,     KC_7,     KC_8,     KC_9,     KC_0,     KC_MINS,  KC_EQL,   KC_BSPC,            KC_PGUP,
 | 
			
		||||
        KC_TAB,   KC_Q,     KC_W,     KC_E,     KC_R,     KC_T,     KC_Y,     KC_U,     KC_I,     KC_O,     KC_P,     KC_LBRC,  KC_RBRC,                      KC_PGDN,
 | 
			
		||||
        KC_CAPS,  KC_A,     KC_S,     KC_D,     KC_F,     KC_G,     KC_H,     KC_J,     KC_K,     KC_L,     KC_SCLN,  KC_QUOT,  KC_NUHS,  KC_ENT,             KC_HOME,
 | 
			
		||||
        KC_LSFT,  KC_NUBS,  KC_Z,     KC_X,     KC_C,     KC_V,     KC_B,     KC_N,     KC_M,     KC_COMM,  KC_DOT,   KC_SLSH,            KC_RSFT,  KC_UP,
 | 
			
		||||
        KC_LCTL,  KC_LGUI,  KC_LALT,                                KC_SPC,                                 KC_RALT, MO(WIN_FN),KC_RCTL,  KC_LEFT,  KC_DOWN,  KC_RGHT),
 | 
			
		||||
 | 
			
		||||
    [WIN_FN] = LAYOUT_ansi_83(
 | 
			
		||||
        _______,  KC_BRID,  KC_BRIU,  KC_TASK,  KC_FILE,  RGB_VAD,  RGB_VAI,  KC_MPRV,  KC_MPLY,  KC_MNXT,  KC_MUTE,  KC_VOLD,  KC_VOLU,  _______,            RGB_TOG,
 | 
			
		||||
        _______,  BT_HST1,  BT_HST2,  BT_HST3,  P2P4G,    _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,            _______,
 | 
			
		||||
        RGB_TOG,  RGB_MOD,  RGB_VAI,  RGB_HUI,  RGB_SAI,  RGB_SPI,  _______,  _______,  _______,  _______,  _______,  _______,  _______,                      _______,
 | 
			
		||||
        _______,  RGB_RMOD, RGB_VAD,  RGB_HUD,  RGB_SAD,  RGB_SPD,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,            KC_END,
 | 
			
		||||
        _______,  _______,  _______,  _______,  _______,  _______,  BAT_LVL,  NK_TOGG,  _______,  _______,  _______,  _______,            _______,  _______,
 | 
			
		||||
        _______,  _______,  _______,                                _______,                                _______,  _______,  _______,  _______,  _______,  _______)
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
// clang-format on
 | 
			
		||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    if (!process_record_lemokey_common(keycode, record)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(ENCODER_MAP_ENABLE)
 | 
			
		||||
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
 | 
			
		||||
    [MAC_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
 | 
			
		||||
    [MAC_FN]   = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
 | 
			
		||||
    [WIN_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
 | 
			
		||||
    [WIN_FN]   = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
 | 
			
		||||
};
 | 
			
		||||
#endif // ENCODER_MAP_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -1,77 +0,0 @@
 | 
			
		|||
/* Copyright 2023 @ 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 "keychron_common.h"
 | 
			
		||||
 | 
			
		||||
enum layers {
 | 
			
		||||
    MAC_BASE,
 | 
			
		||||
    MAC_FN,
 | 
			
		||||
    WIN_BASE,
 | 
			
		||||
    WIN_FN,
 | 
			
		||||
};
 | 
			
		||||
// clang-format off
 | 
			
		||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
			
		||||
 [MAC_BASE] = LAYOUT_ansi_83(
 | 
			
		||||
        KC_ESC,   KC_BRID,  KC_BRIU,  KC_MCTRL, KC_LNPAD, RGB_VAD,  RGB_VAI,  KC_MPRV,  KC_MPLY,  KC_MNXT,  KC_MUTE,  KC_VOLD,  KC_VOLU,  KC_DEL,             KC_MUTE,
 | 
			
		||||
        KC_GRV,   KC_1,     KC_2,     KC_3,     KC_4,     KC_5,     KC_6,     KC_7,     KC_8,     KC_9,     KC_0,     KC_MINS,  KC_EQL,   KC_BSPC,            KC_PGUP,
 | 
			
		||||
        KC_TAB,   KC_Q,     KC_W,     KC_E,     KC_R,     KC_T,     KC_Y,     KC_U,     KC_I,     KC_O,     KC_P,     KC_LBRC,  KC_RBRC,                      KC_PGDN,
 | 
			
		||||
        KC_CAPS,  KC_A,     KC_S,     KC_D,     KC_F,     KC_G,     KC_H,     KC_J,     KC_K,     KC_L,     KC_SCLN,  KC_QUOT,  KC_NUHS,  KC_ENT,             KC_HOME,
 | 
			
		||||
        KC_LSFT,  KC_NUBS,  KC_Z,     KC_X,     KC_C,     KC_V,     KC_B,     KC_N,     KC_M,     KC_COMM,  KC_DOT,   KC_SLSH,            KC_RSFT,  KC_UP,
 | 
			
		||||
        KC_LCTL,  KC_LOPTN, KC_LCMMD,                               KC_SPC,                                 KC_RCMMD,MO(MAC_FN),KC_RCTL,  KC_LEFT,  KC_DOWN,  KC_RGHT),
 | 
			
		||||
 | 
			
		||||
    [MAC_FN] = LAYOUT_ansi_83(
 | 
			
		||||
        _______,  KC_F1,    KC_F2,    KC_F3,    KC_F4,    KC_F5,    KC_F6,    KC_F7,    KC_F8,    KC_F9,    KC_F10,   KC_F11,   KC_F12,   _______,            RGB_TOG,
 | 
			
		||||
        _______,  BT_HST1,  BT_HST2,  BT_HST3,  P2P4G,    _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,            _______,
 | 
			
		||||
        RGB_TOG,  RGB_MOD,  RGB_VAI,  RGB_HUI,  RGB_SAI,  RGB_SPI,  _______,  _______,  _______,  _______,  _______,  _______,  _______,                      _______,
 | 
			
		||||
        _______,  RGB_RMOD, RGB_VAD,  RGB_HUD,  RGB_SAD,  RGB_SPD,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,            KC_END,
 | 
			
		||||
        _______,  _______,  _______,  _______,  _______,  _______,  BAT_LVL,  NK_TOGG,  _______,  _______,  _______,  _______,            _______,  _______,
 | 
			
		||||
        _______,  _______,  _______,                                _______,                                _______,  _______,  _______,  _______,  _______,  _______),
 | 
			
		||||
 | 
			
		||||
    [WIN_BASE] = LAYOUT_ansi_83(
 | 
			
		||||
        KC_ESC,   KC_F1,    KC_F2,    KC_F3,    KC_F4,    KC_F5,    KC_F6,    KC_F7,    KC_F8,    KC_F9,    KC_F10,   KC_F11,   KC_F12,   KC_DEL,             KC_MUTE,
 | 
			
		||||
        KC_GRV,   KC_1,     KC_2,     KC_3,     KC_4,     KC_5,     KC_6,     KC_7,     KC_8,     KC_9,     KC_0,     KC_MINS,  KC_EQL,   KC_BSPC,            KC_PGUP,
 | 
			
		||||
        KC_TAB,   KC_Q,     KC_W,     KC_E,     KC_R,     KC_T,     KC_Y,     KC_U,     KC_I,     KC_O,     KC_P,     KC_LBRC,  KC_RBRC,                      KC_PGDN,
 | 
			
		||||
        KC_CAPS,  KC_A,     KC_S,     KC_D,     KC_F,     KC_G,     KC_H,     KC_J,     KC_K,     KC_L,     KC_SCLN,  KC_QUOT,  KC_NUHS,  KC_ENT,             KC_HOME,
 | 
			
		||||
        KC_LSFT,  KC_NUBS,  KC_Z,     KC_X,     KC_C,     KC_V,     KC_B,     KC_N,     KC_M,     KC_COMM,  KC_DOT,   KC_SLSH,            KC_RSFT,  KC_UP,
 | 
			
		||||
        KC_LCTL,  KC_LGUI,  KC_LALT,                                KC_SPC,                                 KC_RALT, MO(WIN_FN),KC_RCTL,  KC_LEFT,  KC_DOWN,  KC_RGHT),
 | 
			
		||||
 | 
			
		||||
    [WIN_FN] = LAYOUT_ansi_83(
 | 
			
		||||
        _______,  KC_BRID,  KC_BRIU,  KC_TASK,  KC_FILE,  RGB_VAD,  RGB_VAI,  KC_MPRV,  KC_MPLY,  KC_MNXT,  KC_MUTE,  KC_VOLD,  KC_VOLU,  _______,            RGB_TOG,
 | 
			
		||||
        _______,  BT_HST1,  BT_HST2,  BT_HST3,  P2P4G,    _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,            _______,
 | 
			
		||||
        RGB_TOG,  RGB_MOD,  RGB_VAI,  RGB_HUI,  RGB_SAI,  RGB_SPI,  _______,  _______,  _______,  _______,  _______,  _______,  _______,                      _______,
 | 
			
		||||
        _______,  RGB_RMOD, RGB_VAD,  RGB_HUD,  RGB_SAD,  RGB_SPD,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,            KC_END,
 | 
			
		||||
        _______,  _______,  _______,  _______,  _______,  _______,  BAT_LVL,  NK_TOGG,  _______,  _______,  _______,  _______,            _______,  _______,
 | 
			
		||||
        _______,  _______,  _______,                                _______,                                _______,  _______,  _______,  _______,  _______,  _______)
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
// clang-format on
 | 
			
		||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    if (!process_record_lemokey_common(keycode, record)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(ENCODER_MAP_ENABLE)
 | 
			
		||||
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
 | 
			
		||||
    [MAC_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
 | 
			
		||||
    [MAC_FN]   = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
 | 
			
		||||
    [WIN_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
 | 
			
		||||
    [WIN_FN]   = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
 | 
			
		||||
};
 | 
			
		||||
#endif // ENCODER_MAP_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -87,6 +87,10 @@ const led_matrix_driver_t led_matrix_driver = {
 | 
			
		|||
    .flush         = snled27351_flush,
 | 
			
		||||
    .set_value     = snled27351_set_value,
 | 
			
		||||
    .set_value_all = snled27351_set_value_all,
 | 
			
		||||
#ifdef LED_MATRIX_SHUTDOWN_ENABLE
 | 
			
		||||
    .shutdown      = snled27351_shutdown,
 | 
			
		||||
    .exit_shutdown = snled27351_exit_shutdown,
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#elif defined(LED_MATRIX_SNLED27351_SPI)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,6 +86,10 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
 | 
			
		|||
    .flush         = snled27351_flush,
 | 
			
		||||
    .set_color     = snled27351_set_color,
 | 
			
		||||
    .set_color_all = snled27351_set_color_all,
 | 
			
		||||
#        if defined(RGB_MATRIX_DRIVER_SHUTDOWN_ENABLE)
 | 
			
		||||
    .shutdown = snled27351_shutdown,
 | 
			
		||||
    .exit_shutdown = snled27351_exit_shutdown
 | 
			
		||||
#        endif
 | 
			
		||||
};
 | 
			
		||||
#elif defined(RGB_MATRIX_SNLED27351_SPI)
 | 
			
		||||
const rgb_matrix_driver_t rgb_matrix_driver = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue