mirror of
https://github.com/Keychron/qmk_firmware.git
synced 2024-11-25 01:47:10 +06:00
Added Lemokey P1 ANSI
This commit is contained in:
parent
0daedeb229
commit
cc9a612161
|
@ -348,7 +348,7 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LED_MATRIX_ENABLE ?= no
|
LED_MATRIX_ENABLE ?= no
|
||||||
VALID_LED_MATRIX_TYPES := is31fl3731 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 custom
|
VALID_LED_MATRIX_TYPES := is31fl3731 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 snled27351_spi custom
|
||||||
# TODO: is31fl3733 is31fl3737 is31fl3741
|
# TODO: is31fl3733 is31fl3737 is31fl3741
|
||||||
|
|
||||||
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
|
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
|
||||||
|
@ -412,11 +412,17 @@ endif
|
||||||
QUANTUM_LIB_SRC += i2c_master.c
|
QUANTUM_LIB_SRC += i2c_master.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(RGB_MATRIX_DRIVER)), snled27351_spi)
|
||||||
|
OPT_DEFS += -DSNLED27351_SPI -DSTM32_SPI -DHAL_USE_SPI=TRUE
|
||||||
|
COMMON_VPATH += $(DRIVER_PATH)/led
|
||||||
|
SRC += snled27351-simple-spi.c
|
||||||
|
QUANTUM_LIB_SRC += spi_master.c
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
RGB_MATRIX_ENABLE ?= no
|
RGB_MATRIX_ENABLE ?= no
|
||||||
|
|
||||||
VALID_RGB_MATRIX_TYPES := aw20216 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 ws2812 custom
|
VALID_RGB_MATRIX_TYPES := aw20216 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 snled27351_spi ws2812 custom
|
||||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
||||||
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
|
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
|
||||||
$(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
|
$(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
|
||||||
|
@ -514,6 +520,13 @@ endif
|
||||||
QUANTUM_LIB_SRC += i2c_master.c
|
QUANTUM_LIB_SRC += i2c_master.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(RGB_MATRIX_DRIVER)), snled27351_spi)
|
||||||
|
OPT_DEFS += -DSNLED27351_SPI -DSTM32_SPI -DHAL_USE_SPI=TRUE
|
||||||
|
COMMON_VPATH += $(DRIVER_PATH)/led
|
||||||
|
SRC += snled27351-spi.c
|
||||||
|
QUANTUM_LIB_SRC += spi_master.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(RGB_MATRIX_DRIVER)), ws2812)
|
ifeq ($(strip $(RGB_MATRIX_DRIVER)), ws2812)
|
||||||
OPT_DEFS += -DWS2812
|
OPT_DEFS += -DWS2812
|
||||||
WS2812_DRIVER_REQUIRED := yes
|
WS2812_DRIVER_REQUIRED := yes
|
||||||
|
|
235
drivers/led/snled27351-simple-spi.c
Normal file
235
drivers/led/snled27351-simple-spi.c
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
/* 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 "snled27351-simple-spi.h"
|
||||||
|
#include "spi_master.h"
|
||||||
|
|
||||||
|
#define SNLED27351_PWM_REGISTER_COUNT 192
|
||||||
|
#define SNLED27351_LED_CONTROL_REGISTER_COUNT 24
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SNLED27351_PHASE_CHANNEL
|
||||||
|
# define SNLED27351_PHASE_CHANNEL MSKPHASE_12CHANNEL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SNLED27351_CURRENT_TUNE
|
||||||
|
# define SNLED27351_CURRENT_TUNE \
|
||||||
|
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SNLED27351_WRITE (0 << 7)
|
||||||
|
#define SNLED27351_READ (1 << 7)
|
||||||
|
#define SNLED27351_PATTERN (2 << 4)
|
||||||
|
|
||||||
|
#ifdef DRIVER_CS_PINS
|
||||||
|
pin_t cs_pins[] = DRIVER_CS_PINS;
|
||||||
|
#else
|
||||||
|
error "no DRIVER_CS_PINS defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// These buffers match the snled27351 PWM registers.
|
||||||
|
// The control buffers match the PG0 LED On/Off registers.
|
||||||
|
// Storing them like this is optimal for I2C transfers to the registers.
|
||||||
|
// We could optimize this and take out the unused registers from these
|
||||||
|
// buffers and the transfers in snled27351_write_pwm_buffer() but it's
|
||||||
|
// probably not worth the extra complexity.
|
||||||
|
uint8_t g_pwm_buffer[SNLED27351_DRIVER_COUNT][SNLED27351_PWM_REGISTER_COUNT];
|
||||||
|
bool g_pwm_buffer_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||||
|
|
||||||
|
uint8_t g_led_control_registers[SNLED27351_DRIVER_COUNT][SNLED27351_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||||
|
bool g_led_control_registers_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool snled27351_write(uint8_t index, uint8_t page, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||||
|
static uint8_t spi_transfer_buffer[2] = {0};
|
||||||
|
|
||||||
|
if (index > ARRAY_SIZE(((pin_t[])DRIVER_CS_PINS)) - 1) return false;
|
||||||
|
|
||||||
|
if (!spi_start(cs_pins[index], false, 0, SNLED23751_SPI_DIVISOR)) {
|
||||||
|
spi_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_transfer_buffer[0] = SNLED27351_WRITE | SNLED27351_PATTERN | (page & 0x0F);
|
||||||
|
spi_transfer_buffer[1] = reg;
|
||||||
|
|
||||||
|
if (spi_transmit(spi_transfer_buffer, 2) != SPI_STATUS_SUCCESS) {
|
||||||
|
spi_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spi_transmit(data, len) != SPI_STATUS_SUCCESS) {
|
||||||
|
spi_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_stop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool snled27351_write_register(uint8_t index, uint8_t page, uint8_t reg, uint8_t data) {
|
||||||
|
return snled27351_write(index, page, reg, &data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool snled27351_write_pwm_buffer(uint8_t index, uint8_t *pwm_buffer) {
|
||||||
|
if (g_pwm_buffer_update_required[index]) {
|
||||||
|
snled27351_write(index, LED_PWM_PAGE, 0, g_pwm_buffer[index], SNLED27351_PWM_REGISTER_COUNT);
|
||||||
|
}
|
||||||
|
g_pwm_buffer_update_required[index] = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_init_drivers(void) {
|
||||||
|
#if defined(LED_DRIVER_SHUTDOWN_PIN)
|
||||||
|
setPinOutput(LED_DRIVER_SHUTDOWN_PIN);
|
||||||
|
writePinHigh(LED_DRIVER_SHUTDOWN_PIN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
spi_init();
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
|
||||||
|
snled27351_init(i);
|
||||||
|
|
||||||
|
for (int index = 0; index < SNLED27351_LED_COUNT; index++) {
|
||||||
|
snled27351_set_led_control_register(index, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
|
||||||
|
snled27351_update_led_control_registers(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_init(uint8_t index) {
|
||||||
|
setPinOutput(cs_pins[index]);
|
||||||
|
writePinHigh(cs_pins[index]);
|
||||||
|
// Setting LED driver to shutdown mode
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, CONFIGURATION_REG, MSKSW_SHUT_DOWN_MODE);
|
||||||
|
// Setting internal channel pulldown/pullup
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, PDU_REG, MSKSET_CA_CB_CHANNEL);
|
||||||
|
// Select number of scan phase
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SCAN_PHASE_REG, SNLED27351_PHASE_CHANNEL);
|
||||||
|
// Setting PWM Delay Phase
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SLEW_RATE_CONTROL_MODE1_REG, MSKPWM_DELAY_PHASE_ENABLE);
|
||||||
|
// Setting Driving/Sinking Channel Slew Rate
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SLEW_RATE_CONTROL_MODE2_REG, MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE);
|
||||||
|
// Setting Iref
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SOFTWARE_SLEEP_REG, MSKSLEEP_DISABLE);
|
||||||
|
|
||||||
|
// Set LED CONTROL PAGE (Page 0)
|
||||||
|
uint8_t on_off_reg[LED_CONTROL_ON_OFF_LENGTH] = {0};
|
||||||
|
snled27351_write(index, LED_CONTROL_PAGE, 0, on_off_reg, LED_CONTROL_ON_OFF_LENGTH);
|
||||||
|
|
||||||
|
// Set PWM PAGE (Page 1)
|
||||||
|
uint8_t pwm_reg[LED_PWM_LENGTH];
|
||||||
|
memset(pwm_reg, 0, LED_PWM_LENGTH);
|
||||||
|
snled27351_write(index, LED_PWM_PAGE, 0, pwm_reg, LED_PWM_LENGTH);
|
||||||
|
|
||||||
|
// Set CURRENT PAGE (Page 4)
|
||||||
|
uint8_t current_tune_reg[LED_CURRENT_TUNE_LENGTH] = SNLED27351_CURRENT_TUNE;
|
||||||
|
snled27351_write(index, CURRENT_TUNE_PAGE, 0, current_tune_reg, LED_CURRENT_TUNE_LENGTH);
|
||||||
|
|
||||||
|
// // Enable LEDs ON/OFF
|
||||||
|
// memset(on_off_reg, 0xFF, LED_CONTROL_ON_OFF_LENGTH);
|
||||||
|
// snled27351_write(index, LED_CONTROL_PAGE, 0, on_off_reg, LED_CONTROL_ON_OFF_LENGTH);
|
||||||
|
|
||||||
|
// Setting LED driver to normal mode
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, CONFIGURATION_REG, MSKSW_NORMAL_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_set_value(int index, uint8_t value) {
|
||||||
|
snled27351_led_t led;
|
||||||
|
if (index >= 0 && index < SNLED27351_LED_COUNT) {
|
||||||
|
memcpy_P(&led, (&g_snled27351_leds[index]), sizeof(led));
|
||||||
|
|
||||||
|
g_pwm_buffer[led.driver][led.v] = value;
|
||||||
|
g_pwm_buffer_update_required[led.driver] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_set_value_all(uint8_t value) {
|
||||||
|
for (int i = 0; i < SNLED27351_LED_COUNT; i++) {
|
||||||
|
snled27351_set_value(i, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_set_led_control_register(uint8_t index, bool value) {
|
||||||
|
snled27351_led_t led;
|
||||||
|
memcpy_P(&led, (&g_snled27351_leds[index]), sizeof(led));
|
||||||
|
|
||||||
|
uint8_t control_register = led.v / 8;
|
||||||
|
uint8_t bit_value = led.v % 8;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
g_led_control_registers[led.driver][control_register] |= (1 << bit_value);
|
||||||
|
} else {
|
||||||
|
g_led_control_registers[led.driver][control_register] &= ~(1 << bit_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_led_control_registers_update_required[led.driver] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_update_pwm_buffers(uint8_t index) {
|
||||||
|
if (g_pwm_buffer_update_required[index]) {
|
||||||
|
if (!snled27351_write_pwm_buffer(index, g_pwm_buffer[index])) {
|
||||||
|
g_led_control_registers_update_required[index] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_pwm_buffer_update_required[index] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_update_led_control_registers(uint8_t index) {
|
||||||
|
if (g_led_control_registers_update_required[index]) {
|
||||||
|
snled27351_write(index, LED_CONTROL_PAGE, 0, g_led_control_registers[index], 24);
|
||||||
|
}
|
||||||
|
g_led_control_registers_update_required[index] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_flush(void) {
|
||||||
|
for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
|
||||||
|
snled27351_update_pwm_buffers(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 index) {
|
||||||
|
// Select to function page
|
||||||
|
// Setting LED driver to normal mode
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, CONFIGURATION_REG, MSKSW_NORMAL_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_sw_shutdown(uint8_t index) {
|
||||||
|
// Select to function page
|
||||||
|
// Setting LED driver to shutdown mode
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, CONFIGURATION_REG, MSKSW_SHUT_DOWN_MODE);
|
||||||
|
// Write SW Sleep Register
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SOFTWARE_SLEEP_REG, MSKSLEEP_ENABLE);
|
||||||
|
}
|
346
drivers/led/snled27351-simple-spi.h
Normal file
346
drivers/led/snled27351-simple-spi.h
Normal file
|
@ -0,0 +1,346 @@
|
||||||
|
/* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "progmem.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#if defined(LED_MATRIX_SNLED27351_SPI)
|
||||||
|
# define SNLED27351_LED_COUNT LED_MATRIX_LED_COUNT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SNLED27351_DRIVER_COUNT (sizeof(cs_pins) / sizeof(pin_t))
|
||||||
|
typedef struct snled27351_led_t {
|
||||||
|
uint8_t driver : 2;
|
||||||
|
uint8_t v;
|
||||||
|
} PACKED snled27351_led_t;
|
||||||
|
|
||||||
|
extern const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT];
|
||||||
|
|
||||||
|
void snled27351_init_drivers(void);
|
||||||
|
void snled27351_init(uint8_t index);
|
||||||
|
bool snled27351_write_register(uint8_t index, uint8_t page, uint8_t reg, uint8_t data);
|
||||||
|
bool snled27351_write_pwm_buffer(uint8_t index, uint8_t *pwm_buffer);
|
||||||
|
|
||||||
|
void snled27351_set_value(int index, uint8_t value);
|
||||||
|
void snled27351_set_value_all(uint8_t value);
|
||||||
|
|
||||||
|
void snled27351_set_led_control_register(uint8_t index, bool value);
|
||||||
|
|
||||||
|
// This should not be called from an interrupt
|
||||||
|
// (eg. from a timer interrupt).
|
||||||
|
// Call this while idle (in between matrix scans).
|
||||||
|
// If the buffer is dirty, it will update the driver with the buffer.
|
||||||
|
void snled27351_update_pwm_buffers(uint8_t index);
|
||||||
|
void snled27351_update_led_control_registers(uint8_t index);
|
||||||
|
void snled27351_flush(void);
|
||||||
|
void snled27351_shutdown(void);
|
||||||
|
void snled27351_exit_shutdown(void);
|
||||||
|
void snled27351_sw_return_normal(uint8_t index);
|
||||||
|
void snled27351_sw_shutdown(uint8_t index);
|
||||||
|
|
||||||
|
// Registers Page Define
|
||||||
|
#define CONFIGURE_CMD_PAGE 0xFD
|
||||||
|
#define LED_CONTROL_PAGE 0x00
|
||||||
|
#define LED_PWM_PAGE 0x01
|
||||||
|
#define FUNCTION_PAGE 0x03
|
||||||
|
#define CURRENT_TUNE_PAGE 0x04
|
||||||
|
|
||||||
|
// Function Register: address 0x00
|
||||||
|
#define CONFIGURATION_REG 0x00
|
||||||
|
#define MSKSW_SHUT_DOWN_MODE (0x0 << 0)
|
||||||
|
#define MSKSW_NORMAL_MODE (0x1 << 0)
|
||||||
|
|
||||||
|
#define DRIVER_ID_REG 0x11
|
||||||
|
#define SNLED27351_ID 0x8A
|
||||||
|
|
||||||
|
#define PDU_REG 0x13
|
||||||
|
#define MSKSET_CA_CB_CHANNEL 0xAA
|
||||||
|
#define MSKCLR_CA_CB_CHANNEL 0x00
|
||||||
|
|
||||||
|
#define SCAN_PHASE_REG 0x14
|
||||||
|
#define MSKPHASE_12CHANNEL 0x00
|
||||||
|
#define MSKPHASE_11CHANNEL 0x01
|
||||||
|
#define MSKPHASE_10CHANNEL 0x02
|
||||||
|
#define MSKPHASE_9CHANNEL 0x03
|
||||||
|
#define MSKPHASE_8CHANNEL 0x04
|
||||||
|
#define MSKPHASE_7CHANNEL 0x05
|
||||||
|
#define MSKPHASE_6CHANNEL 0x06
|
||||||
|
#define MSKPHASE_5CHANNEL 0x07
|
||||||
|
#define MSKPHASE_4CHANNEL 0x08
|
||||||
|
#define MSKPHASE_3CHANNEL 0x09
|
||||||
|
#define MSKPHASE_2CHANNEL 0x0A
|
||||||
|
#define MSKPHASE_1CHANNEL 0x0B
|
||||||
|
|
||||||
|
#define SLEW_RATE_CONTROL_MODE1_REG 0x15
|
||||||
|
#define MSKPWM_DELAY_PHASE_ENABLE 0x04
|
||||||
|
#define MSKPWM_DELAY_PHASE_DISABLE 0x00
|
||||||
|
|
||||||
|
#define SLEW_RATE_CONTROL_MODE2_REG 0x16
|
||||||
|
#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE 0xC0
|
||||||
|
#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_DISABLE 0x00
|
||||||
|
|
||||||
|
#define OPEN_SHORT_ENABLE_REG 0x17
|
||||||
|
#define MSKOPEN_DETECTION_ENABLE (0x01 << 7)
|
||||||
|
#define MSKOPEN_DETECTION_DISABLE (0x00)
|
||||||
|
|
||||||
|
#define MSKSHORT_DETECTION_ENABLE (0x01 << 6)
|
||||||
|
#define MSKSHORT_DETECTION_DISABLE (0x00)
|
||||||
|
|
||||||
|
#define OPEN_SHORT_DUTY_REG 0x18
|
||||||
|
#define OPEN_SHORT_FLAG_REG 0x19
|
||||||
|
|
||||||
|
#define MSKOPEN_DETECTION_INTERRUPT_ENABLE (0x01 << 7)
|
||||||
|
#define MSKOPEN_DETECTION_INTERRUPT_DISABLE (0x00)
|
||||||
|
|
||||||
|
#define MSKSHORT_DETECTION_INTERRUPT_ENABLE (0x01 << 6)
|
||||||
|
#define MSKSHORT_DETECTION_INTERRUPT_DISABLE (0x00)
|
||||||
|
|
||||||
|
#define SOFTWARE_SLEEP_REG 0x1A
|
||||||
|
#define MSKSLEEP_ENABLE 0x02
|
||||||
|
#define MSKSLEEP_DISABLE 0x00
|
||||||
|
|
||||||
|
// LED Control Registers
|
||||||
|
#define LED_CONTROL_ON_OFF_FIRST_ADDR 0x0
|
||||||
|
#define LED_CONTROL_ON_OFF_LAST_ADDR 0x17
|
||||||
|
#define LED_CONTROL_ON_OFF_LENGTH ((LED_CONTROL_ON_OFF_LAST_ADDR - LED_CONTROL_ON_OFF_FIRST_ADDR) + 1)
|
||||||
|
|
||||||
|
#define LED_CONTROL_OPEN_FIRST_ADDR 0x18
|
||||||
|
#define LED_CONTROL_OPEN_LAST_ADDR 0x2F
|
||||||
|
#define LED_CONTROL_OPEN_LENGTH ((LED_CONTROL_OPEN_LAST_ADDR - LED_CONTROL_OPEN_FIRST_ADDR) + 1)
|
||||||
|
|
||||||
|
#define LED_CONTROL_SHORT_FIRST_ADDR 0x30
|
||||||
|
#define LED_CONTROL_SHORT_LAST_ADDR 0x47
|
||||||
|
#define LED_CONTROL_SHORT_LENGTH ((LED_CONTROL_SHORT_LAST_ADDR - LED_CONTROL_SHORT_FIRST_ADDR) + 1)
|
||||||
|
|
||||||
|
#define LED_CONTROL_PAGE_LENGTH 0x48
|
||||||
|
|
||||||
|
// LED Control Registers
|
||||||
|
#define LED_PWM_FIRST_ADDR 0x00
|
||||||
|
#define LED_PWM_LAST_ADDR 0xBF
|
||||||
|
#define LED_PWM_LENGTH 0xC0
|
||||||
|
|
||||||
|
// Current Tune Registers
|
||||||
|
#define LED_CURRENT_TUNE_FIRST_ADDR 0x00
|
||||||
|
#define LED_CURRENT_TUNE_LAST_ADDR 0x0B
|
||||||
|
#define LED_CURRENT_TUNE_LENGTH 0x0C
|
||||||
|
|
||||||
|
#define A_1 0x00
|
||||||
|
#define A_2 0x01
|
||||||
|
#define A_3 0x02
|
||||||
|
#define A_4 0x03
|
||||||
|
#define A_5 0x04
|
||||||
|
#define A_6 0x05
|
||||||
|
#define A_7 0x06
|
||||||
|
#define A_8 0x07
|
||||||
|
#define A_9 0x08
|
||||||
|
#define A_10 0x09
|
||||||
|
#define A_11 0x0A
|
||||||
|
#define A_12 0x0B
|
||||||
|
#define A_13 0x0C
|
||||||
|
#define A_14 0x0D
|
||||||
|
#define A_15 0x0E
|
||||||
|
#define A_16 0x0F
|
||||||
|
|
||||||
|
#define B_1 0x10
|
||||||
|
#define B_2 0x11
|
||||||
|
#define B_3 0x12
|
||||||
|
#define B_4 0x13
|
||||||
|
#define B_5 0x14
|
||||||
|
#define B_6 0x15
|
||||||
|
#define B_7 0x16
|
||||||
|
#define B_8 0x17
|
||||||
|
#define B_9 0x18
|
||||||
|
#define B_10 0x19
|
||||||
|
#define B_11 0x1A
|
||||||
|
#define B_12 0x1B
|
||||||
|
#define B_13 0x1C
|
||||||
|
#define B_14 0x1D
|
||||||
|
#define B_15 0x1E
|
||||||
|
#define B_16 0x1F
|
||||||
|
|
||||||
|
#define C_1 0x20
|
||||||
|
#define C_2 0x21
|
||||||
|
#define C_3 0x22
|
||||||
|
#define C_4 0x23
|
||||||
|
#define C_5 0x24
|
||||||
|
#define C_6 0x25
|
||||||
|
#define C_7 0x26
|
||||||
|
#define C_8 0x27
|
||||||
|
#define C_9 0x28
|
||||||
|
#define C_10 0x29
|
||||||
|
#define C_11 0x2A
|
||||||
|
#define C_12 0x2B
|
||||||
|
#define C_13 0x2C
|
||||||
|
#define C_14 0x2D
|
||||||
|
#define C_15 0x2E
|
||||||
|
#define C_16 0x2F
|
||||||
|
|
||||||
|
#define D_1 0x30
|
||||||
|
#define D_2 0x31
|
||||||
|
#define D_3 0x32
|
||||||
|
#define D_4 0x33
|
||||||
|
#define D_5 0x34
|
||||||
|
#define D_6 0x35
|
||||||
|
#define D_7 0x36
|
||||||
|
#define D_8 0x37
|
||||||
|
#define D_9 0x38
|
||||||
|
#define D_10 0x39
|
||||||
|
#define D_11 0x3A
|
||||||
|
#define D_12 0x3B
|
||||||
|
#define D_13 0x3C
|
||||||
|
#define D_14 0x3D
|
||||||
|
#define D_15 0x3E
|
||||||
|
#define D_16 0x3F
|
||||||
|
|
||||||
|
#define E_1 0x40
|
||||||
|
#define E_2 0x41
|
||||||
|
#define E_3 0x42
|
||||||
|
#define E_4 0x43
|
||||||
|
#define E_5 0x44
|
||||||
|
#define E_6 0x45
|
||||||
|
#define E_7 0x46
|
||||||
|
#define E_8 0x47
|
||||||
|
#define E_9 0x48
|
||||||
|
#define E_10 0x49
|
||||||
|
#define E_11 0x4A
|
||||||
|
#define E_12 0x4B
|
||||||
|
#define E_13 0x4C
|
||||||
|
#define E_14 0x4D
|
||||||
|
#define E_15 0x4E
|
||||||
|
#define E_16 0x4F
|
||||||
|
|
||||||
|
#define F_1 0x50
|
||||||
|
#define F_2 0x51
|
||||||
|
#define F_3 0x52
|
||||||
|
#define F_4 0x53
|
||||||
|
#define F_5 0x54
|
||||||
|
#define F_6 0x55
|
||||||
|
#define F_7 0x56
|
||||||
|
#define F_8 0x57
|
||||||
|
#define F_9 0x58
|
||||||
|
#define F_10 0x59
|
||||||
|
#define F_11 0x5A
|
||||||
|
#define F_12 0x5B
|
||||||
|
#define F_13 0x5C
|
||||||
|
#define F_14 0x5D
|
||||||
|
#define F_15 0x5E
|
||||||
|
#define F_16 0x5F
|
||||||
|
|
||||||
|
#define G_1 0x60
|
||||||
|
#define G_2 0x61
|
||||||
|
#define G_3 0x62
|
||||||
|
#define G_4 0x63
|
||||||
|
#define G_5 0x64
|
||||||
|
#define G_6 0x65
|
||||||
|
#define G_7 0x66
|
||||||
|
#define G_8 0x67
|
||||||
|
#define G_9 0x68
|
||||||
|
#define G_10 0x69
|
||||||
|
#define G_11 0x6A
|
||||||
|
#define G_12 0x6B
|
||||||
|
#define G_13 0x6C
|
||||||
|
#define G_14 0x6D
|
||||||
|
#define G_15 0x6E
|
||||||
|
#define G_16 0x6F
|
||||||
|
|
||||||
|
#define H_1 0x70
|
||||||
|
#define H_2 0x71
|
||||||
|
#define H_3 0x72
|
||||||
|
#define H_4 0x73
|
||||||
|
#define H_5 0x74
|
||||||
|
#define H_6 0x75
|
||||||
|
#define H_7 0x76
|
||||||
|
#define H_8 0x77
|
||||||
|
#define H_9 0x78
|
||||||
|
#define H_10 0x79
|
||||||
|
#define H_11 0x7A
|
||||||
|
#define H_12 0x7B
|
||||||
|
#define H_13 0x7C
|
||||||
|
#define H_14 0x7D
|
||||||
|
#define H_15 0x7E
|
||||||
|
#define H_16 0x7F
|
||||||
|
|
||||||
|
#define I_1 0x80
|
||||||
|
#define I_2 0x81
|
||||||
|
#define I_3 0x82
|
||||||
|
#define I_4 0x83
|
||||||
|
#define I_5 0x84
|
||||||
|
#define I_6 0x85
|
||||||
|
#define I_7 0x86
|
||||||
|
#define I_8 0x87
|
||||||
|
#define I_9 0x88
|
||||||
|
#define I_10 0x89
|
||||||
|
#define I_11 0x8A
|
||||||
|
#define I_12 0x8B
|
||||||
|
#define I_13 0x8C
|
||||||
|
#define I_14 0x8D
|
||||||
|
#define I_15 0x8E
|
||||||
|
#define I_16 0x8F
|
||||||
|
|
||||||
|
#define J_1 0x90
|
||||||
|
#define J_2 0x91
|
||||||
|
#define J_3 0x92
|
||||||
|
#define J_4 0x93
|
||||||
|
#define J_5 0x94
|
||||||
|
#define J_6 0x95
|
||||||
|
#define J_7 0x96
|
||||||
|
#define J_8 0x97
|
||||||
|
#define J_9 0x98
|
||||||
|
#define J_10 0x99
|
||||||
|
#define J_11 0x9A
|
||||||
|
#define J_12 0x9B
|
||||||
|
#define J_13 0x9C
|
||||||
|
#define J_14 0x9D
|
||||||
|
#define J_15 0x9E
|
||||||
|
#define J_16 0x9F
|
||||||
|
|
||||||
|
#define K_1 0xA0
|
||||||
|
#define K_2 0xA1
|
||||||
|
#define K_3 0xA2
|
||||||
|
#define K_4 0xA3
|
||||||
|
#define K_5 0xA4
|
||||||
|
#define K_6 0xA5
|
||||||
|
#define K_7 0xA6
|
||||||
|
#define K_8 0xA7
|
||||||
|
#define K_9 0xA8
|
||||||
|
#define K_10 0xA9
|
||||||
|
#define K_11 0xAA
|
||||||
|
#define K_12 0xAB
|
||||||
|
#define K_13 0xAC
|
||||||
|
#define K_14 0xAD
|
||||||
|
#define K_15 0xAE
|
||||||
|
#define K_16 0xAF
|
||||||
|
|
||||||
|
#define L_1 0xB0
|
||||||
|
#define L_2 0xB1
|
||||||
|
#define L_3 0xB2
|
||||||
|
#define L_4 0xB3
|
||||||
|
#define L_5 0xB4
|
||||||
|
#define L_6 0xB5
|
||||||
|
#define L_7 0xB6
|
||||||
|
#define L_8 0xB7
|
||||||
|
#define L_9 0xB8
|
||||||
|
#define L_10 0xB9
|
||||||
|
#define L_11 0xBA
|
||||||
|
#define L_12 0xBB
|
||||||
|
#define L_13 0xBC
|
||||||
|
#define L_14 0xBD
|
||||||
|
#define L_15 0xBE
|
||||||
|
#define L_16 0xBF
|
250
drivers/led/snled27351-spi.c
Normal file
250
drivers/led/snled27351-spi.c
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
/* 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 "snled27351-spi.h"
|
||||||
|
#include "spi_master.h"
|
||||||
|
|
||||||
|
#define SNLED27351_PWM_REGISTER_COUNT 192
|
||||||
|
#define SNLED27351_LED_CONTROL_REGISTER_COUNT 24
|
||||||
|
|
||||||
|
#ifndef SNLED27351_PHASE_CHANNEL
|
||||||
|
# define SNLED27351_PHASE_CHANNEL MSKPHASE_12CHANNEL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SNLED27351_CURRENT_TUNE
|
||||||
|
# define SNLED27351_CURRENT_TUNE \
|
||||||
|
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SNLED27351_WRITE (0 << 7)
|
||||||
|
#define SNLED27351_READ (1 << 7)
|
||||||
|
#define SNLED27351_PATTERN (2 << 4)
|
||||||
|
|
||||||
|
#ifdef DRIVER_CS_PINS
|
||||||
|
pin_t cs_pins[] = DRIVER_CS_PINS;
|
||||||
|
#else
|
||||||
|
error "no DRIVER_CS_PINS defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// These buffers match the snled27351 PWM registers.
|
||||||
|
// The control buffers match the PG0 LED On/Off registers.
|
||||||
|
// Storing them like this is optimal for I2C transfers to the registers.
|
||||||
|
// We could optimize this and take out the unused registers from these
|
||||||
|
// buffers and the transfers in snled27351_write_pwm_buffer() but it's
|
||||||
|
// probably not worth the extra complexity.
|
||||||
|
uint8_t g_pwm_buffer[SNLED27351_DRIVER_COUNT][SNLED27351_PWM_REGISTER_COUNT];
|
||||||
|
bool g_pwm_buffer_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||||
|
|
||||||
|
uint8_t g_led_control_registers[SNLED27351_DRIVER_COUNT][SNLED27351_LED_CONTROL_REGISTER_COUNT] = {0};
|
||||||
|
bool g_led_control_registers_update_required[SNLED27351_DRIVER_COUNT] = {false};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool snled27351_write(uint8_t index, uint8_t page, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||||
|
static uint8_t spi_transfer_buffer[2] = {0};
|
||||||
|
|
||||||
|
if (index > ARRAY_SIZE(((pin_t[])DRIVER_CS_PINS)) - 1) return false;
|
||||||
|
|
||||||
|
if (!spi_start(cs_pins[index], false, 0, SNLED27351_SPI_DIVISOR)) {
|
||||||
|
spi_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_transfer_buffer[0] = SNLED27351_WRITE | SNLED27351_PATTERN | (page & 0x0F);
|
||||||
|
spi_transfer_buffer[1] = reg;
|
||||||
|
|
||||||
|
if (spi_transmit(spi_transfer_buffer, 2) != SPI_STATUS_SUCCESS) {
|
||||||
|
spi_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spi_transmit(data, len) != SPI_STATUS_SUCCESS) {
|
||||||
|
spi_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_stop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool snled27351_write_register(uint8_t index, uint8_t page, uint8_t reg, uint8_t data) {
|
||||||
|
return snled27351_write(index, page, reg, &data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool snled27351_write_pwm_buffer(uint8_t index, uint8_t *pwm_buffer) {
|
||||||
|
if (g_pwm_buffer_update_required[index]) {
|
||||||
|
snled27351_write(index, LED_PWM_PAGE, 0, g_pwm_buffer[index], SNLED27351_PWM_REGISTER_COUNT);
|
||||||
|
}
|
||||||
|
g_pwm_buffer_update_required[index] = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_init_drivers(void) {
|
||||||
|
#if defined(LED_DRIVER_SHUTDOWN_PIN)
|
||||||
|
setPinOutput(LED_DRIVER_SHUTDOWN_PIN);
|
||||||
|
writePinHigh(LED_DRIVER_SHUTDOWN_PIN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
spi_init();
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
|
||||||
|
snled27351_init(i);
|
||||||
|
|
||||||
|
for (int index = 0; index < SNLED27351_LED_COUNT; index++) {
|
||||||
|
snled27351_set_led_control_register(index, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
|
||||||
|
snled27351_update_led_control_registers(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_init(uint8_t index) {
|
||||||
|
setPinOutput(cs_pins[index]);
|
||||||
|
writePinHigh(cs_pins[index]);
|
||||||
|
// Setting LED driver to shutdown mode
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, CONFIGURATION_REG, MSKSW_SHUT_DOWN_MODE);
|
||||||
|
// Setting internal channel pulldown/pullup
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, PDU_REG, MSKSET_CA_CB_CHANNEL);
|
||||||
|
// Select number of scan phase
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SCAN_PHASE_REG, SNLED27351_PHASE_CHANNEL);
|
||||||
|
// Setting PWM Delay Phase
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SLEW_RATE_CONTROL_MODE1_REG, MSKPWM_DELAY_PHASE_ENABLE);
|
||||||
|
// Setting Driving/Sinking Channel Slew Rate
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SLEW_RATE_CONTROL_MODE2_REG, MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE);
|
||||||
|
// Setting Iref
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SOFTWARE_SLEEP_REG, MSKSLEEP_DISABLE);
|
||||||
|
|
||||||
|
// Set LED CONTROL PAGE (Page 0)
|
||||||
|
uint8_t on_off_reg[LED_CONTROL_ON_OFF_LENGTH] = {0};
|
||||||
|
snled27351_write(index, LED_CONTROL_PAGE, 0, on_off_reg, LED_CONTROL_ON_OFF_LENGTH);
|
||||||
|
|
||||||
|
// Set PWM PAGE (Page 1)
|
||||||
|
uint8_t pwm_reg[LED_PWM_LENGTH];
|
||||||
|
memset(pwm_reg, 0, LED_PWM_LENGTH);
|
||||||
|
snled27351_write(index, LED_PWM_PAGE, 0, pwm_reg, LED_PWM_LENGTH);
|
||||||
|
|
||||||
|
// Set CURRENT PAGE (Page 4)
|
||||||
|
uint8_t current_tune_reg[LED_CURRENT_TUNE_LENGTH] = SNLED27351_CURRENT_TUNE;
|
||||||
|
snled27351_write(index, CURRENT_TUNE_PAGE, 0, current_tune_reg, LED_CURRENT_TUNE_LENGTH);
|
||||||
|
|
||||||
|
// // Enable LEDs ON/OFF
|
||||||
|
// memset(on_off_reg, 0xFF, LED_CONTROL_ON_OFF_LENGTH);
|
||||||
|
// snled27351_write(index, LED_CONTROL_PAGE, 0, on_off_reg, LED_CONTROL_ON_OFF_LENGTH);
|
||||||
|
|
||||||
|
// Setting LED driver to normal mode
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, CONFIGURATION_REG, MSKSW_NORMAL_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||||
|
snled27351_led_t led;
|
||||||
|
if (index >= 0 && index < SNLED27351_LED_COUNT) {
|
||||||
|
memcpy_P(&led, (&g_snled27351_leds[index]), sizeof(led));
|
||||||
|
|
||||||
|
g_pwm_buffer[led.driver][led.r] = red;
|
||||||
|
g_pwm_buffer[led.driver][led.g] = green;
|
||||||
|
g_pwm_buffer[led.driver][led.b] = blue;
|
||||||
|
g_pwm_buffer_update_required[led.driver] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
|
||||||
|
for (int i = 0; i < SNLED27351_LED_COUNT; i++) {
|
||||||
|
snled27351_set_color(i, red, green, blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
|
||||||
|
snled27351_led_t led;
|
||||||
|
memcpy_P(&led, (&g_snled27351_leds[index]), sizeof(led));
|
||||||
|
|
||||||
|
uint8_t control_register_r = led.r / 8;
|
||||||
|
uint8_t control_register_g = led.g / 8;
|
||||||
|
uint8_t control_register_b = led.b / 8;
|
||||||
|
uint8_t bit_r = led.r % 8;
|
||||||
|
uint8_t bit_g = led.g % 8;
|
||||||
|
uint8_t bit_b = led.b % 8;
|
||||||
|
|
||||||
|
if (red) {
|
||||||
|
g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
|
||||||
|
} else {
|
||||||
|
g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
|
||||||
|
}
|
||||||
|
if (green) {
|
||||||
|
g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
|
||||||
|
} else {
|
||||||
|
g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
|
||||||
|
}
|
||||||
|
if (blue) {
|
||||||
|
g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
|
||||||
|
} else {
|
||||||
|
g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_led_control_registers_update_required[led.driver] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_update_pwm_buffers(uint8_t index) {
|
||||||
|
if (g_pwm_buffer_update_required[index]) {
|
||||||
|
if (!snled27351_write_pwm_buffer(index, g_pwm_buffer[index])) {
|
||||||
|
g_led_control_registers_update_required[index] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_pwm_buffer_update_required[index] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_update_led_control_registers(uint8_t index) {
|
||||||
|
if (g_led_control_registers_update_required[index]) {
|
||||||
|
snled27351_write(index, LED_CONTROL_PAGE, 0, g_led_control_registers[index], 24);
|
||||||
|
}
|
||||||
|
g_led_control_registers_update_required[index] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_flush(void) {
|
||||||
|
for (uint8_t i = 0; i < SNLED27351_DRIVER_COUNT; i++)
|
||||||
|
snled27351_update_pwm_buffers(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 index) {
|
||||||
|
// Select to function page
|
||||||
|
// Setting LED driver to normal mode
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, CONFIGURATION_REG, MSKSW_NORMAL_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void snled27351_sw_shutdown(uint8_t index) {
|
||||||
|
// Select to function page
|
||||||
|
// Setting LED driver to shutdown mode
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, CONFIGURATION_REG, MSKSW_SHUT_DOWN_MODE);
|
||||||
|
// Write SW Sleep Register
|
||||||
|
snled27351_write_register(index, FUNCTION_PAGE, SOFTWARE_SLEEP_REG, MSKSLEEP_ENABLE);
|
||||||
|
}
|
349
drivers/led/snled27351-spi.h
Normal file
349
drivers/led/snled27351-spi.h
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
/* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "progmem.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#if defined(SNLED27351_SPI)
|
||||||
|
# define SNLED27351_LED_COUNT RGB_MATRIX_LED_COUNT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# define SNLED27351_DRIVER_COUNT (sizeof(cs_pins)/sizeof(pin_t))
|
||||||
|
|
||||||
|
typedef struct snled27351_led_t {
|
||||||
|
uint8_t driver : 2;
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
} __attribute__((packed)) snled27351_led_t;
|
||||||
|
|
||||||
|
extern const snled27351_led_t g_snled27351_leds[SNLED27351_LED_COUNT];
|
||||||
|
|
||||||
|
void snled27351_init_drivers(void);
|
||||||
|
void snled27351_init(uint8_t index);
|
||||||
|
bool snled27351_write_register(uint8_t index, uint8_t page, uint8_t reg, uint8_t data);
|
||||||
|
bool snled27351_write_pwm_buffer(uint8_t index, uint8_t *pwm_buffer);
|
||||||
|
|
||||||
|
void snled27351_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
|
||||||
|
void snled27351_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
|
||||||
|
|
||||||
|
void snled27351_set_led_control_register(uint8_t index, bool red, bool green, bool blue);
|
||||||
|
|
||||||
|
// This should not be called from an interrupt
|
||||||
|
// (eg. from a timer interrupt).
|
||||||
|
// Call this while idle (in between matrix scans).
|
||||||
|
// If the buffer is dirty, it will update the driver with the buffer.
|
||||||
|
void snled27351_update_pwm_buffers(uint8_t index);
|
||||||
|
void snled27351_update_led_control_registers(uint8_t index);
|
||||||
|
void snled27351_flush(void);
|
||||||
|
void snled27351_shutdown(void);
|
||||||
|
void snled27351_exit_shutdown(void);
|
||||||
|
void snled27351_sw_return_normal(uint8_t index);
|
||||||
|
void snled27351_sw_shutdown(uint8_t index);
|
||||||
|
|
||||||
|
// Registers Page Define
|
||||||
|
#define CONFIGURE_CMD_PAGE 0xFD
|
||||||
|
#define LED_CONTROL_PAGE 0x00
|
||||||
|
#define LED_PWM_PAGE 0x01
|
||||||
|
#define FUNCTION_PAGE 0x03
|
||||||
|
#define CURRENT_TUNE_PAGE 0x04
|
||||||
|
|
||||||
|
// Function Register: address 0x00
|
||||||
|
#define CONFIGURATION_REG 0x00
|
||||||
|
#define MSKSW_SHUT_DOWN_MODE (0x0 << 0)
|
||||||
|
#define MSKSW_NORMAL_MODE (0x1 << 0)
|
||||||
|
|
||||||
|
#define DRIVER_ID_REG 0x11
|
||||||
|
#define SNLED27351_ID 0x8A
|
||||||
|
|
||||||
|
#define PDU_REG 0x13
|
||||||
|
#define MSKSET_CA_CB_CHANNEL 0xAA
|
||||||
|
#define MSKCLR_CA_CB_CHANNEL 0x00
|
||||||
|
|
||||||
|
#define SCAN_PHASE_REG 0x14
|
||||||
|
#define MSKPHASE_12CHANNEL 0x00
|
||||||
|
#define MSKPHASE_11CHANNEL 0x01
|
||||||
|
#define MSKPHASE_10CHANNEL 0x02
|
||||||
|
#define MSKPHASE_9CHANNEL 0x03
|
||||||
|
#define MSKPHASE_8CHANNEL 0x04
|
||||||
|
#define MSKPHASE_7CHANNEL 0x05
|
||||||
|
#define MSKPHASE_6CHANNEL 0x06
|
||||||
|
#define MSKPHASE_5CHANNEL 0x07
|
||||||
|
#define MSKPHASE_4CHANNEL 0x08
|
||||||
|
#define MSKPHASE_3CHANNEL 0x09
|
||||||
|
#define MSKPHASE_2CHANNEL 0x0A
|
||||||
|
#define MSKPHASE_1CHANNEL 0x0B
|
||||||
|
|
||||||
|
#define SLEW_RATE_CONTROL_MODE1_REG 0x15
|
||||||
|
#define MSKPWM_DELAY_PHASE_ENABLE 0x04
|
||||||
|
#define MSKPWM_DELAY_PHASE_DISABLE 0x00
|
||||||
|
|
||||||
|
#define SLEW_RATE_CONTROL_MODE2_REG 0x16
|
||||||
|
#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE 0xC0
|
||||||
|
#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_DISABLE 0x00
|
||||||
|
|
||||||
|
#define OPEN_SHORT_ENABLE_REG 0x17
|
||||||
|
#define MSKOPEN_DETECTION_ENABLE (0x01 << 7)
|
||||||
|
#define MSKOPEN_DETECTION_DISABLE (0x00)
|
||||||
|
|
||||||
|
#define MSKSHORT_DETECTION_ENABLE (0x01 << 6)
|
||||||
|
#define MSKSHORT_DETECTION_DISABLE (0x00)
|
||||||
|
|
||||||
|
#define OPEN_SHORT_DUTY_REG 0x18
|
||||||
|
#define OPEN_SHORT_FLAG_REG 0x19
|
||||||
|
|
||||||
|
#define MSKOPEN_DETECTION_INTERRUPT_ENABLE (0x01 << 7)
|
||||||
|
#define MSKOPEN_DETECTION_INTERRUPT_DISABLE (0x00)
|
||||||
|
|
||||||
|
#define MSKSHORT_DETECTION_INTERRUPT_ENABLE (0x01 << 6)
|
||||||
|
#define MSKSHORT_DETECTION_INTERRUPT_DISABLE (0x00)
|
||||||
|
|
||||||
|
#define SOFTWARE_SLEEP_REG 0x1A
|
||||||
|
#define MSKSLEEP_ENABLE 0x02
|
||||||
|
#define MSKSLEEP_DISABLE 0x00
|
||||||
|
|
||||||
|
// LED Control Registers
|
||||||
|
#define LED_CONTROL_ON_OFF_FIRST_ADDR 0x0
|
||||||
|
#define LED_CONTROL_ON_OFF_LAST_ADDR 0x17
|
||||||
|
#define LED_CONTROL_ON_OFF_LENGTH ((LED_CONTROL_ON_OFF_LAST_ADDR - LED_CONTROL_ON_OFF_FIRST_ADDR) + 1)
|
||||||
|
|
||||||
|
#define LED_CONTROL_OPEN_FIRST_ADDR 0x18
|
||||||
|
#define LED_CONTROL_OPEN_LAST_ADDR 0x2F
|
||||||
|
#define LED_CONTROL_OPEN_LENGTH ((LED_CONTROL_OPEN_LAST_ADDR - LED_CONTROL_OPEN_FIRST_ADDR) + 1)
|
||||||
|
|
||||||
|
#define LED_CONTROL_SHORT_FIRST_ADDR 0x30
|
||||||
|
#define LED_CONTROL_SHORT_LAST_ADDR 0x47
|
||||||
|
#define LED_CONTROL_SHORT_LENGTH ((LED_CONTROL_SHORT_LAST_ADDR - LED_CONTROL_SHORT_FIRST_ADDR) + 1)
|
||||||
|
|
||||||
|
#define LED_CONTROL_PAGE_LENGTH 0x48
|
||||||
|
|
||||||
|
// LED Control Registers
|
||||||
|
#define LED_PWM_FIRST_ADDR 0x00
|
||||||
|
#define LED_PWM_LAST_ADDR 0xBF
|
||||||
|
#define LED_PWM_LENGTH 0xC0
|
||||||
|
|
||||||
|
// Current Tune Registers
|
||||||
|
#define LED_CURRENT_TUNE_FIRST_ADDR 0x00
|
||||||
|
#define LED_CURRENT_TUNE_LAST_ADDR 0x0B
|
||||||
|
#define LED_CURRENT_TUNE_LENGTH 0x0C
|
||||||
|
|
||||||
|
#define A_1 0x00
|
||||||
|
#define A_2 0x01
|
||||||
|
#define A_3 0x02
|
||||||
|
#define A_4 0x03
|
||||||
|
#define A_5 0x04
|
||||||
|
#define A_6 0x05
|
||||||
|
#define A_7 0x06
|
||||||
|
#define A_8 0x07
|
||||||
|
#define A_9 0x08
|
||||||
|
#define A_10 0x09
|
||||||
|
#define A_11 0x0A
|
||||||
|
#define A_12 0x0B
|
||||||
|
#define A_13 0x0C
|
||||||
|
#define A_14 0x0D
|
||||||
|
#define A_15 0x0E
|
||||||
|
#define A_16 0x0F
|
||||||
|
|
||||||
|
#define B_1 0x10
|
||||||
|
#define B_2 0x11
|
||||||
|
#define B_3 0x12
|
||||||
|
#define B_4 0x13
|
||||||
|
#define B_5 0x14
|
||||||
|
#define B_6 0x15
|
||||||
|
#define B_7 0x16
|
||||||
|
#define B_8 0x17
|
||||||
|
#define B_9 0x18
|
||||||
|
#define B_10 0x19
|
||||||
|
#define B_11 0x1A
|
||||||
|
#define B_12 0x1B
|
||||||
|
#define B_13 0x1C
|
||||||
|
#define B_14 0x1D
|
||||||
|
#define B_15 0x1E
|
||||||
|
#define B_16 0x1F
|
||||||
|
|
||||||
|
#define C_1 0x20
|
||||||
|
#define C_2 0x21
|
||||||
|
#define C_3 0x22
|
||||||
|
#define C_4 0x23
|
||||||
|
#define C_5 0x24
|
||||||
|
#define C_6 0x25
|
||||||
|
#define C_7 0x26
|
||||||
|
#define C_8 0x27
|
||||||
|
#define C_9 0x28
|
||||||
|
#define C_10 0x29
|
||||||
|
#define C_11 0x2A
|
||||||
|
#define C_12 0x2B
|
||||||
|
#define C_13 0x2C
|
||||||
|
#define C_14 0x2D
|
||||||
|
#define C_15 0x2E
|
||||||
|
#define C_16 0x2F
|
||||||
|
|
||||||
|
#define D_1 0x30
|
||||||
|
#define D_2 0x31
|
||||||
|
#define D_3 0x32
|
||||||
|
#define D_4 0x33
|
||||||
|
#define D_5 0x34
|
||||||
|
#define D_6 0x35
|
||||||
|
#define D_7 0x36
|
||||||
|
#define D_8 0x37
|
||||||
|
#define D_9 0x38
|
||||||
|
#define D_10 0x39
|
||||||
|
#define D_11 0x3A
|
||||||
|
#define D_12 0x3B
|
||||||
|
#define D_13 0x3C
|
||||||
|
#define D_14 0x3D
|
||||||
|
#define D_15 0x3E
|
||||||
|
#define D_16 0x3F
|
||||||
|
|
||||||
|
#define E_1 0x40
|
||||||
|
#define E_2 0x41
|
||||||
|
#define E_3 0x42
|
||||||
|
#define E_4 0x43
|
||||||
|
#define E_5 0x44
|
||||||
|
#define E_6 0x45
|
||||||
|
#define E_7 0x46
|
||||||
|
#define E_8 0x47
|
||||||
|
#define E_9 0x48
|
||||||
|
#define E_10 0x49
|
||||||
|
#define E_11 0x4A
|
||||||
|
#define E_12 0x4B
|
||||||
|
#define E_13 0x4C
|
||||||
|
#define E_14 0x4D
|
||||||
|
#define E_15 0x4E
|
||||||
|
#define E_16 0x4F
|
||||||
|
|
||||||
|
#define F_1 0x50
|
||||||
|
#define F_2 0x51
|
||||||
|
#define F_3 0x52
|
||||||
|
#define F_4 0x53
|
||||||
|
#define F_5 0x54
|
||||||
|
#define F_6 0x55
|
||||||
|
#define F_7 0x56
|
||||||
|
#define F_8 0x57
|
||||||
|
#define F_9 0x58
|
||||||
|
#define F_10 0x59
|
||||||
|
#define F_11 0x5A
|
||||||
|
#define F_12 0x5B
|
||||||
|
#define F_13 0x5C
|
||||||
|
#define F_14 0x5D
|
||||||
|
#define F_15 0x5E
|
||||||
|
#define F_16 0x5F
|
||||||
|
|
||||||
|
#define G_1 0x60
|
||||||
|
#define G_2 0x61
|
||||||
|
#define G_3 0x62
|
||||||
|
#define G_4 0x63
|
||||||
|
#define G_5 0x64
|
||||||
|
#define G_6 0x65
|
||||||
|
#define G_7 0x66
|
||||||
|
#define G_8 0x67
|
||||||
|
#define G_9 0x68
|
||||||
|
#define G_10 0x69
|
||||||
|
#define G_11 0x6A
|
||||||
|
#define G_12 0x6B
|
||||||
|
#define G_13 0x6C
|
||||||
|
#define G_14 0x6D
|
||||||
|
#define G_15 0x6E
|
||||||
|
#define G_16 0x6F
|
||||||
|
|
||||||
|
#define H_1 0x70
|
||||||
|
#define H_2 0x71
|
||||||
|
#define H_3 0x72
|
||||||
|
#define H_4 0x73
|
||||||
|
#define H_5 0x74
|
||||||
|
#define H_6 0x75
|
||||||
|
#define H_7 0x76
|
||||||
|
#define H_8 0x77
|
||||||
|
#define H_9 0x78
|
||||||
|
#define H_10 0x79
|
||||||
|
#define H_11 0x7A
|
||||||
|
#define H_12 0x7B
|
||||||
|
#define H_13 0x7C
|
||||||
|
#define H_14 0x7D
|
||||||
|
#define H_15 0x7E
|
||||||
|
#define H_16 0x7F
|
||||||
|
|
||||||
|
#define I_1 0x80
|
||||||
|
#define I_2 0x81
|
||||||
|
#define I_3 0x82
|
||||||
|
#define I_4 0x83
|
||||||
|
#define I_5 0x84
|
||||||
|
#define I_6 0x85
|
||||||
|
#define I_7 0x86
|
||||||
|
#define I_8 0x87
|
||||||
|
#define I_9 0x88
|
||||||
|
#define I_10 0x89
|
||||||
|
#define I_11 0x8A
|
||||||
|
#define I_12 0x8B
|
||||||
|
#define I_13 0x8C
|
||||||
|
#define I_14 0x8D
|
||||||
|
#define I_15 0x8E
|
||||||
|
#define I_16 0x8F
|
||||||
|
|
||||||
|
#define J_1 0x90
|
||||||
|
#define J_2 0x91
|
||||||
|
#define J_3 0x92
|
||||||
|
#define J_4 0x93
|
||||||
|
#define J_5 0x94
|
||||||
|
#define J_6 0x95
|
||||||
|
#define J_7 0x96
|
||||||
|
#define J_8 0x97
|
||||||
|
#define J_9 0x98
|
||||||
|
#define J_10 0x99
|
||||||
|
#define J_11 0x9A
|
||||||
|
#define J_12 0x9B
|
||||||
|
#define J_13 0x9C
|
||||||
|
#define J_14 0x9D
|
||||||
|
#define J_15 0x9E
|
||||||
|
#define J_16 0x9F
|
||||||
|
|
||||||
|
#define K_1 0xA0
|
||||||
|
#define K_2 0xA1
|
||||||
|
#define K_3 0xA2
|
||||||
|
#define K_4 0xA3
|
||||||
|
#define K_5 0xA4
|
||||||
|
#define K_6 0xA5
|
||||||
|
#define K_7 0xA6
|
||||||
|
#define K_8 0xA7
|
||||||
|
#define K_9 0xA8
|
||||||
|
#define K_10 0xA9
|
||||||
|
#define K_11 0xAA
|
||||||
|
#define K_12 0xAB
|
||||||
|
#define K_13 0xAC
|
||||||
|
#define K_14 0xAD
|
||||||
|
#define K_15 0xAE
|
||||||
|
#define K_16 0xAF
|
||||||
|
|
||||||
|
#define L_1 0xB0
|
||||||
|
#define L_2 0xB1
|
||||||
|
#define L_3 0xB2
|
||||||
|
#define L_4 0xB3
|
||||||
|
#define L_5 0xB4
|
||||||
|
#define L_6 0xB5
|
||||||
|
#define L_7 0xB6
|
||||||
|
#define L_8 0xB7
|
||||||
|
#define L_9 0xB8
|
||||||
|
#define L_10 0xB9
|
||||||
|
#define L_11 0xBA
|
||||||
|
#define L_12 0xBB
|
||||||
|
#define L_13 0xBC
|
||||||
|
#define L_14 0xBD
|
||||||
|
#define L_15 0xBE
|
||||||
|
#define L_16 0xBF
|
6
keyboards/lemokey/common/common.mk
Normal file
6
keyboards/lemokey/common/common.mk
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
COMMON_DIR = common
|
||||||
|
SRC += \
|
||||||
|
$(COMMON_DIR)/lemokey_common.c \
|
||||||
|
$(COMMON_DIR)/factory_test.c
|
||||||
|
|
||||||
|
VPATH += $(TOP_DIR)/keyboards/lemokey/$(COMMON_DIR)
|
355
keyboards/lemokey/common/factory_test.c
Normal file
355
keyboards/lemokey/common/factory_test.c
Normal file
|
@ -0,0 +1,355 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
#include "raw_hid.h"
|
||||||
|
#include "via.h"
|
||||||
|
#include "lemokey_task.h"
|
||||||
|
#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
|
||||||
|
|
||||||
|
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,
|
||||||
|
FACTORY_TEST_CMD_GET_DEVICE_ID,
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
} 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 repleased 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
uint8_t payload[32];
|
||||||
|
uint8_t len = 0;
|
||||||
|
|
||||||
|
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];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FACTORY_TEST_CMD_JUMP_TO_BL:
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
case FACTORY_TEST_CMD_GET_DEVICE_ID:
|
||||||
|
payload[len++] = FACTORY_TEST_CMD_GET_DEVICE_ID;
|
||||||
|
payload[len++] = 12;
|
||||||
|
memcpy(&payload[len], (uint32_t *)UID_BASE, 4);
|
||||||
|
memcpy(&payload[len + 4], (uint32_t *)UID_BASE + 4, 4);
|
||||||
|
memcpy(&payload[len + 8], (uint32_t *)UID_BASE + 8, 4);
|
||||||
|
|
||||||
|
len += 12;
|
||||||
|
factory_test_send(payload, len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
keyboards/lemokey/common/factory_test.h
Normal file
33
keyboards/lemokey/common/factory_test.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/* Copyright 2022 @ lokher (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define FACTORY_RESET_CHECK process_record_factory_test
|
||||||
|
#define FACTORY_RESET_TASK factory_test_task
|
||||||
|
|
||||||
|
void factory_test_init(void);
|
||||||
|
|
||||||
|
#if defined(LED_MATRIX_ENABLE) || defined(RGB_MATRIX_ENABLE) || defined(Lightless_Projects)
|
||||||
|
bool factory_test_indicator(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool factory_reset_indicating(void);
|
||||||
|
void factory_test_task(void);
|
||||||
|
void factory_test_rx(uint8_t *data, uint8_t length);
|
||||||
|
|
||||||
|
bool process_record_factory_test(uint16_t keycode, keyrecord_t *record);
|
||||||
|
|
113
keyboards/lemokey/common/lemokey_common.c
Normal file
113
keyboards/lemokey/common/lemokey_common.c
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
#include "lemokey_common.h"
|
||||||
|
#include "raw_hid.h"
|
||||||
|
#include "version.h" // for QMK_BUILDDATE used in EEPROM magic
|
||||||
|
|
||||||
|
#ifdef FACTORY_TEST_ENABLE
|
||||||
|
# include "factory_test.h"
|
||||||
|
# include "lemokey_common.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,};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
static key_combination_t key_comb_list[] = {
|
||||||
|
{2, {KC_LWIN, KC_TAB}},
|
||||||
|
{2, {KC_LWIN, KC_E}},
|
||||||
|
{3, {KC_LSFT, KC_LCMD, KC_4}},
|
||||||
|
{2, {KC_LWIN, KC_C}},
|
||||||
|
#ifdef LOCK_SCREEN_KEY_ENABLE
|
||||||
|
{2, {KC_LWIN, KC_L}},
|
||||||
|
{3, {KC_LCTL, KC_LCMD, KC_Q}},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
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:
|
||||||
|
#ifdef LOCK_SCREEN_KEY_ENABLE
|
||||||
|
case KC_WLCK:
|
||||||
|
case KC_MLCK:
|
||||||
|
#endif
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
61
keyboards/lemokey/common/lemokey_common.h
Normal file
61
keyboards/lemokey/common/lemokey_common.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
enum {
|
||||||
|
KC_LOPTN = QK_KB_0,
|
||||||
|
KC_ROPTN,
|
||||||
|
KC_LCMMD,
|
||||||
|
KC_RCMMD,
|
||||||
|
KC_MCTRL,
|
||||||
|
KC_LNPAD,
|
||||||
|
KC_SIRI,
|
||||||
|
KC_TASK_VIEW,
|
||||||
|
KC_FILE_EXPLORER,
|
||||||
|
KC_SCREEN_SHOT,
|
||||||
|
KC_CORTANA,
|
||||||
|
#ifdef LOCK_SCREEN_KEY_ENABLE
|
||||||
|
KC_WIN_LOCK_SCREEN,
|
||||||
|
KC_MAC_LOCK_SCREEN,
|
||||||
|
#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
|
||||||
|
|
||||||
|
#ifdef LOCK_SCREEN_KEY_ENABLE
|
||||||
|
#define KC_WLCK KC_WIN_LOCK_SCREEN
|
||||||
|
#define KC_MLCK KC_MAC_LOCK_SCREEN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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
|
11
keyboards/lemokey/common/lemokey_common.mk
Normal file
11
keyboards/lemokey/common/lemokey_common.mk
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
OPT_DEFS += -DFACTORY_TEST_ENABLE
|
||||||
|
|
||||||
|
LEMOKEY_COMMON_DIR = common
|
||||||
|
SRC += \
|
||||||
|
$(LEMOKEY_COMMON_DIR)/lemokey_task.c \
|
||||||
|
$(LEMOKEY_COMMON_DIR)/lemokey_common.c \
|
||||||
|
$(LEMOKEY_COMMON_DIR)/lemokey_raw_hid.c \
|
||||||
|
$(LEMOKEY_COMMON_DIR)/factory_test.c
|
||||||
|
|
||||||
|
VPATH += $(TOP_DIR)/keyboards/lemokey/$(LEMOKEY_COMMON_DIR)
|
||||||
|
|
91
keyboards/lemokey/common/lemokey_raw_hid.c
Normal file
91
keyboards/lemokey/common/lemokey_raw_hid.c
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
#include "lemokey_common.h"
|
||||||
|
#include "raw_hid.h"
|
||||||
|
#include "version.h"
|
||||||
|
#ifdef FACTORY_TEST_ENABLE
|
||||||
|
# include "factory_test.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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,
|
||||||
|
};
|
||||||
|
|
||||||
|
void get_support_feature(uint8_t *data) {
|
||||||
|
data[1] = FEATURE_DEFAULT_LAYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lemokey_raw_hid_rx(uint8_t *data, uint8_t length) {
|
||||||
|
switch (data[0]) {
|
||||||
|
case KC_GET_PROTOCOL_VERSION:
|
||||||
|
data[1] = PROTOCOL_VERSION;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KC_GET_FIRMWARE_VERSION: {
|
||||||
|
uint8_t i = 1;
|
||||||
|
data[i++] = 'v';
|
||||||
|
if ((DEVICE_VER & 0xF000) != 0) itoa((DEVICE_VER >> 12), (char *)&data[i++], 16);
|
||||||
|
itoa((DEVICE_VER >> 8) & 0xF, (char *)&data[i++], 16);
|
||||||
|
data[i++] = '.';
|
||||||
|
itoa((DEVICE_VER >> 4) & 0xF, (char *)&data[i++], 16);
|
||||||
|
data[i++] = '.';
|
||||||
|
itoa(DEVICE_VER & 0xF, (char *)&data[i++], 16);
|
||||||
|
data[i++] = ' ';
|
||||||
|
memcpy(&data[i], QMK_BUILDDATE, sizeof(QMK_BUILDDATE));
|
||||||
|
i += sizeof(QMK_BUILDDATE);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case KC_GET_SUPPORT_FEATURE:
|
||||||
|
get_support_feature(&data[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KC_GET_DEFAULT_LAYER:
|
||||||
|
data[1] = get_highest_layer(default_layer_state);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef FACTORY_TEST_ENABLE
|
||||||
|
case 0xAB:
|
||||||
|
factory_test_rx(data, length);
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_hid_send(data, length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(VIA_ENABLE)
|
||||||
|
bool via_command_kb(uint8_t *data, uint8_t length) {
|
||||||
|
return lemokey_raw_hid_rx(data, length);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void raw_hid_receive(uint8_t *data, uint8_t length) {
|
||||||
|
lemokey_raw_hid_rx(data, length);
|
||||||
|
}
|
||||||
|
#endif
|
119
keyboards/lemokey/common/lemokey_task.c
Normal file
119
keyboards/lemokey/common/lemokey_task.c
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "lemokey_task.h"
|
||||||
|
#include "quantum.h"
|
||||||
|
#include "lemokey_common.h"
|
||||||
|
#ifdef FACTORY_TEST_ENABLE
|
||||||
|
#include "factory_test.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__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 FACTORY_TEST_ENABLE
|
||||||
|
if (!process_record_factory_test(keycode, record))
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!process_record_lemokey_kb(keycode, record))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LED_MATRIX_ENABLE)
|
||||||
|
bool led_matrix_indicators_lemokey(void) {
|
||||||
|
#ifdef FACTORY_TEST_ENABLE
|
||||||
|
factory_test_indicator();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(RGB_MATRIX_ENABLE)
|
||||||
|
bool rgb_matrix_indicators_lemokey(void) {
|
||||||
|
# if defined(CAPS_LOCK_INDEX)
|
||||||
|
if (host_keyboard_led_state().caps_lock) {
|
||||||
|
# if defined(DIM_CAPS_LOCK)
|
||||||
|
rgb_matrix_set_color(CAPS_LOCK_INDEX, 0, 0, 0);
|
||||||
|
# else
|
||||||
|
rgb_matrix_set_color(CAPS_LOCK_INDEX, 255, 255, 255);,
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# if defined(NUM_LOCK_INDEX)
|
||||||
|
if (host_keyboard_led_state().num_lock) {
|
||||||
|
rgb_matrix_set_color(NUM_LOCK_INDEX, 255, 255, 255);
|
||||||
|
}
|
||||||
|
# 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 FACTORY_TEST_ENABLE
|
||||||
|
factory_test_task();
|
||||||
|
#endif
|
||||||
|
lemokey_common_task();
|
||||||
|
|
||||||
|
lemokey_task_kb();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
24
keyboards/lemokey/common/lemokey_task.h
Normal file
24
keyboards/lemokey/common/lemokey_task.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.lemokey.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
bool lemokey_task_kb(void);
|
||||||
|
void lemokey_task(void);
|
||||||
|
|
218
keyboards/lemokey/common/matrix.c
Normal file
218
keyboards/lemokey/common/matrix.c
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/* Copyright 2023 ~ 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
#ifndef HC595_STCP
|
||||||
|
# define HC595_STCP B0
|
||||||
|
#endif
|
||||||
|
#ifndef HC595_SHCP
|
||||||
|
# define HC595_SHCP A1
|
||||||
|
#endif
|
||||||
|
#ifndef HC595_DS
|
||||||
|
# define HC595_DS A7
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HC595_START_INDEX
|
||||||
|
# define HC595_START_INDEX 0
|
||||||
|
#endif
|
||||||
|
#ifndef HC595_END_INDEX
|
||||||
|
# define HC595_END_INDEX 15
|
||||||
|
#endif
|
||||||
|
#ifndef HC595_OFFSET_INDEX
|
||||||
|
# define HC595_OFFSET_INDEX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HC595_START_INDEX) && defined(HC595_END_INDEX)
|
||||||
|
# if ((HC595_END_INDEX - HC595_START_INDEX + 1) > 16)
|
||||||
|
# define SIZE_T uint32_t
|
||||||
|
# define UNSELECT_ALL_COL 0xFFFFFFFF
|
||||||
|
# define SELECT_ALL_COL 0x00000000
|
||||||
|
# elif ((HC595_END_INDEX - HC595_START_INDEX + 1) > 8)
|
||||||
|
# define SIZE_T uint16_t
|
||||||
|
# define UNSELECT_ALL_COL 0xFFFF
|
||||||
|
# define SELECT_ALL_COL 0x0000
|
||||||
|
# else
|
||||||
|
# define SIZE_T uint8_t
|
||||||
|
# define UNSELECT_ALL_COL 0xFF
|
||||||
|
# define SELECT_ALL_COL 0x00
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
|
||||||
|
pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
|
||||||
|
|
||||||
|
static inline uint8_t readMatrixPin(pin_t pin) {
|
||||||
|
if (pin != NO_PIN) {
|
||||||
|
return readPin(pin);
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setPinOutput_writeLow(pin_t pin) {
|
||||||
|
setPinOutput(pin);
|
||||||
|
writePinLow(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setPinOutput_writeHigh(pin_t pin) {
|
||||||
|
setPinOutput(pin);
|
||||||
|
writePinHigh(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void HC595_delay(uint16_t n) {
|
||||||
|
while (n-- > 0) {
|
||||||
|
asm volatile("nop" ::: "memory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HC595_output(SIZE_T data, bool bit_flag) {
|
||||||
|
uint8_t n = 1;
|
||||||
|
|
||||||
|
ATOMIC_BLOCK_FORCEON {
|
||||||
|
for (uint8_t i = 0; i < (HC595_END_INDEX - HC595_START_INDEX + 1); i++) {
|
||||||
|
if (data & 0x1) {
|
||||||
|
writePinHigh(HC595_DS);
|
||||||
|
} else {
|
||||||
|
writePinLow(HC595_DS);
|
||||||
|
}
|
||||||
|
writePinHigh(HC595_SHCP);
|
||||||
|
HC595_delay(n);
|
||||||
|
writePinLow(HC595_SHCP);
|
||||||
|
HC595_delay(n);
|
||||||
|
if (bit_flag) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
data = data >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writePinHigh(HC595_STCP);
|
||||||
|
HC595_delay(n);
|
||||||
|
writePinLow(HC595_STCP);
|
||||||
|
HC595_delay(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void select_col(uint8_t col) {
|
||||||
|
if (col < HC595_START_INDEX || col > HC595_END_INDEX) {
|
||||||
|
setPinOutput_writeLow(col_pins[col]);
|
||||||
|
} else {
|
||||||
|
if (col == HC595_START_INDEX) {
|
||||||
|
HC595_output(0x00, true);
|
||||||
|
if (col < HC595_OFFSET_INDEX) {
|
||||||
|
HC595_output(0x01, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unselect_col(uint8_t col) {
|
||||||
|
if (col < HC595_START_INDEX || col > HC595_END_INDEX) {
|
||||||
|
#ifdef MATRIX_UNSELECT_DRIVE_HIGH
|
||||||
|
setPinOutput_writeHigh(col_pins[col]);
|
||||||
|
#else
|
||||||
|
setPinInputHigh(col_pins[col]);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
HC595_output(0x01, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unselect_cols(void) {
|
||||||
|
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||||
|
if (col < HC595_START_INDEX || col > HC595_END_INDEX) {
|
||||||
|
#ifdef MATRIX_UNSELECT_DRIVE_HIGH
|
||||||
|
setPinOutput_writeHigh(col_pins[col]);
|
||||||
|
#else
|
||||||
|
setPinInputHigh(col_pins[col]);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (col == HC595_START_INDEX) {
|
||||||
|
HC595_output(UNSELECT_ALL_COL, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void select_all_cols(void) {
|
||||||
|
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||||
|
if (col < HC595_START_INDEX || col > HC595_END_INDEX) {
|
||||||
|
setPinOutput_writeLow(col_pins[col]);
|
||||||
|
} else {
|
||||||
|
if (col == HC595_START_INDEX) {
|
||||||
|
HC595_output(SELECT_ALL_COL, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter) {
|
||||||
|
// Select col
|
||||||
|
select_col(current_col); // select col
|
||||||
|
HC595_delay(200);
|
||||||
|
|
||||||
|
// For each row...
|
||||||
|
for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
|
||||||
|
// Check row pin state
|
||||||
|
if (readMatrixPin(row_pins[row_index]) == 0) {
|
||||||
|
// Pin LO, set col bit
|
||||||
|
current_matrix[row_index] |= row_shifter;
|
||||||
|
} else {
|
||||||
|
// Pin HI, clear col bit
|
||||||
|
current_matrix[row_index] &= ~row_shifter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unselect col
|
||||||
|
unselect_col(current_col);
|
||||||
|
HC595_delay(200); // wait for all Row signals to go HIGH
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_init_custom(void) {
|
||||||
|
setPinOutput(HC595_DS);
|
||||||
|
setPinOutput(HC595_STCP);
|
||||||
|
setPinOutput(HC595_SHCP);
|
||||||
|
|
||||||
|
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
|
||||||
|
if (row_pins[x] != NO_PIN) {
|
||||||
|
setPinInputHigh(row_pins[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unselect_cols();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
|
||||||
|
matrix_row_t curr_matrix[MATRIX_ROWS] = {0};
|
||||||
|
|
||||||
|
// Set col, read rows
|
||||||
|
matrix_row_t row_shifter = MATRIX_ROW_SHIFTER;
|
||||||
|
for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++, row_shifter <<= 1) {
|
||||||
|
matrix_read_rows_on_col(curr_matrix, current_col, row_shifter);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = memcmp(current_matrix, curr_matrix, sizeof(curr_matrix)) != 0;
|
||||||
|
if (changed) memcpy(current_matrix, curr_matrix, sizeof(curr_matrix));
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void suspend_wakeup_init_kb(void) {
|
||||||
|
// code will run on keyboard wakeup
|
||||||
|
clear_keyboard();
|
||||||
|
}
|
148
keyboards/lemokey/p1/ansi_encoder/ansi_encoder.c
Normal file
148
keyboards/lemokey/p1/ansi_encoder/ansi_encoder.c
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software : you can redistribute it and /or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program.If not, see < http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifdef RGB_MATRIX_ENABLE
|
||||||
|
const snled27351_led_t PROGMEM g_snled27351_leds[RGB_MATRIX_LED_COUNT] = {
|
||||||
|
/* Refer to SNLED27351 manual for these locations
|
||||||
|
* driver
|
||||||
|
* | R location
|
||||||
|
* | | G location
|
||||||
|
* | | | B location
|
||||||
|
* | | | | */
|
||||||
|
{0, A_15, C_15, B_15},
|
||||||
|
{0, A_14, C_14, B_14},
|
||||||
|
{0, A_13, C_13, B_13},
|
||||||
|
{0, A_12, C_12, B_12},
|
||||||
|
{0, A_11, C_11, B_11},
|
||||||
|
{0, A_10, C_10, B_10},
|
||||||
|
{0, A_9, C_9, B_9},
|
||||||
|
{0, A_8, C_8, B_8},
|
||||||
|
{0, A_7, C_7, B_7},
|
||||||
|
{0, A_6, C_6, B_6},
|
||||||
|
{0, A_5, C_5, B_5},
|
||||||
|
{0, A_4, C_4, B_4},
|
||||||
|
{0, A_3, C_3, B_3},
|
||||||
|
{0, A_2, C_2, B_2},
|
||||||
|
|
||||||
|
{0, G_15, I_15, H_15},
|
||||||
|
{0, G_14, I_14, H_14},
|
||||||
|
{0, G_13, I_13, H_13},
|
||||||
|
{0, G_12, I_12, H_12},
|
||||||
|
{0, G_11, I_11, H_11},
|
||||||
|
{0, G_10, I_10, H_10},
|
||||||
|
{0, G_9, I_9, H_9},
|
||||||
|
{0, G_8, I_8, H_8},
|
||||||
|
{0, G_7, I_7, H_7},
|
||||||
|
{0, G_6, I_6, H_6},
|
||||||
|
{0, G_5, I_5, H_5},
|
||||||
|
{0, G_4, I_4, H_4},
|
||||||
|
{0, G_3, I_3, H_3},
|
||||||
|
{0, G_2, I_2, H_2},
|
||||||
|
{0, G_1, I_1, H_1},
|
||||||
|
|
||||||
|
{0, D_15, F_15, E_15},
|
||||||
|
{0, D_14, F_14, E_14},
|
||||||
|
{0, D_13, F_13, E_13},
|
||||||
|
{0, D_12, F_12, E_12},
|
||||||
|
{0, D_11, F_11, E_11},
|
||||||
|
{0, D_10, F_10, E_10},
|
||||||
|
{0, D_9, F_9, E_9},
|
||||||
|
{0, D_8, F_8, E_8},
|
||||||
|
{0, D_7, F_7, E_7},
|
||||||
|
{0, D_6, F_6, E_6},
|
||||||
|
{0, D_5, F_5, E_5},
|
||||||
|
{0, D_4, F_4, E_4},
|
||||||
|
{0, D_3, F_3, E_3},
|
||||||
|
{0, D_2, F_2, E_2},
|
||||||
|
{0, D_1, F_1, E_1},
|
||||||
|
|
||||||
|
{1, A_15, C_15, B_15},
|
||||||
|
{1, A_14, C_14, B_14},
|
||||||
|
{1, A_13, C_13, B_13},
|
||||||
|
{1, A_12, C_12, B_12},
|
||||||
|
{1, A_11, C_11, B_11},
|
||||||
|
{1, A_10, C_10, B_10},
|
||||||
|
{1, A_9, C_9, B_9},
|
||||||
|
{1, A_8, C_8, B_8},
|
||||||
|
{1, A_7, C_7, B_7},
|
||||||
|
{1, A_6, C_6, B_6},
|
||||||
|
{1, A_5, C_5, B_5},
|
||||||
|
{1, A_4, C_4, B_4},
|
||||||
|
{1, A_2, C_2, B_2},
|
||||||
|
{1, A_1, C_1, B_1},
|
||||||
|
|
||||||
|
{1, G_15, I_15, H_15},
|
||||||
|
{1, G_13, I_13, H_13},
|
||||||
|
{1, G_12, I_12, H_12},
|
||||||
|
{1, G_11, I_11, H_11},
|
||||||
|
{1, G_10, I_10, H_10},
|
||||||
|
{1, G_9, I_9, H_9},
|
||||||
|
{1, G_8, I_8, H_8},
|
||||||
|
{1, G_7, I_7, H_7},
|
||||||
|
{1, G_6, I_6, H_6},
|
||||||
|
{1, G_5, I_5, H_5},
|
||||||
|
{1, G_4, I_4, H_4},
|
||||||
|
{1, G_3, I_3, H_3},
|
||||||
|
{1, G_2, I_2, H_2},
|
||||||
|
|
||||||
|
{1, D_15, F_15, E_15},
|
||||||
|
{1, D_14, F_14, E_14},
|
||||||
|
{1, D_13, F_13, E_13},
|
||||||
|
{1, D_9, F_9, E_9},
|
||||||
|
{1, D_6, F_6, E_6},
|
||||||
|
{1, D_5, F_5, E_5},
|
||||||
|
{1, D_4, F_4, E_4},
|
||||||
|
{1, D_3, F_3, E_3},
|
||||||
|
{1, D_2, F_2, E_2},
|
||||||
|
{1, D_1, F_1, E_1},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define __ NO_LED
|
||||||
|
|
||||||
|
led_config_t g_led_config = {
|
||||||
|
{
|
||||||
|
// Key Matrix to LED Index
|
||||||
|
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, __ },
|
||||||
|
{ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 },
|
||||||
|
{ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43 },
|
||||||
|
{ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, __, 56, 57 },
|
||||||
|
{ 58, __, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, __},
|
||||||
|
{ 71, 72, 73, __, __, __, 74, __, __, 75, 76, 77, 78, 79, 80 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// LED Index to Physical Position
|
||||||
|
{0, 0}, {18, 0}, {33, 0}, {48, 0}, {62, 0}, {81, 0}, {95, 0}, {110, 0}, {125, 0}, {143, 0}, {158, 0}, {178, 0}, {187, 0}, {203, 0},
|
||||||
|
{0,15}, {15,15}, {29,15}, {44,15}, {59,15}, {73,15}, {88,15}, {103,15}, {117,15}, {132,15}, {146,15}, {161,15}, {176,15}, {195,15}, {224,15},
|
||||||
|
{4,26}, {22,26}, {37,26}, {51,26}, {66,26}, {81,26}, {95,26}, {110,26}, {125,26}, {139,26}, {154,26}, {173,26}, {187,26}, {201,26}, {224,26},
|
||||||
|
{6,38}, {26,38}, {40,38}, {55,38}, {70,38}, {84,38}, {99,38}, {114,38}, {128,38}, {143,38}, {158,38}, {172,38}, {195,38}, {224,38},
|
||||||
|
{8,49}, {33,49}, {48,49}, {62,49}, {77,49}, {92,49}, {106,49}, {121,49}, {136,49}, {150,49}, {165,49}, {186,49}, {203,52},
|
||||||
|
{2,61}, {20,61}, {38,61}, {94,61}, {147,61}, {161,61}, {178,61}, {192,64}, {203,64}, {224,64},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// RGB LED Index to Flag
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
48
keyboards/lemokey/p1/ansi_encoder/config.h
Normal file
48
keyboards/lemokey/p1/ansi_encoder/config.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef RGB_MATRIX_ENABLE
|
||||||
|
/* RGB Matrix driver configuration */
|
||||||
|
# define DRIVER_COUNT 2
|
||||||
|
# define RGB_MATRIX_LED_COUNT 81
|
||||||
|
|
||||||
|
# define SPI_SCK_PIN A5
|
||||||
|
# define SPI_MISO_PIN A6
|
||||||
|
# define SPI_MOSI_PIN A7
|
||||||
|
|
||||||
|
# define DRIVER_CS_PINS \
|
||||||
|
{ B15, C6 }
|
||||||
|
# define SNLED27351_SPI_DIVISOR 16
|
||||||
|
# define SPI_DRIVER SPIDQ
|
||||||
|
|
||||||
|
/* Scan phase of led driver set as MSKPHASE_9CHANNEL(defined as 0x03 in SNLED27351.h) */
|
||||||
|
# define PHASE_CHANNEL MSKPHASE_9CHANNEL
|
||||||
|
|
||||||
|
/* Set LED driver current */
|
||||||
|
# define SNLED27351_CURRENT_TUNE \
|
||||||
|
{ 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C }
|
||||||
|
|
||||||
|
/* Caps lock indicating led */
|
||||||
|
# define CAPS_LOCK_INDEX 44
|
||||||
|
# define DIM_CAPS_LOCK
|
||||||
|
|
||||||
|
/* win lock indicating led */
|
||||||
|
# define WIN_LOCK_LED_PIN C0
|
||||||
|
# define WIN_LOCK_INDEX 72
|
||||||
|
# define DIM_WIN_LOCK
|
||||||
|
#endif
|
99
keyboards/lemokey/p1/ansi_encoder/info.json
Normal file
99
keyboards/lemokey/p1/ansi_encoder/info.json
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
{
|
||||||
|
"usb": {
|
||||||
|
"pid": "0x0310",
|
||||||
|
"device_version": "1.0.0"
|
||||||
|
},
|
||||||
|
"layouts": {
|
||||||
|
"LAYOUT_ansi_82": {
|
||||||
|
"layout": [
|
||||||
|
{"matrix": [0, 0], "x": 0, "y": 0},
|
||||||
|
{"matrix": [0, 1], "x": 1.25, "y": 0},
|
||||||
|
{"matrix": [0, 2], "x": 2.25, "y": 0},
|
||||||
|
{"matrix": [0, 3], "x": 3.25, "y": 0},
|
||||||
|
{"matrix": [0, 4], "x": 4.25, "y": 0},
|
||||||
|
{"matrix": [0, 5], "x": 5.5, "y": 0},
|
||||||
|
{"matrix": [0, 6], "x": 6.5, "y": 0},
|
||||||
|
{"matrix": [0, 7], "x": 7.5, "y": 0},
|
||||||
|
{"matrix": [0, 8], "x": 8.5, "y": 0},
|
||||||
|
{"matrix": [0, 9], "x": 9.75, "y": 0},
|
||||||
|
{"matrix": [0, 10], "x": 10.75, "y": 0},
|
||||||
|
{"matrix": [0, 11], "x": 11.75, "y": 0},
|
||||||
|
{"matrix": [0, 12], "x": 12.75, "y": 0},
|
||||||
|
{"matrix": [0, 13], "x": 14, "y": 0},
|
||||||
|
{"matrix": [0, 14], "x": 15.25, "y": 0},
|
||||||
|
|
||||||
|
{"matrix": [1, 0], "x": 0, "y": 1.25},
|
||||||
|
{"matrix": [1, 1], "x": 1, "y": 1.25},
|
||||||
|
{"matrix": [1, 2], "x": 2, "y": 1.25},
|
||||||
|
{"matrix": [1, 3], "x": 3, "y": 1.25},
|
||||||
|
{"matrix": [1, 4], "x": 4, "y": 1.25},
|
||||||
|
{"matrix": [1, 5], "x": 5, "y": 1.25},
|
||||||
|
{"matrix": [1, 6], "x": 6, "y": 1.25},
|
||||||
|
{"matrix": [1, 7], "x": 7, "y": 1.25},
|
||||||
|
{"matrix": [1, 8], "x": 8, "y": 1.25},
|
||||||
|
{"matrix": [1, 9], "x": 9, "y": 1.25},
|
||||||
|
{"matrix": [1, 10], "x": 10, "y": 1.25},
|
||||||
|
{"matrix": [1, 11], "x": 11, "y": 1.25},
|
||||||
|
{"matrix": [1, 12], "x": 12, "y": 1.25},
|
||||||
|
{"matrix": [1, 13], "x": 13, "y": 1.25, "w": 2},
|
||||||
|
{"matrix": [1, 14], "x": 15.25, "y": 1.25},
|
||||||
|
|
||||||
|
{"matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5},
|
||||||
|
{"matrix": [2, 1], "x": 1.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 2], "x": 2.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 3], "x": 3.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 4], "x": 4.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 5], "x": 5.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 6], "x": 6.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 7], "x": 7.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 8], "x": 8.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 9], "x": 9.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 10], "x": 10.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 11], "x": 11.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 12], "x": 12.5, "y": 2.25},
|
||||||
|
{"matrix": [2, 13], "x": 13.5, "y": 2.25, "w": 1.5},
|
||||||
|
{"matrix": [2, 14], "x": 15.25, "y": 2.25},
|
||||||
|
|
||||||
|
{"matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75},
|
||||||
|
{"matrix": [3, 1], "x": 1.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 2], "x": 2.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 3], "x": 3.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 4], "x": 4.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 5], "x": 5.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 6], "x": 6.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 7], "x": 7.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 8], "x": 8.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 9], "x": 9.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 10], "x": 10.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 11], "x": 11.75, "y": 3.25},
|
||||||
|
{"matrix": [3, 13], "x": 12.75, "y": 3.25, "w": 2.25},
|
||||||
|
{"matrix": [3, 14], "x": 15.25, "y": 3.25},
|
||||||
|
|
||||||
|
{"matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25},
|
||||||
|
{"matrix": [4, 2], "x": 2.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 3], "x": 3.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 4], "x": 4.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 5], "x": 5.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 6], "x": 6.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 7], "x": 7.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 8], "x": 8.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 9], "x": 9.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 10], "x": 10.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 11], "x": 11.25, "y": 4.25},
|
||||||
|
{"matrix": [4, 12], "x": 12.25, "y": 4.25, "w": 1.75},
|
||||||
|
{"matrix": [4, 13], "x": 14.25, "y": 4.5},
|
||||||
|
|
||||||
|
{"matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.25},
|
||||||
|
{"matrix": [5, 1], "x": 1.25, "y": 5.25, "w": 1.25},
|
||||||
|
{"matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.25},
|
||||||
|
{"matrix": [5, 6], "x": 3.75, "y": 5.25, "w": 6.25},
|
||||||
|
{"matrix": [5, 9], "x": 10, "y": 5.25},
|
||||||
|
{"matrix": [5, 10], "x": 11, "y": 5.25},
|
||||||
|
{"matrix": [5, 11], "x": 12, "y": 5.25},
|
||||||
|
{"matrix": [5, 12], "x": 13.25, "y": 5.5},
|
||||||
|
{"matrix": [5, 13], "x": 14.25, "y": 5.5},
|
||||||
|
{"matrix": [5, 14], "x": 15.25, "y": 5.5}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
77
keyboards/lemokey/p1/ansi_encoder/keymaps/default/keymap.c
Normal file
77
keyboards/lemokey/p1/ansi_encoder/keymaps/default/keymap.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* Copyright 3 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
#include "lemokey_common.h"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
enum layers{
|
||||||
|
MAC_BASE,
|
||||||
|
MAC_FN,
|
||||||
|
WIN_BASE,
|
||||||
|
WIN_FN
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[MAC_BASE] = LAYOUT_ansi_82(
|
||||||
|
KC_ESC, KC_BRID, KC_BRIU, KC_MCTL, KC_LPAD, 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_LCMMD,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)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
if(!process_record_lemokey_common(keycode, record)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
77
keyboards/lemokey/p1/ansi_encoder/keymaps/via/keymap.c
Normal file
77
keyboards/lemokey/p1/ansi_encoder/keymaps/via/keymap.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
#include "lemokey_common.h"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
enum layers {
|
||||||
|
WIN_BASE,
|
||||||
|
WIN_FN,
|
||||||
|
WIN_L2,
|
||||||
|
WIN_L3,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[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_HOME,
|
||||||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
|
||||||
|
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
|
||||||
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
|
||||||
|
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(WIN_FN),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
|
||||||
|
|
||||||
|
[WIN_FN] = LAYOUT_ansi_82(
|
||||||
|
_______, KC_BRID, KC_BRIU, KC_TASK, KC_FILE, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, RGB_TOG,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_END,
|
||||||
|
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, NK_TOGG, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, GU_TOGG, _______, _______, _______, _______, _______, _______, _______, _______),
|
||||||
|
|
||||||
|
[WIN_L2] = LAYOUT_ansi_82(
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______),
|
||||||
|
|
||||||
|
[WIN_L3] = LAYOUT_ansi_82(
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(ENCODER_MAP_ENABLE)
|
||||||
|
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
|
||||||
|
[WIN_BASE] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
|
||||||
|
[WIN_FN] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)},
|
||||||
|
[WIN_L2] = {ENCODER_CCW_CW(KC_VOLD, KC_VOLU)},
|
||||||
|
[WIN_L3] = {ENCODER_CCW_CW(RGB_VAD, RGB_VAI)}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
if(!process_record_lemokey_common(keycode, record)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
1
keyboards/lemokey/p1/ansi_encoder/keymaps/via/rules.mk
Normal file
1
keyboards/lemokey/p1/ansi_encoder/keymaps/via/rules.mk
Normal file
|
@ -0,0 +1 @@
|
||||||
|
VIA_ENABLE = yes
|
1
keyboards/lemokey/p1/ansi_encoder/rules.mk
Normal file
1
keyboards/lemokey/p1/ansi_encoder/rules.mk
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# This file intentionally left blank
|
54
keyboards/lemokey/p1/config.h
Normal file
54
keyboards/lemokey/p1/config.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define UID_BASE 0x1FFFF204U
|
||||||
|
|
||||||
|
/* I2C Driver Configuration */
|
||||||
|
#define I2C1_SCL_PIN B8
|
||||||
|
#define I2C1_SDA_PIN B9
|
||||||
|
#define I2C1_CLOCK_SPEED 400000
|
||||||
|
#define I2C1_DUTY_CYCLE FAST_DUTY_CYCLE_2
|
||||||
|
|
||||||
|
/* EEPROM Driver Configuration */
|
||||||
|
#define EXTERNAL_EEPROM_BYTE_COUNT 2048
|
||||||
|
#define EXTERNAL_EEPROM_PAGE_SIZE 32
|
||||||
|
#define EXTERNAL_EEPROM_WRITE_TIME 3
|
||||||
|
|
||||||
|
/* User used eeprom */
|
||||||
|
//#define EECONFIG_USER_DATA_SIZE 1
|
||||||
|
|
||||||
|
#define I2C1_OPMODE OPMODE_I2C
|
||||||
|
#define EXTERNAL_EEPROM_I2C_BASE_ADDRESS 0b10100010
|
||||||
|
|
||||||
|
/* Encoder Configuration */
|
||||||
|
#define ENCODER_DEFAULT_POS 0x3
|
||||||
|
#define ENCODER_MAP_KEY_DELAY 2
|
||||||
|
|
||||||
|
# define LED_DRIVER_SHUTDOWN_PIN B14
|
||||||
|
|
||||||
|
/* Raw hid command for factory test */
|
||||||
|
# define RAW_HID_CMD 0xAB
|
||||||
|
|
||||||
|
/* Factory test keys */
|
||||||
|
#define FN_KEY_1 MO(1)
|
||||||
|
#define FN_KEY_2 MO(3)
|
||||||
|
#define FN_BL_TRIG_KEY KC_END
|
||||||
|
|
||||||
|
#define MATRIX_IO_DELAY 10
|
||||||
|
|
||||||
|
|
24
keyboards/lemokey/p1/halconf.h
Normal file
24
keyboards/lemokey/p1/halconf.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define _CHIBIOS_HAL_CONF_VER_8_0_
|
||||||
|
|
||||||
|
#define HAL_USE_I2C TRUE
|
||||||
|
#define HAL_USE_SPI TRUE
|
||||||
|
|
||||||
|
#include_next <halconf.h>
|
67
keyboards/lemokey/p1/info.json
Normal file
67
keyboards/lemokey/p1/info.json
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
{
|
||||||
|
"keyboard_name": "Lemokey P1",
|
||||||
|
"manufacturer": "Keychron",
|
||||||
|
"url": "https://github.com/Keychron",
|
||||||
|
"maintainer": "Keychron",
|
||||||
|
"processor": "WB32F3G71",
|
||||||
|
"bootloader": "wb32-dfu",
|
||||||
|
"usb": {
|
||||||
|
"vid": "0x362D"
|
||||||
|
},
|
||||||
|
"features": {
|
||||||
|
"bootmagic": true,
|
||||||
|
"extrakey": true,
|
||||||
|
"mousekey": true,
|
||||||
|
"nkro": true,
|
||||||
|
"rgb_matrix": true,
|
||||||
|
"raw" : true,
|
||||||
|
"send_string" : true
|
||||||
|
},
|
||||||
|
"matrix_pins": {
|
||||||
|
"cols": ["C14", "C15", "C2", "C3", "A0", "A1", "A2", "A3", "B10", "B12", "B13", "C7", "C8", "C9", "A10"],
|
||||||
|
"rows": ["C12", "D2", "B3", "B4", "B5", "B6"]
|
||||||
|
},
|
||||||
|
"diode_direction": "ROW2COL",
|
||||||
|
"eeprom": {
|
||||||
|
"driver": "i2c"
|
||||||
|
},
|
||||||
|
"encoder": {
|
||||||
|
"rotary": [
|
||||||
|
{"pin_a": "A8", "pin_b": "A9"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indicators": {
|
||||||
|
"caps_lock": "C1"
|
||||||
|
},
|
||||||
|
"rgb_matrix": {
|
||||||
|
"driver": "snled27351_spi",
|
||||||
|
"sleep": true,
|
||||||
|
"animations": {
|
||||||
|
"band_spiral_val": true,
|
||||||
|
"breathing": true,
|
||||||
|
"cycle_all": true,
|
||||||
|
"cycle_left_right": true,
|
||||||
|
"cycle_out_in": true,
|
||||||
|
"cycle_out_in_dual": true,
|
||||||
|
"cycle_pinwheel": true,
|
||||||
|
"cycle_spiral": true,
|
||||||
|
"cycle_up_down": true,
|
||||||
|
"digital_rain": true,
|
||||||
|
"dual_beacon": true,
|
||||||
|
"jellybean_raindrops": true,
|
||||||
|
"pixel_rain": true,
|
||||||
|
"rainbow_beacon": true,
|
||||||
|
"rainbow_moving_chevron": true,
|
||||||
|
"solid_reactive_multinexus": true,
|
||||||
|
"solid_reactive_multiwide": true,
|
||||||
|
"solid_reactive_simple": true,
|
||||||
|
"solid_splash": true,
|
||||||
|
"splash": true,
|
||||||
|
"typing_heatmap": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"debounce_type": "sym_eager_pk"
|
||||||
|
},
|
||||||
|
"debounce": 20
|
||||||
|
}
|
26
keyboards/lemokey/p1/mcuconf.h
Normal file
26
keyboards/lemokey/p1/mcuconf.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software : you can redistribute it and /or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program.If not, see < http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include_next <mcuconf.h>
|
||||||
|
|
||||||
|
#undef WB32_I2C_USE_I2C1
|
||||||
|
#define WB32_I2C_USE_I2C1 TRUE
|
||||||
|
|
||||||
|
#undef WB32_SPI_USE_QSPI
|
||||||
|
#define WB32_SPI_USE_QSPI TRUE
|
||||||
|
|
||||||
|
|
34
keyboards/lemokey/p1/p1.c
Normal file
34
keyboards/lemokey/p1/p1.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* Copyright 2024 @ Keychron (https://www.keychron.com)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
#include "eeprom.h"
|
||||||
|
|
||||||
|
void eeconfig_init_kb(void) {
|
||||||
|
#if (EECONFIG_KB_DATA_SIZE) == 0
|
||||||
|
// Reset Keyboard EEPROM value to blank, rather than to a set value
|
||||||
|
eeconfig_update_kb(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
keymap_config.raw = eeconfig_read_keymap();
|
||||||
|
keymap_config.nkro = 0;
|
||||||
|
eeconfig_update_keymap(keymap_config.raw);
|
||||||
|
|
||||||
|
eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 1U << 0);
|
||||||
|
default_layer_set(1U << 0);
|
||||||
|
|
||||||
|
eeconfig_init_user();
|
||||||
|
}
|
21
keyboards/lemokey/p1/readme.md
Normal file
21
keyboards/lemokey/p1/readme.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Lemokey P1
|
||||||
|
|
||||||
|
![Lemokey P1]
|
||||||
|
|
||||||
|
A customizable 75% keyboard.
|
||||||
|
|
||||||
|
* Keyboard Maintainer: [Keychron](https://github.com/keychron)
|
||||||
|
* Hardware Supported: Lemokey P1
|
||||||
|
* Hardware Availability: [Lemokey P1 QMK/VIA Wireless Custom Mechanical Keyboard]
|
||||||
|
|
||||||
|
Make example for this keyboard (after setting up your build environment):
|
||||||
|
|
||||||
|
make keychron/p1/ansi_encoder:default
|
||||||
|
|
||||||
|
Flashing example for this keyboard:
|
||||||
|
|
||||||
|
make keychron/p1/ansi_encoder:default:flash
|
||||||
|
|
||||||
|
**Reset Key**: Disconnect the USB cable, toggle mode switch to "Cable", hold down the *Esc* key or reset button underneath space bar, then connect the USB cable.
|
||||||
|
|
||||||
|
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
3
keyboards/lemokey/p1/rules.mk
Normal file
3
keyboards/lemokey/p1/rules.mk
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
include keyboards/lemokey/common/lemokey_common.mk
|
||||||
|
|
||||||
|
VPATH += $(TOP_DIR)/keyboards/lemokey
|
280
keyboards/lemokey/p1/via_json/p1_ansi_encoder_v1.0.json
Normal file
280
keyboards/lemokey/p1/via_json/p1_ansi_encoder_v1.0.json
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
{
|
||||||
|
"name": "Lemokey P1 ANSI Knob",
|
||||||
|
"vendorId": "0x362D",
|
||||||
|
"productId": "0x0310",
|
||||||
|
"keycodes": ["qmk_lighting"],
|
||||||
|
"menus": [
|
||||||
|
{
|
||||||
|
"label": "Lighting",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"label": "Backlight",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"label": "Brightness",
|
||||||
|
"type": "range",
|
||||||
|
"options": [0, 255],
|
||||||
|
"content": ["id_qmk_rgb_matrix_brightness", 3, 1]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Effect",
|
||||||
|
"type": "dropdown",
|
||||||
|
"content": ["id_qmk_rgb_matrix_effect", 3, 2],
|
||||||
|
"options": [
|
||||||
|
["None", 0],
|
||||||
|
["Solid Color", 1],
|
||||||
|
["Breathing", 2],
|
||||||
|
["Band Spiral Val", 3],
|
||||||
|
["Cycle All", 4],
|
||||||
|
["Cycle Left Right", 5],
|
||||||
|
["Cycle Up Down", 6],
|
||||||
|
["Rainbow Moving Chevron", 7],
|
||||||
|
["Cycle Out In", 8],
|
||||||
|
["Cycle Out In Dual", 9],
|
||||||
|
["Cycle Pinwheel", 10],
|
||||||
|
["Cycle Spiral", 11],
|
||||||
|
["Dual Beacon", 12],
|
||||||
|
["Rainbow Beacon", 13],
|
||||||
|
["Jellybean Raindrops", 14],
|
||||||
|
["Pixel Rain", 15],
|
||||||
|
["Typing Heatmap", 16],
|
||||||
|
["Digital Rain", 17],
|
||||||
|
["Reactive Simple", 18],
|
||||||
|
["Reactive Multiwide", 19],
|
||||||
|
["Reactive Multinexus", 20],
|
||||||
|
["Splash", 21],
|
||||||
|
["Solid Splash", 22]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"showIf": "{id_qmk_rgb_matrix_effect} > 1",
|
||||||
|
"label": "Effect Speed",
|
||||||
|
"type": "range",
|
||||||
|
"options": [0, 255],
|
||||||
|
"content": ["id_qmk_rgb_matrix_effect_speed", 3, 3]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"showIf": "{id_qmk_rgb_matrix_effect} != 0 && ( {id_qmk_rgb_matrix_effect} < 4 || {id_qmk_rgb_matrix_effect} == 18 || ({id_qmk_rgb_matrix_effect} > 17 && {id_qmk_rgb_matrix_effect} != 21) ) ",
|
||||||
|
"label": "Color",
|
||||||
|
"type": "color",
|
||||||
|
"content": ["id_qmk_rgb_matrix_color", 3, 4]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"customKeycodes": [
|
||||||
|
{"name": "Left Option", "title": "Left Option", "shortName": "LOpt"},
|
||||||
|
{"name": "Right Option", "title": "Right Option", "shortName": "ROpt"},
|
||||||
|
{"name": "Left Cmd", "title": "Left Command", "shortName": "LCmd"},
|
||||||
|
{"name": "Right Cmd", "title": "Right Command", "shortName": "RCmd"},
|
||||||
|
{"name": "Misson Control", "title": "Misson Control in Mac", "shortName": "MCtl"},
|
||||||
|
{"name": "Lanuch Pad", "title": "Lanuch Pad in Windows", "shortName": "LPad"},
|
||||||
|
{"name": "Siri", "title": "Siri in macOS", "shortName": "Siri"},
|
||||||
|
{"name": "Task View", "title": "Task View in Windows", "shortName": "Task"},
|
||||||
|
{"name": "File Explorer", "title": "File Explorer in Windows", "shortName": "File"},
|
||||||
|
{"name": "Screen shot", "title": "Screenshot in macOS", "shortName": "SShot"},
|
||||||
|
{"name": "Cortana", "title": "Cortana in Windows", "shortName": "Cortana"}
|
||||||
|
],
|
||||||
|
"matrix": {"rows": 6, "cols" : 15},
|
||||||
|
"layouts": {
|
||||||
|
"keymap": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"c": "#777777"
|
||||||
|
},
|
||||||
|
"0, 0",
|
||||||
|
{
|
||||||
|
"x": 0.25,
|
||||||
|
"c": "#cccccc"
|
||||||
|
},
|
||||||
|
"0, 1",
|
||||||
|
"0, 2",
|
||||||
|
"0, 3",
|
||||||
|
"0, 4",
|
||||||
|
{
|
||||||
|
"x": 0.25,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"0, 5",
|
||||||
|
"0, 6",
|
||||||
|
"0, 7",
|
||||||
|
"0, 8",
|
||||||
|
{
|
||||||
|
"x": 0.25,
|
||||||
|
"c": "#cccccc"
|
||||||
|
},
|
||||||
|
"0, 9",
|
||||||
|
"0, 10",
|
||||||
|
"0, 11",
|
||||||
|
"0, 12",
|
||||||
|
{
|
||||||
|
"x": 0.25,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"0, 13",
|
||||||
|
{
|
||||||
|
"x": 0.25
|
||||||
|
},
|
||||||
|
"0, 14\n\n\n\n\n\n\n\n\ne0"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"y": 0.25,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"1, 0",
|
||||||
|
{
|
||||||
|
"c": "#cccccc"
|
||||||
|
},
|
||||||
|
"1, 1",
|
||||||
|
"1, 2",
|
||||||
|
"1, 3",
|
||||||
|
"1, 4",
|
||||||
|
"1, 5",
|
||||||
|
"1, 6",
|
||||||
|
"1, 7",
|
||||||
|
"1, 8",
|
||||||
|
"1, 9",
|
||||||
|
"1, 10",
|
||||||
|
"1, 11",
|
||||||
|
"1, 12",
|
||||||
|
{
|
||||||
|
"w": 2,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"1, 13",
|
||||||
|
{
|
||||||
|
"x": 0.25
|
||||||
|
},
|
||||||
|
"1, 14"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"w": 1.5,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"2, 0",
|
||||||
|
{
|
||||||
|
"c": "#cccccc"
|
||||||
|
},
|
||||||
|
"2, 1",
|
||||||
|
"2, 2",
|
||||||
|
"2, 3",
|
||||||
|
"2, 4",
|
||||||
|
"2, 5",
|
||||||
|
"2, 6",
|
||||||
|
"2, 7",
|
||||||
|
"2, 8",
|
||||||
|
"2, 9",
|
||||||
|
"2, 10",
|
||||||
|
"2, 11",
|
||||||
|
"2, 12",
|
||||||
|
{
|
||||||
|
"w": 1.5,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"2, 13",
|
||||||
|
{
|
||||||
|
"x": 0.25
|
||||||
|
},
|
||||||
|
"2, 14"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"w": 1.75,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"3, 0",
|
||||||
|
{
|
||||||
|
"c": "#cccccc"
|
||||||
|
},
|
||||||
|
"3, 1",
|
||||||
|
"3, 2",
|
||||||
|
"3, 3",
|
||||||
|
"3, 4",
|
||||||
|
"3, 5",
|
||||||
|
"3, 6",
|
||||||
|
"3, 7",
|
||||||
|
"3, 8",
|
||||||
|
"3, 9",
|
||||||
|
"3, 10",
|
||||||
|
"3, 11",
|
||||||
|
{
|
||||||
|
"w": 2.25,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"3, 13",
|
||||||
|
{
|
||||||
|
"x": 0.25
|
||||||
|
},
|
||||||
|
"3, 14"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"w": 2.25,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"4, 0",
|
||||||
|
{
|
||||||
|
"c": "#cccccc"
|
||||||
|
},
|
||||||
|
"4, 2",
|
||||||
|
"4, 3",
|
||||||
|
"4, 4",
|
||||||
|
"4, 5",
|
||||||
|
"4, 6",
|
||||||
|
"4, 7",
|
||||||
|
"4, 8",
|
||||||
|
"4, 9",
|
||||||
|
"4, 10",
|
||||||
|
"4, 11",
|
||||||
|
{
|
||||||
|
"w": 1.75,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"4, 12",
|
||||||
|
{
|
||||||
|
"x": 0.25,
|
||||||
|
"y": 0.25
|
||||||
|
},
|
||||||
|
"4, 13"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"y": -0.25,
|
||||||
|
"w": 1.25,
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"5, 0",
|
||||||
|
{
|
||||||
|
"w": 1.25
|
||||||
|
},
|
||||||
|
"5, 1",
|
||||||
|
{
|
||||||
|
"w": 1.25
|
||||||
|
},
|
||||||
|
"5, 2",
|
||||||
|
{
|
||||||
|
"w": 6.25,
|
||||||
|
"c": "#cccccc"
|
||||||
|
},
|
||||||
|
"5, 6",
|
||||||
|
{
|
||||||
|
"c": "#aaaaaa"
|
||||||
|
},
|
||||||
|
"5, 9",
|
||||||
|
"5, 10",
|
||||||
|
"5, 11",
|
||||||
|
{
|
||||||
|
"x": 0.25,
|
||||||
|
"y": 0.25
|
||||||
|
},
|
||||||
|
"5, 12",
|
||||||
|
"5, 13",
|
||||||
|
"5, 14"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,9 @@
|
||||||
#ifdef CKLED2001
|
#ifdef CKLED2001
|
||||||
# include "ckled2001-simple.h"
|
# include "ckled2001-simple.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef SNLED27351_SPI
|
||||||
|
# include "snled27351-simple-spi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef LED_MATRIX_LED_FLUSH_LIMIT
|
#ifndef LED_MATRIX_LED_FLUSH_LIMIT
|
||||||
# define LED_MATRIX_LED_FLUSH_LIMIT 16
|
# define LED_MATRIX_LED_FLUSH_LIMIT 16
|
||||||
|
|
|
@ -244,4 +244,23 @@ const led_matrix_driver_t led_matrix_driver = {
|
||||||
.set_value_all = ckled2001_set_value_all,
|
.set_value_all = ckled2001_set_value_all,
|
||||||
};
|
};
|
||||||
# endif
|
# endif
|
||||||
|
#elif defined(SNLED27351_SPI)
|
||||||
|
# include "spi_master.h"
|
||||||
|
|
||||||
|
static void init(void) {
|
||||||
|
spi_init();
|
||||||
|
|
||||||
|
snled27351_init_drivers();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush(void) {
|
||||||
|
snled27351_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
const rgb_matrix_driver_t rgb_matrix_driver = {
|
||||||
|
.init = init,
|
||||||
|
.flush = flush,
|
||||||
|
.set_color = snled27351_set_value,
|
||||||
|
.set_color_all = snled27351_set_value_all,
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
# include "is31flcommon.h"
|
# include "is31flcommon.h"
|
||||||
#elif defined(CKLED2001)
|
#elif defined(CKLED2001)
|
||||||
# include "ckled2001.h"
|
# include "ckled2001.h"
|
||||||
|
#elif defined(SNLED27351_SPI)
|
||||||
|
# include "snled27351-spi.h"
|
||||||
#elif defined(AW20216)
|
#elif defined(AW20216)
|
||||||
# include "aw20216.h"
|
# include "aw20216.h"
|
||||||
#elif defined(WS2812)
|
#elif defined(WS2812)
|
||||||
|
|
|
@ -392,6 +392,25 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
|
||||||
.set_color_all = ckled2001_set_color_all,
|
.set_color_all = ckled2001_set_color_all,
|
||||||
};
|
};
|
||||||
# endif
|
# endif
|
||||||
|
#elif defined(SNLED27351_SPI)
|
||||||
|
# include "spi_master.h"
|
||||||
|
|
||||||
|
static void init(void) {
|
||||||
|
spi_init();
|
||||||
|
|
||||||
|
snled27351_init_drivers();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush(void) {
|
||||||
|
snled27351_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
const rgb_matrix_driver_t rgb_matrix_driver = {
|
||||||
|
.init = init,
|
||||||
|
.flush = flush,
|
||||||
|
.set_color = snled27351_set_color,
|
||||||
|
.set_color_all = snled27351_set_color_all,
|
||||||
|
};
|
||||||
|
|
||||||
#elif defined(AW20216)
|
#elif defined(AW20216)
|
||||||
# include "spi_master.h"
|
# include "spi_master.h"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user