From 8d979fbbc3a168b68280956e5bfabbbd47047534 Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Sun, 4 Jul 2021 20:41:00 +0200 Subject: [PATCH 1/8] Implement a driver for IS31FL3741 LED matrix driver IC --- app/drivers/CMakeLists.txt | 1 + app/drivers/Kconfig | 3 +- app/drivers/led_strip/CMakeLists.txt | 4 + app/drivers/led_strip/Kconfig | 10 + .../led_strip/is31fl3741/CMakeLists.txt | 6 + app/drivers/led_strip/is31fl3741/Kconfig | 20 ++ app/drivers/led_strip/is31fl3741/is31fl3741.c | 267 ++++++++++++++++++ .../led_strip/is31fl3741/issi,is31fl3741.yaml | 6 + .../bindings/led_strip/issi,is31fl3741.yaml | 52 ++++ app/include/dt-bindings/zmk/issi_transform.h | 18 ++ 10 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 app/drivers/led_strip/CMakeLists.txt create mode 100644 app/drivers/led_strip/Kconfig create mode 100644 app/drivers/led_strip/is31fl3741/CMakeLists.txt create mode 100644 app/drivers/led_strip/is31fl3741/Kconfig create mode 100644 app/drivers/led_strip/is31fl3741/is31fl3741.c create mode 100644 app/drivers/led_strip/is31fl3741/issi,is31fl3741.yaml create mode 100644 app/dts/bindings/led_strip/issi,is31fl3741.yaml create mode 100644 app/include/dt-bindings/zmk/issi_transform.h diff --git a/app/drivers/CMakeLists.txt b/app/drivers/CMakeLists.txt index 44d69ac3..aec0b187 100644 --- a/app/drivers/CMakeLists.txt +++ b/app/drivers/CMakeLists.txt @@ -3,5 +3,6 @@ add_subdirectory_ifdef(CONFIG_ZMK_DRIVERS_GPIO gpio) add_subdirectory(kscan) +add_subdirectory(led_strip) add_subdirectory(sensor) add_subdirectory(display) diff --git a/app/drivers/Kconfig b/app/drivers/Kconfig index c57ed334..dc437468 100644 --- a/app/drivers/Kconfig +++ b/app/drivers/Kconfig @@ -3,5 +3,6 @@ rsource "gpio/Kconfig" rsource "kscan/Kconfig" +rsource "led_strip/Kconfig" rsource "sensor/Kconfig" -rsource "display/Kconfig" +rsource "display/Kconfig" \ No newline at end of file diff --git a/app/drivers/led_strip/CMakeLists.txt b/app/drivers/led_strip/CMakeLists.txt new file mode 100644 index 00000000..beb82ae5 --- /dev/null +++ b/app/drivers/led_strip/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +add_subdirectory_ifdef(CONFIG_IS31FL3741 is31fl3741) diff --git a/app/drivers/led_strip/Kconfig b/app/drivers/led_strip/Kconfig new file mode 100644 index 00000000..22f77819 --- /dev/null +++ b/app/drivers/led_strip/Kconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +rsource "is31fl3741/Kconfig" + +config LEG_STRIP_INIT_PRIORITY + int "LED strip initialization priority" + default 90 + help + System initialization priority for LED strip drivers. diff --git a/app/drivers/led_strip/is31fl3741/CMakeLists.txt b/app/drivers/led_strip/is31fl3741/CMakeLists.txt new file mode 100644 index 00000000..91bea8e1 --- /dev/null +++ b/app/drivers/led_strip/is31fl3741/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +zephyr_library() + +zephyr_library_sources(is31fl3741.c) diff --git a/app/drivers/led_strip/is31fl3741/Kconfig b/app/drivers/led_strip/is31fl3741/Kconfig new file mode 100644 index 00000000..0db07f07 --- /dev/null +++ b/app/drivers/led_strip/is31fl3741/Kconfig @@ -0,0 +1,20 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config IS31FL3741 + bool "IS31FL3741 LED Matrix driver" + depends on I2C + help + Enable an IS31FL3741 LED Matrix driver. + + The IS31FL3741 is a general purpose 39x9 LED Matrix programmed + via an I2C compatible interface. Each LED can be dimmed + individually with 8-bit PWM data and 8-bit scaling data which + allows 256 steps of linear PWM dimming and 256 steps of DC current + adjustable level. + +config LED_STRIP_INIT_PRIORITY + int "LED strip initialization priority" + default 90 + help + System initialization priority for LED strip drivers. diff --git a/app/drivers/led_strip/is31fl3741/is31fl3741.c b/app/drivers/led_strip/is31fl3741/is31fl3741.c new file mode 100644 index 00000000..590874a6 --- /dev/null +++ b/app/drivers/led_strip/is31fl3741/is31fl3741.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT issi_is31fl3741 + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#define IS31FL3741_BUFFER_SIZE (39 * 9) +#define IS31FL3741_BUFFER_PAGE_BREAK (0xb4) + +#define IS31FL3741_REG_PS (0xfd) +#define IS31FL3741_REG_PSWL (0xfe) + +#define IS31FL3741_PSWL_ENABLE (0xc5) +#define IS31FL3741_PSWL_DISABLE (0x00) + +#define IS31FL3741_PAGE_PWM_A (0x00) +#define IS31FL3741_PAGE_PWM_B (0x01) +#define IS31FL3741_PAGE_SCALING_A (0x02) +#define IS31FL3741_PAGE_SCALING_B (0x03) +#define IS31FL3741_PAGE_FUNCTION (0x04) + +struct is31fl3741_config { + char *bus; + int reg; + char *label; + char *sdb_port; + gpio_pin_t sdb_pin; + gpio_dt_flags_t sdb_flags; + uint8_t *px_buffer; + size_t px_buffer_size; + uint8_t gcc; + uint8_t sws; + uint16_t *rgb_map; +}; + +struct is31fl3741_data { + const struct device *i2c; + const struct device *gpio; +}; + +static int is31fl3741_reg_write(const struct device *dev, uint8_t addr, uint8_t value) { + const struct is31fl3741_data *data = dev->data; + const struct is31fl3741_config *config = dev->config; + + if (i2c_reg_write_byte(data->i2c, config->reg, addr, value)) { + LOG_ERR("Failed writing value %x to register address %x on device %x.", value, addr, + config->reg); + return -EIO; + } + + return 0; +} + +static int is31fl3741_reg_burst_write(const struct device *dev, uint8_t start_addr, + const uint8_t *buffer, size_t num_bytes) { + const struct is31fl3741_data *data = dev->data; + const struct is31fl3741_config *config = dev->config; + + if (i2c_burst_write(data->i2c, config->reg, start_addr, buffer, num_bytes)) { + LOG_ERR("Failed burst write with starting address %x", start_addr); + return -EIO; + } + + return 0; +} + +static int is31fl3741_set_page(const struct device *dev, uint8_t page_addr) { + if (is31fl3741_reg_write(dev, IS31FL3741_REG_PSWL, IS31FL3741_PSWL_ENABLE)) { + return -EIO; + } + + if (is31fl3741_reg_write(dev, IS31FL3741_REG_PS, page_addr)) { + return -EIO; + } + + return 0; +} + +static inline bool num_pixels_ok(const struct is31fl3741_config *config, size_t num_pixels) { + size_t num_bytes; + + const bool overflow = size_mul_overflow(num_pixels, 3, &num_bytes); + + return !overflow && (num_bytes <= config->px_buffer_size); +} + +/** + * Updates individual LED channels without an RGB interpretation. + */ +static int is31fl3741_strip_update_channels(const struct device *dev, uint8_t *channels, + size_t num_channels) { + const struct is31fl3741_config *config = dev->config; + + if (config->px_buffer_size < num_channels) { + return -ENOMEM; + } + + is31fl3741_set_page(dev, IS31FL3741_PAGE_PWM_A); + + int result; + + result = is31fl3741_reg_burst_write( + dev, + 0x00, + channels, + (num_channels <= IS31FL3741_BUFFER_PAGE_BREAK) ? num_channels : IS31FL3741_BUFFER_PAGE_BREAK); + + if (result || num_channels <= IS31FL3741_BUFFER_PAGE_BREAK) { + return result; + } + + is31fl3741_set_page(dev, IS31FL3741_PAGE_PWM_B); + + return is31fl3741_reg_burst_write(dev, 0x00, channels + 0xb4, num_channels - 0xb4); +} + +/* + * Updates the RGB LED matrix using cs-order devicetree property + * to assign correct R,G,B channels. + */ +static int is31fl3741_strip_update_rgb(const struct device *dev, struct led_rgb *pixels, + size_t num_pixels) { + const struct is31fl3741_config *config = dev->config; + + uint8_t *px_buffer = config->px_buffer; + uint16_t *rgb_map = config->rgb_map; + + size_t i = 0; + size_t j = 0; + + if (!num_pixels_ok(config, num_pixels)) { + return -ENOMEM; + } + + while (i < num_pixels) { + px_buffer[rgb_map[j++]] = pixels[i].r; + px_buffer[rgb_map[j++]] = pixels[i].g; + px_buffer[rgb_map[j++]] = pixels[i].b; + + ++i; + } + + return is31fl3741_strip_update_channels(dev, px_buffer, config->px_buffer_size); +} + +/* + * Initiates a driver instance for IS31FL3741. + * + * SDB is pulled high to enable chip operation followed + * by a reset to clear out all previous values. + * + * Function and scaling registers are then pre-configured based on devicetree settings. + */ +int static is31fl3741_init(const struct device *dev) { + struct is31fl3741_data *data = dev->data; + const struct is31fl3741_config *config = dev->config; + + data->i2c = device_get_binding(config->bus); + + if (data->i2c == NULL) { + LOG_ERR("I2C device %s not found", config->bus); + return -ENODEV; + } + + data->gpio = device_get_binding(config->sdb_port); + + if (data->gpio == NULL) { + LOG_ERR("GPIO device %s not found", config->sdb_port); + return -ENODEV; + } + + gpio_pin_configure(data->gpio, config->sdb_pin, (GPIO_OUTPUT | config->sdb_flags)); + + if (gpio_pin_set(data->gpio, config->sdb_pin, 1)) { + LOG_ERR("SDB pin for %s cannot be pulled high", config->label); + return -EIO; + } + + // Set configuration registers + if (is31fl3741_set_page(dev, IS31FL3741_PAGE_FUNCTION)) { + LOG_ERR("Couldn't switch to function registers on %s", config->label); + return -EIO; + } + + // Reset + is31fl3741_reg_write(dev, 0x3f, 0xae); // Reset + + // Re-set configuration registers + if (is31fl3741_set_page(dev, IS31FL3741_PAGE_FUNCTION)) { + LOG_ERR("Couldn't switch to function registers on %s", config->label); + return -EIO; + } + + // Configure LED driver operation mode + is31fl3741_reg_write( + dev, 0x00, (config->sws << 4) | (0x01 << 3) | 0x01); // SWS, H logic, Normal operation + is31fl3741_reg_write(dev, 0x01, config->gcc); // Set GCC + + // Set all scaling registers to 0xff, brightness is controlled using PWM + uint8_t scaling_buffer[0xb4]; + for (size_t i = 0; i < 0xb4; ++i) { + scaling_buffer[i] = 0xff; + } + + if (is31fl3741_set_page(dev, IS31FL3741_PAGE_SCALING_A)) { + LOG_ERR("Couldn't switch to scaling register A on %s", config->label); + } + + is31fl3741_reg_burst_write(dev, 0x00, scaling_buffer, 0xb4); + + if (is31fl3741_set_page(dev, IS31FL3741_PAGE_SCALING_B)) { + LOG_ERR("Couldn't switch to scaling register B on %s", config->label); + } + + is31fl3741_reg_burst_write(dev, 0x00, scaling_buffer, 0xab); + + return 0; +} + +static const struct led_strip_driver_api is31fl3741_api = { + .update_rgb = is31fl3741_strip_update_rgb, + .update_channels = is31fl3741_strip_update_channels, +}; + +#define IS31FL3741_GCC(idx) \ + (DT_INST_PROP(idx, r_ext) * DT_INST_PROP(idx, led_max_current) * 256 * 256) / (383 * 255) + +#define IS31FL3741_DEVICE(idx) \ + \ + static struct is31fl3741_data is31fl3741_##idx##_data; \ + \ + static uint8_t is31fl3741_##idx##_px_buffer[IS31FL3741_BUFFER_SIZE]; \ + \ + static uint16_t is31fl3741_##idx##_rgb_map[IS31FL3741_BUFFER_SIZE] = DT_INST_PROP(idx, map); \ + \ + static const struct is31fl3741_config is31fl3741_##idx##_config = { \ + .bus = DT_INST_BUS_LABEL(idx), \ + .reg = DT_INST_REG_ADDR(idx), \ + .label = DT_INST_LABEL(idx), \ + .sdb_port = DT_INST_GPIO_LABEL(idx, sdb_gpios), \ + .sdb_pin = DT_INST_GPIO_PIN(idx, sdb_gpios), \ + .sdb_flags = DT_INST_GPIO_FLAGS(idx, sdb_gpios), \ + .px_buffer = is31fl3741_##idx##_px_buffer, \ + .px_buffer_size = IS31FL3741_BUFFER_SIZE, \ + .gcc = IS31FL3741_GCC(idx), \ + .sws = DT_INST_PROP(idx, sw_setting), \ + .rgb_map = is31fl3741_##idx##_rgb_map, \ + }; \ + \ + DEVICE_AND_API_INIT(is31fl3741_##idx, DT_INST_LABEL(idx), &is31fl3741_init, \ + &is31fl3741_##idx##_data, &is31fl3741_##idx##_config, POST_KERNEL, \ + CONFIG_LED_STRIP_INIT_PRIORITY, &is31fl3741_api); + +DT_INST_FOREACH_STATUS_OKAY(IS31FL3741_DEVICE); diff --git a/app/drivers/led_strip/is31fl3741/issi,is31fl3741.yaml b/app/drivers/led_strip/is31fl3741/issi,is31fl3741.yaml new file mode 100644 index 00000000..53d27936 --- /dev/null +++ b/app/drivers/led_strip/is31fl3741/issi,is31fl3741.yaml @@ -0,0 +1,6 @@ +description: | + Driver for the IS31FL3741 LED matrix driver + +compatible: "issi,issi_is31fl3741" + +include: i2c-device.yaml diff --git a/app/dts/bindings/led_strip/issi,is31fl3741.yaml b/app/dts/bindings/led_strip/issi,is31fl3741.yaml new file mode 100644 index 00000000..9b321ee8 --- /dev/null +++ b/app/dts/bindings/led_strip/issi,is31fl3741.yaml @@ -0,0 +1,52 @@ +# Copyright (c) 2020, The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: ISSI IS31FL3741 LED Matrix driver + +compatible: "issi,is31fl3741" + +include: i2c-device.yaml + +properties: + sw-setting: + type: int + required: false + enum: + - 0x00 + - 0x01 + - 0x02 + - 0x03 + - 0x04 + - 0x05 + - 0x06 + - 0x07 + - 0x08 + default: 0x00 + description: | + SW setting used to control the matrix size by turning off SWx pins + as described in the datasheet. + + map: + type: array + required: true + description: | + Configure how RGB pixels are mapped to individual pixel registers. + + r-ext: + type: int + required: true + description: Rext resistor value in kiloohms. + + led-max-current: + type: int + required: true + description: Maximum allowed LED current in mAh. The maximum allowed by the chip is 38. + + sdb-gpios: + type: phandle-array + required: true + description: | + GPIO pin for hardware shutdown functionality. + + chain-length: + type: int diff --git a/app/include/dt-bindings/zmk/issi_transform.h b/app/include/dt-bindings/zmk/issi_transform.h new file mode 100644 index 00000000..fef1137d --- /dev/null +++ b/app/include/dt-bindings/zmk/issi_transform.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +/** + * Maps a 39x9 matrix cell index to the appropriate IS31FL3741 register indexes. + */ +#define PIXEL(n) ( \ + ((0 <= ((n) % 39)) && (((n) % 39) < 30)) \ + ? ((((n) / 39) * 30) + ((n) % 39)) \ + : (210 + (((n) / 39) * 9) + (((n) % 39) - 31))) + +#define RGB(com, r, g, b) PIXEL(com + r) PIXEL(com + g) PIXEL(com + b) + +#define SW(n) ((n - 1) * 39) +#define CS(n) (n - 1) From 8561cfc34f76eb5a3c10efbc788203a093295073 Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Fri, 9 Jul 2021 10:21:52 +0200 Subject: [PATCH 2/8] Replace duplicate LED_STRIP_INIT_PRIORITY definitions with dependencies --- app/drivers/led_strip/Kconfig | 6 ------ app/drivers/led_strip/is31fl3741/Kconfig | 7 +------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/app/drivers/led_strip/Kconfig b/app/drivers/led_strip/Kconfig index 22f77819..2277a777 100644 --- a/app/drivers/led_strip/Kconfig +++ b/app/drivers/led_strip/Kconfig @@ -2,9 +2,3 @@ # SPDX-License-Identifier: MIT rsource "is31fl3741/Kconfig" - -config LEG_STRIP_INIT_PRIORITY - int "LED strip initialization priority" - default 90 - help - System initialization priority for LED strip drivers. diff --git a/app/drivers/led_strip/is31fl3741/Kconfig b/app/drivers/led_strip/is31fl3741/Kconfig index 0db07f07..eee70914 100644 --- a/app/drivers/led_strip/is31fl3741/Kconfig +++ b/app/drivers/led_strip/is31fl3741/Kconfig @@ -4,6 +4,7 @@ config IS31FL3741 bool "IS31FL3741 LED Matrix driver" depends on I2C + depends on LED_STRIP help Enable an IS31FL3741 LED Matrix driver. @@ -12,9 +13,3 @@ config IS31FL3741 individually with 8-bit PWM data and 8-bit scaling data which allows 256 steps of linear PWM dimming and 256 steps of DC current adjustable level. - -config LED_STRIP_INIT_PRIORITY - int "LED strip initialization priority" - default 90 - help - System initialization priority for LED strip drivers. From f31efdab48302c5c2f7a366377502874d40940e4 Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Fri, 9 Jul 2021 10:34:40 +0200 Subject: [PATCH 3/8] Update comment to reflect the correct configuration setting --- app/drivers/led_strip/is31fl3741/is31fl3741.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/drivers/led_strip/is31fl3741/is31fl3741.c b/app/drivers/led_strip/is31fl3741/is31fl3741.c index 590874a6..23b2afb6 100644 --- a/app/drivers/led_strip/is31fl3741/is31fl3741.c +++ b/app/drivers/led_strip/is31fl3741/is31fl3741.c @@ -128,8 +128,7 @@ static int is31fl3741_strip_update_channels(const struct device *dev, uint8_t *c } /* - * Updates the RGB LED matrix using cs-order devicetree property - * to assign correct R,G,B channels. + * Updates the RGB LED matrix according to devicetree's map property. */ static int is31fl3741_strip_update_rgb(const struct device *dev, struct led_rgb *pixels, size_t num_pixels) { From 4ca67aa96756ac284ab11680d56b6257fe73f699 Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Thu, 15 Jul 2021 08:10:52 +0200 Subject: [PATCH 4/8] Fix IS31FL3741 pin mapping macro --- app/include/dt-bindings/zmk/issi_transform.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/include/dt-bindings/zmk/issi_transform.h b/app/include/dt-bindings/zmk/issi_transform.h index fef1137d..a5932315 100644 --- a/app/include/dt-bindings/zmk/issi_transform.h +++ b/app/include/dt-bindings/zmk/issi_transform.h @@ -5,12 +5,12 @@ */ /** - * Maps a 39x9 matrix cell index to the appropriate IS31FL3741 register indexes. + * Maps a 39x9 matrix cell index to a 1D array matching IS31FL3741's PWM registers order. */ -#define PIXEL(n) ( \ - ((0 <= ((n) % 39)) && (((n) % 39) < 30)) \ - ? ((((n) / 39) * 30) + ((n) % 39)) \ - : (210 + (((n) / 39) * 9) + (((n) % 39) - 31))) +#define PIXEL(n) ( \ + (((n) % 39) < 30) \ + ? ((((n) / 39) * 30) + ((n) % 39)) \ + : (270 + (((n) / 39) * 9) + ((n) % 39) - 30)) #define RGB(com, r, g, b) PIXEL(com + r) PIXEL(com + g) PIXEL(com + b) From 88882ab417ded08331d6a814ad039a0145046d2f Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Sat, 4 Dec 2021 21:13:53 +0100 Subject: [PATCH 5/8] Add gamma settings --- app/drivers/led_strip/is31fl3741/is31fl3741.c | 41 +++++++++++-------- .../led_strip/is31fl3741/issi,is31fl3741.yaml | 6 --- .../bindings/led_strip/issi,is31fl3741.yaml | 33 +++++++++++++++ app/include/dt-bindings/zmk/issi_transform.h | 9 ++-- 4 files changed, 61 insertions(+), 28 deletions(-) delete mode 100644 app/drivers/led_strip/is31fl3741/issi,is31fl3741.yaml diff --git a/app/drivers/led_strip/is31fl3741/is31fl3741.c b/app/drivers/led_strip/is31fl3741/is31fl3741.c index 23b2afb6..81b34d84 100644 --- a/app/drivers/led_strip/is31fl3741/is31fl3741.c +++ b/app/drivers/led_strip/is31fl3741/is31fl3741.c @@ -44,6 +44,7 @@ struct is31fl3741_config { uint8_t gcc; uint8_t sws; uint16_t *rgb_map; + uint8_t (*gamma)[256]; }; struct is31fl3741_data { @@ -65,7 +66,7 @@ static int is31fl3741_reg_write(const struct device *dev, uint8_t addr, uint8_t } static int is31fl3741_reg_burst_write(const struct device *dev, uint8_t start_addr, - const uint8_t *buffer, size_t num_bytes) { + const uint8_t *buffer, size_t num_bytes) { const struct is31fl3741_data *data = dev->data; const struct is31fl3741_config *config = dev->config; @@ -101,7 +102,7 @@ static inline bool num_pixels_ok(const struct is31fl3741_config *config, size_t * Updates individual LED channels without an RGB interpretation. */ static int is31fl3741_strip_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) { + size_t num_channels) { const struct is31fl3741_config *config = dev->config; if (config->px_buffer_size < num_channels) { @@ -112,11 +113,10 @@ static int is31fl3741_strip_update_channels(const struct device *dev, uint8_t *c int result; - result = is31fl3741_reg_burst_write( - dev, - 0x00, - channels, - (num_channels <= IS31FL3741_BUFFER_PAGE_BREAK) ? num_channels : IS31FL3741_BUFFER_PAGE_BREAK); + result = is31fl3741_reg_burst_write(dev, 0x00, channels, + (num_channels <= IS31FL3741_BUFFER_PAGE_BREAK) + ? num_channels + : IS31FL3741_BUFFER_PAGE_BREAK); if (result || num_channels <= IS31FL3741_BUFFER_PAGE_BREAK) { return result; @@ -131,7 +131,7 @@ static int is31fl3741_strip_update_channels(const struct device *dev, uint8_t *c * Updates the RGB LED matrix according to devicetree's map property. */ static int is31fl3741_strip_update_rgb(const struct device *dev, struct led_rgb *pixels, - size_t num_pixels) { + size_t num_pixels) { const struct is31fl3741_config *config = dev->config; uint8_t *px_buffer = config->px_buffer; @@ -145,9 +145,9 @@ static int is31fl3741_strip_update_rgb(const struct device *dev, struct led_rgb } while (i < num_pixels) { - px_buffer[rgb_map[j++]] = pixels[i].r; - px_buffer[rgb_map[j++]] = pixels[i].g; - px_buffer[rgb_map[j++]] = pixels[i].b; + px_buffer[rgb_map[j++]] = config->gamma[0][pixels[i].r]; + px_buffer[rgb_map[j++]] = config->gamma[1][pixels[i].g]; + px_buffer[rgb_map[j++]] = config->gamma[2][pixels[i].b]; ++i; } @@ -204,9 +204,9 @@ int static is31fl3741_init(const struct device *dev) { } // Configure LED driver operation mode - is31fl3741_reg_write( - dev, 0x00, (config->sws << 4) | (0x01 << 3) | 0x01); // SWS, H logic, Normal operation - is31fl3741_reg_write(dev, 0x01, config->gcc); // Set GCC + is31fl3741_reg_write(dev, 0x00, + (config->sws << 4) | (0x01 << 3) | 0x01); // SWS, H logic, Normal operation + is31fl3741_reg_write(dev, 0x01, config->gcc); // Set GCC // Set all scaling registers to 0xff, brightness is controlled using PWM uint8_t scaling_buffer[0xb4]; @@ -245,6 +245,12 @@ static const struct led_strip_driver_api is31fl3741_api = { \ static uint16_t is31fl3741_##idx##_rgb_map[IS31FL3741_BUFFER_SIZE] = DT_INST_PROP(idx, map); \ \ + static uint8_t is31fl3741_##idx##_gamma[3][256] = { \ + DT_INST_PROP(idx, red_gamma), \ + DT_INST_PROP(idx, green_gamma), \ + DT_INST_PROP(idx, blue_gamma), \ + }; \ + \ static const struct is31fl3741_config is31fl3741_##idx##_config = { \ .bus = DT_INST_BUS_LABEL(idx), \ .reg = DT_INST_REG_ADDR(idx), \ @@ -257,10 +263,11 @@ static const struct led_strip_driver_api is31fl3741_api = { .gcc = IS31FL3741_GCC(idx), \ .sws = DT_INST_PROP(idx, sw_setting), \ .rgb_map = is31fl3741_##idx##_rgb_map, \ + .gamma = is31fl3741_##idx##_gamma, \ }; \ \ - DEVICE_AND_API_INIT(is31fl3741_##idx, DT_INST_LABEL(idx), &is31fl3741_init, \ - &is31fl3741_##idx##_data, &is31fl3741_##idx##_config, POST_KERNEL, \ - CONFIG_LED_STRIP_INIT_PRIORITY, &is31fl3741_api); + DEVICE_DT_INST_DEFINE(idx, &is31fl3741_init, NULL, &is31fl3741_##idx##_data, \ + &is31fl3741_##idx##_config, POST_KERNEL, CONFIG_LED_STRIP_INIT_PRIORITY, \ + &is31fl3741_api); DT_INST_FOREACH_STATUS_OKAY(IS31FL3741_DEVICE); diff --git a/app/drivers/led_strip/is31fl3741/issi,is31fl3741.yaml b/app/drivers/led_strip/is31fl3741/issi,is31fl3741.yaml deleted file mode 100644 index 53d27936..00000000 --- a/app/drivers/led_strip/is31fl3741/issi,is31fl3741.yaml +++ /dev/null @@ -1,6 +0,0 @@ -description: | - Driver for the IS31FL3741 LED matrix driver - -compatible: "issi,issi_is31fl3741" - -include: i2c-device.yaml diff --git a/app/dts/bindings/led_strip/issi,is31fl3741.yaml b/app/dts/bindings/led_strip/issi,is31fl3741.yaml index 9b321ee8..31f8a552 100644 --- a/app/dts/bindings/led_strip/issi,is31fl3741.yaml +++ b/app/dts/bindings/led_strip/issi,is31fl3741.yaml @@ -50,3 +50,36 @@ properties: chain-length: type: int + required: true + description: | + How many RGB LEDs are driven by the IC. + + red-gamma: + type: array + required: false + default: [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16, 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 29, 29, 29, 29, 32, 32, 32, 32, 35, 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, 41, 44, 44, 44, 44, 47, 47, 47, 47, 50, 50, 50, 50, 53, 53, 53, 53, 57, 57, 57, 57, 61, 61, 61, 61, 65, 65, 65, 65, 69, 69, 69, 69, 73, 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 89, 89, 89, 89, 94, 94, 94, 94, 99, 99, 99, 99, 104, 104, 104, 104, 109, 109, 109, 109, 114, 114, 114, 114, 119, 119, 119, 119, 124, 124, 124, 124, 129, 129, 129, 129, 134, 134, 134, 134, 140, 140, 140, 140, 146, 146, 146, 146, 152, 152, 152, 152, 158, 158, 158, 158, 164, 164, 164, 164, 170, 170, 170, 170, 176, 176, 176, 176, 182, 182, 182, 182, 188, 188, 188, 188, 195, 195, 195, 195, 202, 202, 202, 202, 209, 209, 209, 209, 216, 216, 216, 216, 223, 223, 223, 223, 230, 230, 230, 230, 237, 237, 237, 237, 244, 244, 244, 244, 251, 251, 251, 251, 255, 255, 255, 255 ] + description: | + Gamma correction lookup values for the red channel. + The gamma values make the LED brightness seem more linear to human eyes. + Default values match the recommendation from the IC datasheet but note this may + or may not work for your particular LEDs. + + green-gamma: + type: array + required: false + default: [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16, 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 29, 29, 29, 29, 32, 32, 32, 32, 35, 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, 41, 44, 44, 44, 44, 47, 47, 47, 47, 50, 50, 50, 50, 53, 53, 53, 53, 57, 57, 57, 57, 61, 61, 61, 61, 65, 65, 65, 65, 69, 69, 69, 69, 73, 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 89, 89, 89, 89, 94, 94, 94, 94, 99, 99, 99, 99, 104, 104, 104, 104, 109, 109, 109, 109, 114, 114, 114, 114, 119, 119, 119, 119, 124, 124, 124, 124, 129, 129, 129, 129, 134, 134, 134, 134, 140, 140, 140, 140, 146, 146, 146, 146, 152, 152, 152, 152, 158, 158, 158, 158, 164, 164, 164, 164, 170, 170, 170, 170, 176, 176, 176, 176, 182, 182, 182, 182, 188, 188, 188, 188, 195, 195, 195, 195, 202, 202, 202, 202, 209, 209, 209, 209, 216, 216, 216, 216, 223, 223, 223, 223, 230, 230, 230, 230, 237, 237, 237, 237, 244, 244, 244, 244, 251, 251, 251, 251, 255, 255, 255, 255 ] + description: | + Gamma correction lookup values for the red channel. + The gamma values make the LED brightness seem more linear to human eyes. + Default values match the recommendation from the IC datasheet but note this may + or may not work for your particular LEDs. + + blue-gamma: + type: array + required: false + default: [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16, 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 29, 29, 29, 29, 32, 32, 32, 32, 35, 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, 41, 44, 44, 44, 44, 47, 47, 47, 47, 50, 50, 50, 50, 53, 53, 53, 53, 57, 57, 57, 57, 61, 61, 61, 61, 65, 65, 65, 65, 69, 69, 69, 69, 73, 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 89, 89, 89, 89, 94, 94, 94, 94, 99, 99, 99, 99, 104, 104, 104, 104, 109, 109, 109, 109, 114, 114, 114, 114, 119, 119, 119, 119, 124, 124, 124, 124, 129, 129, 129, 129, 134, 134, 134, 134, 140, 140, 140, 140, 146, 146, 146, 146, 152, 152, 152, 152, 158, 158, 158, 158, 164, 164, 164, 164, 170, 170, 170, 170, 176, 176, 176, 176, 182, 182, 182, 182, 188, 188, 188, 188, 195, 195, 195, 195, 202, 202, 202, 202, 209, 209, 209, 209, 216, 216, 216, 216, 223, 223, 223, 223, 230, 230, 230, 230, 237, 237, 237, 237, 244, 244, 244, 244, 251, 251, 251, 251, 255, 255, 255, 255 ] + description: | + Gamma correction lookup values for the red channel. + The gamma values make the LED brightness seem more linear to human eyes. + Default values match the recommendation from the IC datasheet but note this may + or may not work for your particular LEDs. diff --git a/app/include/dt-bindings/zmk/issi_transform.h b/app/include/dt-bindings/zmk/issi_transform.h index a5932315..8816fb8f 100644 --- a/app/include/dt-bindings/zmk/issi_transform.h +++ b/app/include/dt-bindings/zmk/issi_transform.h @@ -5,12 +5,11 @@ */ /** - * Maps a 39x9 matrix cell index to a 1D array matching IS31FL3741's PWM registers order. + * Maps a 39x9 matrix cell index to a 1D array matching IS31FL3741's PWN registers order. */ -#define PIXEL(n) ( \ - (((n) % 39) < 30) \ - ? ((((n) / 39) * 30) + ((n) % 39)) \ - : (270 + (((n) / 39) * 9) + ((n) % 39) - 30)) +#define PIXEL(n) \ + ((((n) % 39) < 30) ? ((((n) / 39) * 30) + ((n) % 39)) \ + : (270 + (((n) / 39) * 9) + ((n) % 39) - 30)) #define RGB(com, r, g, b) PIXEL(com + r) PIXEL(com + g) PIXEL(com + b) From 35e269ee8d3b382281fca1123ab4890fef5f042e Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Sun, 19 Dec 2021 18:20:48 +0100 Subject: [PATCH 6/8] Refactor IS31FL3741 driver gamma settings --- app/drivers/led_strip/is31fl3741/is31fl3741.c | 69 ++++++++++--------- .../bindings/led_strip/issi,is31fl3741.yaml | 39 ++++++----- 2 files changed, 60 insertions(+), 48 deletions(-) diff --git a/app/drivers/led_strip/is31fl3741/is31fl3741.c b/app/drivers/led_strip/is31fl3741/is31fl3741.c index 81b34d84..c150885d 100644 --- a/app/drivers/led_strip/is31fl3741/is31fl3741.c +++ b/app/drivers/led_strip/is31fl3741/is31fl3741.c @@ -39,17 +39,20 @@ struct is31fl3741_config { char *sdb_port; gpio_pin_t sdb_pin; gpio_dt_flags_t sdb_flags; - uint8_t *px_buffer; size_t px_buffer_size; uint8_t gcc; uint8_t sws; uint16_t *rgb_map; - uint8_t (*gamma)[256]; + uint8_t *gamma; + uint8_t scaling_red; + uint8_t scaling_blue; + uint8_t scaling_green; }; struct is31fl3741_data { const struct device *i2c; const struct device *gpio; + uint8_t *px_buffer; }; static int is31fl3741_reg_write(const struct device *dev, uint8_t addr, uint8_t value) { @@ -133,9 +136,7 @@ static int is31fl3741_strip_update_channels(const struct device *dev, uint8_t *c static int is31fl3741_strip_update_rgb(const struct device *dev, struct led_rgb *pixels, size_t num_pixels) { const struct is31fl3741_config *config = dev->config; - - uint8_t *px_buffer = config->px_buffer; - uint16_t *rgb_map = config->rgb_map; + struct is31fl3741_data *data = dev->data; size_t i = 0; size_t j = 0; @@ -145,14 +146,14 @@ static int is31fl3741_strip_update_rgb(const struct device *dev, struct led_rgb } while (i < num_pixels) { - px_buffer[rgb_map[j++]] = config->gamma[0][pixels[i].r]; - px_buffer[rgb_map[j++]] = config->gamma[1][pixels[i].g]; - px_buffer[rgb_map[j++]] = config->gamma[2][pixels[i].b]; + data->px_buffer[config->rgb_map[j++]] = config->gamma[pixels[i].r]; + data->px_buffer[config->rgb_map[j++]] = config->gamma[pixels[i].g]; + data->px_buffer[config->rgb_map[j++]] = config->gamma[pixels[i].b]; ++i; } - return is31fl3741_strip_update_channels(dev, px_buffer, config->px_buffer_size); + return is31fl3741_strip_update_channels(dev, data->px_buffer, config->px_buffer_size); } /* @@ -164,8 +165,8 @@ static int is31fl3741_strip_update_rgb(const struct device *dev, struct led_rgb * Function and scaling registers are then pre-configured based on devicetree settings. */ int static is31fl3741_init(const struct device *dev) { - struct is31fl3741_data *data = dev->data; const struct is31fl3741_config *config = dev->config; + struct is31fl3741_data *data = dev->data; data->i2c = device_get_binding(config->bus); @@ -208,24 +209,28 @@ int static is31fl3741_init(const struct device *dev) { (config->sws << 4) | (0x01 << 3) | 0x01); // SWS, H logic, Normal operation is31fl3741_reg_write(dev, 0x01, config->gcc); // Set GCC - // Set all scaling registers to 0xff, brightness is controlled using PWM - uint8_t scaling_buffer[0xb4]; - for (size_t i = 0; i < 0xb4; ++i) { - scaling_buffer[i] = 0xff; + // Set scaling registers + uint8_t *px_buffer = data->px_buffer; + uint16_t *rgb_map = config->rgb_map; + + for (int i = 0; i < config->px_buffer_size; i += 3) { + px_buffer[rgb_map[i]] = config->scaling_red; + px_buffer[rgb_map[i + 1]] = config->scaling_green; + px_buffer[rgb_map[i + 2]] = config->scaling_blue; } - if (is31fl3741_set_page(dev, IS31FL3741_PAGE_SCALING_A)) { - LOG_ERR("Couldn't switch to scaling register A on %s", config->label); + is31fl3741_set_page(dev, IS31FL3741_PAGE_SCALING_A); + is31fl3741_reg_burst_write(dev, 0x00, px_buffer, 0xb4); + + is31fl3741_set_page(dev, IS31FL3741_PAGE_SCALING_B); + is31fl3741_reg_burst_write(dev, 0x00, px_buffer + 0xb4, 0xab); + + // Re-initialize px_buffer to prevent any scaling values from being sent + // to PWM registers during normal operation. + for (size_t i = 0; i < config->px_buffer_size; ++i) { + px_buffer[i] = 0; } - is31fl3741_reg_burst_write(dev, 0x00, scaling_buffer, 0xb4); - - if (is31fl3741_set_page(dev, IS31FL3741_PAGE_SCALING_B)) { - LOG_ERR("Couldn't switch to scaling register B on %s", config->label); - } - - is31fl3741_reg_burst_write(dev, 0x00, scaling_buffer, 0xab); - return 0; } @@ -239,17 +244,15 @@ static const struct led_strip_driver_api is31fl3741_api = { #define IS31FL3741_DEVICE(idx) \ \ - static struct is31fl3741_data is31fl3741_##idx##_data; \ - \ static uint8_t is31fl3741_##idx##_px_buffer[IS31FL3741_BUFFER_SIZE]; \ \ + static struct is31fl3741_data is31fl3741_##idx##_data = { \ + .px_buffer = is31fl3741_##idx##_px_buffer, \ + }; \ + \ static uint16_t is31fl3741_##idx##_rgb_map[IS31FL3741_BUFFER_SIZE] = DT_INST_PROP(idx, map); \ \ - static uint8_t is31fl3741_##idx##_gamma[3][256] = { \ - DT_INST_PROP(idx, red_gamma), \ - DT_INST_PROP(idx, green_gamma), \ - DT_INST_PROP(idx, blue_gamma), \ - }; \ + static uint8_t is31fl3741_##idx##_gamma[] = DT_INST_PROP(idx, gamma); \ \ static const struct is31fl3741_config is31fl3741_##idx##_config = { \ .bus = DT_INST_BUS_LABEL(idx), \ @@ -258,12 +261,14 @@ static const struct led_strip_driver_api is31fl3741_api = { .sdb_port = DT_INST_GPIO_LABEL(idx, sdb_gpios), \ .sdb_pin = DT_INST_GPIO_PIN(idx, sdb_gpios), \ .sdb_flags = DT_INST_GPIO_FLAGS(idx, sdb_gpios), \ - .px_buffer = is31fl3741_##idx##_px_buffer, \ .px_buffer_size = IS31FL3741_BUFFER_SIZE, \ .gcc = IS31FL3741_GCC(idx), \ .sws = DT_INST_PROP(idx, sw_setting), \ .rgb_map = is31fl3741_##idx##_rgb_map, \ .gamma = is31fl3741_##idx##_gamma, \ + .scaling_red = DT_INST_PROP(idx, red_scaling), \ + .scaling_green = DT_INST_PROP(idx, green_scaling), \ + .scaling_blue = DT_INST_PROP(idx, blue_scaling), \ }; \ \ DEVICE_DT_INST_DEFINE(idx, &is31fl3741_init, NULL, &is31fl3741_##idx##_data, \ diff --git a/app/dts/bindings/led_strip/issi,is31fl3741.yaml b/app/dts/bindings/led_strip/issi,is31fl3741.yaml index 31f8a552..d104d8e6 100644 --- a/app/dts/bindings/led_strip/issi,is31fl3741.yaml +++ b/app/dts/bindings/led_strip/issi,is31fl3741.yaml @@ -54,32 +54,39 @@ properties: description: | How many RGB LEDs are driven by the IC. - red-gamma: + gamma: type: array required: false default: [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16, 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 29, 29, 29, 29, 32, 32, 32, 32, 35, 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, 41, 44, 44, 44, 44, 47, 47, 47, 47, 50, 50, 50, 50, 53, 53, 53, 53, 57, 57, 57, 57, 61, 61, 61, 61, 65, 65, 65, 65, 69, 69, 69, 69, 73, 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 89, 89, 89, 89, 94, 94, 94, 94, 99, 99, 99, 99, 104, 104, 104, 104, 109, 109, 109, 109, 114, 114, 114, 114, 119, 119, 119, 119, 124, 124, 124, 124, 129, 129, 129, 129, 134, 134, 134, 134, 140, 140, 140, 140, 146, 146, 146, 146, 152, 152, 152, 152, 158, 158, 158, 158, 164, 164, 164, 164, 170, 170, 170, 170, 176, 176, 176, 176, 182, 182, 182, 182, 188, 188, 188, 188, 195, 195, 195, 195, 202, 202, 202, 202, 209, 209, 209, 209, 216, 216, 216, 216, 223, 223, 223, 223, 230, 230, 230, 230, 237, 237, 237, 237, 244, 244, 244, 244, 251, 251, 251, 251, 255, 255, 255, 255 ] description: | - Gamma correction lookup values for the red channel. + Gamma correction lookup values. The gamma values make the LED brightness seem more linear to human eyes. Default values match the recommendation from the IC datasheet but note this may or may not work for your particular LEDs. - green-gamma: - type: array + red-scaling: + type: int required: false - default: [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16, 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 29, 29, 29, 29, 32, 32, 32, 32, 35, 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, 41, 44, 44, 44, 44, 47, 47, 47, 47, 50, 50, 50, 50, 53, 53, 53, 53, 57, 57, 57, 57, 61, 61, 61, 61, 65, 65, 65, 65, 69, 69, 69, 69, 73, 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 89, 89, 89, 89, 94, 94, 94, 94, 99, 99, 99, 99, 104, 104, 104, 104, 109, 109, 109, 109, 114, 114, 114, 114, 119, 119, 119, 119, 124, 124, 124, 124, 129, 129, 129, 129, 134, 134, 134, 134, 140, 140, 140, 140, 146, 146, 146, 146, 152, 152, 152, 152, 158, 158, 158, 158, 164, 164, 164, 164, 170, 170, 170, 170, 176, 176, 176, 176, 182, 182, 182, 182, 188, 188, 188, 188, 195, 195, 195, 195, 202, 202, 202, 202, 209, 209, 209, 209, 216, 216, 216, 216, 223, 223, 223, 223, 230, 230, 230, 230, 237, 237, 237, 237, 244, 244, 244, 244, 251, 251, 251, 251, 255, 255, 255, 255 ] + default: 255 description: | - Gamma correction lookup values for the red channel. - The gamma values make the LED brightness seem more linear to human eyes. - Default values match the recommendation from the IC datasheet but note this may - or may not work for your particular LEDs. + Red channel scaling factor on a scale of 0-255. + This setting adjusts the brightness of red pixels relative to other channels by scaling the amount + of current flowing through them. 255 being equivalent to the value of led-max-current. - blue-gamma: - type: array + green-scaling: + type: int required: false - default: [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16, 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 29, 29, 29, 29, 32, 32, 32, 32, 35, 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, 41, 44, 44, 44, 44, 47, 47, 47, 47, 50, 50, 50, 50, 53, 53, 53, 53, 57, 57, 57, 57, 61, 61, 61, 61, 65, 65, 65, 65, 69, 69, 69, 69, 73, 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 89, 89, 89, 89, 94, 94, 94, 94, 99, 99, 99, 99, 104, 104, 104, 104, 109, 109, 109, 109, 114, 114, 114, 114, 119, 119, 119, 119, 124, 124, 124, 124, 129, 129, 129, 129, 134, 134, 134, 134, 140, 140, 140, 140, 146, 146, 146, 146, 152, 152, 152, 152, 158, 158, 158, 158, 164, 164, 164, 164, 170, 170, 170, 170, 176, 176, 176, 176, 182, 182, 182, 182, 188, 188, 188, 188, 195, 195, 195, 195, 202, 202, 202, 202, 209, 209, 209, 209, 216, 216, 216, 216, 223, 223, 223, 223, 230, 230, 230, 230, 237, 237, 237, 237, 244, 244, 244, 244, 251, 251, 251, 251, 255, 255, 255, 255 ] + default: 255 description: | - Gamma correction lookup values for the red channel. - The gamma values make the LED brightness seem more linear to human eyes. - Default values match the recommendation from the IC datasheet but note this may - or may not work for your particular LEDs. + Green channel scaling factor on a scale of 0-255. + This setting adjusts the brightness of green pixels relative to other channels by scaling the amount + of current flowing through them. 255 being equivalent to the value of led-max-current. + + blue-scaling: + type: int + required: false + default: 255 + description: | + Blue channel scaling factor on a scale of 0-255. + This setting adjusts the brightness of blue pixels relative to other channels by scaling the amount + of current flowing through them. 255 being equivalent to the value of led-max-current. From 585a331470089f8575691a1c37669ee295700082 Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Tue, 13 Jun 2023 15:19:25 +0200 Subject: [PATCH 7/8] Update is31fl3741 driver for Zephyr 3.* --- app/drivers/led_strip/is31fl3741/is31fl3741.c | 67 ++++++++----------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/app/drivers/led_strip/is31fl3741/is31fl3741.c b/app/drivers/led_strip/is31fl3741/is31fl3741.c index c150885d..a1f3ac42 100644 --- a/app/drivers/led_strip/is31fl3741/is31fl3741.c +++ b/app/drivers/led_strip/is31fl3741/is31fl3741.c @@ -6,14 +6,14 @@ #define DT_DRV_COMPAT issi_is31fl3741 -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -33,12 +33,9 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #define IS31FL3741_PAGE_FUNCTION (0x04) struct is31fl3741_config { - char *bus; - int reg; char *label; - char *sdb_port; - gpio_pin_t sdb_pin; - gpio_dt_flags_t sdb_flags; + struct i2c_dt_spec i2c; + struct gpio_dt_spec gpio; size_t px_buffer_size; uint8_t gcc; uint8_t sws; @@ -50,18 +47,15 @@ struct is31fl3741_config { }; struct is31fl3741_data { - const struct device *i2c; - const struct device *gpio; uint8_t *px_buffer; }; static int is31fl3741_reg_write(const struct device *dev, uint8_t addr, uint8_t value) { - const struct is31fl3741_data *data = dev->data; const struct is31fl3741_config *config = dev->config; - if (i2c_reg_write_byte(data->i2c, config->reg, addr, value)) { + if (i2c_reg_write_byte_dt(&config->i2c, addr, value)) { LOG_ERR("Failed writing value %x to register address %x on device %x.", value, addr, - config->reg); + config->i2c.addr); return -EIO; } @@ -70,10 +64,9 @@ static int is31fl3741_reg_write(const struct device *dev, uint8_t addr, uint8_t static int is31fl3741_reg_burst_write(const struct device *dev, uint8_t start_addr, const uint8_t *buffer, size_t num_bytes) { - const struct is31fl3741_data *data = dev->data; const struct is31fl3741_config *config = dev->config; - if (i2c_burst_write(data->i2c, config->reg, start_addr, buffer, num_bytes)) { + if (i2c_burst_write_dt(&config->i2c, start_addr, buffer, num_bytes)) { LOG_ERR("Failed burst write with starting address %x", start_addr); return -EIO; } @@ -108,6 +101,8 @@ static int is31fl3741_strip_update_channels(const struct device *dev, uint8_t *c size_t num_channels) { const struct is31fl3741_config *config = dev->config; + LOG_ERR("UPDATING CHANNELS!"); + if (config->px_buffer_size < num_channels) { return -ENOMEM; } @@ -166,25 +161,24 @@ static int is31fl3741_strip_update_rgb(const struct device *dev, struct led_rgb */ int static is31fl3741_init(const struct device *dev) { const struct is31fl3741_config *config = dev->config; - struct is31fl3741_data *data = dev->data; + const struct is31fl3741_data *data = dev->data; - data->i2c = device_get_binding(config->bus); + if (!device_is_ready(config->i2c.bus)) { + LOG_ERR("I2C device %s not ready", config->i2c.bus->name); + return -ENODEV; + } - if (data->i2c == NULL) { - LOG_ERR("I2C device %s not found", config->bus); + if (!device_is_ready(config->gpio.port)) { + LOG_ERR("GPIO device for %s is not ready", config->label); return -ENODEV; } - data->gpio = device_get_binding(config->sdb_port); - - if (data->gpio == NULL) { - LOG_ERR("GPIO device %s not found", config->sdb_port); - return -ENODEV; + if (gpio_pin_configure_dt(&config->gpio, GPIO_OUTPUT)) { + LOG_ERR("SDB pin for %s cannot be configured", config->label); + return -EIO; } - gpio_pin_configure(data->gpio, config->sdb_pin, (GPIO_OUTPUT | config->sdb_flags)); - - if (gpio_pin_set(data->gpio, config->sdb_pin, 1)) { + if (gpio_pin_set_dt(&config->gpio, 1)) { LOG_ERR("SDB pin for %s cannot be pulled high", config->label); return -EIO; } @@ -255,12 +249,9 @@ static const struct led_strip_driver_api is31fl3741_api = { static uint8_t is31fl3741_##idx##_gamma[] = DT_INST_PROP(idx, gamma); \ \ static const struct is31fl3741_config is31fl3741_##idx##_config = { \ - .bus = DT_INST_BUS_LABEL(idx), \ - .reg = DT_INST_REG_ADDR(idx), \ - .label = DT_INST_LABEL(idx), \ - .sdb_port = DT_INST_GPIO_LABEL(idx, sdb_gpios), \ - .sdb_pin = DT_INST_GPIO_PIN(idx, sdb_gpios), \ - .sdb_flags = DT_INST_GPIO_FLAGS(idx, sdb_gpios), \ + .label = DT_INST_PROP(idx, label), \ + .i2c = I2C_DT_SPEC_INST_GET(idx), \ + .gpio = GPIO_DT_SPEC_INST_GET(idx, sdb_gpios), \ .px_buffer_size = IS31FL3741_BUFFER_SIZE, \ .gcc = IS31FL3741_GCC(idx), \ .sws = DT_INST_PROP(idx, sw_setting), \ From 50d35afeeb878262376c76931cc688021331f527 Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Tue, 13 Jun 2023 15:54:42 +0200 Subject: [PATCH 8/8] Fix formatting --- app/drivers/led_strip/is31fl3741/Kconfig | 20 +- app/drivers/led_strip/is31fl3741/is31fl3741.c | 2 +- .../bindings/led_strip/issi,is31fl3741.yaml | 278 +++++++++++++++++- 3 files changed, 279 insertions(+), 21 deletions(-) diff --git a/app/drivers/led_strip/is31fl3741/Kconfig b/app/drivers/led_strip/is31fl3741/Kconfig index eee70914..ba0dc630 100644 --- a/app/drivers/led_strip/is31fl3741/Kconfig +++ b/app/drivers/led_strip/is31fl3741/Kconfig @@ -2,14 +2,14 @@ # SPDX-License-Identifier: MIT config IS31FL3741 - bool "IS31FL3741 LED Matrix driver" - depends on I2C - depends on LED_STRIP - help - Enable an IS31FL3741 LED Matrix driver. + bool "IS31FL3741 LED Matrix driver" + depends on I2C + depends on LED_STRIP + help + Enable an IS31FL3741 LED Matrix driver. - The IS31FL3741 is a general purpose 39x9 LED Matrix programmed - via an I2C compatible interface. Each LED can be dimmed - individually with 8-bit PWM data and 8-bit scaling data which - allows 256 steps of linear PWM dimming and 256 steps of DC current - adjustable level. + The IS31FL3741 is a general purpose 39x9 LED Matrix programmed + via an I2C compatible interface. Each LED can be dimmed + individually with 8-bit PWM data and 8-bit scaling data which + allows 256 steps of linear PWM dimming and 256 steps of DC current + adjustable level. diff --git a/app/drivers/led_strip/is31fl3741/is31fl3741.c b/app/drivers/led_strip/is31fl3741/is31fl3741.c index a1f3ac42..9efc0b08 100644 --- a/app/drivers/led_strip/is31fl3741/is31fl3741.c +++ b/app/drivers/led_strip/is31fl3741/is31fl3741.c @@ -165,7 +165,7 @@ int static is31fl3741_init(const struct device *dev) { if (!device_is_ready(config->i2c.bus)) { LOG_ERR("I2C device %s not ready", config->i2c.bus->name); - return -ENODEV; + return -ENODEV; } if (!device_is_ready(config->gpio.port)) { diff --git a/app/dts/bindings/led_strip/issi,is31fl3741.yaml b/app/dts/bindings/led_strip/issi,is31fl3741.yaml index d104d8e6..69b63403 100644 --- a/app/dts/bindings/led_strip/issi,is31fl3741.yaml +++ b/app/dts/bindings/led_strip/issi,is31fl3741.yaml @@ -54,16 +54,6 @@ properties: description: | How many RGB LEDs are driven by the IC. - gamma: - type: array - required: false - default: [ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, 14, 14, 16, 16, 16, 16, 18, 18, 18, 18, 20, 20, 20, 20, 22, 22, 22, 22, 24, 24, 24, 24, 26, 26, 26, 26, 29, 29, 29, 29, 32, 32, 32, 32, 35, 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, 41, 44, 44, 44, 44, 47, 47, 47, 47, 50, 50, 50, 50, 53, 53, 53, 53, 57, 57, 57, 57, 61, 61, 61, 61, 65, 65, 65, 65, 69, 69, 69, 69, 73, 73, 73, 73, 77, 77, 77, 77, 81, 81, 81, 81, 85, 85, 85, 85, 89, 89, 89, 89, 94, 94, 94, 94, 99, 99, 99, 99, 104, 104, 104, 104, 109, 109, 109, 109, 114, 114, 114, 114, 119, 119, 119, 119, 124, 124, 124, 124, 129, 129, 129, 129, 134, 134, 134, 134, 140, 140, 140, 140, 146, 146, 146, 146, 152, 152, 152, 152, 158, 158, 158, 158, 164, 164, 164, 164, 170, 170, 170, 170, 176, 176, 176, 176, 182, 182, 182, 182, 188, 188, 188, 188, 195, 195, 195, 195, 202, 202, 202, 202, 209, 209, 209, 209, 216, 216, 216, 216, 223, 223, 223, 223, 230, 230, 230, 230, 237, 237, 237, 237, 244, 244, 244, 244, 251, 251, 251, 251, 255, 255, 255, 255 ] - description: | - Gamma correction lookup values. - The gamma values make the LED brightness seem more linear to human eyes. - Default values match the recommendation from the IC datasheet but note this may - or may not work for your particular LEDs. - red-scaling: type: int required: false @@ -90,3 +80,271 @@ properties: Blue channel scaling factor on a scale of 0-255. This setting adjusts the brightness of blue pixels relative to other channels by scaling the amount of current flowing through them. 255 being equivalent to the value of led-max-current. + + gamma: + type: array + required: false + description: | + Gamma correction lookup values. + The gamma values make the LED brightness seem more linear to human eyes. + Default values match the recommendation from the IC datasheet but note this may + or may not work for your particular LEDs. + default: + [ + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 3, + 3, + 3, + 3, + 4, + 4, + 4, + 4, + 5, + 5, + 5, + 5, + 6, + 6, + 6, + 6, + 7, + 7, + 7, + 7, + 8, + 8, + 8, + 8, + 10, + 10, + 10, + 10, + 12, + 12, + 12, + 12, + 14, + 14, + 14, + 14, + 16, + 16, + 16, + 16, + 18, + 18, + 18, + 18, + 20, + 20, + 20, + 20, + 22, + 22, + 22, + 22, + 24, + 24, + 24, + 24, + 26, + 26, + 26, + 26, + 29, + 29, + 29, + 29, + 32, + 32, + 32, + 32, + 35, + 35, + 35, + 35, + 38, + 38, + 38, + 38, + 41, + 41, + 41, + 41, + 44, + 44, + 44, + 44, + 47, + 47, + 47, + 47, + 50, + 50, + 50, + 50, + 53, + 53, + 53, + 53, + 57, + 57, + 57, + 57, + 61, + 61, + 61, + 61, + 65, + 65, + 65, + 65, + 69, + 69, + 69, + 69, + 73, + 73, + 73, + 73, + 77, + 77, + 77, + 77, + 81, + 81, + 81, + 81, + 85, + 85, + 85, + 85, + 89, + 89, + 89, + 89, + 94, + 94, + 94, + 94, + 99, + 99, + 99, + 99, + 104, + 104, + 104, + 104, + 109, + 109, + 109, + 109, + 114, + 114, + 114, + 114, + 119, + 119, + 119, + 119, + 124, + 124, + 124, + 124, + 129, + 129, + 129, + 129, + 134, + 134, + 134, + 134, + 140, + 140, + 140, + 140, + 146, + 146, + 146, + 146, + 152, + 152, + 152, + 152, + 158, + 158, + 158, + 158, + 164, + 164, + 164, + 164, + 170, + 170, + 170, + 170, + 176, + 176, + 176, + 176, + 182, + 182, + 182, + 182, + 188, + 188, + 188, + 188, + 195, + 195, + 195, + 195, + 202, + 202, + 202, + 202, + 209, + 209, + 209, + 209, + 216, + 216, + 216, + 216, + 223, + 223, + 223, + 223, + 230, + 230, + 230, + 230, + 237, + 237, + 237, + 237, + 244, + 244, + 244, + 244, + 251, + 251, + 251, + 251, + 255, + 255, + 255, + 255, + ]