Merge 5e6342b1cb
into 3772ecb04e
This commit is contained in:
commit
754b3a76e4
9 changed files with 252 additions and 3 deletions
|
@ -5,3 +5,4 @@ add_subdirectory_ifdef(CONFIG_ZMK_DRIVERS_GPIO gpio)
|
||||||
add_subdirectory(kscan)
|
add_subdirectory(kscan)
|
||||||
add_subdirectory(sensor)
|
add_subdirectory(sensor)
|
||||||
add_subdirectory(display)
|
add_subdirectory(display)
|
||||||
|
add_subdirectory(led_strip)
|
||||||
|
|
|
@ -5,3 +5,4 @@ rsource "gpio/Kconfig"
|
||||||
rsource "kscan/Kconfig"
|
rsource "kscan/Kconfig"
|
||||||
rsource "sensor/Kconfig"
|
rsource "sensor/Kconfig"
|
||||||
rsource "display/Kconfig"
|
rsource "display/Kconfig"
|
||||||
|
rsource "led_strip/Kconfig"
|
||||||
|
|
4
app/drivers/led_strip/CMakeLists.txt
Normal file
4
app/drivers/led_strip/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright (c) 2022 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
zephyr_sources_ifdef(CONFIG_CKLED2001 ckled2001.c)
|
4
app/drivers/led_strip/Kconfig
Normal file
4
app/drivers/led_strip/Kconfig
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright (c) 2022 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
rsource "Kconfig.ckled2001"
|
12
app/drivers/led_strip/Kconfig.ckled2001
Normal file
12
app/drivers/led_strip/Kconfig.ckled2001
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# Copyright (c) 2022 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
DT_COMPAT_ZMK_CKLED2001 := zmk,ckled2001
|
||||||
|
|
||||||
|
config CKLED2001
|
||||||
|
bool "CKLED2001 compatible LED strip controller driver"
|
||||||
|
default $(dt_compat_enabled,$(DT_COMPAT_ZMK_CKLED2001))
|
||||||
|
depends on I2C
|
||||||
|
depends on LED_STRIP
|
||||||
|
help
|
||||||
|
Enable driver for CKLED2001 compatible LED strip controller.
|
181
app/drivers/led_strip/ckled2001.c
Normal file
181
app/drivers/led_strip/ckled2001.c
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The ZMK Contributors
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT zmk_ckled2001
|
||||||
|
|
||||||
|
#include <drivers/led_strip.h>
|
||||||
|
|
||||||
|
#define LOG_LEVEL CONFIG_LED_STRIP_LOG_LEVEL
|
||||||
|
#include <logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(ckled2001);
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/i2c.h>
|
||||||
|
|
||||||
|
#define REG_SET_CMD_PAGE 0xFD
|
||||||
|
#define LED_CONTROL_PAGE 0x00
|
||||||
|
#define LED_PWM_PAGE 0x01
|
||||||
|
#define FUNCTION_PAGE 0x03
|
||||||
|
#define CURRENT_TUNE_PAGE 0x04
|
||||||
|
|
||||||
|
#define REG_CONFIGRATION 0x00
|
||||||
|
#define MSKSW_SHUTDOWN_MODE 0x0
|
||||||
|
#define MSKSW_NORMAL_MODE 0x1
|
||||||
|
|
||||||
|
#define REG_PDU 0x13
|
||||||
|
#define MSKSET_CA_CB_CHANNEL 0xAA
|
||||||
|
#define MSKCLR_CA_CB_CHANNEL 0x00
|
||||||
|
|
||||||
|
#define REG_SCAN_PHASE 0x14
|
||||||
|
#define MSKPHASE_CHANNELS(cnt) (12 - cnt)
|
||||||
|
|
||||||
|
#define REG_SLEW_RATE_CONTROL_MODE1 0x15
|
||||||
|
#define MSKPWM_DELAY_PHASE_ENABLE 0x04
|
||||||
|
#define MSKPWM_DELAY_PHASE_DISABLE 0x00
|
||||||
|
|
||||||
|
#define REG_SLEW_RATE_CONTROL_MODE2 0x16
|
||||||
|
#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE 0xC0
|
||||||
|
#define MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_DISABLE 0x00
|
||||||
|
|
||||||
|
#define REG_SOFTWARE_SLEEP 0x1A
|
||||||
|
#define MSKSLEEP_ENABLE 0x02
|
||||||
|
#define MSKSLEEP_DISABLE 0x00
|
||||||
|
|
||||||
|
#define COUNT_BETWEEN(a, b) ((b - a) + 1)
|
||||||
|
|
||||||
|
#define LED_CONTROL_CNT 24
|
||||||
|
#define LED_PWM_CNT 192
|
||||||
|
#define CURRENT_TUNE_CNT 12
|
||||||
|
|
||||||
|
struct ckled2001_channel_map {
|
||||||
|
uint8_t ch_r;
|
||||||
|
uint8_t ch_g;
|
||||||
|
uint8_t ch_b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ckled2001_config {
|
||||||
|
struct i2c_dt_spec bus;
|
||||||
|
uint8_t scan_phase_channels;
|
||||||
|
struct ckled2001_channel_map *map;
|
||||||
|
uint32_t map_cnt;
|
||||||
|
uint8_t *pwm_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int ckled2001_write_reg(const struct device *dev, uint8_t reg, uint8_t value) {
|
||||||
|
const struct ckled2001_config *config = dev->config;
|
||||||
|
return i2c_burst_write_dt(&config->bus, reg, &value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ckled2001_set_control(const struct device *dev, uint8_t value) {
|
||||||
|
ckled2001_write_reg(dev, REG_SET_CMD_PAGE, LED_CONTROL_PAGE);
|
||||||
|
for (int i = 0; i < LED_CONTROL_CNT; i++) {
|
||||||
|
ckled2001_write_reg(dev, i, value);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ckled2001_flush_pwm_buffer(const struct device *dev) {
|
||||||
|
const struct ckled2001_config *config = dev->config;
|
||||||
|
ckled2001_write_reg(dev, REG_SET_CMD_PAGE, LED_PWM_PAGE);
|
||||||
|
return i2c_burst_write_dt(&config->bus, 0, (const uint8_t *)config->pwm_buffer, LED_PWM_CNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ckled2001_update_rgb(const struct device *dev, struct led_rgb *pixels,
|
||||||
|
size_t num_pixels) {
|
||||||
|
const struct ckled2001_config *config = dev->config;
|
||||||
|
|
||||||
|
if (num_pixels > config->map_cnt) {
|
||||||
|
num_pixels = config->map_cnt;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < num_pixels; i++) {
|
||||||
|
config->pwm_buffer[config->map[i].ch_r] = pixels[i].r;
|
||||||
|
config->pwm_buffer[config->map[i].ch_g] = pixels[i].g;
|
||||||
|
config->pwm_buffer[config->map[i].ch_b] = pixels[i].b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ckled2001_flush_pwm_buffer(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ckled2001_update_channels(const struct device *dev, uint8_t *channels,
|
||||||
|
size_t num_channels) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ckled2001_init(const struct device *dev) {
|
||||||
|
const struct ckled2001_config *config = dev->config;
|
||||||
|
|
||||||
|
LOG_INF("Loaded %d channel mappings", config->map_cnt);
|
||||||
|
|
||||||
|
if (!device_is_ready(config->bus.bus)) {
|
||||||
|
LOG_ERR("I2C bus not ready: %s", config->bus.bus->name);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set functions
|
||||||
|
ckled2001_write_reg(dev, REG_SET_CMD_PAGE, FUNCTION_PAGE);
|
||||||
|
ckled2001_write_reg(dev, REG_CONFIGRATION, MSKSW_SHUTDOWN_MODE);
|
||||||
|
ckled2001_write_reg(dev, REG_PDU, MSKSET_CA_CB_CHANNEL);
|
||||||
|
ckled2001_write_reg(dev, REG_SCAN_PHASE, MSKPHASE_CHANNELS(config->scan_phase_channels));
|
||||||
|
ckled2001_write_reg(dev, REG_SLEW_RATE_CONTROL_MODE1, MSKPWM_DELAY_PHASE_ENABLE);
|
||||||
|
ckled2001_write_reg(dev, REG_SLEW_RATE_CONTROL_MODE2,
|
||||||
|
MSKDRIVING_SINKING_CHHANNEL_SLEWRATE_ENABLE);
|
||||||
|
ckled2001_write_reg(dev, REG_SOFTWARE_SLEEP, MSKSLEEP_DISABLE);
|
||||||
|
|
||||||
|
// Turn off all LEDs
|
||||||
|
ckled2001_set_control(dev, 0x00);
|
||||||
|
|
||||||
|
// Init PWM page
|
||||||
|
memset(config->pwm_buffer, 0x00, LED_PWM_CNT);
|
||||||
|
ckled2001_flush_pwm_buffer(dev);
|
||||||
|
|
||||||
|
// Init current page
|
||||||
|
ckled2001_write_reg(dev, REG_SET_CMD_PAGE, CURRENT_TUNE_PAGE);
|
||||||
|
for (int i = 0; i < CURRENT_TUNE_CNT; i++) {
|
||||||
|
switch (i) {
|
||||||
|
case 2:
|
||||||
|
case 5:
|
||||||
|
case 8:
|
||||||
|
case 11:
|
||||||
|
ckled2001_write_reg(dev, i, 0xA0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ckled2001_write_reg(dev, i, 0xFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn on all LEDs
|
||||||
|
ckled2001_set_control(dev, 0xFF);
|
||||||
|
|
||||||
|
// Set to normal mode
|
||||||
|
ckled2001_write_reg(dev, REG_SET_CMD_PAGE, FUNCTION_PAGE);
|
||||||
|
ckled2001_write_reg(dev, REG_CONFIGRATION, MSKSW_NORMAL_MODE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct led_strip_driver_api ckled2001_api = {
|
||||||
|
.update_rgb = ckled2001_update_rgb,
|
||||||
|
.update_channels = ckled2001_update_channels,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CKLED2001_INIT(n) \
|
||||||
|
static uint8_t ckled2001_channel_map##n[] = DT_INST_PROP(n, map); \
|
||||||
|
\
|
||||||
|
static uint8_t ckled2001_pwm_buffer_##n[LED_PWM_CNT]; \
|
||||||
|
\
|
||||||
|
static const struct ckled2001_config ckled2001_config_##n = { \
|
||||||
|
.bus = I2C_DT_SPEC_INST_GET(n), \
|
||||||
|
.scan_phase_channels = DT_INST_PROP_OR(n, scan_phase_channels, 12), \
|
||||||
|
.map = (struct ckled2001_channel_map *)ckled2001_channel_map##n, \
|
||||||
|
.map_cnt = DT_INST_PROP_LEN(n, map) / 3, \
|
||||||
|
.pwm_buffer = ckled2001_pwm_buffer_##n, \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(n, &ckled2001_init, NULL, NULL, &ckled2001_config_##n, POST_KERNEL, \
|
||||||
|
CONFIG_LED_STRIP_INIT_PRIORITY, &ckled2001_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(CKLED2001_INIT);
|
38
app/drivers/zephyr/dts/bindings/led_strip/zmk,ckled2001.yaml
Normal file
38
app/drivers/zephyr/dts/bindings/led_strip/zmk,ckled2001.yaml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# Copyright (c) 2022 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
description: CKLED2001 LED strip controller
|
||||||
|
|
||||||
|
compatible: "zmk,ckled2001"
|
||||||
|
|
||||||
|
include: [i2c-device.yaml]
|
||||||
|
|
||||||
|
properties:
|
||||||
|
label:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
|
||||||
|
chain-length:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
|
||||||
|
scan-phase-channels:
|
||||||
|
type: int
|
||||||
|
default: 12
|
||||||
|
enum:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
- 5
|
||||||
|
- 6
|
||||||
|
- 7
|
||||||
|
- 8
|
||||||
|
- 9
|
||||||
|
- 10
|
||||||
|
- 11
|
||||||
|
- 12
|
||||||
|
|
||||||
|
map:
|
||||||
|
type: array
|
||||||
|
required: true
|
8
app/include/dt-bindings/zmk/ckled2001.h
Normal file
8
app/include/dt-bindings/zmk/ckled2001.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 The ZMK Contributors
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define CK(ch, idx) ((ch << 4) | idx)
|
|
@ -335,15 +335,15 @@ int zmk_rgb_underglow_off() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
k_timer_stop(&underglow_tick);
|
||||||
|
state.on = false;
|
||||||
|
|
||||||
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
|
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
|
||||||
pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0};
|
pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
|
led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS);
|
||||||
|
|
||||||
k_timer_stop(&underglow_tick);
|
|
||||||
state.on = false;
|
|
||||||
|
|
||||||
return zmk_rgb_underglow_save_state();
|
return zmk_rgb_underglow_save_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue