Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

My main QMK branch for Keychron V2 max #257

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
4ae5990
Added wireless support; Added Lemokey L3; Added Keychron V1 Max
lokher Jan 10, 2024
cca8df6
Added shutdown fucntion to snled driver
lokher Jan 11, 2024
15a2edc
Added K3 Max
lokher Jan 11, 2024
74b0845
Added Q1 Max; Updated V1 Max
lokher Jan 11, 2024
8521378
Changed LED_MATRIX_SHUTDOWN_ENABLE to LED_MATRIX_DRIVER_SHUTDOWN_ENA…
lokher Jan 12, 2024
625e099
Added K1 Max ANSI
lokher Jan 13, 2024
2ecd0e7
Added Q60/65 Max ANSI
lokher Jan 13, 2024
6c8de3a
Added Q3 Max
lokher Jan 30, 2024
2f38391
Added Q2 Max
lokher Jan 31, 2024
f45cb07
Added V2 Max
lokher Jan 31, 2024
0b812c9
Add Q5/Q6/Q8/K5/K7/V5 Max
lokher Jan 31, 2024
f9f4cf4
Remove *_CALLBACK_ENABLE related code; Fix V2 Max device name
lokher Feb 1, 2024
6edb298
Add Q10 Pro and Q13 Pro
lokher Feb 17, 2024
4a63b50
Fix Bug #228
lokher Feb 17, 2024
6d12e23
Add Q10 Max ANSI Encoder
lokher Feb 18, 2024
08e8e81
Add K13 Max ANSI
lokher Feb 19, 2024
4fe24e8
Add V3 Max
lokher Mar 2, 2024
a56ef87
Add V6 Max
lokher Mar 2, 2024
f7a0879
Add K17 Pro
lokher Mar 7, 2024
0cd4ee0
fix delay of macro doens't work properly except cable mode
lokher Mar 18, 2024
a07246a
Add V10 Max
lokher Mar 18, 2024
9adbd8b
Fix compiling error of lemokey keyboard
lokher Mar 20, 2024
fd70215
Fix boot magic key position of V10 Max
lokher Mar 21, 2024
53c2c1b
Remove KC_TRANS assignments for keys not existing on keyboards that d…
tam1m Feb 3, 2024
0cddb71
Add defines for keychron custom keycodes when LK_WIRELESS_ENABLE and/…
tam1m Mar 8, 2024
07208a1
Merge pull request #222 from tam1m/wireless_playground
lokher Mar 30, 2024
eba583c
Fix compiling error caused by commit 0cd4ee
lokher Mar 30, 2024
57c5939
Fix incorrect minor version response of kc_get_firmware_version
lokher Apr 2, 2024
9a9cfbb
Fix Q10 Pro compilation error
lokher Apr 12, 2024
c1724ac
Add Q1 Pro VIA json
lokher Apr 12, 2024
e5e57f4
Fixed NKRO issue in wireless mode
lokher Apr 12, 2024
fd04262
Add Lemokey L1
lokher Apr 25, 2024
6aa63c3
Add adaptive NKRO feature
lokher Apr 28, 2024
dda1480
Fixed gpio controlled caps lock LED is cleared incorrectly in wireles…
lokher Apr 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "lib/chibios"]
path = lib/chibios
url = https://github.com/qmk/ChibiOS
url = https://github.com/Keychron/ChibiOS.git
branch = master
[submodule "lib/chibios-contrib"]
path = lib/chibios-contrib
Expand Down
16 changes: 14 additions & 2 deletions builddefs/common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ LED_MATRIX_DRIVER := snled27351
endif

LED_MATRIX_ENABLE ?= no
VALID_LED_MATRIX_TYPES := is31fl3218 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 custom
VALID_LED_MATRIX_TYPES := is31fl3218 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 snled27351_spi custom

ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),)
Expand Down Expand Up @@ -428,6 +428,12 @@ ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
SRC += snled27351-simple.c
endif

ifeq ($(strip $(LED_MATRIX_DRIVER)), snled27351_spi)
SPI_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led
SRC += snled27351-simple-spi.c
endif

endif

# Deprecated driver names - do not use
Expand All @@ -440,7 +446,7 @@ endif

RGB_MATRIX_ENABLE ?= no

VALID_RGB_MATRIX_TYPES := aw20216s is31fl3218 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 ws2812 custom
VALID_RGB_MATRIX_TYPES := aw20216s is31fl3218 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 snled27351_spi ws2812 custom
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
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)
Expand Down Expand Up @@ -535,6 +541,12 @@ ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
SRC += snled27351.c
endif

ifeq ($(strip $(RGB_MATRIX_DRIVER)), snled27351_spi)
SPI_DRIVER_REQUIRED = yes
COMMON_VPATH += $(DRIVER_PATH)/led
SRC += snled27351-spi.c
endif

ifeq ($(strip $(RGB_MATRIX_DRIVER)), ws2812)
WS2812_DRIVER_REQUIRED := yes
endif
Expand Down
235 changes: 235 additions & 0 deletions drivers/led/snled27351-simple-spi.c
Original file line number Diff line number Diff line change
@@ -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);
}
Loading
Loading