From 597de0e29841aa6c738eb40454620bc30d44099a Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 4 Jan 2024 17:05:37 +1100 Subject: LED drivers: rename "simple" to "mono" (#22814) --- builddefs/common_features.mk | 22 +- docs/feature_led_matrix.md | 2 +- drivers/led/issi/is31fl3218-mono.c | 146 +++++++++ drivers/led/issi/is31fl3218-mono.h | 75 +++++ drivers/led/issi/is31fl3218-simple.c | 146 --------- drivers/led/issi/is31fl3218-simple.h | 75 ----- drivers/led/issi/is31fl3731-mono.c | 239 ++++++++++++++ drivers/led/issi/is31fl3731-mono.h | 283 +++++++++++++++++ drivers/led/issi/is31fl3731-simple.c | 239 -------------- drivers/led/issi/is31fl3731-simple.h | 283 ----------------- drivers/led/issi/is31fl3733-mono.c | 270 ++++++++++++++++ drivers/led/issi/is31fl3733-mono.h | 367 ++++++++++++++++++++++ drivers/led/issi/is31fl3733-simple.c | 270 ---------------- drivers/led/issi/is31fl3733-simple.h | 367 ---------------------- drivers/led/issi/is31fl3736-mono.c | 244 +++++++++++++++ drivers/led/issi/is31fl3736-mono.h | 262 ++++++++++++++++ drivers/led/issi/is31fl3736-simple.c | 244 --------------- drivers/led/issi/is31fl3736-simple.h | 262 ---------------- drivers/led/issi/is31fl3737-mono.c | 241 ++++++++++++++ drivers/led/issi/is31fl3737-mono.h | 300 ++++++++++++++++++ drivers/led/issi/is31fl3737-simple.c | 241 -------------- drivers/led/issi/is31fl3737-simple.h | 300 ------------------ drivers/led/issi/is31fl3741-mono.c | 271 ++++++++++++++++ drivers/led/issi/is31fl3741-mono.h | 517 +++++++++++++++++++++++++++++++ drivers/led/issi/is31fl3741-simple.c | 271 ---------------- drivers/led/issi/is31fl3741-simple.h | 517 ------------------------------- drivers/led/issi/is31fl3742a-mono.c | 206 ++++++++++++ drivers/led/issi/is31fl3742a-mono.h | 297 ++++++++++++++++++ drivers/led/issi/is31fl3742a-simple.c | 206 ------------ drivers/led/issi/is31fl3742a-simple.h | 297 ------------------ drivers/led/issi/is31fl3743a-mono.c | 216 +++++++++++++ drivers/led/issi/is31fl3743a-mono.h | 329 ++++++++++++++++++++ drivers/led/issi/is31fl3743a-simple.c | 216 ------------- drivers/led/issi/is31fl3743a-simple.h | 329 -------------------- drivers/led/issi/is31fl3745-mono.c | 216 +++++++++++++ drivers/led/issi/is31fl3745-mono.h | 272 ++++++++++++++++ drivers/led/issi/is31fl3745-simple.c | 216 ------------- drivers/led/issi/is31fl3745-simple.h | 272 ---------------- drivers/led/issi/is31fl3746a-mono.c | 208 +++++++++++++ drivers/led/issi/is31fl3746a-mono.h | 192 ++++++++++++ drivers/led/issi/is31fl3746a-simple.c | 208 ------------- drivers/led/issi/is31fl3746a-simple.h | 192 ------------ drivers/led/snled27351-mono.c | 272 ++++++++++++++++ drivers/led/snled27351-mono.h | 381 +++++++++++++++++++++++ drivers/led/snled27351-simple.c | 272 ---------------- drivers/led/snled27351-simple.h | 381 ----------------------- keyboards/fallacy/indicators.c | 2 +- keyboards/fallacy/rules.mk | 2 +- keyboards/wilba_tech/wt60_a/rules.mk | 2 +- keyboards/wilba_tech/wt65_a/rules.mk | 2 +- keyboards/wilba_tech/wt65_b/rules.mk | 2 +- keyboards/wilba_tech/wt75_a/rules.mk | 2 +- keyboards/wilba_tech/wt75_b/rules.mk | 2 +- keyboards/wilba_tech/wt75_c/rules.mk | 2 +- keyboards/wilba_tech/wt80_a/rules.mk | 2 +- keyboards/wilba_tech/wt_mono_backlight.c | 2 +- quantum/led_matrix/led_matrix_drivers.h | 22 +- 57 files changed, 5837 insertions(+), 5837 deletions(-) create mode 100644 drivers/led/issi/is31fl3218-mono.c create mode 100644 drivers/led/issi/is31fl3218-mono.h delete mode 100644 drivers/led/issi/is31fl3218-simple.c delete mode 100644 drivers/led/issi/is31fl3218-simple.h create mode 100644 drivers/led/issi/is31fl3731-mono.c create mode 100644 drivers/led/issi/is31fl3731-mono.h delete mode 100644 drivers/led/issi/is31fl3731-simple.c delete mode 100644 drivers/led/issi/is31fl3731-simple.h create mode 100644 drivers/led/issi/is31fl3733-mono.c create mode 100644 drivers/led/issi/is31fl3733-mono.h delete mode 100644 drivers/led/issi/is31fl3733-simple.c delete mode 100644 drivers/led/issi/is31fl3733-simple.h create mode 100644 drivers/led/issi/is31fl3736-mono.c create mode 100644 drivers/led/issi/is31fl3736-mono.h delete mode 100644 drivers/led/issi/is31fl3736-simple.c delete mode 100644 drivers/led/issi/is31fl3736-simple.h create mode 100644 drivers/led/issi/is31fl3737-mono.c create mode 100644 drivers/led/issi/is31fl3737-mono.h delete mode 100644 drivers/led/issi/is31fl3737-simple.c delete mode 100644 drivers/led/issi/is31fl3737-simple.h create mode 100644 drivers/led/issi/is31fl3741-mono.c create mode 100644 drivers/led/issi/is31fl3741-mono.h delete mode 100644 drivers/led/issi/is31fl3741-simple.c delete mode 100644 drivers/led/issi/is31fl3741-simple.h create mode 100644 drivers/led/issi/is31fl3742a-mono.c create mode 100644 drivers/led/issi/is31fl3742a-mono.h delete mode 100644 drivers/led/issi/is31fl3742a-simple.c delete mode 100644 drivers/led/issi/is31fl3742a-simple.h create mode 100644 drivers/led/issi/is31fl3743a-mono.c create mode 100644 drivers/led/issi/is31fl3743a-mono.h delete mode 100644 drivers/led/issi/is31fl3743a-simple.c delete mode 100644 drivers/led/issi/is31fl3743a-simple.h create mode 100644 drivers/led/issi/is31fl3745-mono.c create mode 100644 drivers/led/issi/is31fl3745-mono.h delete mode 100644 drivers/led/issi/is31fl3745-simple.c delete mode 100644 drivers/led/issi/is31fl3745-simple.h create mode 100644 drivers/led/issi/is31fl3746a-mono.c create mode 100644 drivers/led/issi/is31fl3746a-mono.h delete mode 100644 drivers/led/issi/is31fl3746a-simple.c delete mode 100644 drivers/led/issi/is31fl3746a-simple.h create mode 100644 drivers/led/snled27351-mono.c create mode 100644 drivers/led/snled27351-mono.h delete mode 100644 drivers/led/snled27351-simple.c delete mode 100644 drivers/led/snled27351-simple.h diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index cfdc63f1d4..a6193991f8 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -362,67 +362,67 @@ ifeq ($(strip $(LED_MATRIX_ENABLE)), yes) ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3218) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3218-simple.c + SRC += is31fl3218-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3731) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3731-simple.c + SRC += is31fl3731-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3733) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3733-simple.c + SRC += is31fl3733-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3736) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3736-simple.c + SRC += is31fl3736-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3737) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3737-simple.c + SRC += is31fl3737-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3741) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3741-simple.c + SRC += is31fl3741-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3742a) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3742a-simple.c + SRC += is31fl3742a-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3743a) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3743a-simple.c + SRC += is31fl3743a-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3745) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3745-simple.c + SRC += is31fl3745-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3746a) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led/issi - SRC += is31fl3746a-simple.c + SRC += is31fl3746a-mono.c endif ifeq ($(strip $(LED_MATRIX_DRIVER)), snled27351) I2C_DRIVER_REQUIRED = yes COMMON_VPATH += $(DRIVER_PATH)/led - SRC += snled27351-simple.c + SRC += snled27351-mono.c endif endif diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md index 9b23ce8884..080a693d18 100644 --- a/docs/feature_led_matrix.md +++ b/docs/feature_led_matrix.md @@ -65,7 +65,7 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = { } ``` -Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/led/issi/is31fl3731-simple.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` ). +Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/led/issi/is31fl3731-mono.h`. The `driver` is the index of the driver you defined in your `config.h` (`0`, `1`, `2`, or `3` ). --- ### IS31FLCOMMON :id=is31flcommon diff --git a/drivers/led/issi/is31fl3218-mono.c b/drivers/led/issi/is31fl3218-mono.c new file mode 100644 index 0000000000..ad818f98b1 --- /dev/null +++ b/drivers/led/issi/is31fl3218-mono.c @@ -0,0 +1,146 @@ +/* Copyright 2018 Jason Williams (Wilba) + * + * 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 . + */ +#include "is31fl3218-mono.h" +#include +#include "i2c_master.h" + +#define IS31FL3218_PWM_REGISTER_COUNT 18 +#define IS31FL3218_LED_CONTROL_REGISTER_COUNT 3 + +#ifndef IS31FL3218_I2C_TIMEOUT +# define IS31FL3218_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3218_I2C_PERSISTENCE +# define IS31FL3218_I2C_PERSISTENCE 0 +#endif + +uint8_t i2c_transfer_buffer[20]; + +// IS31FL3218 has 18 PWM outputs and a fixed I2C address, so no chaining. +uint8_t g_pwm_buffer[IS31FL3218_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required = false; + +uint8_t g_led_control_registers[IS31FL3218_LED_CONTROL_REGISTER_COUNT] = {0}; +bool g_led_control_registers_update_required = false; + +void is31fl3218_write_register(uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; +#if IS31FL3218_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) { + if (i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT); +#endif +} + +void is31fl3218_write_pwm_buffer(uint8_t *pwm_buffer) { + i2c_transfer_buffer[0] = IS31FL3218_REG_PWM; + memcpy(i2c_transfer_buffer + 1, pwm_buffer, 18); + +#if IS31FL3218_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) { + i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT); + } +#else + i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT); +#endif +} + +void is31fl3218_init(void) { + i2c_init(); + + // In case we ever want to reinitialize (?) + is31fl3218_write_register(IS31FL3218_REG_RESET, 0x00); + + // Turn off software shutdown + is31fl3218_write_register(IS31FL3218_REG_SHUTDOWN, 0x01); + + // Set all PWM values to zero + for (uint8_t i = 0; i < IS31FL3218_PWM_REGISTER_COUNT; i++) { + is31fl3218_write_register(IS31FL3218_REG_PWM + i, 0x00); + } + + // turn off all LEDs in the LED control register + for (uint8_t i = 0; i < IS31FL3218_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3218_write_register(IS31FL3218_REG_LED_CONTROL_1 + i, 0x00); + } + + // Load PWM registers and LED Control register data + is31fl3218_write_register(IS31FL3218_REG_UPDATE, 0x01); + + for (int i = 0; i < IS31FL3218_LED_COUNT; i++) { + is31fl3218_set_led_control_register(i, true); + } + + is31fl3218_update_led_control_registers(); +} + +void is31fl3218_set_value(int index, uint8_t value) { + is31fl3218_led_t led; + if (index >= 0 && index < IS31FL3218_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3218_leds[index]), sizeof(led)); + } + if (g_pwm_buffer[led.v - IS31FL3218_REG_PWM] == value) { + return; + } + g_pwm_buffer[led.v - IS31FL3218_REG_PWM] = value; + g_pwm_buffer_update_required = true; +} + +void is31fl3218_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3218_LED_COUNT; i++) { + is31fl3218_set_value(i, value); + } +} + +void is31fl3218_set_led_control_register(uint8_t index, bool value) { + is31fl3218_led_t led; + memcpy_P(&led, (&g_is31fl3218_leds[index]), sizeof(led)); + + uint8_t control_register = (led.v - IS31FL3218_REG_PWM) / 6; + uint8_t bit_value = (led.v - IS31FL3218_REG_PWM) % 6; + + if (value) { + g_led_control_registers[control_register] |= (1 << bit_value); + } else { + g_led_control_registers[control_register] &= ~(1 << bit_value); + } + + g_led_control_registers_update_required = true; +} + +void is31fl3218_update_pwm_buffers(void) { + if (g_pwm_buffer_update_required) { + is31fl3218_write_pwm_buffer(g_pwm_buffer); + // Load PWM registers and LED Control register data + is31fl3218_write_register(IS31FL3218_REG_UPDATE, 0x01); + + g_pwm_buffer_update_required = false; + } +} + +void is31fl3218_update_led_control_registers(void) { + if (g_led_control_registers_update_required) { + for (int i = 0; i < IS31FL3218_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3218_write_register(IS31FL3218_REG_LED_CONTROL_1 + i, g_led_control_registers[i]); + } + + g_led_control_registers_update_required = false; + } +} diff --git a/drivers/led/issi/is31fl3218-mono.h b/drivers/led/issi/is31fl3218-mono.h new file mode 100644 index 0000000000..e0a71f1387 --- /dev/null +++ b/drivers/led/issi/is31fl3218-mono.h @@ -0,0 +1,75 @@ +/* Copyright 2018 Jason Williams (Wilba) + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +#define IS31FL3218_REG_SHUTDOWN 0x00 +#define IS31FL3218_REG_PWM 0x01 +#define IS31FL3218_REG_LED_CONTROL_1 0x13 +#define IS31FL3218_REG_LED_CONTROL_2 0x14 +#define IS31FL3218_REG_LED_CONTROL_3 0x15 +#define IS31FL3218_REG_UPDATE 0x16 +#define IS31FL3218_REG_RESET 0x17 + +#define IS31FL3218_I2C_ADDRESS 0x54 + +#if defined(LED_MATRIX_IS31FL3218) +# define IS31FL3218_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +typedef struct is31fl3218_led_t { + uint8_t v; +} PACKED is31fl3218_led_t; + +extern const is31fl3218_led_t PROGMEM g_is31fl3218_leds[IS31FL3218_LED_COUNT]; + +void is31fl3218_init(void); + +void is31fl3218_write_register(uint8_t reg, uint8_t data); + +void is31fl3218_set_value(int index, uint8_t value); + +void is31fl3218_set_value_all(uint8_t value); + +void is31fl3218_set_led_control_register(uint8_t index, bool value); + +void is31fl3218_update_pwm_buffers(void); + +void is31fl3218_update_led_control_registers(void); + +#define OUT1 0x01 +#define OUT2 0x02 +#define OUT3 0x03 +#define OUT4 0x04 +#define OUT5 0x05 +#define OUT6 0x06 +#define OUT7 0x07 +#define OUT8 0x08 +#define OUT9 0x09 +#define OUT10 0x0A +#define OUT11 0x0B +#define OUT12 0x0C +#define OUT13 0x0D +#define OUT14 0x0E +#define OUT15 0x0F +#define OUT16 0x10 +#define OUT17 0x11 +#define OUT18 0x12 diff --git a/drivers/led/issi/is31fl3218-simple.c b/drivers/led/issi/is31fl3218-simple.c deleted file mode 100644 index d9faa8677d..0000000000 --- a/drivers/led/issi/is31fl3218-simple.c +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright 2018 Jason Williams (Wilba) - * - * 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 . - */ -#include "is31fl3218-simple.h" -#include -#include "i2c_master.h" - -#define IS31FL3218_PWM_REGISTER_COUNT 18 -#define IS31FL3218_LED_CONTROL_REGISTER_COUNT 3 - -#ifndef IS31FL3218_I2C_TIMEOUT -# define IS31FL3218_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3218_I2C_PERSISTENCE -# define IS31FL3218_I2C_PERSISTENCE 0 -#endif - -uint8_t i2c_transfer_buffer[20]; - -// IS31FL3218 has 18 PWM outputs and a fixed I2C address, so no chaining. -uint8_t g_pwm_buffer[IS31FL3218_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required = false; - -uint8_t g_led_control_registers[IS31FL3218_LED_CONTROL_REGISTER_COUNT] = {0}; -bool g_led_control_registers_update_required = false; - -void is31fl3218_write_register(uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; -#if IS31FL3218_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) { - if (i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT); -#endif -} - -void is31fl3218_write_pwm_buffer(uint8_t *pwm_buffer) { - i2c_transfer_buffer[0] = IS31FL3218_REG_PWM; - memcpy(i2c_transfer_buffer + 1, pwm_buffer, 18); - -#if IS31FL3218_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) { - i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT); - } -#else - i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, i2c_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT); -#endif -} - -void is31fl3218_init(void) { - i2c_init(); - - // In case we ever want to reinitialize (?) - is31fl3218_write_register(IS31FL3218_REG_RESET, 0x00); - - // Turn off software shutdown - is31fl3218_write_register(IS31FL3218_REG_SHUTDOWN, 0x01); - - // Set all PWM values to zero - for (uint8_t i = 0; i < IS31FL3218_PWM_REGISTER_COUNT; i++) { - is31fl3218_write_register(IS31FL3218_REG_PWM + i, 0x00); - } - - // turn off all LEDs in the LED control register - for (uint8_t i = 0; i < IS31FL3218_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3218_write_register(IS31FL3218_REG_LED_CONTROL_1 + i, 0x00); - } - - // Load PWM registers and LED Control register data - is31fl3218_write_register(IS31FL3218_REG_UPDATE, 0x01); - - for (int i = 0; i < IS31FL3218_LED_COUNT; i++) { - is31fl3218_set_led_control_register(i, true); - } - - is31fl3218_update_led_control_registers(); -} - -void is31fl3218_set_value(int index, uint8_t value) { - is31fl3218_led_t led; - if (index >= 0 && index < IS31FL3218_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3218_leds[index]), sizeof(led)); - } - if (g_pwm_buffer[led.v - IS31FL3218_REG_PWM] == value) { - return; - } - g_pwm_buffer[led.v - IS31FL3218_REG_PWM] = value; - g_pwm_buffer_update_required = true; -} - -void is31fl3218_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3218_LED_COUNT; i++) { - is31fl3218_set_value(i, value); - } -} - -void is31fl3218_set_led_control_register(uint8_t index, bool value) { - is31fl3218_led_t led; - memcpy_P(&led, (&g_is31fl3218_leds[index]), sizeof(led)); - - uint8_t control_register = (led.v - IS31FL3218_REG_PWM) / 6; - uint8_t bit_value = (led.v - IS31FL3218_REG_PWM) % 6; - - if (value) { - g_led_control_registers[control_register] |= (1 << bit_value); - } else { - g_led_control_registers[control_register] &= ~(1 << bit_value); - } - - g_led_control_registers_update_required = true; -} - -void is31fl3218_update_pwm_buffers(void) { - if (g_pwm_buffer_update_required) { - is31fl3218_write_pwm_buffer(g_pwm_buffer); - // Load PWM registers and LED Control register data - is31fl3218_write_register(IS31FL3218_REG_UPDATE, 0x01); - - g_pwm_buffer_update_required = false; - } -} - -void is31fl3218_update_led_control_registers(void) { - if (g_led_control_registers_update_required) { - for (int i = 0; i < IS31FL3218_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3218_write_register(IS31FL3218_REG_LED_CONTROL_1 + i, g_led_control_registers[i]); - } - - g_led_control_registers_update_required = false; - } -} diff --git a/drivers/led/issi/is31fl3218-simple.h b/drivers/led/issi/is31fl3218-simple.h deleted file mode 100644 index e0a71f1387..0000000000 --- a/drivers/led/issi/is31fl3218-simple.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2018 Jason Williams (Wilba) - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -#define IS31FL3218_REG_SHUTDOWN 0x00 -#define IS31FL3218_REG_PWM 0x01 -#define IS31FL3218_REG_LED_CONTROL_1 0x13 -#define IS31FL3218_REG_LED_CONTROL_2 0x14 -#define IS31FL3218_REG_LED_CONTROL_3 0x15 -#define IS31FL3218_REG_UPDATE 0x16 -#define IS31FL3218_REG_RESET 0x17 - -#define IS31FL3218_I2C_ADDRESS 0x54 - -#if defined(LED_MATRIX_IS31FL3218) -# define IS31FL3218_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -typedef struct is31fl3218_led_t { - uint8_t v; -} PACKED is31fl3218_led_t; - -extern const is31fl3218_led_t PROGMEM g_is31fl3218_leds[IS31FL3218_LED_COUNT]; - -void is31fl3218_init(void); - -void is31fl3218_write_register(uint8_t reg, uint8_t data); - -void is31fl3218_set_value(int index, uint8_t value); - -void is31fl3218_set_value_all(uint8_t value); - -void is31fl3218_set_led_control_register(uint8_t index, bool value); - -void is31fl3218_update_pwm_buffers(void); - -void is31fl3218_update_led_control_registers(void); - -#define OUT1 0x01 -#define OUT2 0x02 -#define OUT3 0x03 -#define OUT4 0x04 -#define OUT5 0x05 -#define OUT6 0x06 -#define OUT7 0x07 -#define OUT8 0x08 -#define OUT9 0x09 -#define OUT10 0x0A -#define OUT11 0x0B -#define OUT12 0x0C -#define OUT13 0x0D -#define OUT14 0x0E -#define OUT15 0x0F -#define OUT16 0x10 -#define OUT17 0x11 -#define OUT18 0x12 diff --git a/drivers/led/issi/is31fl3731-mono.c b/drivers/led/issi/is31fl3731-mono.c new file mode 100644 index 0000000000..74e427ef0d --- /dev/null +++ b/drivers/led/issi/is31fl3731-mono.c @@ -0,0 +1,239 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2019 Clueboard + * Copyright 2021 Doni Crosby + * + * 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 . + */ + +#include "is31fl3731-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3731_PWM_REGISTER_COUNT 144 +#define IS31FL3731_LED_CONTROL_REGISTER_COUNT 18 + +#ifndef IS31FL3731_I2C_TIMEOUT +# define IS31FL3731_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3731_I2C_PERSISTENCE +# define IS31FL3731_I2C_PERSISTENCE 0 +#endif + +uint8_t i2c_transfer_buffer[20]; + +// These buffers match the IS31FL3731 PWM registers 0x24-0xB3. +// 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 is31fl3731_write_pwm_buffer() but it's +// probably not worth the extra complexity. +uint8_t g_pwm_buffer[IS31FL3731_DRIVER_COUNT][IS31FL3731_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3731_DRIVER_COUNT] = {false}; + +uint8_t g_led_control_registers[IS31FL3731_DRIVER_COUNT][IS31FL3731_LED_CONTROL_REGISTER_COUNT] = {0}; +bool g_led_control_registers_update_required[IS31FL3731_DRIVER_COUNT] = {false}; + +void is31fl3731_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3731_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3731_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT) == 0) { + break; + } + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT); +#endif +} + +void is31fl3731_select_page(uint8_t addr, uint8_t page) { + is31fl3731_write_register(addr, IS31FL3731_REG_COMMAND, page); +} + +void is31fl3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // assumes page 0 is already selected + + // transmit PWM registers in 9 transfers of 16 bytes + // i2c_transfer_buffer[] is 20 bytes + + // iterate over the pwm_buffer contents at 16 byte intervals + for (int i = 0; i < IS31FL3731_PWM_REGISTER_COUNT; i += 16) { + // set the first register, e.g. 0x24, 0x34, 0x44, etc. + i2c_transfer_buffer[0] = 0x24 + i; + // copy the data from i to i+15 + // device will auto-increment register for data after the first byte + // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); + +#if IS31FL3731_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3731_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT); +#endif + } +} + +void is31fl3731_init_drivers(void) { + i2c_init(); + + is31fl3731_init(IS31FL3731_I2C_ADDRESS_1); +#if defined(IS31FL3731_I2C_ADDRESS_2) + is31fl3731_init(IS31FL3731_I2C_ADDRESS_2); +# if defined(IS31FL3731_I2C_ADDRESS_3) + is31fl3731_init(IS31FL3731_I2C_ADDRESS_3); +# if defined(IS31FL3731_I2C_ADDRESS_4) + is31fl3731_init(IS31FL3731_I2C_ADDRESS_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3731_LED_COUNT; i++) { + is31fl3731_set_led_control_register(i, true); + } + + is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_1, 0); +#if defined(IS31FL3731_I2C_ADDRESS_2) + is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_2, 1); +# if defined(IS31FL3731_I2C_ADDRESS_3) + is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_3, 2); +# if defined(IS31FL3731_I2C_ADDRESS_4) + is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3731_init(uint8_t addr) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, first enable software shutdown, + // then set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + + is31fl3731_select_page(addr, IS31FL3731_COMMAND_FUNCTION); + + // enable software shutdown + is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_SHUTDOWN, 0x00); +#ifdef IS31FL3731_DEGHOST // set to enable de-ghosting of the array + is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_GHOST_IMAGE_PREVENTION, IS31FL3731_GHOST_IMAGE_PREVENTION_GEN); +#endif + + // this delay was copied from other drivers, might not be needed + wait_ms(10); + + // picture mode + is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_CONFIG, IS31FL3731_CONFIG_MODE_PICTURE); + // display frame 0 + is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_PICTURE_DISPLAY, 0x00); + // audio sync off + is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_AUDIO_SYNC, 0x00); + + is31fl3731_select_page(addr, IS31FL3731_COMMAND_FRAME_1); + + // turn off all LEDs in the LED control register + for (int i = 0; i < IS31FL3731_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3731_write_register(addr, i, 0x00); + } + + // turn off all LEDs in the blink control register (not really needed) + for (int i = 0x12; i <= 0x23; i++) { + is31fl3731_write_register(addr, i, 0x00); + } + + // set PWM on all LEDs to 0 + for (int i = 0x24; i <= 0xB3; i++) { + is31fl3731_write_register(addr, i, 0x00); + } + + is31fl3731_select_page(addr, IS31FL3731_COMMAND_FUNCTION); + + // disable software shutdown + is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_SHUTDOWN, 0x01); + + // select page 0 and leave it selected. + // most usage after initialization is just writing PWM buffers in page 0 + // as there's not much point in double-buffering + is31fl3731_select_page(addr, IS31FL3731_COMMAND_FRAME_1); +} + +void is31fl3731_set_value(int index, uint8_t value) { + is31fl3731_led_t led; + if (index >= 0 && index < IS31FL3731_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3731_leds[index]), sizeof(led)); + + // Subtract 0x24 to get the second index of g_pwm_buffer + + if (g_pwm_buffer[led.driver][led.v - 0x24] == value) { + return; + } + g_pwm_buffer[led.driver][led.v - 0x24] = value; + g_pwm_buffer_update_required[led.driver] = true; + } +} + +void is31fl3731_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3731_LED_COUNT; i++) { + is31fl3731_set_value(i, value); + } +} + +void is31fl3731_set_led_control_register(uint8_t index, bool value) { + is31fl3731_led_t led; + memcpy_P(&led, (&g_is31fl3731_leds[index]), sizeof(led)); + + uint8_t control_register = (led.v - 0x24) / 8; + uint8_t bit_value = (led.v - 0x24) % 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 is31fl3731_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3731_write_pwm_buffer(addr, g_pwm_buffer[index]); + g_pwm_buffer_update_required[index] = false; + } +} + +void is31fl3731_update_led_control_registers(uint8_t addr, uint8_t index) { + if (g_led_control_registers_update_required[index]) { + for (int i = 0; i < IS31FL3731_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3731_write_register(addr, i, g_led_control_registers[index][i]); + } + g_led_control_registers_update_required[index] = false; + } +} + +void is31fl3731_flush(void) { + is31fl3731_update_pwm_buffers(IS31FL3731_I2C_ADDRESS_1, 0); +#if defined(IS31FL3731_I2C_ADDRESS_2) + is31fl3731_update_pwm_buffers(IS31FL3731_I2C_ADDRESS_2, 1); +# if defined(IS31FL3731_I2C_ADDRESS_3) + is31fl3731_update_pwm_buffers(IS31FL3731_I2C_ADDRESS_3, 2); +# if defined(IS31FL3731_I2C_ADDRESS_4) + is31fl3731_update_pwm_buffers(IS31FL3731_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3731-mono.h b/drivers/led/issi/is31fl3731-mono.h new file mode 100644 index 0000000000..ff970a3e5e --- /dev/null +++ b/drivers/led/issi/is31fl3731-mono.h @@ -0,0 +1,283 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2019 Clueboard + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +// ======== DEPRECATED DEFINES - DO NOT USE ======== +#ifdef LED_DRIVER_ADDR_1 +# define IS31FL3731_I2C_ADDRESS_1 LED_DRIVER_ADDR_1 +#endif +#ifdef LED_DRIVER_ADDR_2 +# define IS31FL3731_I2C_ADDRESS_2 LED_DRIVER_ADDR_2 +#endif +#ifdef LED_DRIVER_ADDR_3 +# define IS31FL3731_I2C_ADDRESS_3 LED_DRIVER_ADDR_3 +#endif +#ifdef LED_DRIVER_ADDR_4 +# define IS31FL3731_I2C_ADDRESS_4 LED_DRIVER_ADDR_4 +#endif +#ifdef ISSI_TIMEOUT +# define IS31FL3731_I2C_TIMEOUT ISSI_TIMEOUT +#endif +#ifdef ISSI_PERSISTENCE +# define IS31FL3731_I2C_PERSISTENCE ISSI_PERSISTENCE +#endif +#ifdef ISSI_3731_DEGHOST +# define IS31FL3731_DEGHOST ISSI_3731_DEGHOST +#endif + +#define is31_led is31fl3731_led_t +#define g_is31_leds g_is31fl3731_leds +// ======== + +#define IS31FL3731_REG_COMMAND 0xFD +#define IS31FL3731_COMMAND_FRAME_1 0x00 +#define IS31FL3731_COMMAND_FRAME_2 0x01 +#define IS31FL3731_COMMAND_FRAME_3 0x02 +#define IS31FL3731_COMMAND_FRAME_4 0x03 +#define IS31FL3731_COMMAND_FRAME_5 0x04 +#define IS31FL3731_COMMAND_FRAME_6 0x05 +#define IS31FL3731_COMMAND_FRAME_7 0x06 +#define IS31FL3731_COMMAND_FRAME_8 0x07 +#define IS31FL3731_COMMAND_FUNCTION 0x0B + +#define IS31FL3731_FUNCTION_REG_CONFIG 0x00 +#define IS31FL3731_CONFIG_MODE_PICTURE 0x00 +#define IS31FL3731_CONFIG_MODE_AUTO_PLAY 0x08 +#define IS31FL3731_CONFIG_MODE_AUDIO_PLAY 0x18 + +#define IS31FL3731_FUNCTION_REG_PICTURE_DISPLAY 0x01 +#define IS31FL3731_FUNCTION_REG_AUDIO_SYNC 0x06 +#define IS31FL3731_FUNCTION_REG_SHUTDOWN 0x0A + +// Not defined in the datasheet -- See AN for IC +#define IS31FL3731_FUNCTION_REG_GHOST_IMAGE_PREVENTION 0xC2 +#define IS31FL3731_GHOST_IMAGE_PREVENTION_GEN 0x10 + +#define IS31FL3731_I2C_ADDRESS_GND 0x74 +#define IS31FL3731_I2C_ADDRESS_SCL 0x75 +#define IS31FL3731_I2C_ADDRESS_SDA 0x76 +#define IS31FL3731_I2C_ADDRESS_VCC 0x77 + +#if defined(LED_MATRIX_IS31FL3731) +# define IS31FL3731_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined IS31FL3731_I2C_ADDRESS_4 +# define IS31FL3731_DRIVER_COUNT 4 +#elif defined IS31FL3731_I2C_ADDRESS_3 +# define IS31FL3731_DRIVER_COUNT 3 +#elif defined IS31FL3731_I2C_ADDRESS_2 +# define IS31FL3731_DRIVER_COUNT 2 +#elif defined IS31FL3731_I2C_ADDRESS_1 +# define IS31FL3731_DRIVER_COUNT 1 +#endif + +typedef struct is31fl3731_led_t { + uint8_t driver : 2; + uint8_t v; +} PACKED is31fl3731_led_t; + +extern const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT]; + +void is31fl3731_init_drivers(void); +void is31fl3731_init(uint8_t addr); +void is31fl3731_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3731_select_page(uint8_t addr, uint8_t page); +void is31fl3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3731_set_value(int index, uint8_t value); +void is31fl3731_set_value_all(uint8_t value); + +void is31fl3731_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 is31fl3731_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3731_update_led_control_registers(uint8_t addr, uint8_t index); + +void is31fl3731_flush(void); + +#define C1_1 0x24 +#define C1_2 0x25 +#define C1_3 0x26 +#define C1_4 0x27 +#define C1_5 0x28 +#define C1_6 0x29 +#define C1_7 0x2A +#define C1_8 0x2B + +#define C1_9 0x2C +#define C1_10 0x2D +#define C1_11 0x2E +#define C1_12 0x2F +#define C1_13 0x30 +#define C1_14 0x31 +#define C1_15 0x32 +#define C1_16 0x33 + +#define C2_1 0x34 +#define C2_2 0x35 +#define C2_3 0x36 +#define C2_4 0x37 +#define C2_5 0x38 +#define C2_6 0x39 +#define C2_7 0x3A +#define C2_8 0x3B + +#define C2_9 0x3C +#define C2_10 0x3D +#define C2_11 0x3E +#define C2_12 0x3F +#define C2_13 0x40 +#define C2_14 0x41 +#define C2_15 0x42 +#define C2_16 0x43 + +#define C3_1 0x44 +#define C3_2 0x45 +#define C3_3 0x46 +#define C3_4 0x47 +#define C3_5 0x48 +#define C3_6 0x49 +#define C3_7 0x4A +#define C3_8 0x4B + +#define C3_9 0x4C +#define C3_10 0x4D +#define C3_11 0x4E +#define C3_12 0x4F +#define C3_13 0x50 +#define C3_14 0x51 +#define C3_15 0x52 +#define C3_16 0x53 + +#define C4_1 0x54 +#define C4_2 0x55 +#define C4_3 0x56 +#define C4_4 0x57 +#define C4_5 0x58 +#define C4_6 0x59 +#define C4_7 0x5A +#define C4_8 0x5B + +#define C4_9 0x5C +#define C4_10 0x5D +#define C4_11 0x5E +#define C4_12 0x5F +#define C4_13 0x60 +#define C4_14 0x61 +#define C4_15 0x62 +#define C4_16 0x63 + +#define C5_1 0x64 +#define C5_2 0x65 +#define C5_3 0x66 +#define C5_4 0x67 +#define C5_5 0x68 +#define C5_6 0x69 +#define C5_7 0x6A +#define C5_8 0x6B + +#define C5_9 0x6C +#define C5_10 0x6D +#define C5_11 0x6E +#define C5_12 0x6F +#define C5_13 0x70 +#define C5_14 0x71 +#define C5_15 0x72 +#define C5_16 0x73 + +#define C6_1 0x74 +#define C6_2 0x75 +#define C6_3 0x76 +#define C6_4 0x77 +#define C6_5 0x78 +#define C6_6 0x79 +#define C6_7 0x7A +#define C6_8 0x7B + +#define C6_9 0x7C +#define C6_10 0x7D +#define C6_11 0x7E +#define C6_12 0x7F +#define C6_13 0x80 +#define C6_14 0x81 +#define C6_15 0x82 +#define C6_16 0x83 + +#define C7_1 0x84 +#define C7_2 0x85 +#define C7_3 0x86 +#define C7_4 0x87 +#define C7_5 0x88 +#define C7_6 0x89 +#define C7_7 0x8A +#define C7_8 0x8B + +#define C7_9 0x8C +#define C7_10 0x8D +#define C7_11 0x8E +#define C7_12 0x8F +#define C7_13 0x90 +#define C7_14 0x91 +#define C7_15 0x92 +#define C7_16 0x93 + +#define C8_1 0x94 +#define C8_2 0x95 +#define C8_3 0x96 +#define C8_4 0x97 +#define C8_5 0x98 +#define C8_6 0x99 +#define C8_7 0x9A +#define C8_8 0x9B + +#define C8_9 0x9C +#define C8_10 0x9D +#define C8_11 0x9E +#define C8_12 0x9F +#define C8_13 0xA0 +#define C8_14 0xA1 +#define C8_15 0xA2 +#define C8_16 0xA3 + +#define C9_1 0xA4 +#define C9_2 0xA5 +#define C9_3 0xA6 +#define C9_4 0xA7 +#define C9_5 0xA8 +#define C9_6 0xA9 +#define C9_7 0xAA +#define C9_8 0xAB + +#define C9_9 0xAC +#define C9_10 0xAD +#define C9_11 0xAE +#define C9_12 0xAF +#define C9_13 0xB0 +#define C9_14 0xB1 +#define C9_15 0xB2 +#define C9_16 0xB3 diff --git a/drivers/led/issi/is31fl3731-simple.c b/drivers/led/issi/is31fl3731-simple.c deleted file mode 100644 index 14743717d4..0000000000 --- a/drivers/led/issi/is31fl3731-simple.c +++ /dev/null @@ -1,239 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2019 Clueboard - * Copyright 2021 Doni Crosby - * - * 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 . - */ - -#include "is31fl3731-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3731_PWM_REGISTER_COUNT 144 -#define IS31FL3731_LED_CONTROL_REGISTER_COUNT 18 - -#ifndef IS31FL3731_I2C_TIMEOUT -# define IS31FL3731_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3731_I2C_PERSISTENCE -# define IS31FL3731_I2C_PERSISTENCE 0 -#endif - -uint8_t i2c_transfer_buffer[20]; - -// These buffers match the IS31FL3731 PWM registers 0x24-0xB3. -// 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 is31fl3731_write_pwm_buffer() but it's -// probably not worth the extra complexity. -uint8_t g_pwm_buffer[IS31FL3731_DRIVER_COUNT][IS31FL3731_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3731_DRIVER_COUNT] = {false}; - -uint8_t g_led_control_registers[IS31FL3731_DRIVER_COUNT][IS31FL3731_LED_CONTROL_REGISTER_COUNT] = {0}; -bool g_led_control_registers_update_required[IS31FL3731_DRIVER_COUNT] = {false}; - -void is31fl3731_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3731_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3731_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT) == 0) { - break; - } - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3731_I2C_TIMEOUT); -#endif -} - -void is31fl3731_select_page(uint8_t addr, uint8_t page) { - is31fl3731_write_register(addr, IS31FL3731_REG_COMMAND, page); -} - -void is31fl3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // assumes page 0 is already selected - - // transmit PWM registers in 9 transfers of 16 bytes - // i2c_transfer_buffer[] is 20 bytes - - // iterate over the pwm_buffer contents at 16 byte intervals - for (int i = 0; i < IS31FL3731_PWM_REGISTER_COUNT; i += 16) { - // set the first register, e.g. 0x24, 0x34, 0x44, etc. - i2c_transfer_buffer[0] = 0x24 + i; - // copy the data from i to i+15 - // device will auto-increment register for data after the first byte - // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); - -#if IS31FL3731_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3731_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3731_I2C_TIMEOUT); -#endif - } -} - -void is31fl3731_init_drivers(void) { - i2c_init(); - - is31fl3731_init(IS31FL3731_I2C_ADDRESS_1); -#if defined(IS31FL3731_I2C_ADDRESS_2) - is31fl3731_init(IS31FL3731_I2C_ADDRESS_2); -# if defined(IS31FL3731_I2C_ADDRESS_3) - is31fl3731_init(IS31FL3731_I2C_ADDRESS_3); -# if defined(IS31FL3731_I2C_ADDRESS_4) - is31fl3731_init(IS31FL3731_I2C_ADDRESS_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3731_LED_COUNT; i++) { - is31fl3731_set_led_control_register(i, true); - } - - is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_1, 0); -#if defined(IS31FL3731_I2C_ADDRESS_2) - is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_2, 1); -# if defined(IS31FL3731_I2C_ADDRESS_3) - is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_3, 2); -# if defined(IS31FL3731_I2C_ADDRESS_4) - is31fl3731_update_led_control_registers(IS31FL3731_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3731_init(uint8_t addr) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, first enable software shutdown, - // then set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - - is31fl3731_select_page(addr, IS31FL3731_COMMAND_FUNCTION); - - // enable software shutdown - is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_SHUTDOWN, 0x00); -#ifdef IS31FL3731_DEGHOST // set to enable de-ghosting of the array - is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_GHOST_IMAGE_PREVENTION, IS31FL3731_GHOST_IMAGE_PREVENTION_GEN); -#endif - - // this delay was copied from other drivers, might not be needed - wait_ms(10); - - // picture mode - is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_CONFIG, IS31FL3731_CONFIG_MODE_PICTURE); - // display frame 0 - is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_PICTURE_DISPLAY, 0x00); - // audio sync off - is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_AUDIO_SYNC, 0x00); - - is31fl3731_select_page(addr, IS31FL3731_COMMAND_FRAME_1); - - // turn off all LEDs in the LED control register - for (int i = 0; i < IS31FL3731_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3731_write_register(addr, i, 0x00); - } - - // turn off all LEDs in the blink control register (not really needed) - for (int i = 0x12; i <= 0x23; i++) { - is31fl3731_write_register(addr, i, 0x00); - } - - // set PWM on all LEDs to 0 - for (int i = 0x24; i <= 0xB3; i++) { - is31fl3731_write_register(addr, i, 0x00); - } - - is31fl3731_select_page(addr, IS31FL3731_COMMAND_FUNCTION); - - // disable software shutdown - is31fl3731_write_register(addr, IS31FL3731_FUNCTION_REG_SHUTDOWN, 0x01); - - // select page 0 and leave it selected. - // most usage after initialization is just writing PWM buffers in page 0 - // as there's not much point in double-buffering - is31fl3731_select_page(addr, IS31FL3731_COMMAND_FRAME_1); -} - -void is31fl3731_set_value(int index, uint8_t value) { - is31fl3731_led_t led; - if (index >= 0 && index < IS31FL3731_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3731_leds[index]), sizeof(led)); - - // Subtract 0x24 to get the second index of g_pwm_buffer - - if (g_pwm_buffer[led.driver][led.v - 0x24] == value) { - return; - } - g_pwm_buffer[led.driver][led.v - 0x24] = value; - g_pwm_buffer_update_required[led.driver] = true; - } -} - -void is31fl3731_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3731_LED_COUNT; i++) { - is31fl3731_set_value(i, value); - } -} - -void is31fl3731_set_led_control_register(uint8_t index, bool value) { - is31fl3731_led_t led; - memcpy_P(&led, (&g_is31fl3731_leds[index]), sizeof(led)); - - uint8_t control_register = (led.v - 0x24) / 8; - uint8_t bit_value = (led.v - 0x24) % 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 is31fl3731_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3731_write_pwm_buffer(addr, g_pwm_buffer[index]); - g_pwm_buffer_update_required[index] = false; - } -} - -void is31fl3731_update_led_control_registers(uint8_t addr, uint8_t index) { - if (g_led_control_registers_update_required[index]) { - for (int i = 0; i < IS31FL3731_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3731_write_register(addr, i, g_led_control_registers[index][i]); - } - g_led_control_registers_update_required[index] = false; - } -} - -void is31fl3731_flush(void) { - is31fl3731_update_pwm_buffers(IS31FL3731_I2C_ADDRESS_1, 0); -#if defined(IS31FL3731_I2C_ADDRESS_2) - is31fl3731_update_pwm_buffers(IS31FL3731_I2C_ADDRESS_2, 1); -# if defined(IS31FL3731_I2C_ADDRESS_3) - is31fl3731_update_pwm_buffers(IS31FL3731_I2C_ADDRESS_3, 2); -# if defined(IS31FL3731_I2C_ADDRESS_4) - is31fl3731_update_pwm_buffers(IS31FL3731_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3731-simple.h b/drivers/led/issi/is31fl3731-simple.h deleted file mode 100644 index ff970a3e5e..0000000000 --- a/drivers/led/issi/is31fl3731-simple.h +++ /dev/null @@ -1,283 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2019 Clueboard - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -// ======== DEPRECATED DEFINES - DO NOT USE ======== -#ifdef LED_DRIVER_ADDR_1 -# define IS31FL3731_I2C_ADDRESS_1 LED_DRIVER_ADDR_1 -#endif -#ifdef LED_DRIVER_ADDR_2 -# define IS31FL3731_I2C_ADDRESS_2 LED_DRIVER_ADDR_2 -#endif -#ifdef LED_DRIVER_ADDR_3 -# define IS31FL3731_I2C_ADDRESS_3 LED_DRIVER_ADDR_3 -#endif -#ifdef LED_DRIVER_ADDR_4 -# define IS31FL3731_I2C_ADDRESS_4 LED_DRIVER_ADDR_4 -#endif -#ifdef ISSI_TIMEOUT -# define IS31FL3731_I2C_TIMEOUT ISSI_TIMEOUT -#endif -#ifdef ISSI_PERSISTENCE -# define IS31FL3731_I2C_PERSISTENCE ISSI_PERSISTENCE -#endif -#ifdef ISSI_3731_DEGHOST -# define IS31FL3731_DEGHOST ISSI_3731_DEGHOST -#endif - -#define is31_led is31fl3731_led_t -#define g_is31_leds g_is31fl3731_leds -// ======== - -#define IS31FL3731_REG_COMMAND 0xFD -#define IS31FL3731_COMMAND_FRAME_1 0x00 -#define IS31FL3731_COMMAND_FRAME_2 0x01 -#define IS31FL3731_COMMAND_FRAME_3 0x02 -#define IS31FL3731_COMMAND_FRAME_4 0x03 -#define IS31FL3731_COMMAND_FRAME_5 0x04 -#define IS31FL3731_COMMAND_FRAME_6 0x05 -#define IS31FL3731_COMMAND_FRAME_7 0x06 -#define IS31FL3731_COMMAND_FRAME_8 0x07 -#define IS31FL3731_COMMAND_FUNCTION 0x0B - -#define IS31FL3731_FUNCTION_REG_CONFIG 0x00 -#define IS31FL3731_CONFIG_MODE_PICTURE 0x00 -#define IS31FL3731_CONFIG_MODE_AUTO_PLAY 0x08 -#define IS31FL3731_CONFIG_MODE_AUDIO_PLAY 0x18 - -#define IS31FL3731_FUNCTION_REG_PICTURE_DISPLAY 0x01 -#define IS31FL3731_FUNCTION_REG_AUDIO_SYNC 0x06 -#define IS31FL3731_FUNCTION_REG_SHUTDOWN 0x0A - -// Not defined in the datasheet -- See AN for IC -#define IS31FL3731_FUNCTION_REG_GHOST_IMAGE_PREVENTION 0xC2 -#define IS31FL3731_GHOST_IMAGE_PREVENTION_GEN 0x10 - -#define IS31FL3731_I2C_ADDRESS_GND 0x74 -#define IS31FL3731_I2C_ADDRESS_SCL 0x75 -#define IS31FL3731_I2C_ADDRESS_SDA 0x76 -#define IS31FL3731_I2C_ADDRESS_VCC 0x77 - -#if defined(LED_MATRIX_IS31FL3731) -# define IS31FL3731_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined IS31FL3731_I2C_ADDRESS_4 -# define IS31FL3731_DRIVER_COUNT 4 -#elif defined IS31FL3731_I2C_ADDRESS_3 -# define IS31FL3731_DRIVER_COUNT 3 -#elif defined IS31FL3731_I2C_ADDRESS_2 -# define IS31FL3731_DRIVER_COUNT 2 -#elif defined IS31FL3731_I2C_ADDRESS_1 -# define IS31FL3731_DRIVER_COUNT 1 -#endif - -typedef struct is31fl3731_led_t { - uint8_t driver : 2; - uint8_t v; -} PACKED is31fl3731_led_t; - -extern const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT]; - -void is31fl3731_init_drivers(void); -void is31fl3731_init(uint8_t addr); -void is31fl3731_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3731_select_page(uint8_t addr, uint8_t page); -void is31fl3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3731_set_value(int index, uint8_t value); -void is31fl3731_set_value_all(uint8_t value); - -void is31fl3731_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 is31fl3731_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3731_update_led_control_registers(uint8_t addr, uint8_t index); - -void is31fl3731_flush(void); - -#define C1_1 0x24 -#define C1_2 0x25 -#define C1_3 0x26 -#define C1_4 0x27 -#define C1_5 0x28 -#define C1_6 0x29 -#define C1_7 0x2A -#define C1_8 0x2B - -#define C1_9 0x2C -#define C1_10 0x2D -#define C1_11 0x2E -#define C1_12 0x2F -#define C1_13 0x30 -#define C1_14 0x31 -#define C1_15 0x32 -#define C1_16 0x33 - -#define C2_1 0x34 -#define C2_2 0x35 -#define C2_3 0x36 -#define C2_4 0x37 -#define C2_5 0x38 -#define C2_6 0x39 -#define C2_7 0x3A -#define C2_8 0x3B - -#define C2_9 0x3C -#define C2_10 0x3D -#define C2_11 0x3E -#define C2_12 0x3F -#define C2_13 0x40 -#define C2_14 0x41 -#define C2_15 0x42 -#define C2_16 0x43 - -#define C3_1 0x44 -#define C3_2 0x45 -#define C3_3 0x46 -#define C3_4 0x47 -#define C3_5 0x48 -#define C3_6 0x49 -#define C3_7 0x4A -#define C3_8 0x4B - -#define C3_9 0x4C -#define C3_10 0x4D -#define C3_11 0x4E -#define C3_12 0x4F -#define C3_13 0x50 -#define C3_14 0x51 -#define C3_15 0x52 -#define C3_16 0x53 - -#define C4_1 0x54 -#define C4_2 0x55 -#define C4_3 0x56 -#define C4_4 0x57 -#define C4_5 0x58 -#define C4_6 0x59 -#define C4_7 0x5A -#define C4_8 0x5B - -#define C4_9 0x5C -#define C4_10 0x5D -#define C4_11 0x5E -#define C4_12 0x5F -#define C4_13 0x60 -#define C4_14 0x61 -#define C4_15 0x62 -#define C4_16 0x63 - -#define C5_1 0x64 -#define C5_2 0x65 -#define C5_3 0x66 -#define C5_4 0x67 -#define C5_5 0x68 -#define C5_6 0x69 -#define C5_7 0x6A -#define C5_8 0x6B - -#define C5_9 0x6C -#define C5_10 0x6D -#define C5_11 0x6E -#define C5_12 0x6F -#define C5_13 0x70 -#define C5_14 0x71 -#define C5_15 0x72 -#define C5_16 0x73 - -#define C6_1 0x74 -#define C6_2 0x75 -#define C6_3 0x76 -#define C6_4 0x77 -#define C6_5 0x78 -#define C6_6 0x79 -#define C6_7 0x7A -#define C6_8 0x7B - -#define C6_9 0x7C -#define C6_10 0x7D -#define C6_11 0x7E -#define C6_12 0x7F -#define C6_13 0x80 -#define C6_14 0x81 -#define C6_15 0x82 -#define C6_16 0x83 - -#define C7_1 0x84 -#define C7_2 0x85 -#define C7_3 0x86 -#define C7_4 0x87 -#define C7_5 0x88 -#define C7_6 0x89 -#define C7_7 0x8A -#define C7_8 0x8B - -#define C7_9 0x8C -#define C7_10 0x8D -#define C7_11 0x8E -#define C7_12 0x8F -#define C7_13 0x90 -#define C7_14 0x91 -#define C7_15 0x92 -#define C7_16 0x93 - -#define C8_1 0x94 -#define C8_2 0x95 -#define C8_3 0x96 -#define C8_4 0x97 -#define C8_5 0x98 -#define C8_6 0x99 -#define C8_7 0x9A -#define C8_8 0x9B - -#define C8_9 0x9C -#define C8_10 0x9D -#define C8_11 0x9E -#define C8_12 0x9F -#define C8_13 0xA0 -#define C8_14 0xA1 -#define C8_15 0xA2 -#define C8_16 0xA3 - -#define C9_1 0xA4 -#define C9_2 0xA5 -#define C9_3 0xA6 -#define C9_4 0xA7 -#define C9_5 0xA8 -#define C9_6 0xA9 -#define C9_7 0xAA -#define C9_8 0xAB - -#define C9_9 0xAC -#define C9_10 0xAD -#define C9_11 0xAE -#define C9_12 0xAF -#define C9_13 0xB0 -#define C9_14 0xB1 -#define C9_15 0xB2 -#define C9_16 0xB3 diff --git a/drivers/led/issi/is31fl3733-mono.c b/drivers/led/issi/is31fl3733-mono.c new file mode 100644 index 0000000000..95d16bc4a3 --- /dev/null +++ b/drivers/led/issi/is31fl3733-mono.c @@ -0,0 +1,270 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2021 Doni Crosby + * Copyright 2021 Leo Deng + * + * 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 . + */ + +#include "is31fl3733-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3733_PWM_REGISTER_COUNT 192 +#define IS31FL3733_LED_CONTROL_REGISTER_COUNT 24 + +#ifndef IS31FL3733_I2C_TIMEOUT +# define IS31FL3733_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3733_I2C_PERSISTENCE +# define IS31FL3733_I2C_PERSISTENCE 0 +#endif + +#ifndef IS31FL3733_PWM_FREQUENCY +# define IS31FL3733_PWM_FREQUENCY IS31FL3733_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3733B only +#endif + +#ifndef IS31FL3733_SW_PULLUP +# define IS31FL3733_SW_PULLUP IS31FL3733_PUR_0_OHM +#endif + +#ifndef IS31FL3733_CS_PULLDOWN +# define IS31FL3733_CS_PULLDOWN IS31FL3733_PDR_0_OHM +#endif + +#ifndef IS31FL3733_GLOBAL_CURRENT +# define IS31FL3733_GLOBAL_CURRENT 0xFF +#endif + +#ifndef IS31FL3733_SYNC_1 +# define IS31FL3733_SYNC_1 IS31FL3733_SYNC_NONE +#endif +#ifndef IS31FL3733_SYNC_2 +# define IS31FL3733_SYNC_2 IS31FL3733_SYNC_NONE +#endif +#ifndef IS31FL3733_SYNC_3 +# define IS31FL3733_SYNC_3 IS31FL3733_SYNC_NONE +#endif +#ifndef IS31FL3733_SYNC_4 +# define IS31FL3733_SYNC_4 IS31FL3733_SYNC_NONE +#endif + +uint8_t i2c_transfer_buffer[20]; + +// These buffers match the IS31FL3733 PWM registers. +// The control buffers match the page 0 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 is31fl3733_write_pwm_buffer() but it's +// probably not worth the extra complexity. +uint8_t g_pwm_buffer[IS31FL3733_DRIVER_COUNT][IS31FL3733_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3733_DRIVER_COUNT] = {false}; + +uint8_t g_led_control_registers[IS31FL3733_DRIVER_COUNT][IS31FL3733_LED_CONTROL_REGISTER_COUNT] = {0}; +bool g_led_control_registers_update_required[IS31FL3733_DRIVER_COUNT] = {false}; + +bool is31fl3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + // If the transaction fails function returns false. + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3733_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3733_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) { + return false; + } +#endif + return true; +} + +void is31fl3733_select_page(uint8_t addr, uint8_t page) { + is31fl3733_write_register(addr, IS31FL3733_REG_COMMAND_WRITE_LOCK, IS31FL3733_COMMAND_WRITE_LOCK_MAGIC); + is31fl3733_write_register(addr, IS31FL3733_REG_COMMAND, page); +} + +bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // Assumes page 1 is already selected. + // If any of the transactions fails function returns false. + // Transmit PWM registers in 12 transfers of 16 bytes. + // i2c_transfer_buffer[] is 20 bytes + + // Iterate over the pwm_buffer contents at 16 byte intervals. + for (int i = 0; i < IS31FL3733_PWM_REGISTER_COUNT; i += 16) { + i2c_transfer_buffer[0] = i; + // Copy the data from i to i+15. + // Device will auto-increment register for data after the first byte + // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); + +#if IS31FL3733_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3733_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) { + return false; + } +#endif + } + return true; +} + +void is31fl3733_init_drivers(void) { + i2c_init(); + + is31fl3733_init(IS31FL3733_I2C_ADDRESS_1, IS31FL3733_SYNC_1); +#if defined(IS31FL3733_I2C_ADDRESS_2) + is31fl3733_init(IS31FL3733_I2C_ADDRESS_2, IS31FL3733_SYNC_2); +# if defined(IS31FL3733_I2C_ADDRESS_3) + is31fl3733_init(IS31FL3733_I2C_ADDRESS_3, IS31FL3733_SYNC_3); +# if defined(IS31FL3733_I2C_ADDRESS_4) + is31fl3733_init(IS31FL3733_I2C_ADDRESS_4, IS31FL3733_SYNC_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3733_LED_COUNT; i++) { + is31fl3733_set_led_control_register(i, true); + } + + is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_1, 0); +#if defined(IS31FL3733_I2C_ADDRESS_2) + is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_2, 1); +# if defined(IS31FL3733_I2C_ADDRESS_3) + is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_3, 2); +# if defined(IS31FL3733_I2C_ADDRESS_4) + is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3733_init(uint8_t addr, uint8_t sync) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + // Sync is passed so set it according to the datasheet. + + is31fl3733_select_page(addr, IS31FL3733_COMMAND_LED_CONTROL); + + // Turn off all LEDs. + for (int i = 0; i < IS31FL3733_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3733_write_register(addr, i, 0x00); + } + + is31fl3733_select_page(addr, IS31FL3733_COMMAND_PWM); + + // Set PWM on all LEDs to 0 + // No need to setup Breath registers to PWM as that is the default. + for (int i = 0; i < IS31FL3733_PWM_REGISTER_COUNT; i++) { + is31fl3733_write_register(addr, i, 0x00); + } + + is31fl3733_select_page(addr, IS31FL3733_COMMAND_FUNCTION); + + // Set de-ghost pull-up resistors (SWx) + is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_SW_PULLUP, IS31FL3733_SW_PULLUP); + // Set de-ghost pull-down resistors (CSx) + is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_CS_PULLDOWN, IS31FL3733_CS_PULLDOWN); + // Set global current to maximum. + is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3733_GLOBAL_CURRENT); + // Disable software shutdown. + is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((IS31FL3733_PWM_FREQUENCY & 0b111) << 3) | 0x01); + + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void is31fl3733_set_value(int index, uint8_t value) { + is31fl3733_led_t led; + if (index >= 0 && index < IS31FL3733_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3733_leds[index]), sizeof(led)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + g_pwm_buffer[led.driver][led.v] = value; + g_pwm_buffer_update_required[led.driver] = true; + } +} + +void is31fl3733_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3733_LED_COUNT; i++) { + is31fl3733_set_value(i, value); + } +} + +void is31fl3733_set_led_control_register(uint8_t index, bool value) { + is31fl3733_led_t led; + memcpy_P(&led, (&g_is31fl3733_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 is31fl3733_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3733_select_page(addr, IS31FL3733_COMMAND_PWM); + + // If any of the transactions fail we risk writing dirty page 0, + // refresh page 0 just in case. + if (!is31fl3733_write_pwm_buffer(addr, g_pwm_buffer[index])) { + g_led_control_registers_update_required[index] = true; + } + g_pwm_buffer_update_required[index] = false; + } +} + +void is31fl3733_update_led_control_registers(uint8_t addr, uint8_t index) { + if (g_led_control_registers_update_required[index]) { + is31fl3733_select_page(addr, IS31FL3733_COMMAND_LED_CONTROL); + + for (int i = 0; i < IS31FL3733_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3733_write_register(addr, i, g_led_control_registers[index][i]); + } + g_led_control_registers_update_required[index] = false; + } +} + +void is31fl3733_flush(void) { + is31fl3733_update_pwm_buffers(IS31FL3733_I2C_ADDRESS_1, 0); +#if defined(IS31FL3733_I2C_ADDRESS_2) + is31fl3733_update_pwm_buffers(IS31FL3733_I2C_ADDRESS_2, 1); +# if defined(IS31FL3733_I2C_ADDRESS_3) + is31fl3733_update_pwm_buffers(IS31FL3733_I2C_ADDRESS_3, 2); +# if defined(IS31FL3733_I2C_ADDRESS_4) + is31fl3733_update_pwm_buffers(IS31FL3733_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3733-mono.h b/drivers/led/issi/is31fl3733-mono.h new file mode 100644 index 0000000000..dcb33e448f --- /dev/null +++ b/drivers/led/issi/is31fl3733-mono.h @@ -0,0 +1,367 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2021 Doni Crosby + * Copyright 2021 Leo Deng + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +// ======== DEPRECATED DEFINES - DO NOT USE ======== +#ifdef ISSI_TIMEOUT +# define IS31FL3733_I2C_TIMEOUT ISSI_TIMEOUT +#endif +#ifdef ISSI_PERSISTENCE +# define IS31FL3733_I2C_PERSISTENCE ISSI_PERSISTENCE +#endif +#ifdef ISSI_PWM_FREQUENCY +# define IS31FL3733_PWM_FREQUENCY ISSI_PWM_FREQUENCY +#endif +#ifdef ISSI_SWPULLUP +# define IS31FL3733_SW_PULLUP ISSI_SWPULLUP +#endif +#ifdef ISSI_CSPULLUP +# define IS31FL3733_CS_PULLDOWN ISSI_CSPULLUP +#endif +#ifdef ISSI_GLOBALCURRENT +# define IS31FL3733_GLOBAL_CURRENT ISSI_GLOBALCURRENT +#endif + +#define is31_led is31fl3733_led_t +#define g_is31_leds g_is31fl3733_leds + +#define PUR_0R IS31FL3733_PUR_0_OHM +#define PUR_05KR IS31FL3733_PUR_1K_OHM +#define PUR_3KR IS31FL3733_PUR_2K_OHM +#define PUR_4KR IS31FL3733_PUR_4K_OHM +#define PUR_8KR IS31FL3733_PUR_8K_OHM +#define PUR_16KR IS31FL3733_PUR_16K_OHM +#define PUR_32KR IS31FL3733_PUR_32K_OHM +// ======== + +#define IS31FL3733_REG_INTERRUPT_MASK 0xF0 +#define IS31FL3733_REG_INTERRUPT_STATUS 0xF1 + +#define IS31FL3733_REG_COMMAND 0xFD + +#define IS31FL3733_COMMAND_LED_CONTROL 0x00 +#define IS31FL3733_COMMAND_PWM 0x01 +#define IS31FL3733_COMMAND_AUTO_BREATH 0x02 +#define IS31FL3733_COMMAND_FUNCTION 0x03 + +#define IS31FL3733_FUNCTION_REG_CONFIGURATION 0x00 +#define IS31FL3733_FUNCTION_REG_GLOBAL_CURRENT 0x01 +#define IS31FL3733_FUNCTION_REG_SW_PULLUP 0x0F +#define IS31FL3733_FUNCTION_REG_CS_PULLDOWN 0x10 +#define IS31FL3733_FUNCTION_REG_RESET 0x11 + +#define IS31FL3733_REG_COMMAND_WRITE_LOCK 0xFE +#define IS31FL3733_COMMAND_WRITE_LOCK_MAGIC 0xC5 + +#define IS31FL3733_I2C_ADDRESS_GND_GND 0x50 +#define IS31FL3733_I2C_ADDRESS_GND_SCL 0x51 +#define IS31FL3733_I2C_ADDRESS_GND_SDA 0x52 +#define IS31FL3733_I2C_ADDRESS_GND_VCC 0x53 +#define IS31FL3733_I2C_ADDRESS_SCL_GND 0x54 +#define IS31FL3733_I2C_ADDRESS_SCL_SCL 0x55 +#define IS31FL3733_I2C_ADDRESS_SCL_SDA 0x56 +#define IS31FL3733_I2C_ADDRESS_SCL_VCC 0x57 +#define IS31FL3733_I2C_ADDRESS_SDA_GND 0x58 +#define IS31FL3733_I2C_ADDRESS_SDA_SCL 0x59 +#define IS31FL3733_I2C_ADDRESS_SDA_SDA 0x5A +#define IS31FL3733_I2C_ADDRESS_SDA_VCC 0x5B +#define IS31FL3733_I2C_ADDRESS_VCC_GND 0x5C +#define IS31FL3733_I2C_ADDRESS_VCC_SCL 0x5D +#define IS31FL3733_I2C_ADDRESS_VCC_SDA 0x5E +#define IS31FL3733_I2C_ADDRESS_VCC_VCC 0x5F + +#if defined(LED_MATRIX_IS31FL3733) +# define IS31FL3733_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined(IS31FL3733_I2C_ADDRESS_4) +# define IS31FL3733_DRIVER_COUNT 4 +#elif defined(IS31FL3733_I2C_ADDRESS_3) +# define IS31FL3733_DRIVER_COUNT 3 +#elif defined(IS31FL3733_I2C_ADDRESS_2) +# define IS31FL3733_DRIVER_COUNT 2 +#elif defined(IS31FL3733_I2C_ADDRESS_1) +# define IS31FL3733_DRIVER_COUNT 1 +#endif + +typedef struct is31fl3733_led_t { + uint8_t driver : 2; + uint8_t v; +} PACKED is31fl3733_led_t; + +extern const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT]; + +void is31fl3733_init_drivers(void); +void is31fl3733_init(uint8_t addr, uint8_t sync); +bool is31fl3733_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3733_select_page(uint8_t addr, uint8_t page); +bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3733_set_value(int index, uint8_t value); +void is31fl3733_set_value_all(uint8_t value); + +void is31fl3733_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 is31fl3733_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3733_update_led_control_registers(uint8_t addr, uint8_t index); + +void is31fl3733_flush(void); + +#define IS31FL3733_PDR_0_OHM 0b000 // No pull-down resistor +#define IS31FL3733_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3733_PDR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3733_PDR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3733_PDR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3733_PDR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3733_PDR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3733_PDR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3733_PUR_0_OHM 0b000 // No pull-up resistor +#define IS31FL3733_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3733_PUR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3733_PUR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3733_PUR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3733_PUR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3733_PUR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3733_PUR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3733_PWM_FREQUENCY_8K4_HZ 0b000 +#define IS31FL3733_PWM_FREQUENCY_4K2_HZ 0b001 +#define IS31FL3733_PWM_FREQUENCY_26K7_HZ 0b010 +#define IS31FL3733_PWM_FREQUENCY_2K1_HZ 0b011 +#define IS31FL3733_PWM_FREQUENCY_1K05_HZ 0b100 + +#define IS31FL3733_SYNC_NONE 0b00 +#define IS31FL3733_SYNC_MASTER 0b01 +#define IS31FL3733_SYNC_SLAVE 0b10 + +#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 diff --git a/drivers/led/issi/is31fl3733-simple.c b/drivers/led/issi/is31fl3733-simple.c deleted file mode 100644 index 889d9ef389..0000000000 --- a/drivers/led/issi/is31fl3733-simple.c +++ /dev/null @@ -1,270 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2021 Doni Crosby - * Copyright 2021 Leo Deng - * - * 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 . - */ - -#include "is31fl3733-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3733_PWM_REGISTER_COUNT 192 -#define IS31FL3733_LED_CONTROL_REGISTER_COUNT 24 - -#ifndef IS31FL3733_I2C_TIMEOUT -# define IS31FL3733_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3733_I2C_PERSISTENCE -# define IS31FL3733_I2C_PERSISTENCE 0 -#endif - -#ifndef IS31FL3733_PWM_FREQUENCY -# define IS31FL3733_PWM_FREQUENCY IS31FL3733_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3733B only -#endif - -#ifndef IS31FL3733_SW_PULLUP -# define IS31FL3733_SW_PULLUP IS31FL3733_PUR_0_OHM -#endif - -#ifndef IS31FL3733_CS_PULLDOWN -# define IS31FL3733_CS_PULLDOWN IS31FL3733_PDR_0_OHM -#endif - -#ifndef IS31FL3733_GLOBAL_CURRENT -# define IS31FL3733_GLOBAL_CURRENT 0xFF -#endif - -#ifndef IS31FL3733_SYNC_1 -# define IS31FL3733_SYNC_1 IS31FL3733_SYNC_NONE -#endif -#ifndef IS31FL3733_SYNC_2 -# define IS31FL3733_SYNC_2 IS31FL3733_SYNC_NONE -#endif -#ifndef IS31FL3733_SYNC_3 -# define IS31FL3733_SYNC_3 IS31FL3733_SYNC_NONE -#endif -#ifndef IS31FL3733_SYNC_4 -# define IS31FL3733_SYNC_4 IS31FL3733_SYNC_NONE -#endif - -uint8_t i2c_transfer_buffer[20]; - -// These buffers match the IS31FL3733 PWM registers. -// The control buffers match the page 0 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 is31fl3733_write_pwm_buffer() but it's -// probably not worth the extra complexity. -uint8_t g_pwm_buffer[IS31FL3733_DRIVER_COUNT][IS31FL3733_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3733_DRIVER_COUNT] = {false}; - -uint8_t g_led_control_registers[IS31FL3733_DRIVER_COUNT][IS31FL3733_LED_CONTROL_REGISTER_COUNT] = {0}; -bool g_led_control_registers_update_required[IS31FL3733_DRIVER_COUNT] = {false}; - -bool is31fl3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - // If the transaction fails function returns false. - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3733_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3733_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) { - return false; - } - } -#else - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3733_I2C_TIMEOUT) != 0) { - return false; - } -#endif - return true; -} - -void is31fl3733_select_page(uint8_t addr, uint8_t page) { - is31fl3733_write_register(addr, IS31FL3733_REG_COMMAND_WRITE_LOCK, IS31FL3733_COMMAND_WRITE_LOCK_MAGIC); - is31fl3733_write_register(addr, IS31FL3733_REG_COMMAND, page); -} - -bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // Assumes page 1 is already selected. - // If any of the transactions fails function returns false. - // Transmit PWM registers in 12 transfers of 16 bytes. - // i2c_transfer_buffer[] is 20 bytes - - // Iterate over the pwm_buffer contents at 16 byte intervals. - for (int i = 0; i < IS31FL3733_PWM_REGISTER_COUNT; i += 16) { - i2c_transfer_buffer[0] = i; - // Copy the data from i to i+15. - // Device will auto-increment register for data after the first byte - // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); - -#if IS31FL3733_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3733_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) { - return false; - } - } -#else - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3733_I2C_TIMEOUT) != 0) { - return false; - } -#endif - } - return true; -} - -void is31fl3733_init_drivers(void) { - i2c_init(); - - is31fl3733_init(IS31FL3733_I2C_ADDRESS_1, IS31FL3733_SYNC_1); -#if defined(IS31FL3733_I2C_ADDRESS_2) - is31fl3733_init(IS31FL3733_I2C_ADDRESS_2, IS31FL3733_SYNC_2); -# if defined(IS31FL3733_I2C_ADDRESS_3) - is31fl3733_init(IS31FL3733_I2C_ADDRESS_3, IS31FL3733_SYNC_3); -# if defined(IS31FL3733_I2C_ADDRESS_4) - is31fl3733_init(IS31FL3733_I2C_ADDRESS_4, IS31FL3733_SYNC_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3733_LED_COUNT; i++) { - is31fl3733_set_led_control_register(i, true); - } - - is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_1, 0); -#if defined(IS31FL3733_I2C_ADDRESS_2) - is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_2, 1); -# if defined(IS31FL3733_I2C_ADDRESS_3) - is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_3, 2); -# if defined(IS31FL3733_I2C_ADDRESS_4) - is31fl3733_update_led_control_registers(IS31FL3733_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3733_init(uint8_t addr, uint8_t sync) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, shutdown is enabled last. - // Set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - // Sync is passed so set it according to the datasheet. - - is31fl3733_select_page(addr, IS31FL3733_COMMAND_LED_CONTROL); - - // Turn off all LEDs. - for (int i = 0; i < IS31FL3733_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3733_write_register(addr, i, 0x00); - } - - is31fl3733_select_page(addr, IS31FL3733_COMMAND_PWM); - - // Set PWM on all LEDs to 0 - // No need to setup Breath registers to PWM as that is the default. - for (int i = 0; i < IS31FL3733_PWM_REGISTER_COUNT; i++) { - is31fl3733_write_register(addr, i, 0x00); - } - - is31fl3733_select_page(addr, IS31FL3733_COMMAND_FUNCTION); - - // Set de-ghost pull-up resistors (SWx) - is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_SW_PULLUP, IS31FL3733_SW_PULLUP); - // Set de-ghost pull-down resistors (CSx) - is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_CS_PULLDOWN, IS31FL3733_CS_PULLDOWN); - // Set global current to maximum. - is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3733_GLOBAL_CURRENT); - // Disable software shutdown. - is31fl3733_write_register(addr, IS31FL3733_FUNCTION_REG_CONFIGURATION, ((sync & 0b11) << 6) | ((IS31FL3733_PWM_FREQUENCY & 0b111) << 3) | 0x01); - - // Wait 10ms to ensure the device has woken up. - wait_ms(10); -} - -void is31fl3733_set_value(int index, uint8_t value) { - is31fl3733_led_t led; - if (index >= 0 && index < IS31FL3733_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3733_leds[index]), sizeof(led)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - g_pwm_buffer[led.driver][led.v] = value; - g_pwm_buffer_update_required[led.driver] = true; - } -} - -void is31fl3733_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3733_LED_COUNT; i++) { - is31fl3733_set_value(i, value); - } -} - -void is31fl3733_set_led_control_register(uint8_t index, bool value) { - is31fl3733_led_t led; - memcpy_P(&led, (&g_is31fl3733_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 is31fl3733_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3733_select_page(addr, IS31FL3733_COMMAND_PWM); - - // If any of the transactions fail we risk writing dirty page 0, - // refresh page 0 just in case. - if (!is31fl3733_write_pwm_buffer(addr, g_pwm_buffer[index])) { - g_led_control_registers_update_required[index] = true; - } - g_pwm_buffer_update_required[index] = false; - } -} - -void is31fl3733_update_led_control_registers(uint8_t addr, uint8_t index) { - if (g_led_control_registers_update_required[index]) { - is31fl3733_select_page(addr, IS31FL3733_COMMAND_LED_CONTROL); - - for (int i = 0; i < IS31FL3733_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3733_write_register(addr, i, g_led_control_registers[index][i]); - } - g_led_control_registers_update_required[index] = false; - } -} - -void is31fl3733_flush(void) { - is31fl3733_update_pwm_buffers(IS31FL3733_I2C_ADDRESS_1, 0); -#if defined(IS31FL3733_I2C_ADDRESS_2) - is31fl3733_update_pwm_buffers(IS31FL3733_I2C_ADDRESS_2, 1); -# if defined(IS31FL3733_I2C_ADDRESS_3) - is31fl3733_update_pwm_buffers(IS31FL3733_I2C_ADDRESS_3, 2); -# if defined(IS31FL3733_I2C_ADDRESS_4) - is31fl3733_update_pwm_buffers(IS31FL3733_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3733-simple.h b/drivers/led/issi/is31fl3733-simple.h deleted file mode 100644 index dcb33e448f..0000000000 --- a/drivers/led/issi/is31fl3733-simple.h +++ /dev/null @@ -1,367 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2021 Doni Crosby - * Copyright 2021 Leo Deng - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -// ======== DEPRECATED DEFINES - DO NOT USE ======== -#ifdef ISSI_TIMEOUT -# define IS31FL3733_I2C_TIMEOUT ISSI_TIMEOUT -#endif -#ifdef ISSI_PERSISTENCE -# define IS31FL3733_I2C_PERSISTENCE ISSI_PERSISTENCE -#endif -#ifdef ISSI_PWM_FREQUENCY -# define IS31FL3733_PWM_FREQUENCY ISSI_PWM_FREQUENCY -#endif -#ifdef ISSI_SWPULLUP -# define IS31FL3733_SW_PULLUP ISSI_SWPULLUP -#endif -#ifdef ISSI_CSPULLUP -# define IS31FL3733_CS_PULLDOWN ISSI_CSPULLUP -#endif -#ifdef ISSI_GLOBALCURRENT -# define IS31FL3733_GLOBAL_CURRENT ISSI_GLOBALCURRENT -#endif - -#define is31_led is31fl3733_led_t -#define g_is31_leds g_is31fl3733_leds - -#define PUR_0R IS31FL3733_PUR_0_OHM -#define PUR_05KR IS31FL3733_PUR_1K_OHM -#define PUR_3KR IS31FL3733_PUR_2K_OHM -#define PUR_4KR IS31FL3733_PUR_4K_OHM -#define PUR_8KR IS31FL3733_PUR_8K_OHM -#define PUR_16KR IS31FL3733_PUR_16K_OHM -#define PUR_32KR IS31FL3733_PUR_32K_OHM -// ======== - -#define IS31FL3733_REG_INTERRUPT_MASK 0xF0 -#define IS31FL3733_REG_INTERRUPT_STATUS 0xF1 - -#define IS31FL3733_REG_COMMAND 0xFD - -#define IS31FL3733_COMMAND_LED_CONTROL 0x00 -#define IS31FL3733_COMMAND_PWM 0x01 -#define IS31FL3733_COMMAND_AUTO_BREATH 0x02 -#define IS31FL3733_COMMAND_FUNCTION 0x03 - -#define IS31FL3733_FUNCTION_REG_CONFIGURATION 0x00 -#define IS31FL3733_FUNCTION_REG_GLOBAL_CURRENT 0x01 -#define IS31FL3733_FUNCTION_REG_SW_PULLUP 0x0F -#define IS31FL3733_FUNCTION_REG_CS_PULLDOWN 0x10 -#define IS31FL3733_FUNCTION_REG_RESET 0x11 - -#define IS31FL3733_REG_COMMAND_WRITE_LOCK 0xFE -#define IS31FL3733_COMMAND_WRITE_LOCK_MAGIC 0xC5 - -#define IS31FL3733_I2C_ADDRESS_GND_GND 0x50 -#define IS31FL3733_I2C_ADDRESS_GND_SCL 0x51 -#define IS31FL3733_I2C_ADDRESS_GND_SDA 0x52 -#define IS31FL3733_I2C_ADDRESS_GND_VCC 0x53 -#define IS31FL3733_I2C_ADDRESS_SCL_GND 0x54 -#define IS31FL3733_I2C_ADDRESS_SCL_SCL 0x55 -#define IS31FL3733_I2C_ADDRESS_SCL_SDA 0x56 -#define IS31FL3733_I2C_ADDRESS_SCL_VCC 0x57 -#define IS31FL3733_I2C_ADDRESS_SDA_GND 0x58 -#define IS31FL3733_I2C_ADDRESS_SDA_SCL 0x59 -#define IS31FL3733_I2C_ADDRESS_SDA_SDA 0x5A -#define IS31FL3733_I2C_ADDRESS_SDA_VCC 0x5B -#define IS31FL3733_I2C_ADDRESS_VCC_GND 0x5C -#define IS31FL3733_I2C_ADDRESS_VCC_SCL 0x5D -#define IS31FL3733_I2C_ADDRESS_VCC_SDA 0x5E -#define IS31FL3733_I2C_ADDRESS_VCC_VCC 0x5F - -#if defined(LED_MATRIX_IS31FL3733) -# define IS31FL3733_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined(IS31FL3733_I2C_ADDRESS_4) -# define IS31FL3733_DRIVER_COUNT 4 -#elif defined(IS31FL3733_I2C_ADDRESS_3) -# define IS31FL3733_DRIVER_COUNT 3 -#elif defined(IS31FL3733_I2C_ADDRESS_2) -# define IS31FL3733_DRIVER_COUNT 2 -#elif defined(IS31FL3733_I2C_ADDRESS_1) -# define IS31FL3733_DRIVER_COUNT 1 -#endif - -typedef struct is31fl3733_led_t { - uint8_t driver : 2; - uint8_t v; -} PACKED is31fl3733_led_t; - -extern const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT]; - -void is31fl3733_init_drivers(void); -void is31fl3733_init(uint8_t addr, uint8_t sync); -bool is31fl3733_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3733_select_page(uint8_t addr, uint8_t page); -bool is31fl3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3733_set_value(int index, uint8_t value); -void is31fl3733_set_value_all(uint8_t value); - -void is31fl3733_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 is31fl3733_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3733_update_led_control_registers(uint8_t addr, uint8_t index); - -void is31fl3733_flush(void); - -#define IS31FL3733_PDR_0_OHM 0b000 // No pull-down resistor -#define IS31FL3733_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3733_PDR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3733_PDR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3733_PDR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3733_PDR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3733_PDR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3733_PDR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3733_PUR_0_OHM 0b000 // No pull-up resistor -#define IS31FL3733_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3733_PUR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3733_PUR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3733_PUR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3733_PUR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3733_PUR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3733_PUR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3733_PWM_FREQUENCY_8K4_HZ 0b000 -#define IS31FL3733_PWM_FREQUENCY_4K2_HZ 0b001 -#define IS31FL3733_PWM_FREQUENCY_26K7_HZ 0b010 -#define IS31FL3733_PWM_FREQUENCY_2K1_HZ 0b011 -#define IS31FL3733_PWM_FREQUENCY_1K05_HZ 0b100 - -#define IS31FL3733_SYNC_NONE 0b00 -#define IS31FL3733_SYNC_MASTER 0b01 -#define IS31FL3733_SYNC_SLAVE 0b10 - -#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 diff --git a/drivers/led/issi/is31fl3736-mono.c b/drivers/led/issi/is31fl3736-mono.c new file mode 100644 index 0000000000..5ced65aa06 --- /dev/null +++ b/drivers/led/issi/is31fl3736-mono.c @@ -0,0 +1,244 @@ +/* Copyright 2018 Jason Williams (Wilba) + * Copyright 2021 Doni Crosby + * + * 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 . + */ + +#include "is31fl3736-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3736_PWM_REGISTER_COUNT 192 // actually 96 +#define IS31FL3736_LED_CONTROL_REGISTER_COUNT 24 + +#ifndef IS31FL3736_I2C_TIMEOUT +# define IS31FL3736_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3736_I2C_PERSISTENCE +# define IS31FL3736_I2C_PERSISTENCE 0 +#endif + +#ifndef IS31FL3736_PWM_FREQUENCY +# define IS31FL3736_PWM_FREQUENCY IS31FL3736_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3736B only +#endif + +#ifndef IS31FL3736_SW_PULLUP +# define IS31FL3736_SW_PULLUP IS31FL3736_PUR_0_OHM +#endif + +#ifndef IS31FL3736_CS_PULLDOWN +# define IS31FL3736_CS_PULLDOWN IS31FL3736_PDR_0_OHM +#endif + +#ifndef IS31FL3736_GLOBAL_CURRENT +# define IS31FL3736_GLOBAL_CURRENT 0xFF +#endif + +uint8_t i2c_transfer_buffer[20]; + +// These buffers match the IS31FL3736 PWM registers. +// The control buffers match the page 0 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 is31fl3736_write_pwm_buffer() but it's +// probably not worth the extra complexity. +uint8_t g_pwm_buffer[IS31FL3736_DRIVER_COUNT][IS31FL3736_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3736_DRIVER_COUNT] = {false}; + +uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][IS31FL3736_LED_CONTROL_REGISTER_COUNT] = {0}; +bool g_led_control_registers_update_required[IS31FL3736_DRIVER_COUNT] = {false}; + +void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3736_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT); +#endif +} + +void is31fl3736_select_page(uint8_t addr, uint8_t page) { + is31fl3736_write_register(addr, IS31FL3736_REG_COMMAND_WRITE_LOCK, IS31FL3736_COMMAND_WRITE_LOCK_MAGIC); + is31fl3736_write_register(addr, IS31FL3736_REG_COMMAND, page); +} + +void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // assumes page 1 is already selected + + // transmit PWM registers in 12 transfers of 16 bytes + // i2c_transfer_buffer[] is 20 bytes + + // iterate over the pwm_buffer contents at 16 byte intervals + for (int i = 0; i < IS31FL3736_PWM_REGISTER_COUNT; i += 16) { + i2c_transfer_buffer[0] = i; + // copy the data from i to i+15 + // device will auto-increment register for data after the first byte + // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); + +#if IS31FL3736_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT); +#endif + } +} + +void is31fl3736_init_drivers(void) { + i2c_init(); + + is31fl3736_init(IS31FL3736_I2C_ADDRESS_1); +#if defined(IS31FL3736_I2C_ADDRESS_2) + is31fl3736_init(IS31FL3736_I2C_ADDRESS_2); +# if defined(IS31FL3736_I2C_ADDRESS_3) + is31fl3736_init(IS31FL3736_I2C_ADDRESS_3); +# if defined(IS31FL3736_I2C_ADDRESS_4) + is31fl3736_init(IS31FL3736_I2C_ADDRESS_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3736_LED_COUNT; i++) { + is31fl3736_set_led_control_register(i, true); + } + + is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_1, 0); +#if defined(IS31FL3736_I2C_ADDRESS_2) + is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_2, 1); +# if defined(IS31FL3736_I2C_ADDRESS_3) + is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_3, 2); +# if defined(IS31FL3736_I2C_ADDRESS_4) + is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3736_init(uint8_t addr) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + + is31fl3736_select_page(addr, IS31FL3736_COMMAND_LED_CONTROL); + + // Turn off all LEDs. + for (int i = 0; i < IS31FL3736_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3736_write_register(addr, i, 0x00); + } + + is31fl3736_select_page(addr, IS31FL3736_COMMAND_PWM); + + // Set PWM on all LEDs to 0 + // No need to setup Breath registers to PWM as that is the default. + for (int i = 0; i < IS31FL3736_PWM_REGISTER_COUNT; i++) { + is31fl3736_write_register(addr, i, 0x00); + } + + is31fl3736_select_page(addr, IS31FL3736_COMMAND_FUNCTION); + + // Set de-ghost pull-up resistors (SWx) + is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_SW_PULLUP, IS31FL3736_SW_PULLUP); + // Set de-ghost pull-down resistors (CSx) + is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_CS_PULLDOWN, IS31FL3736_CS_PULLDOWN); + // Set global current to maximum. + is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3736_GLOBAL_CURRENT); + // Disable software shutdown. + is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_CONFIGURATION, ((IS31FL3736_PWM_FREQUENCY & 0b111) << 3) | 0x01); + + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void is31fl3736_set_value(int index, uint8_t value) { + is31fl3736_led_t led; + if (index >= 0 && index < IS31FL3736_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3736_leds[index]), sizeof(led)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + g_pwm_buffer[led.driver][led.v] = value; + g_pwm_buffer_update_required[led.driver] = true; + } +} + +void is31fl3736_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3736_LED_COUNT; i++) { + is31fl3736_set_value(i, value); + } +} + +void is31fl3736_set_led_control_register(uint8_t index, bool value) { + is31fl3736_led_t led; + memcpy_P(&led, (&g_is31fl3736_leds[index]), sizeof(led)); + + // The PWM register for a matrix position (0x00 to 0xBF) is interleaved, so: + // A1=0x00 A2=0x02 A3=0x04 A4=0x06 A5=0x08 A6=0x0A A7=0x0C A8=0x0E + // B1=0x10 B2=0x12 B3=0x14 + // But also, the LED control registers (0x00 to 0x17) are also interleaved, so: + // A1-A4=0x00 A5-A8=0x01 + + 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 is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3736_select_page(addr, IS31FL3736_COMMAND_PWM); + + is31fl3736_write_pwm_buffer(addr, g_pwm_buffer[index]); + g_pwm_buffer_update_required[index] = false; + } +} + +void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index) { + if (g_led_control_registers_update_required[index]) { + is31fl3736_select_page(addr, IS31FL3736_COMMAND_LED_CONTROL); + + for (int i = 0; i < IS31FL3736_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3736_write_register(addr, i, g_led_control_registers[index][i]); + } + g_led_control_registers_update_required[index] = false; + } +} + +void is31fl3736_flush(void) { + is31fl3736_update_pwm_buffers(IS31FL3736_I2C_ADDRESS_1, 0); +#if defined(IS31FL3736_I2C_ADDRESS_2) + is31fl3736_update_pwm_buffers(IS31FL3736_I2C_ADDRESS_2, 1); +# if defined(IS31FL3736_I2C_ADDRESS_3) + is31fl3736_update_pwm_buffers(IS31FL3736_I2C_ADDRESS_3, 2); +# if defined(IS31FL3736_I2C_ADDRESS_4) + is31fl3736_update_pwm_buffers(IS31FL3736_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3736-mono.h b/drivers/led/issi/is31fl3736-mono.h new file mode 100644 index 0000000000..5e80eb646a --- /dev/null +++ b/drivers/led/issi/is31fl3736-mono.h @@ -0,0 +1,262 @@ +/* Copyright 2018 Jason Williams (Wilba) + * Copyright 2021 Doni Crosby + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +// ======== DEPRECATED DEFINES - DO NOT USE ======== +#ifdef ISSI_TIMEOUT +# define IS31FL3736_I2C_TIMEOUT ISSI_TIMEOUT +#endif +#ifdef ISSI_PERSISTENCE +# define IS31FL3736_I2C_PERSISTENCE ISSI_PERSISTENCE +#endif +#ifdef ISSI_SWPULLUP +# define IS31FL3736_SW_PULLUP ISSI_SWPULLUP +#endif +#ifdef ISSI_CSPULLUP +# define IS31FL3736_CS_PULLDOWN ISSI_CSPULLUP +#endif +#ifdef ISSI_GLOBALCURRENT +# define IS31FL3736_GLOBAL_CURRENT ISSI_GLOBALCURRENT +#endif + +#define is31_led is31fl3736_led_t +#define g_is31_leds g_is31fl3736_leds + +#define PUR_0R IS31FL3736_PUR_0_OHM +#define PUR_05KR IS31FL3736_PUR_05K_OHM +#define PUR_1KR IS31FL3736_PUR_1K_OHM +#define PUR_2KR IS31FL3736_PUR_2K_OHM +#define PUR_4KR IS31FL3736_PUR_4K_OHM +#define PUR_8KR IS31FL3736_PUR_8K_OHM +#define PUR_16KR IS31FL3736_PUR_16K_OHM +#define PUR_32KR IS31FL3736_PUR_32K_OHM +// ======== + +#define IS31FL3736_REG_INTERRUPT_MASK 0xF0 +#define IS31FL3736_REG_INTERRUPT_STATUS 0xF1 + +#define IS31FL3736_REG_COMMAND 0xFD + +#define IS31FL3736_COMMAND_LED_CONTROL 0x00 +#define IS31FL3736_COMMAND_PWM 0x01 +#define IS31FL3736_COMMAND_AUTO_BREATH 0x02 +#define IS31FL3736_COMMAND_FUNCTION 0x03 + +#define IS31FL3736_FUNCTION_REG_CONFIGURATION 0x00 +#define IS31FL3736_FUNCTION_REG_GLOBAL_CURRENT 0x01 +#define IS31FL3736_FUNCTION_REG_SW_PULLUP 0x0F +#define IS31FL3736_FUNCTION_REG_CS_PULLDOWN 0x10 +#define IS31FL3736_FUNCTION_REG_RESET 0x11 + +#define IS31FL3736_REG_COMMAND_WRITE_LOCK 0xFE +#define IS31FL3736_COMMAND_WRITE_LOCK_MAGIC 0xC5 + +#define IS31FL3736_I2C_ADDRESS_GND_GND 0x50 +#define IS31FL3736_I2C_ADDRESS_GND_SCL 0x51 +#define IS31FL3736_I2C_ADDRESS_GND_SDA 0x52 +#define IS31FL3736_I2C_ADDRESS_GND_VCC 0x53 +#define IS31FL3736_I2C_ADDRESS_SCL_GND 0x54 +#define IS31FL3736_I2C_ADDRESS_SCL_SCL 0x55 +#define IS31FL3736_I2C_ADDRESS_SCL_SDA 0x56 +#define IS31FL3736_I2C_ADDRESS_SCL_VCC 0x57 +#define IS31FL3736_I2C_ADDRESS_SDA_GND 0x58 +#define IS31FL3736_I2C_ADDRESS_SDA_SCL 0x59 +#define IS31FL3736_I2C_ADDRESS_SDA_SDA 0x5A +#define IS31FL3736_I2C_ADDRESS_SDA_VCC 0x5B +#define IS31FL3736_I2C_ADDRESS_VCC_GND 0x5C +#define IS31FL3736_I2C_ADDRESS_VCC_SCL 0x5D +#define IS31FL3736_I2C_ADDRESS_VCC_SDA 0x5E +#define IS31FL3736_I2C_ADDRESS_VCC_VCC 0x5F + +#if defined(LED_MATRIX_IS31FL3736) +# define IS31FL3736_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined(IS31FL3736_I2C_ADDRESS_4) +# define IS31FL3736_DRIVER_COUNT 4 +#elif defined(IS31FL3736_I2C_ADDRESS_3) +# define IS31FL3736_DRIVER_COUNT 3 +#elif defined(IS31FL3736_I2C_ADDRESS_2) +# define IS31FL3736_DRIVER_COUNT 2 +#elif defined(IS31FL3736_I2C_ADDRESS_1) +# define IS31FL3736_DRIVER_COUNT 1 +#endif + +typedef struct is31fl3736_led_t { + uint8_t driver : 2; + uint8_t v; +} PACKED is31fl3736_led_t; + +extern const is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT]; + +void is31fl3736_init_drivers(void); +void is31fl3736_init(uint8_t addr); +void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3736_select_page(uint8_t addr, uint8_t page); +void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3736_set_value(int index, uint8_t value); +void is31fl3736_set_value_all(uint8_t value); + +void is31fl3736_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 is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index); + +void is31fl3736_flush(void); + +#define IS31FL3736_PDR_0_OHM 0b000 // No pull-down resistor +#define IS31FL3736_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3736_PDR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3736_PDR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3736_PDR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3736_PDR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3736_PDR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3736_PDR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3736_PUR_0_OHM 0b000 // No pull-up resistor +#define IS31FL3736_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3736_PUR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3736_PUR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3736_PUR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3736_PUR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3736_PUR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3736_PUR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3736_PWM_FREQUENCY_8K4_HZ 0b000 +#define IS31FL3736_PWM_FREQUENCY_4K2_HZ 0b001 +#define IS31FL3736_PWM_FREQUENCY_26K7_HZ 0b010 +#define IS31FL3736_PWM_FREQUENCY_2K1_HZ 0b011 +#define IS31FL3736_PWM_FREQUENCY_1K05_HZ 0b100 + +#define A_1 0x00 +#define A_2 0x02 +#define A_3 0x04 +#define A_4 0x06 +#define A_5 0x08 +#define A_6 0x0A +#define A_7 0x0C +#define A_8 0x0E + +#define B_1 0x10 +#define B_2 0x12 +#define B_3 0x14 +#define B_4 0x16 +#define B_5 0x18 +#define B_6 0x1A +#define B_7 0x1C +#define B_8 0x1E + +#define C_1 0x20 +#define C_2 0x22 +#define C_3 0x24 +#define C_4 0x26 +#define C_5 0x28 +#define C_6 0x2A +#define C_7 0x2C +#define C_8 0x2E + +#define D_1 0x30 +#define D_2 0x32 +#define D_3 0x34 +#define D_4 0x36 +#define D_5 0x38 +#define D_6 0x3A +#define D_7 0x3C +#define D_8 0x3E + +#define E_1 0x40 +#define E_2 0x42 +#define E_3 0x44 +#define E_4 0x46 +#define E_5 0x48 +#define E_6 0x4A +#define E_7 0x4C +#define E_8 0x4E + +#define F_1 0x50 +#define F_2 0x52 +#define F_3 0x54 +#define F_4 0x56 +#define F_5 0x58 +#define F_6 0x5A +#define F_7 0x5C +#define F_8 0x5E + +#define G_1 0x60 +#define G_2 0x62 +#define G_3 0x64 +#define G_4 0x66 +#define G_5 0x68 +#define G_6 0x6A +#define G_7 0x6C +#define G_8 0x6E + +#define H_1 0x70 +#define H_2 0x72 +#define H_3 0x74 +#define H_4 0x76 +#define H_5 0x78 +#define H_6 0x7A +#define H_7 0x7C +#define H_8 0x7E + +#define I_1 0x80 +#define I_2 0x82 +#define I_3 0x84 +#define I_4 0x86 +#define I_5 0x88 +#define I_6 0x8A +#define I_7 0x8C +#define I_8 0x8E + +#define J_1 0x90 +#define J_2 0x92 +#define J_3 0x94 +#define J_4 0x96 +#define J_5 0x98 +#define J_6 0x9A +#define J_7 0x9C +#define J_8 0x9E + +#define K_1 0xA0 +#define K_2 0xA2 +#define K_3 0xA4 +#define K_4 0xA6 +#define K_5 0xA8 +#define K_6 0xAA +#define K_7 0xAC +#define K_8 0xAE + +#define L_1 0xB0 +#define L_2 0xB2 +#define L_3 0xB4 +#define L_4 0xB6 +#define L_5 0xB8 +#define L_6 0xBA +#define L_7 0xBC +#define L_8 0xBE diff --git a/drivers/led/issi/is31fl3736-simple.c b/drivers/led/issi/is31fl3736-simple.c deleted file mode 100644 index ac5e0fb453..0000000000 --- a/drivers/led/issi/is31fl3736-simple.c +++ /dev/null @@ -1,244 +0,0 @@ -/* Copyright 2018 Jason Williams (Wilba) - * Copyright 2021 Doni Crosby - * - * 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 . - */ - -#include "is31fl3736-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3736_PWM_REGISTER_COUNT 192 // actually 96 -#define IS31FL3736_LED_CONTROL_REGISTER_COUNT 24 - -#ifndef IS31FL3736_I2C_TIMEOUT -# define IS31FL3736_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3736_I2C_PERSISTENCE -# define IS31FL3736_I2C_PERSISTENCE 0 -#endif - -#ifndef IS31FL3736_PWM_FREQUENCY -# define IS31FL3736_PWM_FREQUENCY IS31FL3736_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3736B only -#endif - -#ifndef IS31FL3736_SW_PULLUP -# define IS31FL3736_SW_PULLUP IS31FL3736_PUR_0_OHM -#endif - -#ifndef IS31FL3736_CS_PULLDOWN -# define IS31FL3736_CS_PULLDOWN IS31FL3736_PDR_0_OHM -#endif - -#ifndef IS31FL3736_GLOBAL_CURRENT -# define IS31FL3736_GLOBAL_CURRENT 0xFF -#endif - -uint8_t i2c_transfer_buffer[20]; - -// These buffers match the IS31FL3736 PWM registers. -// The control buffers match the page 0 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 is31fl3736_write_pwm_buffer() but it's -// probably not worth the extra complexity. -uint8_t g_pwm_buffer[IS31FL3736_DRIVER_COUNT][IS31FL3736_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3736_DRIVER_COUNT] = {false}; - -uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][IS31FL3736_LED_CONTROL_REGISTER_COUNT] = {0}; -bool g_led_control_registers_update_required[IS31FL3736_DRIVER_COUNT] = {false}; - -void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3736_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT); -#endif -} - -void is31fl3736_select_page(uint8_t addr, uint8_t page) { - is31fl3736_write_register(addr, IS31FL3736_REG_COMMAND_WRITE_LOCK, IS31FL3736_COMMAND_WRITE_LOCK_MAGIC); - is31fl3736_write_register(addr, IS31FL3736_REG_COMMAND, page); -} - -void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // assumes page 1 is already selected - - // transmit PWM registers in 12 transfers of 16 bytes - // i2c_transfer_buffer[] is 20 bytes - - // iterate over the pwm_buffer contents at 16 byte intervals - for (int i = 0; i < IS31FL3736_PWM_REGISTER_COUNT; i += 16) { - i2c_transfer_buffer[0] = i; - // copy the data from i to i+15 - // device will auto-increment register for data after the first byte - // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); - -#if IS31FL3736_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT); -#endif - } -} - -void is31fl3736_init_drivers(void) { - i2c_init(); - - is31fl3736_init(IS31FL3736_I2C_ADDRESS_1); -#if defined(IS31FL3736_I2C_ADDRESS_2) - is31fl3736_init(IS31FL3736_I2C_ADDRESS_2); -# if defined(IS31FL3736_I2C_ADDRESS_3) - is31fl3736_init(IS31FL3736_I2C_ADDRESS_3); -# if defined(IS31FL3736_I2C_ADDRESS_4) - is31fl3736_init(IS31FL3736_I2C_ADDRESS_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3736_LED_COUNT; i++) { - is31fl3736_set_led_control_register(i, true); - } - - is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_1, 0); -#if defined(IS31FL3736_I2C_ADDRESS_2) - is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_2, 1); -# if defined(IS31FL3736_I2C_ADDRESS_3) - is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_3, 2); -# if defined(IS31FL3736_I2C_ADDRESS_4) - is31fl3736_update_led_control_registers(IS31FL3736_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3736_init(uint8_t addr) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, shutdown is enabled last. - // Set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - - is31fl3736_select_page(addr, IS31FL3736_COMMAND_LED_CONTROL); - - // Turn off all LEDs. - for (int i = 0; i < IS31FL3736_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3736_write_register(addr, i, 0x00); - } - - is31fl3736_select_page(addr, IS31FL3736_COMMAND_PWM); - - // Set PWM on all LEDs to 0 - // No need to setup Breath registers to PWM as that is the default. - for (int i = 0; i < IS31FL3736_PWM_REGISTER_COUNT; i++) { - is31fl3736_write_register(addr, i, 0x00); - } - - is31fl3736_select_page(addr, IS31FL3736_COMMAND_FUNCTION); - - // Set de-ghost pull-up resistors (SWx) - is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_SW_PULLUP, IS31FL3736_SW_PULLUP); - // Set de-ghost pull-down resistors (CSx) - is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_CS_PULLDOWN, IS31FL3736_CS_PULLDOWN); - // Set global current to maximum. - is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3736_GLOBAL_CURRENT); - // Disable software shutdown. - is31fl3736_write_register(addr, IS31FL3736_FUNCTION_REG_CONFIGURATION, ((IS31FL3736_PWM_FREQUENCY & 0b111) << 3) | 0x01); - - // Wait 10ms to ensure the device has woken up. - wait_ms(10); -} - -void is31fl3736_set_value(int index, uint8_t value) { - is31fl3736_led_t led; - if (index >= 0 && index < IS31FL3736_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3736_leds[index]), sizeof(led)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - g_pwm_buffer[led.driver][led.v] = value; - g_pwm_buffer_update_required[led.driver] = true; - } -} - -void is31fl3736_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3736_LED_COUNT; i++) { - is31fl3736_set_value(i, value); - } -} - -void is31fl3736_set_led_control_register(uint8_t index, bool value) { - is31fl3736_led_t led; - memcpy_P(&led, (&g_is31fl3736_leds[index]), sizeof(led)); - - // The PWM register for a matrix position (0x00 to 0xBF) is interleaved, so: - // A1=0x00 A2=0x02 A3=0x04 A4=0x06 A5=0x08 A6=0x0A A7=0x0C A8=0x0E - // B1=0x10 B2=0x12 B3=0x14 - // But also, the LED control registers (0x00 to 0x17) are also interleaved, so: - // A1-A4=0x00 A5-A8=0x01 - - 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 is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3736_select_page(addr, IS31FL3736_COMMAND_PWM); - - is31fl3736_write_pwm_buffer(addr, g_pwm_buffer[index]); - g_pwm_buffer_update_required[index] = false; - } -} - -void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index) { - if (g_led_control_registers_update_required[index]) { - is31fl3736_select_page(addr, IS31FL3736_COMMAND_LED_CONTROL); - - for (int i = 0; i < IS31FL3736_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3736_write_register(addr, i, g_led_control_registers[index][i]); - } - g_led_control_registers_update_required[index] = false; - } -} - -void is31fl3736_flush(void) { - is31fl3736_update_pwm_buffers(IS31FL3736_I2C_ADDRESS_1, 0); -#if defined(IS31FL3736_I2C_ADDRESS_2) - is31fl3736_update_pwm_buffers(IS31FL3736_I2C_ADDRESS_2, 1); -# if defined(IS31FL3736_I2C_ADDRESS_3) - is31fl3736_update_pwm_buffers(IS31FL3736_I2C_ADDRESS_3, 2); -# if defined(IS31FL3736_I2C_ADDRESS_4) - is31fl3736_update_pwm_buffers(IS31FL3736_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3736-simple.h b/drivers/led/issi/is31fl3736-simple.h deleted file mode 100644 index 5e80eb646a..0000000000 --- a/drivers/led/issi/is31fl3736-simple.h +++ /dev/null @@ -1,262 +0,0 @@ -/* Copyright 2018 Jason Williams (Wilba) - * Copyright 2021 Doni Crosby - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -// ======== DEPRECATED DEFINES - DO NOT USE ======== -#ifdef ISSI_TIMEOUT -# define IS31FL3736_I2C_TIMEOUT ISSI_TIMEOUT -#endif -#ifdef ISSI_PERSISTENCE -# define IS31FL3736_I2C_PERSISTENCE ISSI_PERSISTENCE -#endif -#ifdef ISSI_SWPULLUP -# define IS31FL3736_SW_PULLUP ISSI_SWPULLUP -#endif -#ifdef ISSI_CSPULLUP -# define IS31FL3736_CS_PULLDOWN ISSI_CSPULLUP -#endif -#ifdef ISSI_GLOBALCURRENT -# define IS31FL3736_GLOBAL_CURRENT ISSI_GLOBALCURRENT -#endif - -#define is31_led is31fl3736_led_t -#define g_is31_leds g_is31fl3736_leds - -#define PUR_0R IS31FL3736_PUR_0_OHM -#define PUR_05KR IS31FL3736_PUR_05K_OHM -#define PUR_1KR IS31FL3736_PUR_1K_OHM -#define PUR_2KR IS31FL3736_PUR_2K_OHM -#define PUR_4KR IS31FL3736_PUR_4K_OHM -#define PUR_8KR IS31FL3736_PUR_8K_OHM -#define PUR_16KR IS31FL3736_PUR_16K_OHM -#define PUR_32KR IS31FL3736_PUR_32K_OHM -// ======== - -#define IS31FL3736_REG_INTERRUPT_MASK 0xF0 -#define IS31FL3736_REG_INTERRUPT_STATUS 0xF1 - -#define IS31FL3736_REG_COMMAND 0xFD - -#define IS31FL3736_COMMAND_LED_CONTROL 0x00 -#define IS31FL3736_COMMAND_PWM 0x01 -#define IS31FL3736_COMMAND_AUTO_BREATH 0x02 -#define IS31FL3736_COMMAND_FUNCTION 0x03 - -#define IS31FL3736_FUNCTION_REG_CONFIGURATION 0x00 -#define IS31FL3736_FUNCTION_REG_GLOBAL_CURRENT 0x01 -#define IS31FL3736_FUNCTION_REG_SW_PULLUP 0x0F -#define IS31FL3736_FUNCTION_REG_CS_PULLDOWN 0x10 -#define IS31FL3736_FUNCTION_REG_RESET 0x11 - -#define IS31FL3736_REG_COMMAND_WRITE_LOCK 0xFE -#define IS31FL3736_COMMAND_WRITE_LOCK_MAGIC 0xC5 - -#define IS31FL3736_I2C_ADDRESS_GND_GND 0x50 -#define IS31FL3736_I2C_ADDRESS_GND_SCL 0x51 -#define IS31FL3736_I2C_ADDRESS_GND_SDA 0x52 -#define IS31FL3736_I2C_ADDRESS_GND_VCC 0x53 -#define IS31FL3736_I2C_ADDRESS_SCL_GND 0x54 -#define IS31FL3736_I2C_ADDRESS_SCL_SCL 0x55 -#define IS31FL3736_I2C_ADDRESS_SCL_SDA 0x56 -#define IS31FL3736_I2C_ADDRESS_SCL_VCC 0x57 -#define IS31FL3736_I2C_ADDRESS_SDA_GND 0x58 -#define IS31FL3736_I2C_ADDRESS_SDA_SCL 0x59 -#define IS31FL3736_I2C_ADDRESS_SDA_SDA 0x5A -#define IS31FL3736_I2C_ADDRESS_SDA_VCC 0x5B -#define IS31FL3736_I2C_ADDRESS_VCC_GND 0x5C -#define IS31FL3736_I2C_ADDRESS_VCC_SCL 0x5D -#define IS31FL3736_I2C_ADDRESS_VCC_SDA 0x5E -#define IS31FL3736_I2C_ADDRESS_VCC_VCC 0x5F - -#if defined(LED_MATRIX_IS31FL3736) -# define IS31FL3736_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined(IS31FL3736_I2C_ADDRESS_4) -# define IS31FL3736_DRIVER_COUNT 4 -#elif defined(IS31FL3736_I2C_ADDRESS_3) -# define IS31FL3736_DRIVER_COUNT 3 -#elif defined(IS31FL3736_I2C_ADDRESS_2) -# define IS31FL3736_DRIVER_COUNT 2 -#elif defined(IS31FL3736_I2C_ADDRESS_1) -# define IS31FL3736_DRIVER_COUNT 1 -#endif - -typedef struct is31fl3736_led_t { - uint8_t driver : 2; - uint8_t v; -} PACKED is31fl3736_led_t; - -extern const is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT]; - -void is31fl3736_init_drivers(void); -void is31fl3736_init(uint8_t addr); -void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3736_select_page(uint8_t addr, uint8_t page); -void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3736_set_value(int index, uint8_t value); -void is31fl3736_set_value_all(uint8_t value); - -void is31fl3736_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 is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index); - -void is31fl3736_flush(void); - -#define IS31FL3736_PDR_0_OHM 0b000 // No pull-down resistor -#define IS31FL3736_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3736_PDR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3736_PDR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3736_PDR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3736_PDR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3736_PDR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3736_PDR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3736_PUR_0_OHM 0b000 // No pull-up resistor -#define IS31FL3736_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3736_PUR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3736_PUR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3736_PUR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3736_PUR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3736_PUR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3736_PUR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3736_PWM_FREQUENCY_8K4_HZ 0b000 -#define IS31FL3736_PWM_FREQUENCY_4K2_HZ 0b001 -#define IS31FL3736_PWM_FREQUENCY_26K7_HZ 0b010 -#define IS31FL3736_PWM_FREQUENCY_2K1_HZ 0b011 -#define IS31FL3736_PWM_FREQUENCY_1K05_HZ 0b100 - -#define A_1 0x00 -#define A_2 0x02 -#define A_3 0x04 -#define A_4 0x06 -#define A_5 0x08 -#define A_6 0x0A -#define A_7 0x0C -#define A_8 0x0E - -#define B_1 0x10 -#define B_2 0x12 -#define B_3 0x14 -#define B_4 0x16 -#define B_5 0x18 -#define B_6 0x1A -#define B_7 0x1C -#define B_8 0x1E - -#define C_1 0x20 -#define C_2 0x22 -#define C_3 0x24 -#define C_4 0x26 -#define C_5 0x28 -#define C_6 0x2A -#define C_7 0x2C -#define C_8 0x2E - -#define D_1 0x30 -#define D_2 0x32 -#define D_3 0x34 -#define D_4 0x36 -#define D_5 0x38 -#define D_6 0x3A -#define D_7 0x3C -#define D_8 0x3E - -#define E_1 0x40 -#define E_2 0x42 -#define E_3 0x44 -#define E_4 0x46 -#define E_5 0x48 -#define E_6 0x4A -#define E_7 0x4C -#define E_8 0x4E - -#define F_1 0x50 -#define F_2 0x52 -#define F_3 0x54 -#define F_4 0x56 -#define F_5 0x58 -#define F_6 0x5A -#define F_7 0x5C -#define F_8 0x5E - -#define G_1 0x60 -#define G_2 0x62 -#define G_3 0x64 -#define G_4 0x66 -#define G_5 0x68 -#define G_6 0x6A -#define G_7 0x6C -#define G_8 0x6E - -#define H_1 0x70 -#define H_2 0x72 -#define H_3 0x74 -#define H_4 0x76 -#define H_5 0x78 -#define H_6 0x7A -#define H_7 0x7C -#define H_8 0x7E - -#define I_1 0x80 -#define I_2 0x82 -#define I_3 0x84 -#define I_4 0x86 -#define I_5 0x88 -#define I_6 0x8A -#define I_7 0x8C -#define I_8 0x8E - -#define J_1 0x90 -#define J_2 0x92 -#define J_3 0x94 -#define J_4 0x96 -#define J_5 0x98 -#define J_6 0x9A -#define J_7 0x9C -#define J_8 0x9E - -#define K_1 0xA0 -#define K_2 0xA2 -#define K_3 0xA4 -#define K_4 0xA6 -#define K_5 0xA8 -#define K_6 0xAA -#define K_7 0xAC -#define K_8 0xAE - -#define L_1 0xB0 -#define L_2 0xB2 -#define L_3 0xB4 -#define L_4 0xB6 -#define L_5 0xB8 -#define L_6 0xBA -#define L_7 0xBC -#define L_8 0xBE diff --git a/drivers/led/issi/is31fl3737-mono.c b/drivers/led/issi/is31fl3737-mono.c new file mode 100644 index 0000000000..56f169550b --- /dev/null +++ b/drivers/led/issi/is31fl3737-mono.c @@ -0,0 +1,241 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2021 Doni Crosby + * + * 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 . + */ + +#include "is31fl3737-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3737_PWM_REGISTER_COUNT 192 // actually 144 +#define IS31FL3737_LED_CONTROL_REGISTER_COUNT 24 + +#ifndef IS31FL3737_I2C_TIMEOUT +# define IS31FL3737_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3737_I2C_PERSISTENCE +# define IS31FL3737_I2C_PERSISTENCE 0 +#endif + +#ifndef IS31FL3737_PWM_FREQUENCY +# define IS31FL3737_PWM_FREQUENCY IS31FL3737_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3737B only +#endif + +#ifndef IS31FL3737_SW_PULLUP +# define IS31FL3737_SW_PULLUP IS31FL3737_PUR_0_OHM +#endif + +#ifndef IS31FL3737_CS_PULLDOWN +# define IS31FL3737_CS_PULLDOWN IS31FL3737_PDR_0_OHM +#endif + +#ifndef IS31FL3737_GLOBAL_CURRENT +# define IS31FL3737_GLOBAL_CURRENT 0xFF +#endif + +uint8_t i2c_transfer_buffer[20]; + +// These buffers match the IS31FL3737 PWM registers. +// The control buffers match the page 0 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 is31fl3737_write_pwm_buffer() but it's +// probably not worth the extra complexity. + +uint8_t g_pwm_buffer[IS31FL3737_DRIVER_COUNT][IS31FL3737_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3737_DRIVER_COUNT] = {false}; + +uint8_t g_led_control_registers[IS31FL3737_DRIVER_COUNT][IS31FL3737_LED_CONTROL_REGISTER_COUNT] = {0}; +bool g_led_control_registers_update_required[IS31FL3737_DRIVER_COUNT] = {false}; + +void is31fl3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3737_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3737_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT); +#endif +} + +void is31fl3737_select_page(uint8_t addr, uint8_t page) { + is31fl3737_write_register(addr, IS31FL3737_REG_COMMAND_WRITE_LOCK, IS31FL3737_COMMAND_WRITE_LOCK_MAGIC); + is31fl3737_write_register(addr, IS31FL3737_REG_COMMAND, page); +} + +void is31fl3737_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // assumes page 1 is already selected + + // transmit PWM registers in 12 transfers of 16 bytes + // i2c_transfer_buffer[] is 20 bytes + + // iterate over the pwm_buffer contents at 16 byte intervals + for (int i = 0; i < IS31FL3737_PWM_REGISTER_COUNT; i += 16) { + i2c_transfer_buffer[0] = i; + // copy the data from i to i+15 + // device will auto-increment register for data after the first byte + // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); + +#if IS31FL3737_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3737_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT); +#endif + } +} + +void is31fl3737_init_drivers(void) { + i2c_init(); + + is31fl3737_init(IS31FL3737_I2C_ADDRESS_1); +#if defined(IS31FL3737_I2C_ADDRESS_2) + is31fl3737_init(IS31FL3737_I2C_ADDRESS_2); +# if defined(IS31FL3737_I2C_ADDRESS_3) + is31fl3737_init(IS31FL3737_I2C_ADDRESS_3); +# if defined(IS31FL3737_I2C_ADDRESS_4) + is31fl3737_init(IS31FL3737_I2C_ADDRESS_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3737_LED_COUNT; i++) { + is31fl3737_set_led_control_register(i, true); + } + + is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_1, 0); +#if defined(IS31FL3737_I2C_ADDRESS_2) + is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_2, 1); +# if defined(IS31FL3737_I2C_ADDRESS_3) + is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_3, 2); +# if defined(IS31FL3737_I2C_ADDRESS_4) + is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3737_init(uint8_t addr) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + + is31fl3737_select_page(addr, IS31FL3737_COMMAND_LED_CONTROL); + + // Turn off all LEDs. + for (int i = 0; i < IS31FL3737_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3737_write_register(addr, i, 0x00); + } + + is31fl3737_select_page(addr, IS31FL3737_COMMAND_PWM); + + // Set PWM on all LEDs to 0 + // No need to setup Breath registers to PWM as that is the default. + for (int i = 0; i < IS31FL3737_PWM_REGISTER_COUNT; i++) { + is31fl3737_write_register(addr, i, 0x00); + } + + is31fl3737_select_page(addr, IS31FL3737_COMMAND_FUNCTION); + + // Set de-ghost pull-up resistors (SWx) + is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_SW_PULLUP, IS31FL3737_SW_PULLUP); + // Set de-ghost pull-down resistors (CSx) + is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_CS_PULLDOWN, IS31FL3737_CS_PULLDOWN); + // Set global current to maximum. + is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3737_GLOBAL_CURRENT); + // Disable software shutdown. + is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_CONFIGURATION, ((IS31FL3737_PWM_FREQUENCY & 0b111) << 3) | 0x01); + + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void is31fl3737_set_value(int index, uint8_t value) { + is31fl3737_led_t led; + if (index >= 0 && index < IS31FL3737_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3737_leds[index]), sizeof(led)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + g_pwm_buffer[led.driver][led.v] = value; + g_pwm_buffer_update_required[led.driver] = true; + } +} + +void is31fl3737_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3737_LED_COUNT; i++) { + is31fl3737_set_value(i, value); + } +} + +void is31fl3737_set_led_control_register(uint8_t index, bool value) { + is31fl3737_led_t led; + memcpy_P(&led, (&g_is31fl3737_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 is31fl3737_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3737_select_page(addr, IS31FL3737_COMMAND_PWM); + + is31fl3737_write_pwm_buffer(addr, g_pwm_buffer[index]); + g_pwm_buffer_update_required[index] = false; + } +} + +void is31fl3737_update_led_control_registers(uint8_t addr, uint8_t index) { + if (g_led_control_registers_update_required[index]) { + is31fl3737_select_page(addr, IS31FL3737_COMMAND_LED_CONTROL); + + for (int i = 0; i < IS31FL3737_LED_CONTROL_REGISTER_COUNT; i++) { + is31fl3737_write_register(addr, i, g_led_control_registers[index][i]); + } + g_led_control_registers_update_required[index] = false; + } +} + +void is31fl3737_flush(void) { + is31fl3737_update_pwm_buffers(IS31FL3737_I2C_ADDRESS_1, 0); +#if defined(IS31FL3737_I2C_ADDRESS_2) + is31fl3737_update_pwm_buffers(IS31FL3737_I2C_ADDRESS_2, 1); +# if defined(IS31FL3737_I2C_ADDRESS_3) + is31fl3737_update_pwm_buffers(IS31FL3737_I2C_ADDRESS_3, 2); +# if defined(IS31FL3737_I2C_ADDRESS_4) + is31fl3737_update_pwm_buffers(IS31FL3737_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3737-mono.h b/drivers/led/issi/is31fl3737-mono.h new file mode 100644 index 0000000000..a11d2ef423 --- /dev/null +++ b/drivers/led/issi/is31fl3737-mono.h @@ -0,0 +1,300 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2021 Doni Crosby + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +// ======== DEPRECATED DEFINES - DO NOT USE ======== +#ifdef ISSI_TIMEOUT +# define IS31FL3737_I2C_TIMEOUT ISSI_TIMEOUT +#endif +#ifdef ISSI_PERSISTENCE +# define IS31FL3737_I2C_PERSISTENCE ISSI_PERSISTENCE +#endif +#ifdef ISSI_PWM_FREQUENCY +# define IS31FL3737_PWM_FREQUENCY ISSI_PWM_FREQUENCY +#endif +#ifdef ISSI_SWPULLUP +# define IS31FL3737_SW_PULLUP ISSI_SWPULLUP +#endif +#ifdef ISSI_CSPULLUP +# define IS31FL3737_CS_PULLDOWN ISSI_CSPULLUP +#endif +#ifdef ISSI_GLOBALCURRENT +# define IS31FL3737_GLOBAL_CURRENT ISSI_GLOBALCURRENT +#endif + +#define PUR_0R IS31FL3737_PUR_0_OHM +#define PUR_05KR IS31FL3737_PUR_0K5_OHM +#define PUR_1KR IS31FL3737_PUR_1K_OHM +#define PUR_2KR IS31FL3737_PUR_2K_OHM +#define PUR_4KR IS31FL3737_PUR_4K_OHM +#define PUR_8KR IS31FL3737_PUR_8K_OHM +#define PUR_16KR IS31FL3737_PUR_16K_OHM +#define PUR_32KR IS31FL3737_PUR_32K_OHM +// ======== + +#define IS31FL3737_REG_INTERRUPT_MASK 0xF0 +#define IS31FL3737_REG_INTERRUPT_STATUS 0xF1 + +#define IS31FL3737_REG_COMMAND 0xFD + +#define IS31FL3737_COMMAND_LED_CONTROL 0x00 +#define IS31FL3737_COMMAND_PWM 0x01 +#define IS31FL3737_COMMAND_AUTO_BREATH 0x02 +#define IS31FL3737_COMMAND_FUNCTION 0x03 + +#define IS31FL3737_FUNCTION_REG_CONFIGURATION 0x00 +#define IS31FL3737_FUNCTION_REG_GLOBAL_CURRENT 0x01 +#define IS31FL3737_FUNCTION_REG_SW_PULLUP 0x0F +#define IS31FL3737_FUNCTION_REG_CS_PULLDOWN 0x10 +#define IS31FL3737_FUNCTION_REG_RESET 0x11 + +#define IS31FL3737_REG_COMMAND_WRITE_LOCK 0xFE +#define IS31FL3737_COMMAND_WRITE_LOCK_MAGIC 0xC5 + +#define IS31FL3737_I2C_ADDRESS_GND 0x50 +#define IS31FL3737_I2C_ADDRESS_SCL 0x55 +#define IS31FL3737_I2C_ADDRESS_SDA 0x5A +#define IS31FL3737_I2C_ADDRESS_VCC 0x5F + +#if defined(LED_MATRIX_IS31FL3737) +# define IS31FL3737_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined(IS31FL3737_I2C_ADDRESS_4) +# define IS31FL3737_DRIVER_COUNT 4 +#elif defined(IS31FL3737_I2C_ADDRESS_3) +# define IS31FL3737_DRIVER_COUNT 3 +#elif defined(IS31FL3737_I2C_ADDRESS_2) +# define IS31FL3737_DRIVER_COUNT 2 +#elif defined(IS31FL3737_I2C_ADDRESS_1) +# define IS31FL3737_DRIVER_COUNT 1 +#endif + +typedef struct is31fl3737_led_t { + uint8_t driver : 2; + uint8_t v; +} PACKED is31fl3737_led_t; + +extern const is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT]; + +void is31fl3737_init_drivers(void); +void is31fl3737_init(uint8_t addr); +void is31fl3737_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3737_select_page(uint8_t addr, uint8_t page); +void is31fl3737_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3737_set_value(int index, uint8_t value); +void is31fl3737_set_value_all(uint8_t value); + +void is31fl3737_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 is31fl3737_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3737_update_led_control_registers(uint8_t addr, uint8_t index); + +void is31fl3737_flush(void); + +#define IS31FL3737_PDR_0_OHM 0b000 // No pull-down resistor +#define IS31FL3737_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3737_PDR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3737_PDR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3737_PDR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3737_PDR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3737_PDR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3737_PDR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3737_PUR_0_OHM 0b000 // No pull-up resistor +#define IS31FL3737_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3737_PUR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3737_PUR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3737_PUR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3737_PUR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3737_PUR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3737_PUR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3737_PWM_FREQUENCY_8K4_HZ 0b000 +#define IS31FL3737_PWM_FREQUENCY_4K2_HZ 0b001 +#define IS31FL3737_PWM_FREQUENCY_26K7_HZ 0b010 +#define IS31FL3737_PWM_FREQUENCY_2K1_HZ 0b011 +#define IS31FL3737_PWM_FREQUENCY_1K05_HZ 0b100 + +#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 0x08 +#define A_8 0x09 +#define A_9 0x0A +#define A_10 0x0B +#define A_11 0x0C +#define A_12 0x0D + +#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 0x18 +#define B_8 0x19 +#define B_9 0x1A +#define B_10 0x1B +#define B_11 0x1C +#define B_12 0x1D + +#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 0x28 +#define C_8 0x29 +#define C_9 0x2A +#define C_10 0x2B +#define C_11 0x2C +#define C_12 0x2D + +#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 0x38 +#define D_8 0x39 +#define D_9 0x3A +#define D_10 0x3B +#define D_11 0x3C +#define D_12 0x3D + +#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 0x48 +#define E_8 0x49 +#define E_9 0x4A +#define E_10 0x4B +#define E_11 0x4C +#define E_12 0x4D + +#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 0x58 +#define F_8 0x59 +#define F_9 0x5A +#define F_10 0x5B +#define F_11 0x5C +#define F_12 0x5D + +#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 0x68 +#define G_8 0x69 +#define G_9 0x6A +#define G_10 0x6B +#define G_11 0x6C +#define G_12 0x6D + +#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 0x78 +#define H_8 0x79 +#define H_9 0x7A +#define H_10 0x7B +#define H_11 0x7C +#define H_12 0x7D + +#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 0x88 +#define I_8 0x89 +#define I_9 0x8A +#define I_10 0x8B +#define I_11 0x8C +#define I_12 0x8D + +#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 0x98 +#define J_8 0x99 +#define J_9 0x9A +#define J_10 0x9B +#define J_11 0x9C +#define J_12 0x9D + +#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 0xA8 +#define K_8 0xA9 +#define K_9 0xAA +#define K_10 0xAB +#define K_11 0xAC +#define K_12 0xAD + +#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 0xB8 +#define L_8 0xB9 +#define L_9 0xBA +#define L_10 0xBB +#define L_11 0xBC +#define L_12 0xBD diff --git a/drivers/led/issi/is31fl3737-simple.c b/drivers/led/issi/is31fl3737-simple.c deleted file mode 100644 index 967a102b48..0000000000 --- a/drivers/led/issi/is31fl3737-simple.c +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2021 Doni Crosby - * - * 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 . - */ - -#include "is31fl3737-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3737_PWM_REGISTER_COUNT 192 // actually 144 -#define IS31FL3737_LED_CONTROL_REGISTER_COUNT 24 - -#ifndef IS31FL3737_I2C_TIMEOUT -# define IS31FL3737_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3737_I2C_PERSISTENCE -# define IS31FL3737_I2C_PERSISTENCE 0 -#endif - -#ifndef IS31FL3737_PWM_FREQUENCY -# define IS31FL3737_PWM_FREQUENCY IS31FL3737_PWM_FREQUENCY_8K4_HZ // PFS - IS31FL3737B only -#endif - -#ifndef IS31FL3737_SW_PULLUP -# define IS31FL3737_SW_PULLUP IS31FL3737_PUR_0_OHM -#endif - -#ifndef IS31FL3737_CS_PULLDOWN -# define IS31FL3737_CS_PULLDOWN IS31FL3737_PDR_0_OHM -#endif - -#ifndef IS31FL3737_GLOBAL_CURRENT -# define IS31FL3737_GLOBAL_CURRENT 0xFF -#endif - -uint8_t i2c_transfer_buffer[20]; - -// These buffers match the IS31FL3737 PWM registers. -// The control buffers match the page 0 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 is31fl3737_write_pwm_buffer() but it's -// probably not worth the extra complexity. - -uint8_t g_pwm_buffer[IS31FL3737_DRIVER_COUNT][IS31FL3737_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3737_DRIVER_COUNT] = {false}; - -uint8_t g_led_control_registers[IS31FL3737_DRIVER_COUNT][IS31FL3737_LED_CONTROL_REGISTER_COUNT] = {0}; -bool g_led_control_registers_update_required[IS31FL3737_DRIVER_COUNT] = {false}; - -void is31fl3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3737_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3737_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3737_I2C_TIMEOUT); -#endif -} - -void is31fl3737_select_page(uint8_t addr, uint8_t page) { - is31fl3737_write_register(addr, IS31FL3737_REG_COMMAND_WRITE_LOCK, IS31FL3737_COMMAND_WRITE_LOCK_MAGIC); - is31fl3737_write_register(addr, IS31FL3737_REG_COMMAND, page); -} - -void is31fl3737_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // assumes page 1 is already selected - - // transmit PWM registers in 12 transfers of 16 bytes - // i2c_transfer_buffer[] is 20 bytes - - // iterate over the pwm_buffer contents at 16 byte intervals - for (int i = 0; i < IS31FL3737_PWM_REGISTER_COUNT; i += 16) { - i2c_transfer_buffer[0] = i; - // copy the data from i to i+15 - // device will auto-increment register for data after the first byte - // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); - -#if IS31FL3737_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3737_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3737_I2C_TIMEOUT); -#endif - } -} - -void is31fl3737_init_drivers(void) { - i2c_init(); - - is31fl3737_init(IS31FL3737_I2C_ADDRESS_1); -#if defined(IS31FL3737_I2C_ADDRESS_2) - is31fl3737_init(IS31FL3737_I2C_ADDRESS_2); -# if defined(IS31FL3737_I2C_ADDRESS_3) - is31fl3737_init(IS31FL3737_I2C_ADDRESS_3); -# if defined(IS31FL3737_I2C_ADDRESS_4) - is31fl3737_init(IS31FL3737_I2C_ADDRESS_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3737_LED_COUNT; i++) { - is31fl3737_set_led_control_register(i, true); - } - - is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_1, 0); -#if defined(IS31FL3737_I2C_ADDRESS_2) - is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_2, 1); -# if defined(IS31FL3737_I2C_ADDRESS_3) - is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_3, 2); -# if defined(IS31FL3737_I2C_ADDRESS_4) - is31fl3737_update_led_control_registers(IS31FL3737_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3737_init(uint8_t addr) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, shutdown is enabled last. - // Set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - - is31fl3737_select_page(addr, IS31FL3737_COMMAND_LED_CONTROL); - - // Turn off all LEDs. - for (int i = 0; i < IS31FL3737_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3737_write_register(addr, i, 0x00); - } - - is31fl3737_select_page(addr, IS31FL3737_COMMAND_PWM); - - // Set PWM on all LEDs to 0 - // No need to setup Breath registers to PWM as that is the default. - for (int i = 0; i < IS31FL3737_PWM_REGISTER_COUNT; i++) { - is31fl3737_write_register(addr, i, 0x00); - } - - is31fl3737_select_page(addr, IS31FL3737_COMMAND_FUNCTION); - - // Set de-ghost pull-up resistors (SWx) - is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_SW_PULLUP, IS31FL3737_SW_PULLUP); - // Set de-ghost pull-down resistors (CSx) - is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_CS_PULLDOWN, IS31FL3737_CS_PULLDOWN); - // Set global current to maximum. - is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3737_GLOBAL_CURRENT); - // Disable software shutdown. - is31fl3737_write_register(addr, IS31FL3737_FUNCTION_REG_CONFIGURATION, ((IS31FL3737_PWM_FREQUENCY & 0b111) << 3) | 0x01); - - // Wait 10ms to ensure the device has woken up. - wait_ms(10); -} - -void is31fl3737_set_value(int index, uint8_t value) { - is31fl3737_led_t led; - if (index >= 0 && index < IS31FL3737_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3737_leds[index]), sizeof(led)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - g_pwm_buffer[led.driver][led.v] = value; - g_pwm_buffer_update_required[led.driver] = true; - } -} - -void is31fl3737_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3737_LED_COUNT; i++) { - is31fl3737_set_value(i, value); - } -} - -void is31fl3737_set_led_control_register(uint8_t index, bool value) { - is31fl3737_led_t led; - memcpy_P(&led, (&g_is31fl3737_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 is31fl3737_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3737_select_page(addr, IS31FL3737_COMMAND_PWM); - - is31fl3737_write_pwm_buffer(addr, g_pwm_buffer[index]); - g_pwm_buffer_update_required[index] = false; - } -} - -void is31fl3737_update_led_control_registers(uint8_t addr, uint8_t index) { - if (g_led_control_registers_update_required[index]) { - is31fl3737_select_page(addr, IS31FL3737_COMMAND_LED_CONTROL); - - for (int i = 0; i < IS31FL3737_LED_CONTROL_REGISTER_COUNT; i++) { - is31fl3737_write_register(addr, i, g_led_control_registers[index][i]); - } - g_led_control_registers_update_required[index] = false; - } -} - -void is31fl3737_flush(void) { - is31fl3737_update_pwm_buffers(IS31FL3737_I2C_ADDRESS_1, 0); -#if defined(IS31FL3737_I2C_ADDRESS_2) - is31fl3737_update_pwm_buffers(IS31FL3737_I2C_ADDRESS_2, 1); -# if defined(IS31FL3737_I2C_ADDRESS_3) - is31fl3737_update_pwm_buffers(IS31FL3737_I2C_ADDRESS_3, 2); -# if defined(IS31FL3737_I2C_ADDRESS_4) - is31fl3737_update_pwm_buffers(IS31FL3737_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3737-simple.h b/drivers/led/issi/is31fl3737-simple.h deleted file mode 100644 index a11d2ef423..0000000000 --- a/drivers/led/issi/is31fl3737-simple.h +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2021 Doni Crosby - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -// ======== DEPRECATED DEFINES - DO NOT USE ======== -#ifdef ISSI_TIMEOUT -# define IS31FL3737_I2C_TIMEOUT ISSI_TIMEOUT -#endif -#ifdef ISSI_PERSISTENCE -# define IS31FL3737_I2C_PERSISTENCE ISSI_PERSISTENCE -#endif -#ifdef ISSI_PWM_FREQUENCY -# define IS31FL3737_PWM_FREQUENCY ISSI_PWM_FREQUENCY -#endif -#ifdef ISSI_SWPULLUP -# define IS31FL3737_SW_PULLUP ISSI_SWPULLUP -#endif -#ifdef ISSI_CSPULLUP -# define IS31FL3737_CS_PULLDOWN ISSI_CSPULLUP -#endif -#ifdef ISSI_GLOBALCURRENT -# define IS31FL3737_GLOBAL_CURRENT ISSI_GLOBALCURRENT -#endif - -#define PUR_0R IS31FL3737_PUR_0_OHM -#define PUR_05KR IS31FL3737_PUR_0K5_OHM -#define PUR_1KR IS31FL3737_PUR_1K_OHM -#define PUR_2KR IS31FL3737_PUR_2K_OHM -#define PUR_4KR IS31FL3737_PUR_4K_OHM -#define PUR_8KR IS31FL3737_PUR_8K_OHM -#define PUR_16KR IS31FL3737_PUR_16K_OHM -#define PUR_32KR IS31FL3737_PUR_32K_OHM -// ======== - -#define IS31FL3737_REG_INTERRUPT_MASK 0xF0 -#define IS31FL3737_REG_INTERRUPT_STATUS 0xF1 - -#define IS31FL3737_REG_COMMAND 0xFD - -#define IS31FL3737_COMMAND_LED_CONTROL 0x00 -#define IS31FL3737_COMMAND_PWM 0x01 -#define IS31FL3737_COMMAND_AUTO_BREATH 0x02 -#define IS31FL3737_COMMAND_FUNCTION 0x03 - -#define IS31FL3737_FUNCTION_REG_CONFIGURATION 0x00 -#define IS31FL3737_FUNCTION_REG_GLOBAL_CURRENT 0x01 -#define IS31FL3737_FUNCTION_REG_SW_PULLUP 0x0F -#define IS31FL3737_FUNCTION_REG_CS_PULLDOWN 0x10 -#define IS31FL3737_FUNCTION_REG_RESET 0x11 - -#define IS31FL3737_REG_COMMAND_WRITE_LOCK 0xFE -#define IS31FL3737_COMMAND_WRITE_LOCK_MAGIC 0xC5 - -#define IS31FL3737_I2C_ADDRESS_GND 0x50 -#define IS31FL3737_I2C_ADDRESS_SCL 0x55 -#define IS31FL3737_I2C_ADDRESS_SDA 0x5A -#define IS31FL3737_I2C_ADDRESS_VCC 0x5F - -#if defined(LED_MATRIX_IS31FL3737) -# define IS31FL3737_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined(IS31FL3737_I2C_ADDRESS_4) -# define IS31FL3737_DRIVER_COUNT 4 -#elif defined(IS31FL3737_I2C_ADDRESS_3) -# define IS31FL3737_DRIVER_COUNT 3 -#elif defined(IS31FL3737_I2C_ADDRESS_2) -# define IS31FL3737_DRIVER_COUNT 2 -#elif defined(IS31FL3737_I2C_ADDRESS_1) -# define IS31FL3737_DRIVER_COUNT 1 -#endif - -typedef struct is31fl3737_led_t { - uint8_t driver : 2; - uint8_t v; -} PACKED is31fl3737_led_t; - -extern const is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT]; - -void is31fl3737_init_drivers(void); -void is31fl3737_init(uint8_t addr); -void is31fl3737_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3737_select_page(uint8_t addr, uint8_t page); -void is31fl3737_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3737_set_value(int index, uint8_t value); -void is31fl3737_set_value_all(uint8_t value); - -void is31fl3737_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 is31fl3737_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3737_update_led_control_registers(uint8_t addr, uint8_t index); - -void is31fl3737_flush(void); - -#define IS31FL3737_PDR_0_OHM 0b000 // No pull-down resistor -#define IS31FL3737_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3737_PDR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3737_PDR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3737_PDR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3737_PDR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3737_PDR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3737_PDR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3737_PUR_0_OHM 0b000 // No pull-up resistor -#define IS31FL3737_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3737_PUR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3737_PUR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3737_PUR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3737_PUR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3737_PUR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3737_PUR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3737_PWM_FREQUENCY_8K4_HZ 0b000 -#define IS31FL3737_PWM_FREQUENCY_4K2_HZ 0b001 -#define IS31FL3737_PWM_FREQUENCY_26K7_HZ 0b010 -#define IS31FL3737_PWM_FREQUENCY_2K1_HZ 0b011 -#define IS31FL3737_PWM_FREQUENCY_1K05_HZ 0b100 - -#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 0x08 -#define A_8 0x09 -#define A_9 0x0A -#define A_10 0x0B -#define A_11 0x0C -#define A_12 0x0D - -#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 0x18 -#define B_8 0x19 -#define B_9 0x1A -#define B_10 0x1B -#define B_11 0x1C -#define B_12 0x1D - -#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 0x28 -#define C_8 0x29 -#define C_9 0x2A -#define C_10 0x2B -#define C_11 0x2C -#define C_12 0x2D - -#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 0x38 -#define D_8 0x39 -#define D_9 0x3A -#define D_10 0x3B -#define D_11 0x3C -#define D_12 0x3D - -#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 0x48 -#define E_8 0x49 -#define E_9 0x4A -#define E_10 0x4B -#define E_11 0x4C -#define E_12 0x4D - -#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 0x58 -#define F_8 0x59 -#define F_9 0x5A -#define F_10 0x5B -#define F_11 0x5C -#define F_12 0x5D - -#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 0x68 -#define G_8 0x69 -#define G_9 0x6A -#define G_10 0x6B -#define G_11 0x6C -#define G_12 0x6D - -#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 0x78 -#define H_8 0x79 -#define H_9 0x7A -#define H_10 0x7B -#define H_11 0x7C -#define H_12 0x7D - -#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 0x88 -#define I_8 0x89 -#define I_9 0x8A -#define I_10 0x8B -#define I_11 0x8C -#define I_12 0x8D - -#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 0x98 -#define J_8 0x99 -#define J_9 0x9A -#define J_10 0x9B -#define J_11 0x9C -#define J_12 0x9D - -#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 0xA8 -#define K_8 0xA9 -#define K_9 0xAA -#define K_10 0xAB -#define K_11 0xAC -#define K_12 0xAD - -#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 0xB8 -#define L_8 0xB9 -#define L_9 0xBA -#define L_10 0xBB -#define L_11 0xBC -#define L_12 0xBD diff --git a/drivers/led/issi/is31fl3741-mono.c b/drivers/led/issi/is31fl3741-mono.c new file mode 100644 index 0000000000..72260654ef --- /dev/null +++ b/drivers/led/issi/is31fl3741-mono.c @@ -0,0 +1,271 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2020 MelGeek + * + * 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 . + */ + +#include "is31fl3741-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3741_PWM_REGISTER_COUNT 351 +#define IS31FL3741_SCALING_REGISTER_COUNT 351 + +#ifndef IS31FL3741_I2C_TIMEOUT +# define IS31FL3741_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3741_I2C_PERSISTENCE +# define IS31FL3741_I2C_PERSISTENCE 0 +#endif + +#ifndef IS31FL3741_CONFIGURATION +# define IS31FL3741_CONFIGURATION 0x01 +#endif + +#ifndef IS31FL3741_PWM_FREQUENCY +# define IS31FL3741_PWM_FREQUENCY IS31FL3741_PWM_FREQUENCY_29K_HZ +#endif + +#ifndef IS31FL3741_SW_PULLUP +# define IS31FL3741_SW_PULLUP IS31FL3741_PUR_32K_OHM +#endif + +#ifndef IS31FL3741_CS_PULLDOWN +# define IS31FL3741_CS_PULLDOWN IS31FL3741_PDR_32K_OHM +#endif + +#ifndef IS31FL3741_GLOBAL_CURRENT +# define IS31FL3741_GLOBAL_CURRENT 0xFF +#endif + +uint8_t i2c_transfer_buffer[20] = {0xFF}; + +// These buffers match the IS31FL3741 and IS31FL3741A PWM registers. +// The scaling buffers match the page 2 and 3 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 is31fl3741_write_pwm_buffer() but it's +// probably not worth the extra complexity. +uint8_t g_pwm_buffer[IS31FL3741_DRIVER_COUNT][IS31FL3741_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3741_DRIVER_COUNT] = {false}; +bool g_scaling_registers_update_required[IS31FL3741_DRIVER_COUNT] = {false}; + +uint8_t g_scaling_registers[IS31FL3741_DRIVER_COUNT][IS31FL3741_SCALING_REGISTER_COUNT]; + +void is31fl3741_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3741_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT); +#endif +} + +void is31fl3741_select_page(uint8_t addr, uint8_t page) { + is31fl3741_write_register(addr, IS31FL3741_REG_COMMAND_WRITE_LOCK, IS31FL3741_COMMAND_WRITE_LOCK_MAGIC); + is31fl3741_write_register(addr, IS31FL3741_REG_COMMAND, page); +} + +bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // Assume page 0 is already selected + + for (int i = 0; i < 342; i += 18) { + if (i == 180) { + is31fl3741_select_page(addr, IS31FL3741_COMMAND_PWM_1); + } + + i2c_transfer_buffer[0] = i % 180; + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 18); + +#if IS31FL3741_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) { + return false; + } +#endif + } + + // transfer the left cause the total number is 351 + i2c_transfer_buffer[0] = 162; + memcpy(i2c_transfer_buffer + 1, pwm_buffer + 342, 9); + +#if IS31FL3741_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) { + return false; + } +#endif + + return true; +} + +void is31fl3741_init_drivers(void) { + i2c_init(); + + is31fl3741_init(IS31FL3741_I2C_ADDRESS_1); +#if defined(IS31FL3741_I2C_ADDRESS_2) + is31fl3741_init(IS31FL3741_I2C_ADDRESS_2); +# if defined(IS31FL3741_I2C_ADDRESS_3) + is31fl3741_init(IS31FL3741_I2C_ADDRESS_3); +# if defined(IS31FL3741_I2C_ADDRESS_4) + is31fl3741_init(IS31FL3741_I2C_ADDRESS_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3741_LED_COUNT; i++) { + is31fl3741_set_led_control_register(i, true); + } + + is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_1, 0); +#if defined(IS31FL3741_I2C_ADDRESS_2) + is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_2, 1); +# if defined(IS31FL3741_I2C_ADDRESS_3) + is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_3, 2); +# if defined(IS31FL3741_I2C_ADDRESS_4) + is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3741_init(uint8_t addr) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + // Unlock the command register. + + is31fl3741_select_page(addr, IS31FL3741_COMMAND_FUNCTION); + + // Set to Normal operation + is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_CONFIGURATION, IS31FL3741_CONFIGURATION); + + // Set Golbal Current Control Register + is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3741_GLOBAL_CURRENT); + // Set Pull up & Down for SWx CSy + is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_PULLDOWNUP, ((IS31FL3741_CS_PULLDOWN << 4) | IS31FL3741_SW_PULLUP)); + // Set PWM frequency + is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_PWM_FREQUENCY, (IS31FL3741_PWM_FREQUENCY & 0b1111)); + + // is31fl3741_update_led_scaling_registers(addr, 0xFF, 0xFF, 0xFF); + + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void is31fl3741_set_value(int index, uint8_t value) { + is31fl3741_led_t led; + if (index >= 0 && index < IS31FL3741_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3741_leds[index]), sizeof(led)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + g_pwm_buffer_update_required[led.driver] = true; + g_pwm_buffer[led.driver][led.v] = value; + } +} + +void is31fl3741_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3741_LED_COUNT; i++) { + is31fl3741_set_value(i, value); + } +} + +void is31fl3741_set_led_control_register(uint8_t index, bool value) { + is31fl3741_led_t led; + memcpy_P(&led, (&g_is31fl3741_leds[index]), sizeof(led)); + + if (value) { + g_scaling_registers[led.driver][led.v] = 0xFF; + } else { + g_scaling_registers[led.driver][led.v] = 0x00; + } + + g_scaling_registers_update_required[led.driver] = true; +} + +void is31fl3741_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3741_select_page(addr, IS31FL3741_COMMAND_PWM_0); + + is31fl3741_write_pwm_buffer(addr, g_pwm_buffer[index]); + } + + g_pwm_buffer_update_required[index] = false; +} + +void is31fl3741_set_pwm_buffer(const is31fl3741_led_t *pled, uint8_t value) { + g_pwm_buffer[pled->driver][pled->v] = value; + + g_pwm_buffer_update_required[pled->driver] = true; +} + +void is31fl3741_update_led_control_registers(uint8_t addr, uint8_t index) { + if (g_scaling_registers_update_required[index]) { + is31fl3741_select_page(addr, IS31FL3741_COMMAND_SCALING_0); + + // CS1_SW1 to CS30_SW6 are on page 2 + for (int i = CS1_SW1; i <= CS30_SW6; ++i) { + is31fl3741_write_register(addr, i, g_scaling_registers[index][i]); + } + + is31fl3741_select_page(addr, IS31FL3741_COMMAND_SCALING_1); + + // CS1_SW7 to CS39_SW9 are on page 3 + for (int i = CS1_SW7; i <= CS39_SW9; ++i) { + is31fl3741_write_register(addr, i - CS1_SW7, g_scaling_registers[index][i]); + } + + g_scaling_registers_update_required[index] = false; + } +} + +void is31fl3741_set_scaling_registers(const is31fl3741_led_t *pled, uint8_t value) { + g_scaling_registers[pled->driver][pled->v] = value; + + g_scaling_registers_update_required[pled->driver] = true; +} + +void is31fl3741_flush(void) { + is31fl3741_update_pwm_buffers(IS31FL3741_I2C_ADDRESS_1, 0); +#if defined(IS31FL3741_I2C_ADDRESS_2) + is31fl3741_update_pwm_buffers(IS31FL3741_I2C_ADDRESS_2, 1); +# if defined(IS31FL3741_I2C_ADDRESS_3) + is31fl3741_update_pwm_buffers(IS31FL3741_I2C_ADDRESS_3, 2); +# if defined(IS31FL3741_I2C_ADDRESS_4) + is31fl3741_update_pwm_buffers(IS31FL3741_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3741-mono.h b/drivers/led/issi/is31fl3741-mono.h new file mode 100644 index 0000000000..462543a5bb --- /dev/null +++ b/drivers/led/issi/is31fl3741-mono.h @@ -0,0 +1,517 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2020 MelGeek + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +// ======== DEPRECATED DEFINES - DO NOT USE ======== +#ifdef ISSI_TIMEOUT +# define IS31FL3741_I2C_TIMEOUT ISSI_TIMEOUT +#endif +#ifdef ISSI_PERSISTENCE +# define IS31FL3741_I2C_PERSISTENCE ISSI_PERSISTENCE +#endif +#ifdef ISSI_CONFIGURATION +# define IS31FL3741_CONFIGURATION ISSI_CONFIGURATION +#endif +#ifdef ISSI_SWPULLUP +# define IS31FL3741_SW_PULLUP ISSI_SWPULLUP +#endif +#ifdef ISSI_CSPULLUP +# define IS31FL3741_CS_PULLDOWN ISSI_CSPULLUP +#endif +#ifdef ISSI_GLOBALCURRENT +# define IS31FL3741_GLOBAL_CURRENT ISSI_GLOBALCURRENT +#endif + +#define PUR_0R IS31FL3741_PUR_0_OHM +#define PUR_05KR IS31FL3741_PUR_0K5_OHM +#define PUR_1KR IS31FL3741_PUR_1K_OHM +#define PUR_2KR IS31FL3741_PUR_2K_OHM +#define PUR_4KR IS31FL3741_PUR_4K_OHM +#define PUR_8KR IS31FL3741_PUR_8K_OHM +#define PUR_16KR IS31FL3741_PUR_16K_OHM +#define PUR_32KR IS31FL3741_PUR_32K_OHM +// ======== + +#define IS31FL3741_REG_INTERRUPT_MASK 0xF0 +#define IS31FL3741_REG_INTERRUPT_STATUS 0xF1 +#define IS31FL3741_REG_ID 0xFC + +#define IS31FL3741_REG_COMMAND 0xFD + +#define IS31FL3741_COMMAND_PWM_0 0x00 +#define IS31FL3741_COMMAND_PWM_1 0x01 +#define IS31FL3741_COMMAND_SCALING_0 0x02 +#define IS31FL3741_COMMAND_SCALING_1 0x03 +#define IS31FL3741_COMMAND_FUNCTION 0x04 + +#define IS31FL3741_FUNCTION_REG_CONFIGURATION 0x00 +#define IS31FL3741_FUNCTION_REG_GLOBAL_CURRENT 0x01 +#define IS31FL3741_FUNCTION_REG_PULLDOWNUP 0x02 +#define IS31FL3741_FUNCTION_REG_PWM_FREQUENCY 0x36 +#define IS31FL3741_FUNCTION_REG_RESET 0x3F + +#define IS31FL3741_REG_COMMAND_WRITE_LOCK 0xFE +#define IS31FL3741_COMMAND_WRITE_LOCK_MAGIC 0xC5 + +#define IS31FL3741_I2C_ADDRESS_GND 0x30 +#define IS31FL3741_I2C_ADDRESS_SCL 0x31 +#define IS31FL3741_I2C_ADDRESS_SDA 0x32 +#define IS31FL3741_I2C_ADDRESS_VCC 0x33 + +#if defined(LED_MATRIX_IS31FL3741) +# define IS31FL3741_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined(IS31FL3741_I2C_ADDRESS_4) +# define IS31FL3741_DRIVER_COUNT 4 +#elif defined(IS31FL3741_I2C_ADDRESS_3) +# define IS31FL3741_DRIVER_COUNT 3 +#elif defined(IS31FL3741_I2C_ADDRESS_2) +# define IS31FL3741_DRIVER_COUNT 2 +#elif defined(IS31FL3741_I2C_ADDRESS_1) +# define IS31FL3741_DRIVER_COUNT 1 +#endif + +typedef struct is31fl3741_led_t { + uint8_t driver : 2; + uint16_t v : 9; +} PACKED is31fl3741_led_t; + +extern const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT]; + +void is31fl3741_init_drivers(void); +void is31fl3741_init(uint8_t addr); +void is31fl3741_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3741_select_page(uint8_t addr, uint8_t page); +bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3741_set_value(int index, uint8_t value); +void is31fl3741_set_value_all(uint8_t value); + +void is31fl3741_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 is31fl3741_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3741_update_led_control_registers(uint8_t addr, uint8_t index); +void is31fl3741_set_scaling_registers(const is31fl3741_led_t *pled, uint8_t value); + +void is31fl3741_set_pwm_buffer(const is31fl3741_led *pled, uint8_t value); + +void is31fl3741_flush(void); + +#define IS31FL3741_PDR_0_OHM 0b000 // No pull-down resistor +#define IS31FL3741_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3741_PDR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3741_PDR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3741_PDR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3741_PDR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3741_PDR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3741_PDR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3741_PUR_0_OHM 0b000 // No pull-up resistor +#define IS31FL3741_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3741_PUR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3741_PUR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3741_PUR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3741_PUR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3741_PUR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3741_PUR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3741_PWM_FREQUENCY_29K_HZ 0b0000 +#define IS31FL3741_PWM_FREQUENCY_3K6_HZ 0b0011 +#define IS31FL3741_PWM_FREQUENCY_1K8_HZ 0b0111 +#define IS31FL3741_PWM_FREQUENCY_900_HZ 0b1011 + +#define CS1_SW1 0x00 +#define CS2_SW1 0x01 +#define CS3_SW1 0x02 +#define CS4_SW1 0x03 +#define CS5_SW1 0x04 +#define CS6_SW1 0x05 +#define CS7_SW1 0x06 +#define CS8_SW1 0x07 +#define CS9_SW1 0x08 +#define CS10_SW1 0x09 +#define CS11_SW1 0x0A +#define CS12_SW1 0x0B +#define CS13_SW1 0x0C +#define CS14_SW1 0x0D +#define CS15_SW1 0x0E +#define CS16_SW1 0x0F +#define CS17_SW1 0x10 +#define CS18_SW1 0x11 +#define CS19_SW1 0x12 +#define CS20_SW1 0x13 +#define CS21_SW1 0x14 +#define CS22_SW1 0x15 +#define CS23_SW1 0x16 +#define CS24_SW1 0x17 +#define CS25_SW1 0x18 +#define CS26_SW1 0x19 +#define CS27_SW1 0x1A +#define CS28_SW1 0x1B +#define CS29_SW1 0x1C +#define CS30_SW1 0x1D + +#define CS1_SW2 0x1E +#define CS2_SW2 0x1F +#define CS3_SW2 0x20 +#define CS4_SW2 0x21 +#define CS5_SW2 0x22 +#define CS6_SW2 0x23 +#define CS7_SW2 0x24 +#define CS8_SW2 0x25 +#define CS9_SW2 0x26 +#define CS10_SW2 0x27 +#define CS11_SW2 0x28 +#define CS12_SW2 0x29 +#define CS13_SW2 0x2A +#define CS14_SW2 0x2B +#define CS15_SW2 0x2C +#define CS16_SW2 0x2D +#define CS17_SW2 0x2E +#define CS18_SW2 0x2F +#define CS19_SW2 0x30 +#define CS20_SW2 0x31 +#define CS21_SW2 0x32 +#define CS22_SW2 0x33 +#define CS23_SW2 0x34 +#define CS24_SW2 0x35 +#define CS25_SW2 0x36 +#define CS26_SW2 0x37 +#define CS27_SW2 0x38 +#define CS28_SW2 0x39 +#define CS29_SW2 0x3A +#define CS30_SW2 0x3B + +#define CS1_SW3 0x3C +#define CS2_SW3 0x3D +#define CS3_SW3 0x3E +#define CS4_SW3 0x3F +#define CS5_SW3 0x40 +#define CS6_SW3 0x41 +#define CS7_SW3 0x42 +#define CS8_SW3 0x43 +#define CS9_SW3 0x44 +#define CS10_SW3 0x45 +#define CS11_SW3 0x46 +#define CS12_SW3 0x47 +#define CS13_SW3 0x48 +#define CS14_SW3 0x49 +#define CS15_SW3 0x4A +#define CS16_SW3 0x4B +#define CS17_SW3 0x4C +#define CS18_SW3 0x4D +#define CS19_SW3 0x4E +#define CS20_SW3 0x4F +#define CS21_SW3 0x50 +#define CS22_SW3 0x51 +#define CS23_SW3 0x52 +#define CS24_SW3 0x53 +#define CS25_SW3 0x54 +#define CS26_SW3 0x55 +#define CS27_SW3 0x56 +#define CS28_SW3 0x57 +#define CS29_SW3 0x58 +#define CS30_SW3 0x59 + +#define CS1_SW4 0x5A +#define CS2_SW4 0x5B +#define CS3_SW4 0x5C +#define CS4_SW4 0x5D +#define CS5_SW4 0x5E +#define CS6_SW4 0x5F +#define CS7_SW4 0x60 +#define CS8_SW4 0x61 +#define CS9_SW4 0x62 +#define CS10_SW4 0x63 +#define CS11_SW4 0x64 +#define CS12_SW4 0x65 +#define CS13_SW4 0x66 +#define CS14_SW4 0x67 +#define CS15_SW4 0x68 +#define CS16_SW4 0x69 +#define CS17_SW4 0x6A +#define CS18_SW4 0x6B +#define CS19_SW4 0x6C +#define CS20_SW4 0x6D +#define CS21_SW4 0x6E +#define CS22_SW4 0x6F +#define CS23_SW4 0x70 +#define CS24_SW4 0x71 +#define CS25_SW4 0x72 +#define CS26_SW4 0x73 +#define CS27_SW4 0x74 +#define CS28_SW4 0x75 +#define CS29_SW4 0x76 +#define CS30_SW4 0x77 + +#define CS1_SW5 0x78 +#define CS2_SW5 0x79 +#define CS3_SW5 0x7A +#define CS4_SW5 0x7B +#define CS5_SW5 0x7C +#define CS6_SW5 0x7D +#define CS7_SW5 0x7E +#define CS8_SW5 0x7F +#define CS9_SW5 0x80 +#define CS10_SW5 0x81 +#define CS11_SW5 0x82 +#define CS12_SW5 0x83 +#define CS13_SW5 0x84 +#define CS14_SW5 0x85 +#define CS15_SW5 0x86 +#define CS16_SW5 0x87 +#define CS17_SW5 0x88 +#define CS18_SW5 0x89 +#define CS19_SW5 0x8A +#define CS20_SW5 0x8B +#define CS21_SW5 0x8C +#define CS22_SW5 0x8D +#define CS23_SW5 0x8E +#define CS24_SW5 0x8F +#define CS25_SW5 0x90 +#define CS26_SW5 0x91 +#define CS27_SW5 0x92 +#define CS28_SW5 0x93 +#define CS29_SW5 0x94 +#define CS30_SW5 0x95 + +#define CS1_SW6 0x96 +#define CS2_SW6 0x97 +#define CS3_SW6 0x98 +#define CS4_SW6 0x99 +#define CS5_SW6 0x9A +#define CS6_SW6 0x9B +#define CS7_SW6 0x9C +#define CS8_SW6 0x9D +#define CS9_SW6 0x9E +#define CS10_SW6 0x9F +#define CS11_SW6 0xA0 +#define CS12_SW6 0xA1 +#define CS13_SW6 0xA2 +#define CS14_SW6 0xA3 +#define CS15_SW6 0xA4 +#define CS16_SW6 0xA5 +#define CS17_SW6 0xA6 +#define CS18_SW6 0xA7 +#define CS19_SW6 0xA8 +#define CS20_SW6 0xA9 +#define CS21_SW6 0xAA +#define CS22_SW6 0xAB +#define CS23_SW6 0xAC +#define CS24_SW6 0xAD +#define CS25_SW6 0xAE +#define CS26_SW6 0xAF +#define CS27_SW6 0xB0 +#define CS28_SW6 0xB1 +#define CS29_SW6 0xB2 +#define CS30_SW6 0xB3 + +#define CS1_SW7 0xB4 +#define CS2_SW7 0xB5 +#define CS3_SW7 0xB6 +#define CS4_SW7 0xB7 +#define CS5_SW7 0xB8 +#define CS6_SW7 0xB9 +#define CS7_SW7 0xBA +#define CS8_SW7 0xBB +#define CS9_SW7 0xBC +#define CS10_SW7 0xBD +#define CS11_SW7 0xBE +#define CS12_SW7 0xBF +#define CS13_SW7 0xC0 +#define CS14_SW7 0xC1 +#define CS15_SW7 0xC2 +#define CS16_SW7 0xC3 +#define CS17_SW7 0xC4 +#define CS18_SW7 0xC5 +#define CS19_SW7 0xC6 +#define CS20_SW7 0xC7 +#define CS21_SW7 0xC8 +#define CS22_SW7 0xC9 +#define CS23_SW7 0xCA +#define CS24_SW7 0xCB +#define CS25_SW7 0xCC +#define CS26_SW7 0xCD +#define CS27_SW7 0xCE +#define CS28_SW7 0xCF +#define CS29_SW7 0xD0 +#define CS30_SW7 0xD1 + +#define CS1_SW8 0xD2 +#define CS2_SW8 0xD3 +#define CS3_SW8 0xD4 +#define CS4_SW8 0xD5 +#define CS5_SW8 0xD6 +#define CS6_SW8 0xD7 +#define CS7_SW8 0xD8 +#define CS8_SW8 0xD9 +#define CS9_SW8 0xDA +#define CS10_SW8 0xDB +#define CS11_SW8 0xDC +#define CS12_SW8 0xDD +#define CS13_SW8 0xDE +#define CS14_SW8 0xDF +#define CS15_SW8 0xE0 +#define CS16_SW8 0xE1 +#define CS17_SW8 0xE2 +#define CS18_SW8 0xE3 +#define CS19_SW8 0xE4 +#define CS20_SW8 0xE5 +#define CS21_SW8 0xE6 +#define CS22_SW8 0xE7 +#define CS23_SW8 0xE8 +#define CS24_SW8 0xE9 +#define CS25_SW8 0xEA +#define CS26_SW8 0xEB +#define CS27_SW8 0xEC +#define CS28_SW8 0xED +#define CS29_SW8 0xEE +#define CS30_SW8 0xEF + +#define CS1_SW9 0xF0 +#define CS2_SW9 0xF1 +#define CS3_SW9 0xF2 +#define CS4_SW9 0xF3 +#define CS5_SW9 0xF4 +#define CS6_SW9 0xF5 +#define CS7_SW9 0xF6 +#define CS8_SW9 0xF7 +#define CS9_SW9 0xF8 +#define CS10_SW9 0xF9 +#define CS11_SW9 0xFA +#define CS12_SW9 0xFB +#define CS13_SW9 0xFC +#define CS14_SW9 0xFD +#define CS15_SW9 0xFE +#define CS16_SW9 0xFF +#define CS17_SW9 0x100 +#define CS18_SW9 0x101 +#define CS19_SW9 0x102 +#define CS20_SW9 0x103 +#define CS21_SW9 0x104 +#define CS22_SW9 0x105 +#define CS23_SW9 0x106 +#define CS24_SW9 0x107 +#define CS25_SW9 0x108 +#define CS26_SW9 0x109 +#define CS27_SW9 0x10A +#define CS28_SW9 0x10B +#define CS29_SW9 0x10C +#define CS30_SW9 0x10D + +#define CS31_SW1 0x10E +#define CS32_SW1 0x10F +#define CS33_SW1 0x110 +#define CS34_SW1 0x111 +#define CS35_SW1 0x112 +#define CS36_SW1 0x113 +#define CS37_SW1 0x114 +#define CS38_SW1 0x115 +#define CS39_SW1 0x116 + +#define CS31_SW2 0x117 +#define CS32_SW2 0x118 +#define CS33_SW2 0x119 +#define CS34_SW2 0x11A +#define CS35_SW2 0x11B +#define CS36_SW2 0x11C +#define CS37_SW2 0x11D +#define CS38_SW2 0x11E +#define CS39_SW2 0x11F + +#define CS31_SW3 0x120 +#define CS32_SW3 0x121 +#define CS33_SW3 0x122 +#define CS34_SW3 0x123 +#define CS35_SW3 0x124 +#define CS36_SW3 0x125 +#define CS37_SW3 0x126 +#define CS38_SW3 0x127 +#define CS39_SW3 0x128 + +#define CS31_SW4 0x129 +#define CS32_SW4 0x12A +#define CS33_SW4 0x12B +#define CS34_SW4 0x12C +#define CS35_SW4 0x12D +#define CS36_SW4 0x12E +#define CS37_SW4 0x12F +#define CS38_SW4 0x130 +#define CS39_SW4 0x131 + +#define CS31_SW5 0x132 +#define CS32_SW5 0x133 +#define CS33_SW5 0x134 +#define CS34_SW5 0x135 +#define CS35_SW5 0x136 +#define CS36_SW5 0x137 +#define CS37_SW5 0x138 +#define CS38_SW5 0x139 +#define CS39_SW5 0x13A + +#define CS31_SW6 0x13B +#define CS32_SW6 0x13C +#define CS33_SW6 0x13D +#define CS34_SW6 0x13E +#define CS35_SW6 0x13F +#define CS36_SW6 0x140 +#define CS37_SW6 0x141 +#define CS38_SW6 0x142 +#define CS39_SW6 0x143 + +#define CS31_SW7 0x144 +#define CS32_SW7 0x145 +#define CS33_SW7 0x146 +#define CS34_SW7 0x147 +#define CS35_SW7 0x148 +#define CS36_SW7 0x149 +#define CS37_SW7 0x14A +#define CS38_SW7 0x14B +#define CS39_SW7 0x14C + +#define CS31_SW8 0x14D +#define CS32_SW8 0x14E +#define CS33_SW8 0x14F +#define CS34_SW8 0x150 +#define CS35_SW8 0x151 +#define CS36_SW8 0x152 +#define CS37_SW8 0x153 +#define CS38_SW8 0x154 +#define CS39_SW8 0x155 + +#define CS31_SW9 0x156 +#define CS32_SW9 0x157 +#define CS33_SW9 0x158 +#define CS34_SW9 0x159 +#define CS35_SW9 0x15A +#define CS36_SW9 0x15B +#define CS37_SW9 0x15C +#define CS38_SW9 0x15D +#define CS39_SW9 0x15E diff --git a/drivers/led/issi/is31fl3741-simple.c b/drivers/led/issi/is31fl3741-simple.c deleted file mode 100644 index 3e9b3d8b25..0000000000 --- a/drivers/led/issi/is31fl3741-simple.c +++ /dev/null @@ -1,271 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2020 MelGeek - * - * 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 . - */ - -#include "is31fl3741-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3741_PWM_REGISTER_COUNT 351 -#define IS31FL3741_SCALING_REGISTER_COUNT 351 - -#ifndef IS31FL3741_I2C_TIMEOUT -# define IS31FL3741_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3741_I2C_PERSISTENCE -# define IS31FL3741_I2C_PERSISTENCE 0 -#endif - -#ifndef IS31FL3741_CONFIGURATION -# define IS31FL3741_CONFIGURATION 0x01 -#endif - -#ifndef IS31FL3741_PWM_FREQUENCY -# define IS31FL3741_PWM_FREQUENCY IS31FL3741_PWM_FREQUENCY_29K_HZ -#endif - -#ifndef IS31FL3741_SW_PULLUP -# define IS31FL3741_SW_PULLUP IS31FL3741_PUR_32K_OHM -#endif - -#ifndef IS31FL3741_CS_PULLDOWN -# define IS31FL3741_CS_PULLDOWN IS31FL3741_PDR_32K_OHM -#endif - -#ifndef IS31FL3741_GLOBAL_CURRENT -# define IS31FL3741_GLOBAL_CURRENT 0xFF -#endif - -uint8_t i2c_transfer_buffer[20] = {0xFF}; - -// These buffers match the IS31FL3741 and IS31FL3741A PWM registers. -// The scaling buffers match the page 2 and 3 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 is31fl3741_write_pwm_buffer() but it's -// probably not worth the extra complexity. -uint8_t g_pwm_buffer[IS31FL3741_DRIVER_COUNT][IS31FL3741_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3741_DRIVER_COUNT] = {false}; -bool g_scaling_registers_update_required[IS31FL3741_DRIVER_COUNT] = {false}; - -uint8_t g_scaling_registers[IS31FL3741_DRIVER_COUNT][IS31FL3741_SCALING_REGISTER_COUNT]; - -void is31fl3741_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3741_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3741_I2C_TIMEOUT); -#endif -} - -void is31fl3741_select_page(uint8_t addr, uint8_t page) { - is31fl3741_write_register(addr, IS31FL3741_REG_COMMAND_WRITE_LOCK, IS31FL3741_COMMAND_WRITE_LOCK_MAGIC); - is31fl3741_write_register(addr, IS31FL3741_REG_COMMAND, page); -} - -bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // Assume page 0 is already selected - - for (int i = 0; i < 342; i += 18) { - if (i == 180) { - is31fl3741_select_page(addr, IS31FL3741_COMMAND_PWM_1); - } - - i2c_transfer_buffer[0] = i % 180; - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 18); - -#if IS31FL3741_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) { - return false; - } - } -#else - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 19, IS31FL3741_I2C_TIMEOUT) != 0) { - return false; - } -#endif - } - - // transfer the left cause the total number is 351 - i2c_transfer_buffer[0] = 162; - memcpy(i2c_transfer_buffer + 1, pwm_buffer + 342, 9); - -#if IS31FL3741_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) { - return false; - } - } -#else - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 10, IS31FL3741_I2C_TIMEOUT) != 0) { - return false; - } -#endif - - return true; -} - -void is31fl3741_init_drivers(void) { - i2c_init(); - - is31fl3741_init(IS31FL3741_I2C_ADDRESS_1); -#if defined(IS31FL3741_I2C_ADDRESS_2) - is31fl3741_init(IS31FL3741_I2C_ADDRESS_2); -# if defined(IS31FL3741_I2C_ADDRESS_3) - is31fl3741_init(IS31FL3741_I2C_ADDRESS_3); -# if defined(IS31FL3741_I2C_ADDRESS_4) - is31fl3741_init(IS31FL3741_I2C_ADDRESS_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3741_LED_COUNT; i++) { - is31fl3741_set_led_control_register(i, true); - } - - is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_1, 0); -#if defined(IS31FL3741_I2C_ADDRESS_2) - is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_2, 1); -# if defined(IS31FL3741_I2C_ADDRESS_3) - is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_3, 2); -# if defined(IS31FL3741_I2C_ADDRESS_4) - is31fl3741_update_led_control_registers(IS31FL3741_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3741_init(uint8_t addr) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, shutdown is enabled last. - // Set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - // Unlock the command register. - - is31fl3741_select_page(addr, IS31FL3741_COMMAND_FUNCTION); - - // Set to Normal operation - is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_CONFIGURATION, IS31FL3741_CONFIGURATION); - - // Set Golbal Current Control Register - is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3741_GLOBAL_CURRENT); - // Set Pull up & Down for SWx CSy - is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_PULLDOWNUP, ((IS31FL3741_CS_PULLDOWN << 4) | IS31FL3741_SW_PULLUP)); - // Set PWM frequency - is31fl3741_write_register(addr, IS31FL3741_FUNCTION_REG_PWM_FREQUENCY, (IS31FL3741_PWM_FREQUENCY & 0b1111)); - - // is31fl3741_update_led_scaling_registers(addr, 0xFF, 0xFF, 0xFF); - - // Wait 10ms to ensure the device has woken up. - wait_ms(10); -} - -void is31fl3741_set_value(int index, uint8_t value) { - is31fl3741_led_t led; - if (index >= 0 && index < IS31FL3741_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3741_leds[index]), sizeof(led)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - g_pwm_buffer_update_required[led.driver] = true; - g_pwm_buffer[led.driver][led.v] = value; - } -} - -void is31fl3741_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3741_LED_COUNT; i++) { - is31fl3741_set_value(i, value); - } -} - -void is31fl3741_set_led_control_register(uint8_t index, bool value) { - is31fl3741_led_t led; - memcpy_P(&led, (&g_is31fl3741_leds[index]), sizeof(led)); - - if (value) { - g_scaling_registers[led.driver][led.v] = 0xFF; - } else { - g_scaling_registers[led.driver][led.v] = 0x00; - } - - g_scaling_registers_update_required[led.driver] = true; -} - -void is31fl3741_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3741_select_page(addr, IS31FL3741_COMMAND_PWM_0); - - is31fl3741_write_pwm_buffer(addr, g_pwm_buffer[index]); - } - - g_pwm_buffer_update_required[index] = false; -} - -void is31fl3741_set_pwm_buffer(const is31fl3741_led_t *pled, uint8_t value) { - g_pwm_buffer[pled->driver][pled->v] = value; - - g_pwm_buffer_update_required[pled->driver] = true; -} - -void is31fl3741_update_led_control_registers(uint8_t addr, uint8_t index) { - if (g_scaling_registers_update_required[index]) { - is31fl3741_select_page(addr, IS31FL3741_COMMAND_SCALING_0); - - // CS1_SW1 to CS30_SW6 are on page 2 - for (int i = CS1_SW1; i <= CS30_SW6; ++i) { - is31fl3741_write_register(addr, i, g_scaling_registers[index][i]); - } - - is31fl3741_select_page(addr, IS31FL3741_COMMAND_SCALING_1); - - // CS1_SW7 to CS39_SW9 are on page 3 - for (int i = CS1_SW7; i <= CS39_SW9; ++i) { - is31fl3741_write_register(addr, i - CS1_SW7, g_scaling_registers[index][i]); - } - - g_scaling_registers_update_required[index] = false; - } -} - -void is31fl3741_set_scaling_registers(const is31fl3741_led_t *pled, uint8_t value) { - g_scaling_registers[pled->driver][pled->v] = value; - - g_scaling_registers_update_required[pled->driver] = true; -} - -void is31fl3741_flush(void) { - is31fl3741_update_pwm_buffers(IS31FL3741_I2C_ADDRESS_1, 0); -#if defined(IS31FL3741_I2C_ADDRESS_2) - is31fl3741_update_pwm_buffers(IS31FL3741_I2C_ADDRESS_2, 1); -# if defined(IS31FL3741_I2C_ADDRESS_3) - is31fl3741_update_pwm_buffers(IS31FL3741_I2C_ADDRESS_3, 2); -# if defined(IS31FL3741_I2C_ADDRESS_4) - is31fl3741_update_pwm_buffers(IS31FL3741_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3741-simple.h b/drivers/led/issi/is31fl3741-simple.h deleted file mode 100644 index 462543a5bb..0000000000 --- a/drivers/led/issi/is31fl3741-simple.h +++ /dev/null @@ -1,517 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2020 MelGeek - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -// ======== DEPRECATED DEFINES - DO NOT USE ======== -#ifdef ISSI_TIMEOUT -# define IS31FL3741_I2C_TIMEOUT ISSI_TIMEOUT -#endif -#ifdef ISSI_PERSISTENCE -# define IS31FL3741_I2C_PERSISTENCE ISSI_PERSISTENCE -#endif -#ifdef ISSI_CONFIGURATION -# define IS31FL3741_CONFIGURATION ISSI_CONFIGURATION -#endif -#ifdef ISSI_SWPULLUP -# define IS31FL3741_SW_PULLUP ISSI_SWPULLUP -#endif -#ifdef ISSI_CSPULLUP -# define IS31FL3741_CS_PULLDOWN ISSI_CSPULLUP -#endif -#ifdef ISSI_GLOBALCURRENT -# define IS31FL3741_GLOBAL_CURRENT ISSI_GLOBALCURRENT -#endif - -#define PUR_0R IS31FL3741_PUR_0_OHM -#define PUR_05KR IS31FL3741_PUR_0K5_OHM -#define PUR_1KR IS31FL3741_PUR_1K_OHM -#define PUR_2KR IS31FL3741_PUR_2K_OHM -#define PUR_4KR IS31FL3741_PUR_4K_OHM -#define PUR_8KR IS31FL3741_PUR_8K_OHM -#define PUR_16KR IS31FL3741_PUR_16K_OHM -#define PUR_32KR IS31FL3741_PUR_32K_OHM -// ======== - -#define IS31FL3741_REG_INTERRUPT_MASK 0xF0 -#define IS31FL3741_REG_INTERRUPT_STATUS 0xF1 -#define IS31FL3741_REG_ID 0xFC - -#define IS31FL3741_REG_COMMAND 0xFD - -#define IS31FL3741_COMMAND_PWM_0 0x00 -#define IS31FL3741_COMMAND_PWM_1 0x01 -#define IS31FL3741_COMMAND_SCALING_0 0x02 -#define IS31FL3741_COMMAND_SCALING_1 0x03 -#define IS31FL3741_COMMAND_FUNCTION 0x04 - -#define IS31FL3741_FUNCTION_REG_CONFIGURATION 0x00 -#define IS31FL3741_FUNCTION_REG_GLOBAL_CURRENT 0x01 -#define IS31FL3741_FUNCTION_REG_PULLDOWNUP 0x02 -#define IS31FL3741_FUNCTION_REG_PWM_FREQUENCY 0x36 -#define IS31FL3741_FUNCTION_REG_RESET 0x3F - -#define IS31FL3741_REG_COMMAND_WRITE_LOCK 0xFE -#define IS31FL3741_COMMAND_WRITE_LOCK_MAGIC 0xC5 - -#define IS31FL3741_I2C_ADDRESS_GND 0x30 -#define IS31FL3741_I2C_ADDRESS_SCL 0x31 -#define IS31FL3741_I2C_ADDRESS_SDA 0x32 -#define IS31FL3741_I2C_ADDRESS_VCC 0x33 - -#if defined(LED_MATRIX_IS31FL3741) -# define IS31FL3741_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined(IS31FL3741_I2C_ADDRESS_4) -# define IS31FL3741_DRIVER_COUNT 4 -#elif defined(IS31FL3741_I2C_ADDRESS_3) -# define IS31FL3741_DRIVER_COUNT 3 -#elif defined(IS31FL3741_I2C_ADDRESS_2) -# define IS31FL3741_DRIVER_COUNT 2 -#elif defined(IS31FL3741_I2C_ADDRESS_1) -# define IS31FL3741_DRIVER_COUNT 1 -#endif - -typedef struct is31fl3741_led_t { - uint8_t driver : 2; - uint16_t v : 9; -} PACKED is31fl3741_led_t; - -extern const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT]; - -void is31fl3741_init_drivers(void); -void is31fl3741_init(uint8_t addr); -void is31fl3741_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3741_select_page(uint8_t addr, uint8_t page); -bool is31fl3741_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3741_set_value(int index, uint8_t value); -void is31fl3741_set_value_all(uint8_t value); - -void is31fl3741_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 is31fl3741_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3741_update_led_control_registers(uint8_t addr, uint8_t index); -void is31fl3741_set_scaling_registers(const is31fl3741_led_t *pled, uint8_t value); - -void is31fl3741_set_pwm_buffer(const is31fl3741_led *pled, uint8_t value); - -void is31fl3741_flush(void); - -#define IS31FL3741_PDR_0_OHM 0b000 // No pull-down resistor -#define IS31FL3741_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3741_PDR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3741_PDR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3741_PDR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3741_PDR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3741_PDR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3741_PDR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3741_PUR_0_OHM 0b000 // No pull-up resistor -#define IS31FL3741_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3741_PUR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3741_PUR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3741_PUR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3741_PUR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3741_PUR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3741_PUR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3741_PWM_FREQUENCY_29K_HZ 0b0000 -#define IS31FL3741_PWM_FREQUENCY_3K6_HZ 0b0011 -#define IS31FL3741_PWM_FREQUENCY_1K8_HZ 0b0111 -#define IS31FL3741_PWM_FREQUENCY_900_HZ 0b1011 - -#define CS1_SW1 0x00 -#define CS2_SW1 0x01 -#define CS3_SW1 0x02 -#define CS4_SW1 0x03 -#define CS5_SW1 0x04 -#define CS6_SW1 0x05 -#define CS7_SW1 0x06 -#define CS8_SW1 0x07 -#define CS9_SW1 0x08 -#define CS10_SW1 0x09 -#define CS11_SW1 0x0A -#define CS12_SW1 0x0B -#define CS13_SW1 0x0C -#define CS14_SW1 0x0D -#define CS15_SW1 0x0E -#define CS16_SW1 0x0F -#define CS17_SW1 0x10 -#define CS18_SW1 0x11 -#define CS19_SW1 0x12 -#define CS20_SW1 0x13 -#define CS21_SW1 0x14 -#define CS22_SW1 0x15 -#define CS23_SW1 0x16 -#define CS24_SW1 0x17 -#define CS25_SW1 0x18 -#define CS26_SW1 0x19 -#define CS27_SW1 0x1A -#define CS28_SW1 0x1B -#define CS29_SW1 0x1C -#define CS30_SW1 0x1D - -#define CS1_SW2 0x1E -#define CS2_SW2 0x1F -#define CS3_SW2 0x20 -#define CS4_SW2 0x21 -#define CS5_SW2 0x22 -#define CS6_SW2 0x23 -#define CS7_SW2 0x24 -#define CS8_SW2 0x25 -#define CS9_SW2 0x26 -#define CS10_SW2 0x27 -#define CS11_SW2 0x28 -#define CS12_SW2 0x29 -#define CS13_SW2 0x2A -#define CS14_SW2 0x2B -#define CS15_SW2 0x2C -#define CS16_SW2 0x2D -#define CS17_SW2 0x2E -#define CS18_SW2 0x2F -#define CS19_SW2 0x30 -#define CS20_SW2 0x31 -#define CS21_SW2 0x32 -#define CS22_SW2 0x33 -#define CS23_SW2 0x34 -#define CS24_SW2 0x35 -#define CS25_SW2 0x36 -#define CS26_SW2 0x37 -#define CS27_SW2 0x38 -#define CS28_SW2 0x39 -#define CS29_SW2 0x3A -#define CS30_SW2 0x3B - -#define CS1_SW3 0x3C -#define CS2_SW3 0x3D -#define CS3_SW3 0x3E -#define CS4_SW3 0x3F -#define CS5_SW3 0x40 -#define CS6_SW3 0x41 -#define CS7_SW3 0x42 -#define CS8_SW3 0x43 -#define CS9_SW3 0x44 -#define CS10_SW3 0x45 -#define CS11_SW3 0x46 -#define CS12_SW3 0x47 -#define CS13_SW3 0x48 -#define CS14_SW3 0x49 -#define CS15_SW3 0x4A -#define CS16_SW3 0x4B -#define CS17_SW3 0x4C -#define CS18_SW3 0x4D -#define CS19_SW3 0x4E -#define CS20_SW3 0x4F -#define CS21_SW3 0x50 -#define CS22_SW3 0x51 -#define CS23_SW3 0x52 -#define CS24_SW3 0x53 -#define CS25_SW3 0x54 -#define CS26_SW3 0x55 -#define CS27_SW3 0x56 -#define CS28_SW3 0x57 -#define CS29_SW3 0x58 -#define CS30_SW3 0x59 - -#define CS1_SW4 0x5A -#define CS2_SW4 0x5B -#define CS3_SW4 0x5C -#define CS4_SW4 0x5D -#define CS5_SW4 0x5E -#define CS6_SW4 0x5F -#define CS7_SW4 0x60 -#define CS8_SW4 0x61 -#define CS9_SW4 0x62 -#define CS10_SW4 0x63 -#define CS11_SW4 0x64 -#define CS12_SW4 0x65 -#define CS13_SW4 0x66 -#define CS14_SW4 0x67 -#define CS15_SW4 0x68 -#define CS16_SW4 0x69 -#define CS17_SW4 0x6A -#define CS18_SW4 0x6B -#define CS19_SW4 0x6C -#define CS20_SW4 0x6D -#define CS21_SW4 0x6E -#define CS22_SW4 0x6F -#define CS23_SW4 0x70 -#define CS24_SW4 0x71 -#define CS25_SW4 0x72 -#define CS26_SW4 0x73 -#define CS27_SW4 0x74 -#define CS28_SW4 0x75 -#define CS29_SW4 0x76 -#define CS30_SW4 0x77 - -#define CS1_SW5 0x78 -#define CS2_SW5 0x79 -#define CS3_SW5 0x7A -#define CS4_SW5 0x7B -#define CS5_SW5 0x7C -#define CS6_SW5 0x7D -#define CS7_SW5 0x7E -#define CS8_SW5 0x7F -#define CS9_SW5 0x80 -#define CS10_SW5 0x81 -#define CS11_SW5 0x82 -#define CS12_SW5 0x83 -#define CS13_SW5 0x84 -#define CS14_SW5 0x85 -#define CS15_SW5 0x86 -#define CS16_SW5 0x87 -#define CS17_SW5 0x88 -#define CS18_SW5 0x89 -#define CS19_SW5 0x8A -#define CS20_SW5 0x8B -#define CS21_SW5 0x8C -#define CS22_SW5 0x8D -#define CS23_SW5 0x8E -#define CS24_SW5 0x8F -#define CS25_SW5 0x90 -#define CS26_SW5 0x91 -#define CS27_SW5 0x92 -#define CS28_SW5 0x93 -#define CS29_SW5 0x94 -#define CS30_SW5 0x95 - -#define CS1_SW6 0x96 -#define CS2_SW6 0x97 -#define CS3_SW6 0x98 -#define CS4_SW6 0x99 -#define CS5_SW6 0x9A -#define CS6_SW6 0x9B -#define CS7_SW6 0x9C -#define CS8_SW6 0x9D -#define CS9_SW6 0x9E -#define CS10_SW6 0x9F -#define CS11_SW6 0xA0 -#define CS12_SW6 0xA1 -#define CS13_SW6 0xA2 -#define CS14_SW6 0xA3 -#define CS15_SW6 0xA4 -#define CS16_SW6 0xA5 -#define CS17_SW6 0xA6 -#define CS18_SW6 0xA7 -#define CS19_SW6 0xA8 -#define CS20_SW6 0xA9 -#define CS21_SW6 0xAA -#define CS22_SW6 0xAB -#define CS23_SW6 0xAC -#define CS24_SW6 0xAD -#define CS25_SW6 0xAE -#define CS26_SW6 0xAF -#define CS27_SW6 0xB0 -#define CS28_SW6 0xB1 -#define CS29_SW6 0xB2 -#define CS30_SW6 0xB3 - -#define CS1_SW7 0xB4 -#define CS2_SW7 0xB5 -#define CS3_SW7 0xB6 -#define CS4_SW7 0xB7 -#define CS5_SW7 0xB8 -#define CS6_SW7 0xB9 -#define CS7_SW7 0xBA -#define CS8_SW7 0xBB -#define CS9_SW7 0xBC -#define CS10_SW7 0xBD -#define CS11_SW7 0xBE -#define CS12_SW7 0xBF -#define CS13_SW7 0xC0 -#define CS14_SW7 0xC1 -#define CS15_SW7 0xC2 -#define CS16_SW7 0xC3 -#define CS17_SW7 0xC4 -#define CS18_SW7 0xC5 -#define CS19_SW7 0xC6 -#define CS20_SW7 0xC7 -#define CS21_SW7 0xC8 -#define CS22_SW7 0xC9 -#define CS23_SW7 0xCA -#define CS24_SW7 0xCB -#define CS25_SW7 0xCC -#define CS26_SW7 0xCD -#define CS27_SW7 0xCE -#define CS28_SW7 0xCF -#define CS29_SW7 0xD0 -#define CS30_SW7 0xD1 - -#define CS1_SW8 0xD2 -#define CS2_SW8 0xD3 -#define CS3_SW8 0xD4 -#define CS4_SW8 0xD5 -#define CS5_SW8 0xD6 -#define CS6_SW8 0xD7 -#define CS7_SW8 0xD8 -#define CS8_SW8 0xD9 -#define CS9_SW8 0xDA -#define CS10_SW8 0xDB -#define CS11_SW8 0xDC -#define CS12_SW8 0xDD -#define CS13_SW8 0xDE -#define CS14_SW8 0xDF -#define CS15_SW8 0xE0 -#define CS16_SW8 0xE1 -#define CS17_SW8 0xE2 -#define CS18_SW8 0xE3 -#define CS19_SW8 0xE4 -#define CS20_SW8 0xE5 -#define CS21_SW8 0xE6 -#define CS22_SW8 0xE7 -#define CS23_SW8 0xE8 -#define CS24_SW8 0xE9 -#define CS25_SW8 0xEA -#define CS26_SW8 0xEB -#define CS27_SW8 0xEC -#define CS28_SW8 0xED -#define CS29_SW8 0xEE -#define CS30_SW8 0xEF - -#define CS1_SW9 0xF0 -#define CS2_SW9 0xF1 -#define CS3_SW9 0xF2 -#define CS4_SW9 0xF3 -#define CS5_SW9 0xF4 -#define CS6_SW9 0xF5 -#define CS7_SW9 0xF6 -#define CS8_SW9 0xF7 -#define CS9_SW9 0xF8 -#define CS10_SW9 0xF9 -#define CS11_SW9 0xFA -#define CS12_SW9 0xFB -#define CS13_SW9 0xFC -#define CS14_SW9 0xFD -#define CS15_SW9 0xFE -#define CS16_SW9 0xFF -#define CS17_SW9 0x100 -#define CS18_SW9 0x101 -#define CS19_SW9 0x102 -#define CS20_SW9 0x103 -#define CS21_SW9 0x104 -#define CS22_SW9 0x105 -#define CS23_SW9 0x106 -#define CS24_SW9 0x107 -#define CS25_SW9 0x108 -#define CS26_SW9 0x109 -#define CS27_SW9 0x10A -#define CS28_SW9 0x10B -#define CS29_SW9 0x10C -#define CS30_SW9 0x10D - -#define CS31_SW1 0x10E -#define CS32_SW1 0x10F -#define CS33_SW1 0x110 -#define CS34_SW1 0x111 -#define CS35_SW1 0x112 -#define CS36_SW1 0x113 -#define CS37_SW1 0x114 -#define CS38_SW1 0x115 -#define CS39_SW1 0x116 - -#define CS31_SW2 0x117 -#define CS32_SW2 0x118 -#define CS33_SW2 0x119 -#define CS34_SW2 0x11A -#define CS35_SW2 0x11B -#define CS36_SW2 0x11C -#define CS37_SW2 0x11D -#define CS38_SW2 0x11E -#define CS39_SW2 0x11F - -#define CS31_SW3 0x120 -#define CS32_SW3 0x121 -#define CS33_SW3 0x122 -#define CS34_SW3 0x123 -#define CS35_SW3 0x124 -#define CS36_SW3 0x125 -#define CS37_SW3 0x126 -#define CS38_SW3 0x127 -#define CS39_SW3 0x128 - -#define CS31_SW4 0x129 -#define CS32_SW4 0x12A -#define CS33_SW4 0x12B -#define CS34_SW4 0x12C -#define CS35_SW4 0x12D -#define CS36_SW4 0x12E -#define CS37_SW4 0x12F -#define CS38_SW4 0x130 -#define CS39_SW4 0x131 - -#define CS31_SW5 0x132 -#define CS32_SW5 0x133 -#define CS33_SW5 0x134 -#define CS34_SW5 0x135 -#define CS35_SW5 0x136 -#define CS36_SW5 0x137 -#define CS37_SW5 0x138 -#define CS38_SW5 0x139 -#define CS39_SW5 0x13A - -#define CS31_SW6 0x13B -#define CS32_SW6 0x13C -#define CS33_SW6 0x13D -#define CS34_SW6 0x13E -#define CS35_SW6 0x13F -#define CS36_SW6 0x140 -#define CS37_SW6 0x141 -#define CS38_SW6 0x142 -#define CS39_SW6 0x143 - -#define CS31_SW7 0x144 -#define CS32_SW7 0x145 -#define CS33_SW7 0x146 -#define CS34_SW7 0x147 -#define CS35_SW7 0x148 -#define CS36_SW7 0x149 -#define CS37_SW7 0x14A -#define CS38_SW7 0x14B -#define CS39_SW7 0x14C - -#define CS31_SW8 0x14D -#define CS32_SW8 0x14E -#define CS33_SW8 0x14F -#define CS34_SW8 0x150 -#define CS35_SW8 0x151 -#define CS36_SW8 0x152 -#define CS37_SW8 0x153 -#define CS38_SW8 0x154 -#define CS39_SW8 0x155 - -#define CS31_SW9 0x156 -#define CS32_SW9 0x157 -#define CS33_SW9 0x158 -#define CS34_SW9 0x159 -#define CS35_SW9 0x15A -#define CS36_SW9 0x15B -#define CS37_SW9 0x15C -#define CS38_SW9 0x15D -#define CS39_SW9 0x15E diff --git a/drivers/led/issi/is31fl3742a-mono.c b/drivers/led/issi/is31fl3742a-mono.c new file mode 100644 index 0000000000..7d9095429d --- /dev/null +++ b/drivers/led/issi/is31fl3742a-mono.c @@ -0,0 +1,206 @@ +#include "is31fl3742a-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3742A_PWM_REGISTER_COUNT 180 +#define IS31FL3742A_SCALING_REGISTER_COUNT 180 + +#ifndef IS31FL3742A_I2C_TIMEOUT +# define IS31FL3742A_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3742A_I2C_PERSISTENCE +# define IS31FL3742A_I2C_PERSISTENCE 0 +#endif + +#ifndef IS31FL3742A_CONFIGURATION +# define IS31FL3742A_CONFIGURATION 0x31 +#endif + +#ifndef IS31FL3742A_PWM_FREQUENCY +# define IS31FL3742A_PWM_FREQUENCY IS31FL3742A_PWM_FREQUENCY_29K_HZ +#endif + +#ifndef IS31FL3742A_SW_PULLDOWN +# define IS31FL3742A_SW_PULLDOWN IS31FL3742A_PDR_8K_OHM +#endif + +#ifndef IS31FL3742A_CS_PULLUP +# define IS31FL3742A_CS_PULLUP IS31FL3742A_PUR_8K_OHM +#endif + +#ifndef IS31FL3742A_GLOBAL_CURRENT +# define IS31FL3742A_GLOBAL_CURRENT 0xFF +#endif + +uint8_t i2c_transfer_buffer[20] = {0xFF}; + +uint8_t g_pwm_buffer[IS31FL3742A_DRIVER_COUNT][IS31FL3742A_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3742A_DRIVER_COUNT] = {false}; +bool g_scaling_registers_update_required[IS31FL3742A_DRIVER_COUNT] = {false}; + +uint8_t g_scaling_registers[IS31FL3742A_DRIVER_COUNT][IS31FL3742A_SCALING_REGISTER_COUNT]; + +void is31fl3742a_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3742A_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3742A_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3742A_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3742A_I2C_TIMEOUT); +#endif +} + +void is31fl3742a_select_page(uint8_t addr, uint8_t page) { + is31fl3742a_write_register(addr, IS31FL3742A_REG_COMMAND_WRITE_LOCK, IS31FL3742A_COMMAND_WRITE_LOCK_MAGIC); + is31fl3742a_write_register(addr, IS31FL3742A_REG_COMMAND, page); +} + +void is31fl3742a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // Assumes page 0 is already selected. + // If any of the transactions fails function returns false. + // Transmit PWM registers in 12 transfers of 16 bytes. + // i2c_transfer_buffer[] is 20 bytes + + // Iterate over the pwm_buffer contents at 16 byte intervals. + for (int i = 0; i < IS31FL3742A_PWM_REGISTER_COUNT; i += 16) { + i2c_transfer_buffer[0] = i; + // Copy the data from i to i+15. + // Device will auto-increment register for data after the first byte + // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); + +#if IS31FL3742A_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3742A_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3742A_I2C_TIMEOUT) != 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3742A_I2C_TIMEOUT); +#endif + } +} + +void is31fl3742a_init_drivers(void) { + i2c_init(); + + is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_1); +#if defined(IS31FL3742A_I2C_ADDRESS_2) + is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_2); +# if defined(IS31FL3742A_I2C_ADDRESS_3) + is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_3); +# if defined(IS31FL3742A_I2C_ADDRESS_4) + is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3742A_LED_COUNT; i++) { + is31fl3742a_set_scaling_register(i, 0xFF); + } + + is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_1, 0); +#if defined(IS31FL3742A_I2C_ADDRESS_2) + is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_2, 1); +# if defined(IS31FL3742A_I2C_ADDRESS_3) + is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_3, 2); +# if defined(IS31FL3742A_I2C_ADDRESS_4) + is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3742a_init(uint8_t addr) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + + is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_SCALING); + + // Turn off all LEDs. + for (int i = 0; i < IS31FL3742A_SCALING_REGISTER_COUNT; i++) { + is31fl3742a_write_register(addr, i, 0x00); + } + + is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_PWM); + + for (int i = 0; i < IS31FL3742A_PWM_REGISTER_COUNT; i++) { + is31fl3742a_write_register(addr, i, 0x00); + } + + is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_FUNCTION); + + is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_PULLDOWNUP, (IS31FL3742A_SW_PULLDOWN << 4) | IS31FL3742A_CS_PULLUP); + is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3742A_GLOBAL_CURRENT); + is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_PWM_FREQUENCY, (IS31FL3742A_PWM_FREQUENCY & 0b0111)); + is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_CONFIGURATION, IS31FL3742A_CONFIGURATION); + + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void is31fl3742a_set_value(int index, uint8_t value) { + is31fl3742a_led_t led; + if (index >= 0 && index < IS31FL3742A_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3742a_leds[index]), sizeof(led)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + g_pwm_buffer[led.driver][led.v] = value; + g_pwm_buffer_update_required[led.driver] = true; + } +} + +void is31fl3742a_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3742A_LED_COUNT; i++) { + is31fl3742a_set_value(i, value); + } +} + +void is31fl3742a_set_scaling_register(uint8_t index, uint8_t value) { + is31fl3742a_led_t led; + memcpy_P(&led, (&g_is31fl3742a_leds[index]), sizeof(led)); + + g_scaling_registers[led.driver][led.v] = value; + + g_scaling_registers_update_required[led.driver] = true; +} + +void is31fl3742a_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_PWM); + + is31fl3742a_write_pwm_buffer(addr, g_pwm_buffer[index]); + g_pwm_buffer_update_required[index] = false; + } +} + +void is31fl3742a_update_scaling_registers(uint8_t addr, uint8_t index) { + if (g_scaling_registers_update_required[index]) { + is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_SCALING); + + for (int i = 0; i < IS31FL3742A_SCALING_REGISTER_COUNT; i++) { + is31fl3742a_write_register(addr, i, g_scaling_registers[index][i]); + } + g_scaling_registers_update_required[index] = false; + } +} + +void is31fl3742a_flush(void) { + is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_1, 0); +#if defined(IS31FL3742A_I2C_ADDRESS_2) + is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_2, 1); +# if defined(IS31FL3742A_I2C_ADDRESS_3) + is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_3, 2); +# if defined(IS31FL3742A_I2C_ADDRESS_4) + is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3742a-mono.h b/drivers/led/issi/is31fl3742a-mono.h new file mode 100644 index 0000000000..04614e4f6e --- /dev/null +++ b/drivers/led/issi/is31fl3742a-mono.h @@ -0,0 +1,297 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2020 MelGeek + * Copyright 2021 MasterSpoon + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +#define IS31FL3742A_REG_INTERRUPT_MASK 0xF0 +#define IS31FL3742A_REG_INTERRUPT_STATUS 0xF1 +#define IS31FL3742A_REG_ID 0xFC + +#define IS31FL3742A_REG_COMMAND 0xFD + +#define IS31FL3742A_COMMAND_PWM 0x00 +#define IS31FL3742A_COMMAND_SCALING 0x02 +#define IS31FL3742A_COMMAND_FUNCTION 0x04 + +#define IS31FL3742A_FUNCTION_REG_CONFIGURATION 0x00 +#define IS31FL3742A_FUNCTION_REG_GLOBAL_CURRENT 0x01 +#define IS31FL3742A_FUNCTION_REG_PULLDOWNUP 0x02 +#define IS31FL3742A_FUNCTION_REG_PWM_FREQUENCY 0x36 +#define IS31FL3742A_FUNCTION_REG_RESET 0x3F +#define IS31FL3742A_FUNCTION_REG_SPREAD_SPECTRUM 0x41 + +#define IS31FL3742A_REG_COMMAND_WRITE_LOCK 0xFE +#define IS31FL3742A_COMMAND_WRITE_LOCK_MAGIC 0xC5 + +#define IS31FL3742A_I2C_ADDRESS_GND 0x30 +#define IS31FL3742A_I2C_ADDRESS_SCL 0x31 +#define IS31FL3742A_I2C_ADDRESS_SDA 0x32 +#define IS31FL3742A_I2C_ADDRESS_VCC 0x33 + +#if defined(LED_MATRIX_IS31FL3742A) +# define IS31FL3742A_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined(IS31FL3742A_I2C_ADDRESS_4) +# define IS31FL3742A_DRIVER_COUNT 4 +#elif defined(IS31FL3742A_I2C_ADDRESS_3) +# define IS31FL3742A_DRIVER_COUNT 3 +#elif defined(IS31FL3742A_I2C_ADDRESS_2) +# define IS31FL3742A_DRIVER_COUNT 2 +#elif defined(IS31FL3742A_I2C_ADDRESS_1) +# define IS31FL3742A_DRIVER_COUNT 1 +#endif + +typedef struct is31fl3742a_led_t { + uint8_t driver : 2; + uint8_t v; +} PACKED is31fl3742a_led_t; + +extern const is31fl3742a_led_t PROGMEM g_is31fl3742a_leds[IS31FL3742A_LED_COUNT]; + +void is31fl3742a_init_drivers(void); +void is31fl3742a_init(uint8_t addr); +void is31fl3742a_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3742a_select_page(uint8_t addr, uint8_t page); +void is31fl3742a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3742a_set_value(int index, uint8_t value); +void is31fl3742a_set_value_all(uint8_t value); + +void is31fl3742a_set_scaling_register(uint8_t index, uint8_t value); + +void is31fl3742a_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3742a_update_scaling_registers(uint8_t addr, uint8_t index); + +void is31fl3742a_flush(void); + +#define IS31FL3742A_PDR_0_OHM 0b000 // No pull-down resistor +#define IS31FL3742A_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3742A_PDR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3742A_PDR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3742A_PDR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3742A_PDR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3742A_PDR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3742A_PDR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3742A_PUR_0_OHM 0b000 // No pull-up resistor +#define IS31FL3742A_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor +#define IS31FL3742A_PUR_1K_OHM 0b010 // 1 kOhm resistor +#define IS31FL3742A_PUR_2K_OHM 0b011 // 2 kOhm resistor +#define IS31FL3742A_PUR_4K_OHM 0b100 // 4 kOhm resistor +#define IS31FL3742A_PUR_8K_OHM 0b101 // 8 kOhm resistor +#define IS31FL3742A_PUR_16K_OHM 0b110 // 16 kOhm resistor +#define IS31FL3742A_PUR_32K_OHM 0b111 // 32 kOhm resistor + +#define IS31FL3742A_PWM_FREQUENCY_29K_HZ 0b0000 +#define IS31FL3742A_PWM_FREQUENCY_3K6_HZ 0b0011 +#define IS31FL3742A_PWM_FREQUENCY_1K8_HZ 0b0111 +#define IS31FL3742A_PWM_FREQUENCY_900_HZ 0b1011 + +#define CS1_SW1 0x00 +#define CS2_SW1 0x01 +#define CS3_SW1 0x02 +#define CS4_SW1 0x03 +#define CS5_SW1 0x04 +#define CS6_SW1 0x05 +#define CS7_SW1 0x06 +#define CS8_SW1 0x07 +#define CS9_SW1 0x08 +#define CS10_SW1 0x09 +#define CS11_SW1 0x0A +#define CS12_SW1 0x0B +#define CS13_SW1 0x0C +#define CS14_SW1 0x0D +#define CS15_SW1 0x0E +#define CS16_SW1 0x0F +#define CS17_SW1 0x10 +#define CS18_SW1 0x11 +#define CS19_SW1 0x12 +#define CS20_SW1 0x13 +#define CS21_SW1 0x14 +#define CS22_SW1 0x15 +#define CS23_SW1 0x16 +#define CS24_SW1 0x17 +#define CS25_SW1 0x18 +#define CS26_SW1 0x19 +#define CS27_SW1 0x1A +#define CS28_SW1 0x1B +#define CS29_SW1 0x1C +#define CS30_SW1 0x1D + +#define CS1_SW2 0x1E +#define CS2_SW2 0x1F +#define CS3_SW2 0x20 +#define CS4_SW2 0x21 +#define CS5_SW2 0x22 +#define CS6_SW2 0x23 +#define CS7_SW2 0x24 +#define CS8_SW2 0x25 +#define CS9_SW2 0x26 +#define CS10_SW2 0x27 +#define CS11_SW2 0x28 +#define CS12_SW2 0x29 +#define CS13_SW2 0x2A +#define CS14_SW2 0x2B +#define CS15_SW2 0x2C +#define CS16_SW2 0x2D +#define CS17_SW2 0x2E +#define CS18_SW2 0x2F +#define CS19_SW2 0x30 +#define CS20_SW2 0x31 +#define CS21_SW2 0x32 +#define CS22_SW2 0x33 +#define CS23_SW2 0x34 +#define CS24_SW2 0x35 +#define CS25_SW2 0x36 +#define CS26_SW2 0x37 +#define CS27_SW2 0x38 +#define CS28_SW2 0x39 +#define CS29_SW2 0x3A +#define CS30_SW2 0x3B + +#define CS1_SW3 0x3C +#define CS2_SW3 0x3D +#define CS3_SW3 0x3E +#define CS4_SW3 0x3F +#define CS5_SW3 0x40 +#define CS6_SW3 0x41 +#define CS7_SW3 0x42 +#define CS8_SW3 0x43 +#define CS9_SW3 0x44 +#define CS10_SW3 0x45 +#define CS11_SW3 0x46 +#define CS12_SW3 0x47 +#define CS13_SW3 0x48 +#define CS14_SW3 0x49 +#define CS15_SW3 0x4A +#define CS16_SW3 0x4B +#define CS17_SW3 0x4C +#define CS18_SW3 0x4D +#define CS19_SW3 0x4E +#define CS20_SW3 0x4F +#define CS21_SW3 0x50 +#define CS22_SW3 0x51 +#define CS23_SW3 0x52 +#define CS24_SW3 0x53 +#define CS25_SW3 0x54 +#define CS26_SW3 0x55 +#define CS27_SW3 0x56 +#define CS28_SW3 0x57 +#define CS29_SW3 0x58 +#define CS30_SW3 0x59 + +#define CS1_SW4 0x5A +#define CS2_SW4 0x5B +#define CS3_SW4 0x5C +#define CS4_SW4 0x5D +#define CS5_SW4 0x5E +#define CS6_SW4 0x5F +#define CS7_SW4 0x60 +#define CS8_SW4 0x61 +#define CS9_SW4 0x62 +#define CS10_SW4 0x63 +#define CS11_SW4 0x64 +#define CS12_SW4 0x65 +#define CS13_SW4 0x66 +#define CS14_SW4 0x67 +#define CS15_SW4 0x68 +#define CS16_SW4 0x69 +#define CS17_SW4 0x6A +#define CS18_SW4 0x6B +#define CS19_SW4 0x6C +#define CS20_SW4 0x6D +#define CS21_SW4 0x6E +#define CS22_SW4 0x6F +#define CS23_SW4 0x70 +#define CS24_SW4 0x71 +#define CS25_SW4 0x72 +#define CS26_SW4 0x73 +#define CS27_SW4 0x74 +#define CS28_SW4 0x75 +#define CS29_SW4 0x76 +#define CS30_SW4 0x77 + +#define CS1_SW5 0x78 +#define CS2_SW5 0x79 +#define CS3_SW5 0x7A +#define CS4_SW5 0x7B +#define CS5_SW5 0x7C +#define CS6_SW5 0x7D +#define CS7_SW5 0x7E +#define CS8_SW5 0x7F +#define CS9_SW5 0x80 +#define CS10_SW5 0x81 +#define CS11_SW5 0x82 +#define CS12_SW5 0x83 +#define CS13_SW5 0x84 +#define CS14_SW5 0x85 +#define CS15_SW5 0x86 +#define CS16_SW5 0x87 +#define CS17_SW5 0x88 +#define CS18_SW5 0x89 +#define CS19_SW5 0x8A +#define CS20_SW5 0x8B +#define CS21_SW5 0x8C +#define CS22_SW5 0x8D +#define CS23_SW5 0x8E +#define CS24_SW5 0x8F +#define CS25_SW5 0x90 +#define CS26_SW5 0x91 +#define CS27_SW5 0x92 +#define CS28_SW5 0x93 +#define CS29_SW5 0x94 +#define CS30_SW5 0x95 + +#define CS1_SW6 0x96 +#define CS2_SW6 0x97 +#define CS3_SW6 0x98 +#define CS4_SW6 0x99 +#define CS5_SW6 0x9A +#define CS6_SW6 0x9B +#define CS7_SW6 0x9C +#define CS8_SW6 0x9D +#define CS9_SW6 0x9E +#define CS10_SW6 0x9F +#define CS11_SW6 0xA0 +#define CS12_SW6 0xA1 +#define CS13_SW6 0xA2 +#define CS14_SW6 0xA3 +#define CS15_SW6 0xA4 +#define CS16_SW6 0xA5 +#define CS17_SW6 0xA6 +#define CS18_SW6 0xA7 +#define CS19_SW6 0xA8 +#define CS20_SW6 0xA9 +#define CS21_SW6 0xAA +#define CS22_SW6 0xAB +#define CS23_SW6 0xAC +#define CS24_SW6 0xAD +#define CS25_SW6 0xAE +#define CS26_SW6 0xAF +#define CS27_SW6 0xB0 +#define CS28_SW6 0xB1 +#define CS29_SW6 0xB2 +#define CS30_SW6 0xB3 diff --git a/drivers/led/issi/is31fl3742a-simple.c b/drivers/led/issi/is31fl3742a-simple.c deleted file mode 100644 index ee6e8741b9..0000000000 --- a/drivers/led/issi/is31fl3742a-simple.c +++ /dev/null @@ -1,206 +0,0 @@ -#include "is31fl3742a-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3742A_PWM_REGISTER_COUNT 180 -#define IS31FL3742A_SCALING_REGISTER_COUNT 180 - -#ifndef IS31FL3742A_I2C_TIMEOUT -# define IS31FL3742A_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3742A_I2C_PERSISTENCE -# define IS31FL3742A_I2C_PERSISTENCE 0 -#endif - -#ifndef IS31FL3742A_CONFIGURATION -# define IS31FL3742A_CONFIGURATION 0x31 -#endif - -#ifndef IS31FL3742A_PWM_FREQUENCY -# define IS31FL3742A_PWM_FREQUENCY IS31FL3742A_PWM_FREQUENCY_29K_HZ -#endif - -#ifndef IS31FL3742A_SW_PULLDOWN -# define IS31FL3742A_SW_PULLDOWN IS31FL3742A_PDR_8K_OHM -#endif - -#ifndef IS31FL3742A_CS_PULLUP -# define IS31FL3742A_CS_PULLUP IS31FL3742A_PUR_8K_OHM -#endif - -#ifndef IS31FL3742A_GLOBAL_CURRENT -# define IS31FL3742A_GLOBAL_CURRENT 0xFF -#endif - -uint8_t i2c_transfer_buffer[20] = {0xFF}; - -uint8_t g_pwm_buffer[IS31FL3742A_DRIVER_COUNT][IS31FL3742A_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3742A_DRIVER_COUNT] = {false}; -bool g_scaling_registers_update_required[IS31FL3742A_DRIVER_COUNT] = {false}; - -uint8_t g_scaling_registers[IS31FL3742A_DRIVER_COUNT][IS31FL3742A_SCALING_REGISTER_COUNT]; - -void is31fl3742a_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3742A_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3742A_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3742A_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3742A_I2C_TIMEOUT); -#endif -} - -void is31fl3742a_select_page(uint8_t addr, uint8_t page) { - is31fl3742a_write_register(addr, IS31FL3742A_REG_COMMAND_WRITE_LOCK, IS31FL3742A_COMMAND_WRITE_LOCK_MAGIC); - is31fl3742a_write_register(addr, IS31FL3742A_REG_COMMAND, page); -} - -void is31fl3742a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // Assumes page 0 is already selected. - // If any of the transactions fails function returns false. - // Transmit PWM registers in 12 transfers of 16 bytes. - // i2c_transfer_buffer[] is 20 bytes - - // Iterate over the pwm_buffer contents at 16 byte intervals. - for (int i = 0; i < IS31FL3742A_PWM_REGISTER_COUNT; i += 16) { - i2c_transfer_buffer[0] = i; - // Copy the data from i to i+15. - // Device will auto-increment register for data after the first byte - // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); - -#if IS31FL3742A_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3742A_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3742A_I2C_TIMEOUT) != 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3742A_I2C_TIMEOUT); -#endif - } -} - -void is31fl3742a_init_drivers(void) { - i2c_init(); - - is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_1); -#if defined(IS31FL3742A_I2C_ADDRESS_2) - is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_2); -# if defined(IS31FL3742A_I2C_ADDRESS_3) - is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_3); -# if defined(IS31FL3742A_I2C_ADDRESS_4) - is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3742A_LED_COUNT; i++) { - is31fl3742a_set_scaling_register(i, 0xFF); - } - - is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_1, 0); -#if defined(IS31FL3742A_I2C_ADDRESS_2) - is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_2, 1); -# if defined(IS31FL3742A_I2C_ADDRESS_3) - is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_3, 2); -# if defined(IS31FL3742A_I2C_ADDRESS_4) - is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3742a_init(uint8_t addr) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, shutdown is enabled last. - // Set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - - is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_SCALING); - - // Turn off all LEDs. - for (int i = 0; i < IS31FL3742A_SCALING_REGISTER_COUNT; i++) { - is31fl3742a_write_register(addr, i, 0x00); - } - - is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_PWM); - - for (int i = 0; i < IS31FL3742A_PWM_REGISTER_COUNT; i++) { - is31fl3742a_write_register(addr, i, 0x00); - } - - is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_FUNCTION); - - is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_PULLDOWNUP, (IS31FL3742A_SW_PULLDOWN << 4) | IS31FL3742A_CS_PULLUP); - is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3742A_GLOBAL_CURRENT); - is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_PWM_FREQUENCY, (IS31FL3742A_PWM_FREQUENCY & 0b0111)); - is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_CONFIGURATION, IS31FL3742A_CONFIGURATION); - - // Wait 10ms to ensure the device has woken up. - wait_ms(10); -} - -void is31fl3742a_set_value(int index, uint8_t value) { - is31fl3742a_led_t led; - if (index >= 0 && index < IS31FL3742A_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3742a_leds[index]), sizeof(led)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - g_pwm_buffer[led.driver][led.v] = value; - g_pwm_buffer_update_required[led.driver] = true; - } -} - -void is31fl3742a_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3742A_LED_COUNT; i++) { - is31fl3742a_set_value(i, value); - } -} - -void is31fl3742a_set_scaling_register(uint8_t index, uint8_t value) { - is31fl3742a_led_t led; - memcpy_P(&led, (&g_is31fl3742a_leds[index]), sizeof(led)); - - g_scaling_registers[led.driver][led.v] = value; - - g_scaling_registers_update_required[led.driver] = true; -} - -void is31fl3742a_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_PWM); - - is31fl3742a_write_pwm_buffer(addr, g_pwm_buffer[index]); - g_pwm_buffer_update_required[index] = false; - } -} - -void is31fl3742a_update_scaling_registers(uint8_t addr, uint8_t index) { - if (g_scaling_registers_update_required[index]) { - is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_SCALING); - - for (int i = 0; i < IS31FL3742A_SCALING_REGISTER_COUNT; i++) { - is31fl3742a_write_register(addr, i, g_scaling_registers[index][i]); - } - g_scaling_registers_update_required[index] = false; - } -} - -void is31fl3742a_flush(void) { - is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_1, 0); -#if defined(IS31FL3742A_I2C_ADDRESS_2) - is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_2, 1); -# if defined(IS31FL3742A_I2C_ADDRESS_3) - is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_3, 2); -# if defined(IS31FL3742A_I2C_ADDRESS_4) - is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3742a-simple.h b/drivers/led/issi/is31fl3742a-simple.h deleted file mode 100644 index 04614e4f6e..0000000000 --- a/drivers/led/issi/is31fl3742a-simple.h +++ /dev/null @@ -1,297 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2020 MelGeek - * Copyright 2021 MasterSpoon - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -#define IS31FL3742A_REG_INTERRUPT_MASK 0xF0 -#define IS31FL3742A_REG_INTERRUPT_STATUS 0xF1 -#define IS31FL3742A_REG_ID 0xFC - -#define IS31FL3742A_REG_COMMAND 0xFD - -#define IS31FL3742A_COMMAND_PWM 0x00 -#define IS31FL3742A_COMMAND_SCALING 0x02 -#define IS31FL3742A_COMMAND_FUNCTION 0x04 - -#define IS31FL3742A_FUNCTION_REG_CONFIGURATION 0x00 -#define IS31FL3742A_FUNCTION_REG_GLOBAL_CURRENT 0x01 -#define IS31FL3742A_FUNCTION_REG_PULLDOWNUP 0x02 -#define IS31FL3742A_FUNCTION_REG_PWM_FREQUENCY 0x36 -#define IS31FL3742A_FUNCTION_REG_RESET 0x3F -#define IS31FL3742A_FUNCTION_REG_SPREAD_SPECTRUM 0x41 - -#define IS31FL3742A_REG_COMMAND_WRITE_LOCK 0xFE -#define IS31FL3742A_COMMAND_WRITE_LOCK_MAGIC 0xC5 - -#define IS31FL3742A_I2C_ADDRESS_GND 0x30 -#define IS31FL3742A_I2C_ADDRESS_SCL 0x31 -#define IS31FL3742A_I2C_ADDRESS_SDA 0x32 -#define IS31FL3742A_I2C_ADDRESS_VCC 0x33 - -#if defined(LED_MATRIX_IS31FL3742A) -# define IS31FL3742A_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined(IS31FL3742A_I2C_ADDRESS_4) -# define IS31FL3742A_DRIVER_COUNT 4 -#elif defined(IS31FL3742A_I2C_ADDRESS_3) -# define IS31FL3742A_DRIVER_COUNT 3 -#elif defined(IS31FL3742A_I2C_ADDRESS_2) -# define IS31FL3742A_DRIVER_COUNT 2 -#elif defined(IS31FL3742A_I2C_ADDRESS_1) -# define IS31FL3742A_DRIVER_COUNT 1 -#endif - -typedef struct is31fl3742a_led_t { - uint8_t driver : 2; - uint8_t v; -} PACKED is31fl3742a_led_t; - -extern const is31fl3742a_led_t PROGMEM g_is31fl3742a_leds[IS31FL3742A_LED_COUNT]; - -void is31fl3742a_init_drivers(void); -void is31fl3742a_init(uint8_t addr); -void is31fl3742a_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3742a_select_page(uint8_t addr, uint8_t page); -void is31fl3742a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3742a_set_value(int index, uint8_t value); -void is31fl3742a_set_value_all(uint8_t value); - -void is31fl3742a_set_scaling_register(uint8_t index, uint8_t value); - -void is31fl3742a_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3742a_update_scaling_registers(uint8_t addr, uint8_t index); - -void is31fl3742a_flush(void); - -#define IS31FL3742A_PDR_0_OHM 0b000 // No pull-down resistor -#define IS31FL3742A_PDR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3742A_PDR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3742A_PDR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3742A_PDR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3742A_PDR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3742A_PDR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3742A_PDR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3742A_PUR_0_OHM 0b000 // No pull-up resistor -#define IS31FL3742A_PUR_0K5_OHM 0b001 // 0.5 kOhm resistor -#define IS31FL3742A_PUR_1K_OHM 0b010 // 1 kOhm resistor -#define IS31FL3742A_PUR_2K_OHM 0b011 // 2 kOhm resistor -#define IS31FL3742A_PUR_4K_OHM 0b100 // 4 kOhm resistor -#define IS31FL3742A_PUR_8K_OHM 0b101 // 8 kOhm resistor -#define IS31FL3742A_PUR_16K_OHM 0b110 // 16 kOhm resistor -#define IS31FL3742A_PUR_32K_OHM 0b111 // 32 kOhm resistor - -#define IS31FL3742A_PWM_FREQUENCY_29K_HZ 0b0000 -#define IS31FL3742A_PWM_FREQUENCY_3K6_HZ 0b0011 -#define IS31FL3742A_PWM_FREQUENCY_1K8_HZ 0b0111 -#define IS31FL3742A_PWM_FREQUENCY_900_HZ 0b1011 - -#define CS1_SW1 0x00 -#define CS2_SW1 0x01 -#define CS3_SW1 0x02 -#define CS4_SW1 0x03 -#define CS5_SW1 0x04 -#define CS6_SW1 0x05 -#define CS7_SW1 0x06 -#define CS8_SW1 0x07 -#define CS9_SW1 0x08 -#define CS10_SW1 0x09 -#define CS11_SW1 0x0A -#define CS12_SW1 0x0B -#define CS13_SW1 0x0C -#define CS14_SW1 0x0D -#define CS15_SW1 0x0E -#define CS16_SW1 0x0F -#define CS17_SW1 0x10 -#define CS18_SW1 0x11 -#define CS19_SW1 0x12 -#define CS20_SW1 0x13 -#define CS21_SW1 0x14 -#define CS22_SW1 0x15 -#define CS23_SW1 0x16 -#define CS24_SW1 0x17 -#define CS25_SW1 0x18 -#define CS26_SW1 0x19 -#define CS27_SW1 0x1A -#define CS28_SW1 0x1B -#define CS29_SW1 0x1C -#define CS30_SW1 0x1D - -#define CS1_SW2 0x1E -#define CS2_SW2 0x1F -#define CS3_SW2 0x20 -#define CS4_SW2 0x21 -#define CS5_SW2 0x22 -#define CS6_SW2 0x23 -#define CS7_SW2 0x24 -#define CS8_SW2 0x25 -#define CS9_SW2 0x26 -#define CS10_SW2 0x27 -#define CS11_SW2 0x28 -#define CS12_SW2 0x29 -#define CS13_SW2 0x2A -#define CS14_SW2 0x2B -#define CS15_SW2 0x2C -#define CS16_SW2 0x2D -#define CS17_SW2 0x2E -#define CS18_SW2 0x2F -#define CS19_SW2 0x30 -#define CS20_SW2 0x31 -#define CS21_SW2 0x32 -#define CS22_SW2 0x33 -#define CS23_SW2 0x34 -#define CS24_SW2 0x35 -#define CS25_SW2 0x36 -#define CS26_SW2 0x37 -#define CS27_SW2 0x38 -#define CS28_SW2 0x39 -#define CS29_SW2 0x3A -#define CS30_SW2 0x3B - -#define CS1_SW3 0x3C -#define CS2_SW3 0x3D -#define CS3_SW3 0x3E -#define CS4_SW3 0x3F -#define CS5_SW3 0x40 -#define CS6_SW3 0x41 -#define CS7_SW3 0x42 -#define CS8_SW3 0x43 -#define CS9_SW3 0x44 -#define CS10_SW3 0x45 -#define CS11_SW3 0x46 -#define CS12_SW3 0x47 -#define CS13_SW3 0x48 -#define CS14_SW3 0x49 -#define CS15_SW3 0x4A -#define CS16_SW3 0x4B -#define CS17_SW3 0x4C -#define CS18_SW3 0x4D -#define CS19_SW3 0x4E -#define CS20_SW3 0x4F -#define CS21_SW3 0x50 -#define CS22_SW3 0x51 -#define CS23_SW3 0x52 -#define CS24_SW3 0x53 -#define CS25_SW3 0x54 -#define CS26_SW3 0x55 -#define CS27_SW3 0x56 -#define CS28_SW3 0x57 -#define CS29_SW3 0x58 -#define CS30_SW3 0x59 - -#define CS1_SW4 0x5A -#define CS2_SW4 0x5B -#define CS3_SW4 0x5C -#define CS4_SW4 0x5D -#define CS5_SW4 0x5E -#define CS6_SW4 0x5F -#define CS7_SW4 0x60 -#define CS8_SW4 0x61 -#define CS9_SW4 0x62 -#define CS10_SW4 0x63 -#define CS11_SW4 0x64 -#define CS12_SW4 0x65 -#define CS13_SW4 0x66 -#define CS14_SW4 0x67 -#define CS15_SW4 0x68 -#define CS16_SW4 0x69 -#define CS17_SW4 0x6A -#define CS18_SW4 0x6B -#define CS19_SW4 0x6C -#define CS20_SW4 0x6D -#define CS21_SW4 0x6E -#define CS22_SW4 0x6F -#define CS23_SW4 0x70 -#define CS24_SW4 0x71 -#define CS25_SW4 0x72 -#define CS26_SW4 0x73 -#define CS27_SW4 0x74 -#define CS28_SW4 0x75 -#define CS29_SW4 0x76 -#define CS30_SW4 0x77 - -#define CS1_SW5 0x78 -#define CS2_SW5 0x79 -#define CS3_SW5 0x7A -#define CS4_SW5 0x7B -#define CS5_SW5 0x7C -#define CS6_SW5 0x7D -#define CS7_SW5 0x7E -#define CS8_SW5 0x7F -#define CS9_SW5 0x80 -#define CS10_SW5 0x81 -#define CS11_SW5 0x82 -#define CS12_SW5 0x83 -#define CS13_SW5 0x84 -#define CS14_SW5 0x85 -#define CS15_SW5 0x86 -#define CS16_SW5 0x87 -#define CS17_SW5 0x88 -#define CS18_SW5 0x89 -#define CS19_SW5 0x8A -#define CS20_SW5 0x8B -#define CS21_SW5 0x8C -#define CS22_SW5 0x8D -#define CS23_SW5 0x8E -#define CS24_SW5 0x8F -#define CS25_SW5 0x90 -#define CS26_SW5 0x91 -#define CS27_SW5 0x92 -#define CS28_SW5 0x93 -#define CS29_SW5 0x94 -#define CS30_SW5 0x95 - -#define CS1_SW6 0x96 -#define CS2_SW6 0x97 -#define CS3_SW6 0x98 -#define CS4_SW6 0x99 -#define CS5_SW6 0x9A -#define CS6_SW6 0x9B -#define CS7_SW6 0x9C -#define CS8_SW6 0x9D -#define CS9_SW6 0x9E -#define CS10_SW6 0x9F -#define CS11_SW6 0xA0 -#define CS12_SW6 0xA1 -#define CS13_SW6 0xA2 -#define CS14_SW6 0xA3 -#define CS15_SW6 0xA4 -#define CS16_SW6 0xA5 -#define CS17_SW6 0xA6 -#define CS18_SW6 0xA7 -#define CS19_SW6 0xA8 -#define CS20_SW6 0xA9 -#define CS21_SW6 0xAA -#define CS22_SW6 0xAB -#define CS23_SW6 0xAC -#define CS24_SW6 0xAD -#define CS25_SW6 0xAE -#define CS26_SW6 0xAF -#define CS27_SW6 0xB0 -#define CS28_SW6 0xB1 -#define CS29_SW6 0xB2 -#define CS30_SW6 0xB3 diff --git a/drivers/led/issi/is31fl3743a-mono.c b/drivers/led/issi/is31fl3743a-mono.c new file mode 100644 index 0000000000..f8340222e4 --- /dev/null +++ b/drivers/led/issi/is31fl3743a-mono.c @@ -0,0 +1,216 @@ +#include "is31fl3743a-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3743A_PWM_REGISTER_COUNT 198 +#define IS31FL3743A_SCALING_REGISTER_COUNT 198 + +#ifndef IS31FL3743A_I2C_TIMEOUT +# define IS31FL3743A_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3743A_I2C_PERSISTENCE +# define IS31FL3743A_I2C_PERSISTENCE 0 +#endif + +#ifndef IS31FL3743A_CONFIGURATION +# define IS31FL3743A_CONFIGURATION 0x01 +#endif + +#ifndef IS31FL3743A_SW_PULLDOWN +# define IS31FL3743A_SW_PULLDOWN IS31FL3743A_PDR_2K_OHM_SW_OFF +#endif + +#ifndef IS31FL3743A_CS_PULLUP +# define IS31FL3743A_CS_PULLUP IS31FL3743A_PUR_2K_OHM_CS_OFF +#endif + +#ifndef IS31FL3743A_GLOBAL_CURRENT +# define IS31FL3743A_GLOBAL_CURRENT 0xFF +#endif + +#ifndef IS31FL3743A_SYNC_1 +# define IS31FL3743A_SYNC_1 IS31FL3743A_SYNC_NONE +#endif +#ifndef IS31FL3743A_SYNC_2 +# define IS31FL3743A_SYNC_2 IS31FL3743A_SYNC_NONE +#endif +#ifndef IS31FL3743A_SYNC_3 +# define IS31FL3743A_SYNC_3 IS31FL3743A_SYNC_NONE +#endif +#ifndef IS31FL3743A_SYNC_4 +# define IS31FL3743A_SYNC_4 IS31FL3743A_SYNC_NONE +#endif + +uint8_t i2c_transfer_buffer[20] = {0xFF}; + +uint8_t g_pwm_buffer[IS31FL3743A_DRIVER_COUNT][IS31FL3743A_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3743A_DRIVER_COUNT] = {false}; +bool g_scaling_registers_update_required[IS31FL3743A_DRIVER_COUNT] = {false}; + +uint8_t g_scaling_registers[IS31FL3743A_DRIVER_COUNT][IS31FL3743A_SCALING_REGISTER_COUNT]; + +void is31fl3743a_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3743A_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3743A_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3743A_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3743A_I2C_TIMEOUT); +#endif +} + +void is31fl3743a_select_page(uint8_t addr, uint8_t page) { + is31fl3743a_write_register(addr, IS31FL3743A_REG_COMMAND_WRITE_LOCK, IS31FL3743A_COMMAND_WRITE_LOCK_MAGIC); + is31fl3743a_write_register(addr, IS31FL3743A_REG_COMMAND, page); +} + +void is31fl3743a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // Assumes page 0 is already selected. + // If any of the transactions fails function returns false. + // Transmit PWM registers in 12 transfers of 16 bytes. + // i2c_transfer_buffer[] is 20 bytes + + // Iterate over the pwm_buffer contents at 16 byte intervals. + for (int i = 0; i < IS31FL3743A_PWM_REGISTER_COUNT; i += 16) { + i2c_transfer_buffer[0] = i + 1; + // Copy the data from i to i+15. + // Device will auto-increment register for data after the first byte + // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); + +#if IS31FL3743A_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3743A_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3743A_I2C_TIMEOUT) != 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3743A_I2C_TIMEOUT); +#endif + } +} + +void is31fl3743a_init_drivers(void) { + i2c_init(); + + is31fl3743a_init(IS31FL3743A_I2C_ADDRESS_1, IS31FL3743A_SYNC_1); +#if defined(IS31FL3743A_I2C_ADDRESS_2) + is31fl3743a_init(IS31FL3743A_I2C_ADDRESS_2, IS31FL3743A_SYNC_2); +# if defined(IS31FL3743A_I2C_ADDRESS_3) + is31fl3743a_init(IS31FL3743A_I2C_ADDRESS_3, IS31FL3743A_SYNC_3); +# if defined(IS31FL3743A_I2C_ADDRESS_4) + is31fl3743a_init(IS31FL3743A_I2C_ADDRESS_4, IS31FL3743A_SYNC_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3743A_LED_COUNT; i++) { + is31fl3743a_set_scaling_register(i, 0xFF); + } + + is31fl3743a_update_scaling_registers(IS31FL3743A_I2C_ADDRESS_1, 0); +#if defined(IS31FL3743A_I2C_ADDRESS_2) + is31fl3743a_update_scaling_registers(IS31FL3743A_I2C_ADDRESS_2, 1); +# if defined(IS31FL3743A_I2C_ADDRESS_3) + is31fl3743a_update_scaling_registers(IS31FL3743A_I2C_ADDRESS_3, 2); +# if defined(IS31FL3743A_I2C_ADDRESS_4) + is31fl3743a_update_scaling_registers(IS31FL3743A_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3743a_init(uint8_t addr, uint8_t sync) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + + is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_SCALING); + + // Turn off all LEDs. + for (int i = 0; i < IS31FL3743A_SCALING_REGISTER_COUNT; i++) { + is31fl3743a_write_register(addr, i + 1, 0x00); + } + + is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_PWM); + + for (int i = 0; i < IS31FL3743A_PWM_REGISTER_COUNT; i++) { + is31fl3743a_write_register(addr, i + 1, 0x00); + } + + is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_FUNCTION); + + is31fl3743a_write_register(addr, IS31FL3743A_FUNCTION_REG_PULLDOWNUP, (IS31FL3743A_SW_PULLDOWN << 4) | IS31FL3743A_CS_PULLUP); + is31fl3743a_write_register(addr, IS31FL3743A_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3743A_GLOBAL_CURRENT); + is31fl3743a_write_register(addr, IS31FL3743A_FUNCTION_REG_SPREAD_SPECTRUM, (sync & 0b11) << 6); + is31fl3743a_write_register(addr, IS31FL3743A_FUNCTION_REG_CONFIGURATION, IS31FL3743A_CONFIGURATION); + + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void is31fl3743a_set_value(int index, uint8_t value) { + is31fl3743a_led_t led; + if (index >= 0 && index < IS31FL3743A_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3743a_leds[index]), sizeof(led)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + g_pwm_buffer_update_required[led.driver] = true; + g_pwm_buffer[led.driver][led.v] = value; + } +} + +void is31fl3743a_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3743A_LED_COUNT; i++) { + is31fl3743a_set_value(i, value); + } +} + +void is31fl3743a_set_scaling_register(uint8_t index, uint8_t value) { + is31fl3743a_led_t led; + memcpy_P(&led, (&g_is31fl3743a_leds[index]), sizeof(led)); + + g_scaling_registers[led.driver][led.v] = value; + + g_scaling_registers_update_required[led.driver] = true; +} + +void is31fl3743a_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_PWM); + + is31fl3743a_write_pwm_buffer(addr, g_pwm_buffer[index]); + } + + g_pwm_buffer_update_required[index] = false; +} + +void is31fl3743a_update_scaling_registers(uint8_t addr, uint8_t index) { + if (g_scaling_registers_update_required[index]) { + is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_SCALING); + + for (int i = 0; i < IS31FL3743A_SCALING_REGISTER_COUNT; i++) { + is31fl3743a_write_register(addr, i + 1, g_scaling_registers[index][i]); + } + g_scaling_registers_update_required[index] = false; + } +} + +void is31fl3743a_flush(void) { + is31fl3743a_update_pwm_buffers(IS31FL3743A_I2C_ADDRESS_1, 0); +#if defined(IS31FL3743A_I2C_ADDRESS_2) + is31fl3743a_update_pwm_buffers(IS31FL3743A_I2C_ADDRESS_2, 1); +# if defined(IS31FL3743A_I2C_ADDRESS_3) + is31fl3743a_update_pwm_buffers(IS31FL3743A_I2C_ADDRESS_3, 2); +# if defined(IS31FL3743A_I2C_ADDRESS_4) + is31fl3743a_update_pwm_buffers(IS31FL3743A_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3743a-mono.h b/drivers/led/issi/is31fl3743a-mono.h new file mode 100644 index 0000000000..544531ec25 --- /dev/null +++ b/drivers/led/issi/is31fl3743a-mono.h @@ -0,0 +1,329 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2020 MelGeek + * Copyright 2021 MasterSpoon + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +#define IS31FL3743A_REG_ID 0xFC + +#define IS31FL3743A_REG_COMMAND 0xFD + +#define IS31FL3743A_COMMAND_PWM 0x00 +#define IS31FL3743A_COMMAND_SCALING 0x01 +#define IS31FL3743A_COMMAND_FUNCTION 0x02 + +#define IS31FL3743A_FUNCTION_REG_CONFIGURATION 0x00 +#define IS31FL3743A_FUNCTION_REG_GLOBAL_CURRENT 0x01 +#define IS31FL3743A_FUNCTION_REG_PULLDOWNUP 0x02 +#define IS31FL3743A_FUNCTION_REG_TEMPERATURE 0x24 +#define IS31FL3743A_FUNCTION_REG_SPREAD_SPECTRUM 0x25 +#define IS31FL3743A_FUNCTION_REG_RESET 0x2F + +#define IS31FL3743A_REG_COMMAND_WRITE_LOCK 0xFE +#define IS31FL3743A_COMMAND_WRITE_LOCK_MAGIC 0xC5 + +#define IS31FL3743A_I2C_ADDRESS_GND_GND 0x20 +#define IS31FL3743A_I2C_ADDRESS_GND_SCL 0x21 +#define IS31FL3743A_I2C_ADDRESS_GND_SDA 0x22 +#define IS31FL3743A_I2C_ADDRESS_GND_VCC 0x23 +#define IS31FL3743A_I2C_ADDRESS_SCL_GND 0x24 +#define IS31FL3743A_I2C_ADDRESS_SCL_SCL 0x25 +#define IS31FL3743A_I2C_ADDRESS_SCL_SDA 0x26 +#define IS31FL3743A_I2C_ADDRESS_SCL_VCC 0x27 +#define IS31FL3743A_I2C_ADDRESS_SDA_GND 0x28 +#define IS31FL3743A_I2C_ADDRESS_SDA_SCL 0x29 +#define IS31FL3743A_I2C_ADDRESS_SDA_SDA 0x2A +#define IS31FL3743A_I2C_ADDRESS_SDA_VCC 0x2B +#define IS31FL3743A_I2C_ADDRESS_VCC_GND 0x2C +#define IS31FL3743A_I2C_ADDRESS_VCC_SCL 0x2D +#define IS31FL3743A_I2C_ADDRESS_VCC_SDA 0x2E +#define IS31FL3743A_I2C_ADDRESS_VCC_VCC 0x2F + +#if defined(LED_MATRIX_IS31FL3743A) +# define IS31FL3743A_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined(IS31FL3743A_I2C_ADDRESS_4) +# define IS31FL3743A_DRIVER_COUNT 4 +#elif defined(IS31FL3743A_I2C_ADDRESS_3) +# define IS31FL3743A_DRIVER_COUNT 3 +#elif defined(IS31FL3743A_I2C_ADDRESS_2) +# define IS31FL3743A_DRIVER_COUNT 2 +#elif defined(IS31FL3743A_I2C_ADDRESS_1) +# define IS31FL3743A_DRIVER_COUNT 1 +#endif + +typedef struct is31fl3743a_led_t { + uint8_t driver : 2; + uint8_t v; +} PACKED is31fl3743a_led_t; + +extern const is31fl3743a_led_t PROGMEM g_is31fl3743a_leds[IS31FL3743A_LED_COUNT]; + +void is31fl3743a_init_drivers(void); +void is31fl3743a_init(uint8_t addr, uint8_t sync); +void is31fl3743a_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3743a_select_page(uint8_t addr, uint8_t page); +void is31fl3743a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3743a_set_value(int index, uint8_t value); +void is31fl3743a_set_value_all(uint8_t value); + +void is31fl3743a_set_scaling_register(uint8_t index, uint8_t value); + +void is31fl3743a_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3743a_update_scaling_registers(uint8_t addr, uint8_t index); + +void is31fl3743a_flush(void); + +#define IS31FL3743A_PDR_0_OHM 0b000 // No pull-down resistor +#define IS31FL3743A_PDR_0K5_OHM_SW_OFF 0b001 // 0.5 kOhm resistor in SWx off time +#define IS31FL3743A_PDR_1K_OHM_SW_OFF 0b010 // 1 kOhm resistor in SWx off time +#define IS31FL3743A_PDR_2K_OHM_SW_OFF 0b011 // 2 kOhm resistor in SWx off time +#define IS31FL3743A_PDR_1K_OHM 0b100 // 1 kOhm resistor +#define IS31FL3743A_PDR_2K_OHM 0b101 // 2 kOhm resistor +#define IS31FL3743A_PDR_4K_OHM 0b110 // 4 kOhm resistor +#define IS31FL3743A_PDR_8K_OHM 0b111 // 8 kOhm resistor + +#define IS31FL3743A_PUR_0_OHM 0b000 // No pull-up resistor +#define IS31FL3743A_PUR_0K5_OHM_CS_OFF 0b001 // 0.5 kOhm resistor in CSy off time +#define IS31FL3743A_PUR_1K_OHM_CS_OFF 0b010 // 1 kOhm resistor in CSy off time +#define IS31FL3743A_PUR_2K_OHM_CS_OFF 0b011 // 2 kOhm resistor in CSy off time +#define IS31FL3743A_PUR_1K_OHM 0b100 // 1 kOhm resistor +#define IS31FL3743A_PUR_2K_OHM 0b101 // 2 kOhm resistor +#define IS31FL3743A_PUR_4K_OHM 0b110 // 4 kOhm resistor +#define IS31FL3743A_PUR_8K_OHM 0b111 // 8 kOhm resistor + +#define IS31FL3743A_SYNC_NONE 0b00 +#define IS31FL3743A_SYNC_SLAVE 0b10 +#define IS31FL3743A_SYNC_MASTER 0b11 + +#define CS1_SW1 0x00 +#define CS2_SW1 0x01 +#define CS3_SW1 0x02 +#define CS4_SW1 0x03 +#define CS5_SW1 0x04 +#define CS6_SW1 0x05 +#define CS7_SW1 0x06 +#define CS8_SW1 0x07 +#define CS9_SW1 0x08 +#define CS10_SW1 0x09 +#define CS11_SW1 0x0A +#define CS12_SW1 0x0B +#define CS13_SW1 0x0C +#define CS14_SW1 0x0D +#define CS15_SW1 0x0E +#define CS16_SW1 0x0F +#define CS17_SW1 0x10 +#define CS18_SW1 0x11 + +#define CS1_SW2 0x12 +#define CS2_SW2 0x13 +#define CS3_SW2 0x14 +#define CS4_SW2 0x15 +#define CS5_SW2 0x16 +#define CS6_SW2 0x17 +#define CS7_SW2 0x18 +#define CS8_SW2 0x19 +#define CS9_SW2 0x1A +#define CS10_SW2 0x1B +#define CS11_SW2 0x1C +#define CS12_SW2 0x1D +#define CS13_SW2 0x1E +#define CS14_SW2 0x1F +#define CS15_SW2 0x20 +#define CS16_SW2 0x21 +#define CS17_SW2 0x22 +#define CS18_SW2 0x23 + +#define CS1_SW3 0x24 +#define CS2_SW3 0x25 +#define CS3_SW3 0x26 +#define CS4_SW3 0x27 +#define CS5_SW3 0x28 +#define CS6_SW3 0x29 +#define CS7_SW3 0x2A +#define CS8_SW3 0x2B +#define CS9_SW3 0x2C +#define CS10_SW3 0x2D +#define CS11_SW3 0x2E +#define CS12_SW3 0x2F +#define CS13_SW3 0x30 +#define CS14_SW3 0x31 +#define CS15_SW3 0x32 +#define CS16_SW3 0x33 +#define CS17_SW3 0x34 +#define CS18_SW3 0x35 + +#define CS1_SW4 0x36 +#define CS2_SW4 0x37 +#define CS3_SW4 0x38 +#define CS4_SW4 0x39 +#define CS5_SW4 0x3A +#define CS6_SW4 0x3B +#define CS7_SW4 0x3C +#define CS8_SW4 0x3D +#define CS9_SW4 0x3E +#define CS10_SW4 0x3F +#define CS11_SW4 0x40 +#define CS12_SW4 0x41 +#define CS13_SW4 0x42 +#define CS14_SW4 0x43 +#define CS15_SW4 0x44 +#define CS16_SW4 0x45 +#define CS17_SW4 0x46 +#define CS18_SW4 0x47 + +#define CS1_SW5 0x48 +#define CS2_SW5 0x49 +#define CS3_SW5 0x4A +#define CS4_SW5 0x4B +#define CS5_SW5 0x4C +#define CS6_SW5 0x4D +#define CS7_SW5 0x4E +#define CS8_SW5 0x4F +#define CS9_SW5 0x50 +#define CS10_SW5 0x51 +#define CS11_SW5 0x52 +#define CS12_SW5 0x53 +#define CS13_SW5 0x54 +#define CS14_SW5 0x55 +#define CS15_SW5 0x56 +#define CS16_SW5 0x57 +#define CS17_SW5 0x58 +#define CS18_SW5 0x59 + +#define CS1_SW6 0x5A +#define CS2_SW6 0x5B +#define CS3_SW6 0x5C +#define CS4_SW6 0x5D +#define CS5_SW6 0x5E +#define CS6_SW6 0x5F +#define CS7_SW6 0x60 +#define CS8_SW6 0x61 +#define CS9_SW6 0x62 +#define CS10_SW6 0x63 +#define CS11_SW6 0x64 +#define CS12_SW6 0x65 +#define CS13_SW6 0x66 +#define CS14_SW6 0x67 +#define CS15_SW6 0x68 +#define CS16_SW6 0x69 +#define CS17_SW6 0x6A +#define CS18_SW6 0x6B + +#define CS1_SW7 0x6C +#define CS2_SW7 0x6D +#define CS3_SW7 0x6E +#define CS4_SW7 0x6F +#define CS5_SW7 0x70 +#define CS6_SW7 0x71 +#define CS7_SW7 0x72 +#define CS8_SW7 0x73 +#define CS9_SW7 0x74 +#define CS10_SW7 0x75 +#define CS11_SW7 0x76 +#define CS12_SW7 0x77 +#define CS13_SW7 0x78 +#define CS14_SW7 0x79 +#define CS15_SW7 0x7A +#define CS16_SW7 0x7B +#define CS17_SW7 0x7C +#define CS18_SW7 0x7D + +#define CS1_SW8 0x7E +#define CS2_SW8 0x7F +#define CS3_SW8 0x80 +#define CS4_SW8 0x81 +#define CS5_SW8 0x82 +#define CS6_SW8 0x83 +#define CS7_SW8 0x84 +#define CS8_SW8 0x85 +#define CS9_SW8 0x86 +#define CS10_SW8 0x87 +#define CS11_SW8 0x88 +#define CS12_SW8 0x89 +#define CS13_SW8 0x8A +#define CS14_SW8 0x8B +#define CS15_SW8 0x8C +#define CS16_SW8 0x8D +#define CS17_SW8 0x8E +#define CS18_SW8 0x8F + +#define CS1_SW9 0x90 +#define CS2_SW9 0x91 +#define CS3_SW9 0x92 +#define CS4_SW9 0x93 +#define CS5_SW9 0x94 +#define CS6_SW9 0x95 +#define CS7_SW9 0x96 +#define CS8_SW9 0x97 +#define CS9_SW9 0x98 +#define CS10_SW9 0x99 +#define CS11_SW9 0x9A +#define CS12_SW9 0x9B +#define CS13_SW9 0x9C +#define CS14_SW9 0x9D +#define CS15_SW9 0x9E +#define CS16_SW9 0x9F +#define CS17_SW9 0xA0 +#define CS18_SW9 0xA1 + +#define CS1_SW10 0xA2 +#define CS2_SW10 0xA3 +#define CS3_SW10 0xA4 +#define CS4_SW10 0xA5 +#define CS5_SW10 0xA6 +#define CS6_SW10 0xA7 +#define CS7_SW10 0xA8 +#define CS8_SW10 0xA9 +#define CS9_SW10 0xAA +#define CS10_SW10 0xAB +#define CS11_SW10 0xAC +#define CS12_SW10 0xAD +#define CS13_SW10 0xAE +#define CS14_SW10 0xAF +#define CS15_SW10 0xB0 +#define CS16_SW10 0xB1 +#define CS17_SW10 0xB2 +#define CS18_SW10 0xB3 + +#define CS1_SW11 0xB4 +#define CS2_SW11 0xB5 +#define CS3_SW11 0xB6 +#define CS4_SW11 0xB7 +#define CS5_SW11 0xB8 +#define CS6_SW11 0xB9 +#define CS7_SW11 0xBA +#define CS8_SW11 0xBB +#define CS9_SW11 0xBC +#define CS10_SW11 0xBD +#define CS11_SW11 0xBE +#define CS12_SW11 0xBF +#define CS13_SW11 0xC0 +#define CS14_SW11 0xC1 +#define CS15_SW11 0xC2 +#define CS16_SW11 0xC3 +#define CS17_SW11 0xC4 +#define CS18_SW11 0xC5 diff --git a/drivers/led/issi/is31fl3743a-simple.c b/drivers/led/issi/is31fl3743a-simple.c deleted file mode 100644 index 26c42ea69c..0000000000 --- a/drivers/led/issi/is31fl3743a-simple.c +++ /dev/null @@ -1,216 +0,0 @@ -#include "is31fl3743a-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3743A_PWM_REGISTER_COUNT 198 -#define IS31FL3743A_SCALING_REGISTER_COUNT 198 - -#ifndef IS31FL3743A_I2C_TIMEOUT -# define IS31FL3743A_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3743A_I2C_PERSISTENCE -# define IS31FL3743A_I2C_PERSISTENCE 0 -#endif - -#ifndef IS31FL3743A_CONFIGURATION -# define IS31FL3743A_CONFIGURATION 0x01 -#endif - -#ifndef IS31FL3743A_SW_PULLDOWN -# define IS31FL3743A_SW_PULLDOWN IS31FL3743A_PDR_2K_OHM_SW_OFF -#endif - -#ifndef IS31FL3743A_CS_PULLUP -# define IS31FL3743A_CS_PULLUP IS31FL3743A_PUR_2K_OHM_CS_OFF -#endif - -#ifndef IS31FL3743A_GLOBAL_CURRENT -# define IS31FL3743A_GLOBAL_CURRENT 0xFF -#endif - -#ifndef IS31FL3743A_SYNC_1 -# define IS31FL3743A_SYNC_1 IS31FL3743A_SYNC_NONE -#endif -#ifndef IS31FL3743A_SYNC_2 -# define IS31FL3743A_SYNC_2 IS31FL3743A_SYNC_NONE -#endif -#ifndef IS31FL3743A_SYNC_3 -# define IS31FL3743A_SYNC_3 IS31FL3743A_SYNC_NONE -#endif -#ifndef IS31FL3743A_SYNC_4 -# define IS31FL3743A_SYNC_4 IS31FL3743A_SYNC_NONE -#endif - -uint8_t i2c_transfer_buffer[20] = {0xFF}; - -uint8_t g_pwm_buffer[IS31FL3743A_DRIVER_COUNT][IS31FL3743A_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3743A_DRIVER_COUNT] = {false}; -bool g_scaling_registers_update_required[IS31FL3743A_DRIVER_COUNT] = {false}; - -uint8_t g_scaling_registers[IS31FL3743A_DRIVER_COUNT][IS31FL3743A_SCALING_REGISTER_COUNT]; - -void is31fl3743a_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3743A_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3743A_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3743A_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3743A_I2C_TIMEOUT); -#endif -} - -void is31fl3743a_select_page(uint8_t addr, uint8_t page) { - is31fl3743a_write_register(addr, IS31FL3743A_REG_COMMAND_WRITE_LOCK, IS31FL3743A_COMMAND_WRITE_LOCK_MAGIC); - is31fl3743a_write_register(addr, IS31FL3743A_REG_COMMAND, page); -} - -void is31fl3743a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // Assumes page 0 is already selected. - // If any of the transactions fails function returns false. - // Transmit PWM registers in 12 transfers of 16 bytes. - // i2c_transfer_buffer[] is 20 bytes - - // Iterate over the pwm_buffer contents at 16 byte intervals. - for (int i = 0; i < IS31FL3743A_PWM_REGISTER_COUNT; i += 16) { - i2c_transfer_buffer[0] = i + 1; - // Copy the data from i to i+15. - // Device will auto-increment register for data after the first byte - // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); - -#if IS31FL3743A_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3743A_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3743A_I2C_TIMEOUT) != 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3743A_I2C_TIMEOUT); -#endif - } -} - -void is31fl3743a_init_drivers(void) { - i2c_init(); - - is31fl3743a_init(IS31FL3743A_I2C_ADDRESS_1, IS31FL3743A_SYNC_1); -#if defined(IS31FL3743A_I2C_ADDRESS_2) - is31fl3743a_init(IS31FL3743A_I2C_ADDRESS_2, IS31FL3743A_SYNC_2); -# if defined(IS31FL3743A_I2C_ADDRESS_3) - is31fl3743a_init(IS31FL3743A_I2C_ADDRESS_3, IS31FL3743A_SYNC_3); -# if defined(IS31FL3743A_I2C_ADDRESS_4) - is31fl3743a_init(IS31FL3743A_I2C_ADDRESS_4, IS31FL3743A_SYNC_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3743A_LED_COUNT; i++) { - is31fl3743a_set_scaling_register(i, 0xFF); - } - - is31fl3743a_update_scaling_registers(IS31FL3743A_I2C_ADDRESS_1, 0); -#if defined(IS31FL3743A_I2C_ADDRESS_2) - is31fl3743a_update_scaling_registers(IS31FL3743A_I2C_ADDRESS_2, 1); -# if defined(IS31FL3743A_I2C_ADDRESS_3) - is31fl3743a_update_scaling_registers(IS31FL3743A_I2C_ADDRESS_3, 2); -# if defined(IS31FL3743A_I2C_ADDRESS_4) - is31fl3743a_update_scaling_registers(IS31FL3743A_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3743a_init(uint8_t addr, uint8_t sync) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, shutdown is enabled last. - // Set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - - is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_SCALING); - - // Turn off all LEDs. - for (int i = 0; i < IS31FL3743A_SCALING_REGISTER_COUNT; i++) { - is31fl3743a_write_register(addr, i + 1, 0x00); - } - - is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_PWM); - - for (int i = 0; i < IS31FL3743A_PWM_REGISTER_COUNT; i++) { - is31fl3743a_write_register(addr, i + 1, 0x00); - } - - is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_FUNCTION); - - is31fl3743a_write_register(addr, IS31FL3743A_FUNCTION_REG_PULLDOWNUP, (IS31FL3743A_SW_PULLDOWN << 4) | IS31FL3743A_CS_PULLUP); - is31fl3743a_write_register(addr, IS31FL3743A_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3743A_GLOBAL_CURRENT); - is31fl3743a_write_register(addr, IS31FL3743A_FUNCTION_REG_SPREAD_SPECTRUM, (sync & 0b11) << 6); - is31fl3743a_write_register(addr, IS31FL3743A_FUNCTION_REG_CONFIGURATION, IS31FL3743A_CONFIGURATION); - - // Wait 10ms to ensure the device has woken up. - wait_ms(10); -} - -void is31fl3743a_set_value(int index, uint8_t value) { - is31fl3743a_led_t led; - if (index >= 0 && index < IS31FL3743A_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3743a_leds[index]), sizeof(led)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - g_pwm_buffer_update_required[led.driver] = true; - g_pwm_buffer[led.driver][led.v] = value; - } -} - -void is31fl3743a_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3743A_LED_COUNT; i++) { - is31fl3743a_set_value(i, value); - } -} - -void is31fl3743a_set_scaling_register(uint8_t index, uint8_t value) { - is31fl3743a_led_t led; - memcpy_P(&led, (&g_is31fl3743a_leds[index]), sizeof(led)); - - g_scaling_registers[led.driver][led.v] = value; - - g_scaling_registers_update_required[led.driver] = true; -} - -void is31fl3743a_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_PWM); - - is31fl3743a_write_pwm_buffer(addr, g_pwm_buffer[index]); - } - - g_pwm_buffer_update_required[index] = false; -} - -void is31fl3743a_update_scaling_registers(uint8_t addr, uint8_t index) { - if (g_scaling_registers_update_required[index]) { - is31fl3743a_select_page(addr, IS31FL3743A_COMMAND_SCALING); - - for (int i = 0; i < IS31FL3743A_SCALING_REGISTER_COUNT; i++) { - is31fl3743a_write_register(addr, i + 1, g_scaling_registers[index][i]); - } - g_scaling_registers_update_required[index] = false; - } -} - -void is31fl3743a_flush(void) { - is31fl3743a_update_pwm_buffers(IS31FL3743A_I2C_ADDRESS_1, 0); -#if defined(IS31FL3743A_I2C_ADDRESS_2) - is31fl3743a_update_pwm_buffers(IS31FL3743A_I2C_ADDRESS_2, 1); -# if defined(IS31FL3743A_I2C_ADDRESS_3) - is31fl3743a_update_pwm_buffers(IS31FL3743A_I2C_ADDRESS_3, 2); -# if defined(IS31FL3743A_I2C_ADDRESS_4) - is31fl3743a_update_pwm_buffers(IS31FL3743A_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3743a-simple.h b/drivers/led/issi/is31fl3743a-simple.h deleted file mode 100644 index 544531ec25..0000000000 --- a/drivers/led/issi/is31fl3743a-simple.h +++ /dev/null @@ -1,329 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2020 MelGeek - * Copyright 2021 MasterSpoon - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -#define IS31FL3743A_REG_ID 0xFC - -#define IS31FL3743A_REG_COMMAND 0xFD - -#define IS31FL3743A_COMMAND_PWM 0x00 -#define IS31FL3743A_COMMAND_SCALING 0x01 -#define IS31FL3743A_COMMAND_FUNCTION 0x02 - -#define IS31FL3743A_FUNCTION_REG_CONFIGURATION 0x00 -#define IS31FL3743A_FUNCTION_REG_GLOBAL_CURRENT 0x01 -#define IS31FL3743A_FUNCTION_REG_PULLDOWNUP 0x02 -#define IS31FL3743A_FUNCTION_REG_TEMPERATURE 0x24 -#define IS31FL3743A_FUNCTION_REG_SPREAD_SPECTRUM 0x25 -#define IS31FL3743A_FUNCTION_REG_RESET 0x2F - -#define IS31FL3743A_REG_COMMAND_WRITE_LOCK 0xFE -#define IS31FL3743A_COMMAND_WRITE_LOCK_MAGIC 0xC5 - -#define IS31FL3743A_I2C_ADDRESS_GND_GND 0x20 -#define IS31FL3743A_I2C_ADDRESS_GND_SCL 0x21 -#define IS31FL3743A_I2C_ADDRESS_GND_SDA 0x22 -#define IS31FL3743A_I2C_ADDRESS_GND_VCC 0x23 -#define IS31FL3743A_I2C_ADDRESS_SCL_GND 0x24 -#define IS31FL3743A_I2C_ADDRESS_SCL_SCL 0x25 -#define IS31FL3743A_I2C_ADDRESS_SCL_SDA 0x26 -#define IS31FL3743A_I2C_ADDRESS_SCL_VCC 0x27 -#define IS31FL3743A_I2C_ADDRESS_SDA_GND 0x28 -#define IS31FL3743A_I2C_ADDRESS_SDA_SCL 0x29 -#define IS31FL3743A_I2C_ADDRESS_SDA_SDA 0x2A -#define IS31FL3743A_I2C_ADDRESS_SDA_VCC 0x2B -#define IS31FL3743A_I2C_ADDRESS_VCC_GND 0x2C -#define IS31FL3743A_I2C_ADDRESS_VCC_SCL 0x2D -#define IS31FL3743A_I2C_ADDRESS_VCC_SDA 0x2E -#define IS31FL3743A_I2C_ADDRESS_VCC_VCC 0x2F - -#if defined(LED_MATRIX_IS31FL3743A) -# define IS31FL3743A_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined(IS31FL3743A_I2C_ADDRESS_4) -# define IS31FL3743A_DRIVER_COUNT 4 -#elif defined(IS31FL3743A_I2C_ADDRESS_3) -# define IS31FL3743A_DRIVER_COUNT 3 -#elif defined(IS31FL3743A_I2C_ADDRESS_2) -# define IS31FL3743A_DRIVER_COUNT 2 -#elif defined(IS31FL3743A_I2C_ADDRESS_1) -# define IS31FL3743A_DRIVER_COUNT 1 -#endif - -typedef struct is31fl3743a_led_t { - uint8_t driver : 2; - uint8_t v; -} PACKED is31fl3743a_led_t; - -extern const is31fl3743a_led_t PROGMEM g_is31fl3743a_leds[IS31FL3743A_LED_COUNT]; - -void is31fl3743a_init_drivers(void); -void is31fl3743a_init(uint8_t addr, uint8_t sync); -void is31fl3743a_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3743a_select_page(uint8_t addr, uint8_t page); -void is31fl3743a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3743a_set_value(int index, uint8_t value); -void is31fl3743a_set_value_all(uint8_t value); - -void is31fl3743a_set_scaling_register(uint8_t index, uint8_t value); - -void is31fl3743a_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3743a_update_scaling_registers(uint8_t addr, uint8_t index); - -void is31fl3743a_flush(void); - -#define IS31FL3743A_PDR_0_OHM 0b000 // No pull-down resistor -#define IS31FL3743A_PDR_0K5_OHM_SW_OFF 0b001 // 0.5 kOhm resistor in SWx off time -#define IS31FL3743A_PDR_1K_OHM_SW_OFF 0b010 // 1 kOhm resistor in SWx off time -#define IS31FL3743A_PDR_2K_OHM_SW_OFF 0b011 // 2 kOhm resistor in SWx off time -#define IS31FL3743A_PDR_1K_OHM 0b100 // 1 kOhm resistor -#define IS31FL3743A_PDR_2K_OHM 0b101 // 2 kOhm resistor -#define IS31FL3743A_PDR_4K_OHM 0b110 // 4 kOhm resistor -#define IS31FL3743A_PDR_8K_OHM 0b111 // 8 kOhm resistor - -#define IS31FL3743A_PUR_0_OHM 0b000 // No pull-up resistor -#define IS31FL3743A_PUR_0K5_OHM_CS_OFF 0b001 // 0.5 kOhm resistor in CSy off time -#define IS31FL3743A_PUR_1K_OHM_CS_OFF 0b010 // 1 kOhm resistor in CSy off time -#define IS31FL3743A_PUR_2K_OHM_CS_OFF 0b011 // 2 kOhm resistor in CSy off time -#define IS31FL3743A_PUR_1K_OHM 0b100 // 1 kOhm resistor -#define IS31FL3743A_PUR_2K_OHM 0b101 // 2 kOhm resistor -#define IS31FL3743A_PUR_4K_OHM 0b110 // 4 kOhm resistor -#define IS31FL3743A_PUR_8K_OHM 0b111 // 8 kOhm resistor - -#define IS31FL3743A_SYNC_NONE 0b00 -#define IS31FL3743A_SYNC_SLAVE 0b10 -#define IS31FL3743A_SYNC_MASTER 0b11 - -#define CS1_SW1 0x00 -#define CS2_SW1 0x01 -#define CS3_SW1 0x02 -#define CS4_SW1 0x03 -#define CS5_SW1 0x04 -#define CS6_SW1 0x05 -#define CS7_SW1 0x06 -#define CS8_SW1 0x07 -#define CS9_SW1 0x08 -#define CS10_SW1 0x09 -#define CS11_SW1 0x0A -#define CS12_SW1 0x0B -#define CS13_SW1 0x0C -#define CS14_SW1 0x0D -#define CS15_SW1 0x0E -#define CS16_SW1 0x0F -#define CS17_SW1 0x10 -#define CS18_SW1 0x11 - -#define CS1_SW2 0x12 -#define CS2_SW2 0x13 -#define CS3_SW2 0x14 -#define CS4_SW2 0x15 -#define CS5_SW2 0x16 -#define CS6_SW2 0x17 -#define CS7_SW2 0x18 -#define CS8_SW2 0x19 -#define CS9_SW2 0x1A -#define CS10_SW2 0x1B -#define CS11_SW2 0x1C -#define CS12_SW2 0x1D -#define CS13_SW2 0x1E -#define CS14_SW2 0x1F -#define CS15_SW2 0x20 -#define CS16_SW2 0x21 -#define CS17_SW2 0x22 -#define CS18_SW2 0x23 - -#define CS1_SW3 0x24 -#define CS2_SW3 0x25 -#define CS3_SW3 0x26 -#define CS4_SW3 0x27 -#define CS5_SW3 0x28 -#define CS6_SW3 0x29 -#define CS7_SW3 0x2A -#define CS8_SW3 0x2B -#define CS9_SW3 0x2C -#define CS10_SW3 0x2D -#define CS11_SW3 0x2E -#define CS12_SW3 0x2F -#define CS13_SW3 0x30 -#define CS14_SW3 0x31 -#define CS15_SW3 0x32 -#define CS16_SW3 0x33 -#define CS17_SW3 0x34 -#define CS18_SW3 0x35 - -#define CS1_SW4 0x36 -#define CS2_SW4 0x37 -#define CS3_SW4 0x38 -#define CS4_SW4 0x39 -#define CS5_SW4 0x3A -#define CS6_SW4 0x3B -#define CS7_SW4 0x3C -#define CS8_SW4 0x3D -#define CS9_SW4 0x3E -#define CS10_SW4 0x3F -#define CS11_SW4 0x40 -#define CS12_SW4 0x41 -#define CS13_SW4 0x42 -#define CS14_SW4 0x43 -#define CS15_SW4 0x44 -#define CS16_SW4 0x45 -#define CS17_SW4 0x46 -#define CS18_SW4 0x47 - -#define CS1_SW5 0x48 -#define CS2_SW5 0x49 -#define CS3_SW5 0x4A -#define CS4_SW5 0x4B -#define CS5_SW5 0x4C -#define CS6_SW5 0x4D -#define CS7_SW5 0x4E -#define CS8_SW5 0x4F -#define CS9_SW5 0x50 -#define CS10_SW5 0x51 -#define CS11_SW5 0x52 -#define CS12_SW5 0x53 -#define CS13_SW5 0x54 -#define CS14_SW5 0x55 -#define CS15_SW5 0x56 -#define CS16_SW5 0x57 -#define CS17_SW5 0x58 -#define CS18_SW5 0x59 - -#define CS1_SW6 0x5A -#define CS2_SW6 0x5B -#define CS3_SW6 0x5C -#define CS4_SW6 0x5D -#define CS5_SW6 0x5E -#define CS6_SW6 0x5F -#define CS7_SW6 0x60 -#define CS8_SW6 0x61 -#define CS9_SW6 0x62 -#define CS10_SW6 0x63 -#define CS11_SW6 0x64 -#define CS12_SW6 0x65 -#define CS13_SW6 0x66 -#define CS14_SW6 0x67 -#define CS15_SW6 0x68 -#define CS16_SW6 0x69 -#define CS17_SW6 0x6A -#define CS18_SW6 0x6B - -#define CS1_SW7 0x6C -#define CS2_SW7 0x6D -#define CS3_SW7 0x6E -#define CS4_SW7 0x6F -#define CS5_SW7 0x70 -#define CS6_SW7 0x71 -#define CS7_SW7 0x72 -#define CS8_SW7 0x73 -#define CS9_SW7 0x74 -#define CS10_SW7 0x75 -#define CS11_SW7 0x76 -#define CS12_SW7 0x77 -#define CS13_SW7 0x78 -#define CS14_SW7 0x79 -#define CS15_SW7 0x7A -#define CS16_SW7 0x7B -#define CS17_SW7 0x7C -#define CS18_SW7 0x7D - -#define CS1_SW8 0x7E -#define CS2_SW8 0x7F -#define CS3_SW8 0x80 -#define CS4_SW8 0x81 -#define CS5_SW8 0x82 -#define CS6_SW8 0x83 -#define CS7_SW8 0x84 -#define CS8_SW8 0x85 -#define CS9_SW8 0x86 -#define CS10_SW8 0x87 -#define CS11_SW8 0x88 -#define CS12_SW8 0x89 -#define CS13_SW8 0x8A -#define CS14_SW8 0x8B -#define CS15_SW8 0x8C -#define CS16_SW8 0x8D -#define CS17_SW8 0x8E -#define CS18_SW8 0x8F - -#define CS1_SW9 0x90 -#define CS2_SW9 0x91 -#define CS3_SW9 0x92 -#define CS4_SW9 0x93 -#define CS5_SW9 0x94 -#define CS6_SW9 0x95 -#define CS7_SW9 0x96 -#define CS8_SW9 0x97 -#define CS9_SW9 0x98 -#define CS10_SW9 0x99 -#define CS11_SW9 0x9A -#define CS12_SW9 0x9B -#define CS13_SW9 0x9C -#define CS14_SW9 0x9D -#define CS15_SW9 0x9E -#define CS16_SW9 0x9F -#define CS17_SW9 0xA0 -#define CS18_SW9 0xA1 - -#define CS1_SW10 0xA2 -#define CS2_SW10 0xA3 -#define CS3_SW10 0xA4 -#define CS4_SW10 0xA5 -#define CS5_SW10 0xA6 -#define CS6_SW10 0xA7 -#define CS7_SW10 0xA8 -#define CS8_SW10 0xA9 -#define CS9_SW10 0xAA -#define CS10_SW10 0xAB -#define CS11_SW10 0xAC -#define CS12_SW10 0xAD -#define CS13_SW10 0xAE -#define CS14_SW10 0xAF -#define CS15_SW10 0xB0 -#define CS16_SW10 0xB1 -#define CS17_SW10 0xB2 -#define CS18_SW10 0xB3 - -#define CS1_SW11 0xB4 -#define CS2_SW11 0xB5 -#define CS3_SW11 0xB6 -#define CS4_SW11 0xB7 -#define CS5_SW11 0xB8 -#define CS6_SW11 0xB9 -#define CS7_SW11 0xBA -#define CS8_SW11 0xBB -#define CS9_SW11 0xBC -#define CS10_SW11 0xBD -#define CS11_SW11 0xBE -#define CS12_SW11 0xBF -#define CS13_SW11 0xC0 -#define CS14_SW11 0xC1 -#define CS15_SW11 0xC2 -#define CS16_SW11 0xC3 -#define CS17_SW11 0xC4 -#define CS18_SW11 0xC5 diff --git a/drivers/led/issi/is31fl3745-mono.c b/drivers/led/issi/is31fl3745-mono.c new file mode 100644 index 0000000000..c99f397f53 --- /dev/null +++ b/drivers/led/issi/is31fl3745-mono.c @@ -0,0 +1,216 @@ +#include "is31fl3745-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3745_PWM_REGISTER_COUNT 144 +#define IS31FL3745_SCALING_REGISTER_COUNT 144 + +#ifndef IS31FL3745_I2C_TIMEOUT +# define IS31FL3745_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3745_I2C_PERSISTENCE +# define IS31FL3745_I2C_PERSISTENCE 0 +#endif + +#ifndef IS31FL3745_CONFIGURATION +# define IS31FL3745_CONFIGURATION 0x31 +#endif + +#ifndef IS31FL3745_SW_PULLDOWN +# define IS31FL3745_SW_PULLDOWN IS31FL3745_PDR_2K_OHM_SW_OFF +#endif + +#ifndef IS31FL3745_CS_PULLUP +# define IS31FL3745_CS_PULLUP IS31FL3745_PUR_2K_OHM_CS_OFF +#endif + +#ifndef IS31FL3745_GLOBAL_CURRENT +# define IS31FL3745_GLOBAL_CURRENT 0xFF +#endif + +#ifndef IS31FL3745_SYNC_1 +# define IS31FL3745_SYNC_1 IS31FL3745_SYNC_NONE +#endif +#ifndef IS31FL3745_SYNC_2 +# define IS31FL3745_SYNC_2 IS31FL3745_SYNC_NONE +#endif +#ifndef IS31FL3745_SYNC_3 +# define IS31FL3745_SYNC_3 IS31FL3745_SYNC_NONE +#endif +#ifndef IS31FL3745_SYNC_4 +# define IS31FL3745_SYNC_4 IS31FL3745_SYNC_NONE +#endif + +uint8_t i2c_transfer_buffer[20] = {0xFF}; + +uint8_t g_pwm_buffer[IS31FL3745_DRIVER_COUNT][IS31FL3745_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3745_DRIVER_COUNT] = {false}; +bool g_scaling_registers_update_required[IS31FL3745_DRIVER_COUNT] = {false}; + +uint8_t g_scaling_registers[IS31FL3745_DRIVER_COUNT][IS31FL3745_SCALING_REGISTER_COUNT]; + +void is31fl3745_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3745_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3745_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3745_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3745_I2C_TIMEOUT); +#endif +} + +void is31fl3745_select_page(uint8_t addr, uint8_t page) { + is31fl3745_write_register(addr, IS31FL3745_REG_COMMAND_WRITE_LOCK, IS31FL3745_COMMAND_WRITE_LOCK_MAGIC); + is31fl3745_write_register(addr, IS31FL3745_REG_COMMAND, page); +} + +void is31fl3745_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // Assumes page 0 is already selected. + // If any of the transactions fails function returns false. + // Transmit PWM registers in 12 transfers of 16 bytes. + // i2c_transfer_buffer[] is 20 bytes + + // Iterate over the pwm_buffer contents at 16 byte intervals. + for (int i = 0; i < IS31FL3745_PWM_REGISTER_COUNT; i += 16) { + i2c_transfer_buffer[0] = i + 1; + // Copy the data from i to i+15. + // Device will auto-increment register for data after the first byte + // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); + +#if IS31FL3745_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3745_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3745_I2C_TIMEOUT) != 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3745_I2C_TIMEOUT); +#endif + } +} + +void is31fl3745_init_drivers(void) { + i2c_init(); + + is31fl3745_init(IS31FL3745_I2C_ADDRESS_1, IS31FL3745_SYNC_1); +#if defined(IS31FL3745_I2C_ADDRESS_2) + is31fl3745_init(IS31FL3745_I2C_ADDRESS_2, IS31FL3745_SYNC_2); +# if defined(IS31FL3745_I2C_ADDRESS_3) + is31fl3745_init(IS31FL3745_I2C_ADDRESS_3, IS31FL3745_SYNC_3); +# if defined(IS31FL3745_I2C_ADDRESS_4) + is31fl3745_init(IS31FL3745_I2C_ADDRESS_4, IS31FL3745_SYNC_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3745_LED_COUNT; i++) { + is31fl3745_set_scaling_register(i, 0xFF); + } + + is31fl3745_update_scaling_registers(IS31FL3745_I2C_ADDRESS_1, 0); +#if defined(IS31FL3745_I2C_ADDRESS_2) + is31fl3745_update_scaling_registers(IS31FL3745_I2C_ADDRESS_2, 1); +# if defined(IS31FL3745_I2C_ADDRESS_3) + is31fl3745_update_scaling_registers(IS31FL3745_I2C_ADDRESS_3, 2); +# if defined(IS31FL3745_I2C_ADDRESS_4) + is31fl3745_update_scaling_registers(IS31FL3745_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3745_init(uint8_t addr, uint8_t sync) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + + is31fl3745_select_page(addr, IS31FL3745_COMMAND_SCALING); + + // Turn off all LEDs. + for (int i = 0; i < IS31FL3745_SCALING_REGISTER_COUNT; i++) { + is31fl3745_write_register(addr, i + 1, 0x00); + } + + is31fl3745_select_page(addr, IS31FL3745_COMMAND_PWM); + + for (int i = 0; i < IS31FL3745_PWM_REGISTER_COUNT; i++) { + is31fl3745_write_register(addr, i + 1, 0x00); + } + + is31fl3745_select_page(addr, IS31FL3745_COMMAND_FUNCTION); + + is31fl3745_write_register(addr, IS31FL3745_FUNCTION_REG_PULLDOWNUP, (IS31FL3745_SW_PULLDOWN << 4) | IS31FL3745_CS_PULLUP); + is31fl3745_write_register(addr, IS31FL3745_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3745_GLOBAL_CURRENT); + is31fl3745_write_register(addr, IS31FL3745_FUNCTION_REG_SPREAD_SPECTRUM, (sync & 0b11) << 6); + is31fl3745_write_register(addr, IS31FL3745_FUNCTION_REG_CONFIGURATION, IS31FL3745_CONFIGURATION); + + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void is31fl3745_set_value(int index, uint8_t value) { + is31fl3745_led_t led; + if (index >= 0 && index < IS31FL3745_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3745_leds[index]), sizeof(led)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + g_pwm_buffer_update_required[led.driver] = true; + g_pwm_buffer[led.driver][led.v] = value; + } +} + +void is31fl3745_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3745_LED_COUNT; i++) { + is31fl3745_set_value(i, value); + } +} + +void is31fl3745_set_scaling_register(uint8_t index, uint8_t value) { + is31fl3745_led_t led; + memcpy_P(&led, (&g_is31fl3745_leds[index]), sizeof(led)); + + g_scaling_registers[led.driver][led.v] = value; + + g_scaling_registers_update_required[led.driver] = true; +} + +void is31fl3745_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3745_select_page(addr, IS31FL3745_COMMAND_PWM); + + is31fl3745_write_pwm_buffer(addr, g_pwm_buffer[index]); + } + + g_pwm_buffer_update_required[index] = false; +} + +void is31fl3745_update_scaling_registers(uint8_t addr, uint8_t index) { + if (g_scaling_registers_update_required[index]) { + is31fl3745_select_page(addr, IS31FL3745_COMMAND_SCALING); + + for (int i = 0; i < IS31FL3745_SCALING_REGISTER_COUNT; i++) { + is31fl3745_write_register(addr, i + 1, g_scaling_registers[index][i]); + } + g_scaling_registers_update_required[index] = false; + } +} + +void is31fl3745_flush(void) { + is31fl3745_update_pwm_buffers(IS31FL3745_I2C_ADDRESS_1, 0); +#if defined(IS31FL3745_I2C_ADDRESS_2) + is31fl3745_update_pwm_buffers(IS31FL3745_I2C_ADDRESS_2, 1); +# if defined(IS31FL3745_I2C_ADDRESS_3) + is31fl3745_update_pwm_buffers(IS31FL3745_I2C_ADDRESS_3, 2); +# if defined(IS31FL3745_I2C_ADDRESS_4) + is31fl3745_update_pwm_buffers(IS31FL3745_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3745-mono.h b/drivers/led/issi/is31fl3745-mono.h new file mode 100644 index 0000000000..dbff193acd --- /dev/null +++ b/drivers/led/issi/is31fl3745-mono.h @@ -0,0 +1,272 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2020 MelGeek + * Copyright 2021 MasterSpoon + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +#define IS31FL3745_REG_ID 0xFC + +#define IS31FL3745_REG_COMMAND 0xFD + +#define IS31FL3745_COMMAND_PWM 0x00 +#define IS31FL3745_COMMAND_SCALING 0x01 +#define IS31FL3745_COMMAND_FUNCTION 0x02 + +#define IS31FL3745_FUNCTION_REG_CONFIGURATION 0x00 +#define IS31FL3745_FUNCTION_REG_GLOBAL_CURRENT 0x01 +#define IS31FL3745_FUNCTION_REG_PULLDOWNUP 0x02 +#define IS31FL3745_FUNCTION_REG_TEMPERATURE 0x24 +#define IS31FL3745_FUNCTION_REG_SPREAD_SPECTRUM 0x25 +#define IS31FL3745_FUNCTION_REG_RESET 0x2F + +#define IS31FL3745_REG_COMMAND_WRITE_LOCK 0xFE +#define IS31FL3745_COMMAND_WRITE_LOCK_MAGIC 0xC5 + +#define IS31FL3745_I2C_ADDRESS_GND_GND 0x20 +#define IS31FL3745_I2C_ADDRESS_GND_SCL 0x21 +#define IS31FL3745_I2C_ADDRESS_GND_SDA 0x22 +#define IS31FL3745_I2C_ADDRESS_GND_VCC 0x23 +#define IS31FL3745_I2C_ADDRESS_SCL_GND 0x24 +#define IS31FL3745_I2C_ADDRESS_SCL_SCL 0x25 +#define IS31FL3745_I2C_ADDRESS_SCL_SDA 0x26 +#define IS31FL3745_I2C_ADDRESS_SCL_VCC 0x27 +#define IS31FL3745_I2C_ADDRESS_SDA_GND 0x28 +#define IS31FL3745_I2C_ADDRESS_SDA_SCL 0x29 +#define IS31FL3745_I2C_ADDRESS_SDA_SDA 0x2A +#define IS31FL3745_I2C_ADDRESS_SDA_VCC 0x2B +#define IS31FL3745_I2C_ADDRESS_VCC_GND 0x2C +#define IS31FL3745_I2C_ADDRESS_VCC_SCL 0x2D +#define IS31FL3745_I2C_ADDRESS_VCC_SDA 0x2E +#define IS31FL3745_I2C_ADDRESS_VCC_VCC 0x2F + +#if defined(LED_MATRIX_IS31FL3745) +# define IS31FL3745_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined(IS31FL3745_I2C_ADDRESS_4) +# define IS31FL3745_DRIVER_COUNT 4 +#elif defined(IS31FL3745_I2C_ADDRESS_3) +# define IS31FL3745_DRIVER_COUNT 3 +#elif defined(IS31FL3745_I2C_ADDRESS_2) +# define IS31FL3745_DRIVER_COUNT 2 +#elif defined(IS31FL3745_I2C_ADDRESS_1) +# define IS31FL3745_DRIVER_COUNT 1 +#endif + +typedef struct is31fl3745_led_t { + uint8_t driver : 2; + uint8_t v; +} PACKED is31fl3745_led_t; + +extern const is31fl3745_led_t PROGMEM g_is31fl3745_leds[IS31FL3745_LED_COUNT]; + +void is31fl3745_init_drivers(void); +void is31fl3745_init(uint8_t addr, uint8_t sync); +void is31fl3745_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3745_select_page(uint8_t addr, uint8_t page); +void is31fl3745_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3745_set_value(int index, uint8_t value); +void is31fl3745_set_value_all(uint8_t value); + +void is31fl3745_set_scaling_register(uint8_t index, uint8_t value); + +void is31fl3745_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3745_update_scaling_registers(uint8_t addr, uint8_t index); + +void is31fl3745_flush(void); + +#define IS31FL3745_PDR_0_OHM 0b000 // No pull-down resistor +#define IS31FL3745_PDR_0K5_OHM_SW_OFF 0b001 // 0.5 kOhm resistor in SWx off time +#define IS31FL3745_PDR_1K_OHM_SW_OFF 0b010 // 1 kOhm resistor in SWx off time +#define IS31FL3745_PDR_2K_OHM_SW_OFF 0b011 // 2 kOhm resistor in SWx off time +#define IS31FL3745_PDR_1K_OHM 0b100 // 1 kOhm resistor +#define IS31FL3745_PDR_2K_OHM 0b101 // 2 kOhm resistor +#define IS31FL3745_PDR_4K_OHM 0b110 // 4 kOhm resistor +#define IS31FL3745_PDR_8K_OHM 0b111 // 8 kOhm resistor + +#define IS31FL3745_PUR_0_OHM 0b000 // No pull-up resistor +#define IS31FL3745_PUR_0K5_OHM_CS_OFF 0b001 // 0.5 kOhm resistor in CSy off time +#define IS31FL3745_PUR_1K_OHM_CS_OFF 0b010 // 1 kOhm resistor in CSy off time +#define IS31FL3745_PUR_2K_OHM_CS_OFF 0b011 // 2 kOhm resistor in CSy off time +#define IS31FL3745_PUR_1K_OHM 0b100 // 1 kOhm resistor +#define IS31FL3745_PUR_2K_OHM 0b101 // 2 kOhm resistor +#define IS31FL3745_PUR_4K_OHM 0b110 // 4 kOhm resistor +#define IS31FL3745_PUR_8K_OHM 0b111 // 8 kOhm resistor + +#define IS31FL3745_SYNC_NONE 0b00 +#define IS31FL3745_SYNC_SLAVE 0b10 +#define IS31FL3745_SYNC_MASTER 0b11 + +#define CS1_SW1 0x00 +#define CS2_SW1 0x01 +#define CS3_SW1 0x02 +#define CS4_SW1 0x03 +#define CS5_SW1 0x04 +#define CS6_SW1 0x05 +#define CS7_SW1 0x06 +#define CS8_SW1 0x07 +#define CS9_SW1 0x08 +#define CS10_SW1 0x09 +#define CS11_SW1 0x0A +#define CS12_SW1 0x0B +#define CS13_SW1 0x0C +#define CS14_SW1 0x0D +#define CS15_SW1 0x0E +#define CS16_SW1 0x0F +#define CS17_SW1 0x10 +#define CS18_SW1 0x11 + +#define CS1_SW2 0x12 +#define CS2_SW2 0x13 +#define CS3_SW2 0x14 +#define CS4_SW2 0x15 +#define CS5_SW2 0x16 +#define CS6_SW2 0x17 +#define CS7_SW2 0x18 +#define CS8_SW2 0x19 +#define CS9_SW2 0x1A +#define CS10_SW2 0x1B +#define CS11_SW2 0x1C +#define CS12_SW2 0x1D +#define CS13_SW2 0x1E +#define CS14_SW2 0x1F +#define CS15_SW2 0x20 +#define CS16_SW2 0x21 +#define CS17_SW2 0x22 +#define CS18_SW2 0x23 + +#define CS1_SW3 0x24 +#define CS2_SW3 0x25 +#define CS3_SW3 0x26 +#define CS4_SW3 0x27 +#define CS5_SW3 0x28 +#define CS6_SW3 0x29 +#define CS7_SW3 0x2A +#define CS8_SW3 0x2B +#define CS9_SW3 0x2C +#define CS10_SW3 0x2D +#define CS11_SW3 0x2E +#define CS12_SW3 0x2F +#define CS13_SW3 0x30 +#define CS14_SW3 0x31 +#define CS15_SW3 0x32 +#define CS16_SW3 0x33 +#define CS17_SW3 0x34 +#define CS18_SW3 0x35 + +#define CS1_SW4 0x36 +#define CS2_SW4 0x37 +#define CS3_SW4 0x38 +#define CS4_SW4 0x39 +#define CS5_SW4 0x3A +#define CS6_SW4 0x3B +#define CS7_SW4 0x3C +#define CS8_SW4 0x3D +#define CS9_SW4 0x3E +#define CS10_SW4 0x3F +#define CS11_SW4 0x40 +#define CS12_SW4 0x41 +#define CS13_SW4 0x42 +#define CS14_SW4 0x43 +#define CS15_SW4 0x44 +#define CS16_SW4 0x45 +#define CS17_SW4 0x46 +#define CS18_SW4 0x47 + +#define CS1_SW5 0x48 +#define CS2_SW5 0x49 +#define CS3_SW5 0x4A +#define CS4_SW5 0x4B +#define CS5_SW5 0x4C +#define CS6_SW5 0x4D +#define CS7_SW5 0x4E +#define CS8_SW5 0x4F +#define CS9_SW5 0x50 +#define CS10_SW5 0x51 +#define CS11_SW5 0x52 +#define CS12_SW5 0x53 +#define CS13_SW5 0x54 +#define CS14_SW5 0x55 +#define CS15_SW5 0x56 +#define CS16_SW5 0x57 +#define CS17_SW5 0x58 +#define CS18_SW5 0x59 + +#define CS1_SW6 0x5A +#define CS2_SW6 0x5B +#define CS3_SW6 0x5C +#define CS4_SW6 0x5D +#define CS5_SW6 0x5E +#define CS6_SW6 0x5F +#define CS7_SW6 0x60 +#define CS8_SW6 0x61 +#define CS9_SW6 0x62 +#define CS10_SW6 0x63 +#define CS11_SW6 0x64 +#define CS12_SW6 0x65 +#define CS13_SW6 0x66 +#define CS14_SW6 0x67 +#define CS15_SW6 0x68 +#define CS16_SW6 0x69 +#define CS17_SW6 0x6A +#define CS18_SW6 0x6B + +#define CS1_SW7 0x6C +#define CS2_SW7 0x6D +#define CS3_SW7 0x6E +#define CS4_SW7 0x6F +#define CS5_SW7 0x70 +#define CS6_SW7 0x71 +#define CS7_SW7 0x72 +#define CS8_SW7 0x73 +#define CS9_SW7 0x74 +#define CS10_SW7 0x75 +#define CS11_SW7 0x76 +#define CS12_SW7 0x77 +#define CS13_SW7 0x78 +#define CS14_SW7 0x79 +#define CS15_SW7 0x7A +#define CS16_SW7 0x7B +#define CS17_SW7 0x7C +#define CS18_SW7 0x7D + +#define CS1_SW8 0x7E +#define CS2_SW8 0x7F +#define CS3_SW8 0x80 +#define CS4_SW8 0x81 +#define CS5_SW8 0x82 +#define CS6_SW8 0x83 +#define CS7_SW8 0x84 +#define CS8_SW8 0x85 +#define CS9_SW8 0x86 +#define CS10_SW8 0x87 +#define CS11_SW8 0x88 +#define CS12_SW8 0x89 +#define CS13_SW8 0x8A +#define CS14_SW8 0x8B +#define CS15_SW8 0x8C +#define CS16_SW8 0x8D +#define CS17_SW8 0x8E +#define CS18_SW8 0x8F diff --git a/drivers/led/issi/is31fl3745-simple.c b/drivers/led/issi/is31fl3745-simple.c deleted file mode 100644 index 46b41fe3d4..0000000000 --- a/drivers/led/issi/is31fl3745-simple.c +++ /dev/null @@ -1,216 +0,0 @@ -#include "is31fl3745-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3745_PWM_REGISTER_COUNT 144 -#define IS31FL3745_SCALING_REGISTER_COUNT 144 - -#ifndef IS31FL3745_I2C_TIMEOUT -# define IS31FL3745_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3745_I2C_PERSISTENCE -# define IS31FL3745_I2C_PERSISTENCE 0 -#endif - -#ifndef IS31FL3745_CONFIGURATION -# define IS31FL3745_CONFIGURATION 0x31 -#endif - -#ifndef IS31FL3745_SW_PULLDOWN -# define IS31FL3745_SW_PULLDOWN IS31FL3745_PDR_2K_OHM_SW_OFF -#endif - -#ifndef IS31FL3745_CS_PULLUP -# define IS31FL3745_CS_PULLUP IS31FL3745_PUR_2K_OHM_CS_OFF -#endif - -#ifndef IS31FL3745_GLOBAL_CURRENT -# define IS31FL3745_GLOBAL_CURRENT 0xFF -#endif - -#ifndef IS31FL3745_SYNC_1 -# define IS31FL3745_SYNC_1 IS31FL3745_SYNC_NONE -#endif -#ifndef IS31FL3745_SYNC_2 -# define IS31FL3745_SYNC_2 IS31FL3745_SYNC_NONE -#endif -#ifndef IS31FL3745_SYNC_3 -# define IS31FL3745_SYNC_3 IS31FL3745_SYNC_NONE -#endif -#ifndef IS31FL3745_SYNC_4 -# define IS31FL3745_SYNC_4 IS31FL3745_SYNC_NONE -#endif - -uint8_t i2c_transfer_buffer[20] = {0xFF}; - -uint8_t g_pwm_buffer[IS31FL3745_DRIVER_COUNT][IS31FL3745_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3745_DRIVER_COUNT] = {false}; -bool g_scaling_registers_update_required[IS31FL3745_DRIVER_COUNT] = {false}; - -uint8_t g_scaling_registers[IS31FL3745_DRIVER_COUNT][IS31FL3745_SCALING_REGISTER_COUNT]; - -void is31fl3745_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3745_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3745_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3745_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3745_I2C_TIMEOUT); -#endif -} - -void is31fl3745_select_page(uint8_t addr, uint8_t page) { - is31fl3745_write_register(addr, IS31FL3745_REG_COMMAND_WRITE_LOCK, IS31FL3745_COMMAND_WRITE_LOCK_MAGIC); - is31fl3745_write_register(addr, IS31FL3745_REG_COMMAND, page); -} - -void is31fl3745_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // Assumes page 0 is already selected. - // If any of the transactions fails function returns false. - // Transmit PWM registers in 12 transfers of 16 bytes. - // i2c_transfer_buffer[] is 20 bytes - - // Iterate over the pwm_buffer contents at 16 byte intervals. - for (int i = 0; i < IS31FL3745_PWM_REGISTER_COUNT; i += 16) { - i2c_transfer_buffer[0] = i + 1; - // Copy the data from i to i+15. - // Device will auto-increment register for data after the first byte - // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); - -#if IS31FL3745_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3745_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3745_I2C_TIMEOUT) != 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3745_I2C_TIMEOUT); -#endif - } -} - -void is31fl3745_init_drivers(void) { - i2c_init(); - - is31fl3745_init(IS31FL3745_I2C_ADDRESS_1, IS31FL3745_SYNC_1); -#if defined(IS31FL3745_I2C_ADDRESS_2) - is31fl3745_init(IS31FL3745_I2C_ADDRESS_2, IS31FL3745_SYNC_2); -# if defined(IS31FL3745_I2C_ADDRESS_3) - is31fl3745_init(IS31FL3745_I2C_ADDRESS_3, IS31FL3745_SYNC_3); -# if defined(IS31FL3745_I2C_ADDRESS_4) - is31fl3745_init(IS31FL3745_I2C_ADDRESS_4, IS31FL3745_SYNC_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3745_LED_COUNT; i++) { - is31fl3745_set_scaling_register(i, 0xFF); - } - - is31fl3745_update_scaling_registers(IS31FL3745_I2C_ADDRESS_1, 0); -#if defined(IS31FL3745_I2C_ADDRESS_2) - is31fl3745_update_scaling_registers(IS31FL3745_I2C_ADDRESS_2, 1); -# if defined(IS31FL3745_I2C_ADDRESS_3) - is31fl3745_update_scaling_registers(IS31FL3745_I2C_ADDRESS_3, 2); -# if defined(IS31FL3745_I2C_ADDRESS_4) - is31fl3745_update_scaling_registers(IS31FL3745_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3745_init(uint8_t addr, uint8_t sync) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, shutdown is enabled last. - // Set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - - is31fl3745_select_page(addr, IS31FL3745_COMMAND_SCALING); - - // Turn off all LEDs. - for (int i = 0; i < IS31FL3745_SCALING_REGISTER_COUNT; i++) { - is31fl3745_write_register(addr, i + 1, 0x00); - } - - is31fl3745_select_page(addr, IS31FL3745_COMMAND_PWM); - - for (int i = 0; i < IS31FL3745_PWM_REGISTER_COUNT; i++) { - is31fl3745_write_register(addr, i + 1, 0x00); - } - - is31fl3745_select_page(addr, IS31FL3745_COMMAND_FUNCTION); - - is31fl3745_write_register(addr, IS31FL3745_FUNCTION_REG_PULLDOWNUP, (IS31FL3745_SW_PULLDOWN << 4) | IS31FL3745_CS_PULLUP); - is31fl3745_write_register(addr, IS31FL3745_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3745_GLOBAL_CURRENT); - is31fl3745_write_register(addr, IS31FL3745_FUNCTION_REG_SPREAD_SPECTRUM, (sync & 0b11) << 6); - is31fl3745_write_register(addr, IS31FL3745_FUNCTION_REG_CONFIGURATION, IS31FL3745_CONFIGURATION); - - // Wait 10ms to ensure the device has woken up. - wait_ms(10); -} - -void is31fl3745_set_value(int index, uint8_t value) { - is31fl3745_led_t led; - if (index >= 0 && index < IS31FL3745_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3745_leds[index]), sizeof(led)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - g_pwm_buffer_update_required[led.driver] = true; - g_pwm_buffer[led.driver][led.v] = value; - } -} - -void is31fl3745_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3745_LED_COUNT; i++) { - is31fl3745_set_value(i, value); - } -} - -void is31fl3745_set_scaling_register(uint8_t index, uint8_t value) { - is31fl3745_led_t led; - memcpy_P(&led, (&g_is31fl3745_leds[index]), sizeof(led)); - - g_scaling_registers[led.driver][led.v] = value; - - g_scaling_registers_update_required[led.driver] = true; -} - -void is31fl3745_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3745_select_page(addr, IS31FL3745_COMMAND_PWM); - - is31fl3745_write_pwm_buffer(addr, g_pwm_buffer[index]); - } - - g_pwm_buffer_update_required[index] = false; -} - -void is31fl3745_update_scaling_registers(uint8_t addr, uint8_t index) { - if (g_scaling_registers_update_required[index]) { - is31fl3745_select_page(addr, IS31FL3745_COMMAND_SCALING); - - for (int i = 0; i < IS31FL3745_SCALING_REGISTER_COUNT; i++) { - is31fl3745_write_register(addr, i + 1, g_scaling_registers[index][i]); - } - g_scaling_registers_update_required[index] = false; - } -} - -void is31fl3745_flush(void) { - is31fl3745_update_pwm_buffers(IS31FL3745_I2C_ADDRESS_1, 0); -#if defined(IS31FL3745_I2C_ADDRESS_2) - is31fl3745_update_pwm_buffers(IS31FL3745_I2C_ADDRESS_2, 1); -# if defined(IS31FL3745_I2C_ADDRESS_3) - is31fl3745_update_pwm_buffers(IS31FL3745_I2C_ADDRESS_3, 2); -# if defined(IS31FL3745_I2C_ADDRESS_4) - is31fl3745_update_pwm_buffers(IS31FL3745_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3745-simple.h b/drivers/led/issi/is31fl3745-simple.h deleted file mode 100644 index dbff193acd..0000000000 --- a/drivers/led/issi/is31fl3745-simple.h +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2020 MelGeek - * Copyright 2021 MasterSpoon - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -#define IS31FL3745_REG_ID 0xFC - -#define IS31FL3745_REG_COMMAND 0xFD - -#define IS31FL3745_COMMAND_PWM 0x00 -#define IS31FL3745_COMMAND_SCALING 0x01 -#define IS31FL3745_COMMAND_FUNCTION 0x02 - -#define IS31FL3745_FUNCTION_REG_CONFIGURATION 0x00 -#define IS31FL3745_FUNCTION_REG_GLOBAL_CURRENT 0x01 -#define IS31FL3745_FUNCTION_REG_PULLDOWNUP 0x02 -#define IS31FL3745_FUNCTION_REG_TEMPERATURE 0x24 -#define IS31FL3745_FUNCTION_REG_SPREAD_SPECTRUM 0x25 -#define IS31FL3745_FUNCTION_REG_RESET 0x2F - -#define IS31FL3745_REG_COMMAND_WRITE_LOCK 0xFE -#define IS31FL3745_COMMAND_WRITE_LOCK_MAGIC 0xC5 - -#define IS31FL3745_I2C_ADDRESS_GND_GND 0x20 -#define IS31FL3745_I2C_ADDRESS_GND_SCL 0x21 -#define IS31FL3745_I2C_ADDRESS_GND_SDA 0x22 -#define IS31FL3745_I2C_ADDRESS_GND_VCC 0x23 -#define IS31FL3745_I2C_ADDRESS_SCL_GND 0x24 -#define IS31FL3745_I2C_ADDRESS_SCL_SCL 0x25 -#define IS31FL3745_I2C_ADDRESS_SCL_SDA 0x26 -#define IS31FL3745_I2C_ADDRESS_SCL_VCC 0x27 -#define IS31FL3745_I2C_ADDRESS_SDA_GND 0x28 -#define IS31FL3745_I2C_ADDRESS_SDA_SCL 0x29 -#define IS31FL3745_I2C_ADDRESS_SDA_SDA 0x2A -#define IS31FL3745_I2C_ADDRESS_SDA_VCC 0x2B -#define IS31FL3745_I2C_ADDRESS_VCC_GND 0x2C -#define IS31FL3745_I2C_ADDRESS_VCC_SCL 0x2D -#define IS31FL3745_I2C_ADDRESS_VCC_SDA 0x2E -#define IS31FL3745_I2C_ADDRESS_VCC_VCC 0x2F - -#if defined(LED_MATRIX_IS31FL3745) -# define IS31FL3745_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined(IS31FL3745_I2C_ADDRESS_4) -# define IS31FL3745_DRIVER_COUNT 4 -#elif defined(IS31FL3745_I2C_ADDRESS_3) -# define IS31FL3745_DRIVER_COUNT 3 -#elif defined(IS31FL3745_I2C_ADDRESS_2) -# define IS31FL3745_DRIVER_COUNT 2 -#elif defined(IS31FL3745_I2C_ADDRESS_1) -# define IS31FL3745_DRIVER_COUNT 1 -#endif - -typedef struct is31fl3745_led_t { - uint8_t driver : 2; - uint8_t v; -} PACKED is31fl3745_led_t; - -extern const is31fl3745_led_t PROGMEM g_is31fl3745_leds[IS31FL3745_LED_COUNT]; - -void is31fl3745_init_drivers(void); -void is31fl3745_init(uint8_t addr, uint8_t sync); -void is31fl3745_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3745_select_page(uint8_t addr, uint8_t page); -void is31fl3745_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3745_set_value(int index, uint8_t value); -void is31fl3745_set_value_all(uint8_t value); - -void is31fl3745_set_scaling_register(uint8_t index, uint8_t value); - -void is31fl3745_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3745_update_scaling_registers(uint8_t addr, uint8_t index); - -void is31fl3745_flush(void); - -#define IS31FL3745_PDR_0_OHM 0b000 // No pull-down resistor -#define IS31FL3745_PDR_0K5_OHM_SW_OFF 0b001 // 0.5 kOhm resistor in SWx off time -#define IS31FL3745_PDR_1K_OHM_SW_OFF 0b010 // 1 kOhm resistor in SWx off time -#define IS31FL3745_PDR_2K_OHM_SW_OFF 0b011 // 2 kOhm resistor in SWx off time -#define IS31FL3745_PDR_1K_OHM 0b100 // 1 kOhm resistor -#define IS31FL3745_PDR_2K_OHM 0b101 // 2 kOhm resistor -#define IS31FL3745_PDR_4K_OHM 0b110 // 4 kOhm resistor -#define IS31FL3745_PDR_8K_OHM 0b111 // 8 kOhm resistor - -#define IS31FL3745_PUR_0_OHM 0b000 // No pull-up resistor -#define IS31FL3745_PUR_0K5_OHM_CS_OFF 0b001 // 0.5 kOhm resistor in CSy off time -#define IS31FL3745_PUR_1K_OHM_CS_OFF 0b010 // 1 kOhm resistor in CSy off time -#define IS31FL3745_PUR_2K_OHM_CS_OFF 0b011 // 2 kOhm resistor in CSy off time -#define IS31FL3745_PUR_1K_OHM 0b100 // 1 kOhm resistor -#define IS31FL3745_PUR_2K_OHM 0b101 // 2 kOhm resistor -#define IS31FL3745_PUR_4K_OHM 0b110 // 4 kOhm resistor -#define IS31FL3745_PUR_8K_OHM 0b111 // 8 kOhm resistor - -#define IS31FL3745_SYNC_NONE 0b00 -#define IS31FL3745_SYNC_SLAVE 0b10 -#define IS31FL3745_SYNC_MASTER 0b11 - -#define CS1_SW1 0x00 -#define CS2_SW1 0x01 -#define CS3_SW1 0x02 -#define CS4_SW1 0x03 -#define CS5_SW1 0x04 -#define CS6_SW1 0x05 -#define CS7_SW1 0x06 -#define CS8_SW1 0x07 -#define CS9_SW1 0x08 -#define CS10_SW1 0x09 -#define CS11_SW1 0x0A -#define CS12_SW1 0x0B -#define CS13_SW1 0x0C -#define CS14_SW1 0x0D -#define CS15_SW1 0x0E -#define CS16_SW1 0x0F -#define CS17_SW1 0x10 -#define CS18_SW1 0x11 - -#define CS1_SW2 0x12 -#define CS2_SW2 0x13 -#define CS3_SW2 0x14 -#define CS4_SW2 0x15 -#define CS5_SW2 0x16 -#define CS6_SW2 0x17 -#define CS7_SW2 0x18 -#define CS8_SW2 0x19 -#define CS9_SW2 0x1A -#define CS10_SW2 0x1B -#define CS11_SW2 0x1C -#define CS12_SW2 0x1D -#define CS13_SW2 0x1E -#define CS14_SW2 0x1F -#define CS15_SW2 0x20 -#define CS16_SW2 0x21 -#define CS17_SW2 0x22 -#define CS18_SW2 0x23 - -#define CS1_SW3 0x24 -#define CS2_SW3 0x25 -#define CS3_SW3 0x26 -#define CS4_SW3 0x27 -#define CS5_SW3 0x28 -#define CS6_SW3 0x29 -#define CS7_SW3 0x2A -#define CS8_SW3 0x2B -#define CS9_SW3 0x2C -#define CS10_SW3 0x2D -#define CS11_SW3 0x2E -#define CS12_SW3 0x2F -#define CS13_SW3 0x30 -#define CS14_SW3 0x31 -#define CS15_SW3 0x32 -#define CS16_SW3 0x33 -#define CS17_SW3 0x34 -#define CS18_SW3 0x35 - -#define CS1_SW4 0x36 -#define CS2_SW4 0x37 -#define CS3_SW4 0x38 -#define CS4_SW4 0x39 -#define CS5_SW4 0x3A -#define CS6_SW4 0x3B -#define CS7_SW4 0x3C -#define CS8_SW4 0x3D -#define CS9_SW4 0x3E -#define CS10_SW4 0x3F -#define CS11_SW4 0x40 -#define CS12_SW4 0x41 -#define CS13_SW4 0x42 -#define CS14_SW4 0x43 -#define CS15_SW4 0x44 -#define CS16_SW4 0x45 -#define CS17_SW4 0x46 -#define CS18_SW4 0x47 - -#define CS1_SW5 0x48 -#define CS2_SW5 0x49 -#define CS3_SW5 0x4A -#define CS4_SW5 0x4B -#define CS5_SW5 0x4C -#define CS6_SW5 0x4D -#define CS7_SW5 0x4E -#define CS8_SW5 0x4F -#define CS9_SW5 0x50 -#define CS10_SW5 0x51 -#define CS11_SW5 0x52 -#define CS12_SW5 0x53 -#define CS13_SW5 0x54 -#define CS14_SW5 0x55 -#define CS15_SW5 0x56 -#define CS16_SW5 0x57 -#define CS17_SW5 0x58 -#define CS18_SW5 0x59 - -#define CS1_SW6 0x5A -#define CS2_SW6 0x5B -#define CS3_SW6 0x5C -#define CS4_SW6 0x5D -#define CS5_SW6 0x5E -#define CS6_SW6 0x5F -#define CS7_SW6 0x60 -#define CS8_SW6 0x61 -#define CS9_SW6 0x62 -#define CS10_SW6 0x63 -#define CS11_SW6 0x64 -#define CS12_SW6 0x65 -#define CS13_SW6 0x66 -#define CS14_SW6 0x67 -#define CS15_SW6 0x68 -#define CS16_SW6 0x69 -#define CS17_SW6 0x6A -#define CS18_SW6 0x6B - -#define CS1_SW7 0x6C -#define CS2_SW7 0x6D -#define CS3_SW7 0x6E -#define CS4_SW7 0x6F -#define CS5_SW7 0x70 -#define CS6_SW7 0x71 -#define CS7_SW7 0x72 -#define CS8_SW7 0x73 -#define CS9_SW7 0x74 -#define CS10_SW7 0x75 -#define CS11_SW7 0x76 -#define CS12_SW7 0x77 -#define CS13_SW7 0x78 -#define CS14_SW7 0x79 -#define CS15_SW7 0x7A -#define CS16_SW7 0x7B -#define CS17_SW7 0x7C -#define CS18_SW7 0x7D - -#define CS1_SW8 0x7E -#define CS2_SW8 0x7F -#define CS3_SW8 0x80 -#define CS4_SW8 0x81 -#define CS5_SW8 0x82 -#define CS6_SW8 0x83 -#define CS7_SW8 0x84 -#define CS8_SW8 0x85 -#define CS9_SW8 0x86 -#define CS10_SW8 0x87 -#define CS11_SW8 0x88 -#define CS12_SW8 0x89 -#define CS13_SW8 0x8A -#define CS14_SW8 0x8B -#define CS15_SW8 0x8C -#define CS16_SW8 0x8D -#define CS17_SW8 0x8E -#define CS18_SW8 0x8F diff --git a/drivers/led/issi/is31fl3746a-mono.c b/drivers/led/issi/is31fl3746a-mono.c new file mode 100644 index 0000000000..e0c29f3bd3 --- /dev/null +++ b/drivers/led/issi/is31fl3746a-mono.c @@ -0,0 +1,208 @@ +#include "is31fl3746a-mono.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3746A_PWM_REGISTER_COUNT 72 +#define IS31FL3746A_SCALING_REGISTER_COUNT 72 + +#ifndef IS31FL3746A_I2C_TIMEOUT +# define IS31FL3746A_I2C_TIMEOUT 100 +#endif + +#ifndef IS31FL3746A_I2C_PERSISTENCE +# define IS31FL3746A_I2C_PERSISTENCE 0 +#endif + +#ifndef IS31FL3746A_CONFIGURATION +# define IS31FL3746A_CONFIGURATION 0x01 +#endif + +#ifndef IS31FL3746A_PWM_FREQUENCY +# define IS31FL3746A_PWM_FREQUENCY IS31FL3746A_PWM_FREQUENCY_29K_HZ +#endif + +#ifndef IS31FL3746A_SW_PULLDOWN +# define IS31FL3746A_SW_PULLDOWN IS31FL3746A_PDR_2K_OHM_SW_OFF +#endif + +#ifndef IS31FL3746A_CS_PULLUP +# define IS31FL3746A_CS_PULLUP IS31FL3746A_PUR_2K_OHM_CS_OFF +#endif + +#ifndef IS31FL3746A_GLOBAL_CURRENT +# define IS31FL3746A_GLOBAL_CURRENT 0xFF +#endif + +uint8_t i2c_transfer_buffer[20] = {0xFF}; + +uint8_t g_pwm_buffer[IS31FL3746A_DRIVER_COUNT][IS31FL3746A_PWM_REGISTER_COUNT]; +bool g_pwm_buffer_update_required[IS31FL3746A_DRIVER_COUNT] = {false}; +bool g_scaling_registers_update_required[IS31FL3746A_DRIVER_COUNT] = {false}; + +uint8_t g_scaling_registers[IS31FL3746A_DRIVER_COUNT][IS31FL3746A_SCALING_REGISTER_COUNT]; + +void is31fl3746a_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if IS31FL3746A_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3746A_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3746A_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3746A_I2C_TIMEOUT); +#endif +} + +void is31fl3746a_select_page(uint8_t addr, uint8_t page) { + is31fl3746a_write_register(addr, IS31FL3746A_REG_COMMAND_WRITE_LOCK, IS31FL3746A_COMMAND_WRITE_LOCK_MAGIC); + is31fl3746a_write_register(addr, IS31FL3746A_REG_COMMAND, page); +} + +void is31fl3746a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // Assumes page 0 is already selected. + // If any of the transactions fails function returns false. + // Transmit PWM registers in 12 transfers of 16 bytes. + // i2c_transfer_buffer[] is 20 bytes + + // Iterate over the pwm_buffer contents at 16 byte intervals. + for (int i = 0; i < IS31FL3746A_PWM_REGISTER_COUNT; i += 16) { + i2c_transfer_buffer[0] = i + 1; + // Copy the data from i to i+15. + // Device will auto-increment register for data after the first byte + // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. + memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); + +#if IS31FL3746A_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3746A_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3746A_I2C_TIMEOUT) != 0) break; + } +#else + i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3746A_I2C_TIMEOUT); +#endif + } +} + +void is31fl3746a_init_drivers(void) { + i2c_init(); + + is31fl3746a_init(IS31FL3746A_I2C_ADDRESS_1); +#if defined(IS31FL3746A_I2C_ADDRESS_2) + is31fl3746a_init(IS31FL3746A_I2C_ADDRESS_2); +# if defined(IS31FL3746A_I2C_ADDRESS_3) + is31fl3746a_init(IS31FL3746A_I2C_ADDRESS_3); +# if defined(IS31FL3746A_I2C_ADDRESS_4) + is31fl3746a_init(IS31FL3746A_I2C_ADDRESS_4); +# endif +# endif +#endif + + for (int i = 0; i < IS31FL3746A_LED_COUNT; i++) { + is31fl3746a_set_scaling_register(i, 0xFF); + } + + is31fl3746a_update_scaling_registers(IS31FL3746A_I2C_ADDRESS_1, 0); +#if defined(IS31FL3746A_I2C_ADDRESS_2) + is31fl3746a_update_scaling_registers(IS31FL3746A_I2C_ADDRESS_2, 1); +# if defined(IS31FL3746A_I2C_ADDRESS_3) + is31fl3746a_update_scaling_registers(IS31FL3746A_I2C_ADDRESS_3, 2); +# if defined(IS31FL3746A_I2C_ADDRESS_4) + is31fl3746a_update_scaling_registers(IS31FL3746A_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void is31fl3746a_init(uint8_t addr) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + + is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_SCALING); + + // Turn off all LEDs. + for (int i = 0; i < IS31FL3746A_SCALING_REGISTER_COUNT; i++) { + is31fl3746a_write_register(addr, i + 1, 0x00); + } + + is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_PWM); + + for (int i = 0; i < IS31FL3746A_PWM_REGISTER_COUNT; i++) { + is31fl3746a_write_register(addr, i + 1, 0x00); + } + + is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_FUNCTION); + + is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_PULLDOWNUP, (IS31FL3746A_SW_PULLDOWN << 4) | IS31FL3746A_CS_PULLUP); + is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3746A_GLOBAL_CURRENT); + is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_PWM_ENABLE, 0x01); + is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_PWM_FREQUENCY, IS31FL3746A_PWM_FREQUENCY); + is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_CONFIGURATION, IS31FL3746A_CONFIGURATION); + + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void is31fl3746a_set_color(int index, uint8_t value) { + is31fl3746a_led_t led; + if (index >= 0 && index < IS31FL3746A_LED_COUNT) { + memcpy_P(&led, (&g_is31fl3746a_leds[index]), sizeof(led)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + g_pwm_buffer_update_required[led.driver] = true; + g_pwm_buffer[led.driver][led.v] = value; + } +} + +void is31fl3746a_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3746A_LED_COUNT; i++) { + is31fl3746a_set_value(i, value); + } +} + +void is31fl3746a_set_scaling_register(uint8_t index, uint8_t value) { + is31fl3746a_led_t led; + memcpy_P(&led, (&g_is31fl3746a_leds[index]), sizeof(led)); + + g_scaling_registers[led.driver][led.v] = value; + + g_scaling_registers_update_required[led.driver] = true; +} + +void is31fl3746a_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_PWM); + + is31fl3746a_write_pwm_buffer(addr, g_pwm_buffer[index]); + } + + g_pwm_buffer_update_required[index] = false; +} + +void is31fl3746a_update_scaling_registers(uint8_t addr, uint8_t index) { + if (g_scaling_registers_update_required[index]) { + is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_SCALING); + + for (int i = 0; i < IS31FL3746A_SCALING_REGISTER_COUNT; i++) { + is31fl3746a_write_register(addr, i + 1, g_scaling_registers[index][i]); + } + g_scaling_registers_update_required[index] = false; + } +} + +void is31fl3746a_flush(void) { + is31fl3746a_update_pwm_buffers(IS31FL3746A_I2C_ADDRESS_1, 0); +#if defined(IS31FL3746A_I2C_ADDRESS_2) + is31fl3746a_update_pwm_buffers(IS31FL3746A_I2C_ADDRESS_2, 1); +# if defined(IS31FL3746A_I2C_ADDRESS_3) + is31fl3746a_update_pwm_buffers(IS31FL3746A_I2C_ADDRESS_3, 2); +# if defined(IS31FL3746A_I2C_ADDRESS_4) + is31fl3746a_update_pwm_buffers(IS31FL3746A_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} diff --git a/drivers/led/issi/is31fl3746a-mono.h b/drivers/led/issi/is31fl3746a-mono.h new file mode 100644 index 0000000000..eda644ad19 --- /dev/null +++ b/drivers/led/issi/is31fl3746a-mono.h @@ -0,0 +1,192 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2020 MelGeek + * Copyright 2021 MasterSpoon + * + * 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +#define IS31FL3746A_REG_ID 0xFC + +#define IS31FL3746A_REG_COMMAND 0xFD + +#define IS31FL3746A_COMMAND_PWM 0x00 +#define IS31FL3746A_COMMAND_SCALING 0x01 +#define IS31FL3746A_COMMAND_FUNCTION 0x01 + +#define IS31FL3746A_FUNCTION_REG_CONFIGURATION 0x50 +#define IS31FL3746A_FUNCTION_REG_GLOBAL_CURRENT 0x51 +#define IS31FL3746A_FUNCTION_REG_PULLDOWNUP 0x52 +#define IS31FL3746A_FUNCTION_REG_TEMPERATURE 0x5F +#define IS31FL3746A_FUNCTION_REG_SPREAD_SPECTRUM 0x60 +#define IS31FL3746A_FUNCTION_REG_RESET 0x8F +#define IS31FL3746A_FUNCTION_REG_PWM_ENABLE 0xE0 +#define IS31FL3746A_FUNCTION_REG_PWM_FREQUENCY 0xE2 + +#define IS31FL3746A_REG_COMMAND_WRITE_LOCK 0xFE +#define IS31FL3746A_COMMAND_WRITE_LOCK_MAGIC 0xC5 + +#define IS31FL3746A_I2C_ADDRESS_GND_GND 0x60 +#define IS31FL3746A_I2C_ADDRESS_GND_SCL 0x61 +#define IS31FL3746A_I2C_ADDRESS_GND_SDA 0x62 +#define IS31FL3746A_I2C_ADDRESS_GND_VCC 0x63 +#define IS31FL3746A_I2C_ADDRESS_SCL_GND 0x64 +#define IS31FL3746A_I2C_ADDRESS_SCL_SCL 0x65 +#define IS31FL3746A_I2C_ADDRESS_SCL_SDA 0x66 +#define IS31FL3746A_I2C_ADDRESS_SCL_VCC 0x67 +#define IS31FL3746A_I2C_ADDRESS_SDA_GND 0x68 +#define IS31FL3746A_I2C_ADDRESS_SDA_SCL 0x69 +#define IS31FL3746A_I2C_ADDRESS_SDA_SDA 0x6A +#define IS31FL3746A_I2C_ADDRESS_SDA_VCC 0x6B +#define IS31FL3746A_I2C_ADDRESS_VCC_GND 0x6C +#define IS31FL3746A_I2C_ADDRESS_VCC_SCL 0x6D +#define IS31FL3746A_I2C_ADDRESS_VCC_SDA 0x6E +#define IS31FL3746A_I2C_ADDRESS_VCC_VCC 0x6F + +#if defined(LED_MATRIX_IS31FL3746A) +# define IS31FL3746A_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +typedef struct is31fl3746a_led_t { + uint8_t driver : 2; + uint8_t v; +} PACKED is31fl3746a_led_t; + +extern const is31fl3746a_led_t PROGMEM g_is31fl3746a_leds[IS31FL3746A_LED_COUNT]; + +void is31fl3746a_init_drivers(void); +void is31fl3746a_init(uint8_t addr, uint8_t sync); +void is31fl3746a_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3746a_select_page(uint8_t addr, uint8_t page); +void is31fl3746a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3746a_set_value(int index, uint8_t value); +void is31fl3746a_set_value_all(uint8_t value); + +void is31fl3746a_set_scaling_register(uint8_t index, uint8_t value); + +void is31fl3746a_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3746a_update_scaling_registers(uint8_t addr, uint8_t index); + +void is31fl3746a_flush(void); + +#define IS31FL3746A_PDR_0_OHM 0b000 // No pull-down resistor +#define IS31FL3746A_PDR_0K5_OHM_SW_OFF 0b001 // 0.5 kOhm resistor in SWx off time +#define IS31FL3746A_PDR_1K_OHM_SW_OFF 0b010 // 1 kOhm resistor in SWx off time +#define IS31FL3746A_PDR_2K_OHM_SW_OFF 0b011 // 2 kOhm resistor in SWx off time +#define IS31FL3746A_PDR_1K_OHM 0b100 // 1 kOhm resistor +#define IS31FL3746A_PDR_2K_OHM 0b101 // 2 kOhm resistor +#define IS31FL3746A_PDR_4K_OHM 0b110 // 4 kOhm resistor +#define IS31FL3746A_PDR_8K_OHM 0b111 // 8 kOhm resistor + +#define IS31FL3746A_PUR_0_OHM 0b000 // No pull-up resistor +#define IS31FL3746A_PUR_0K5_OHM_CS_OFF 0b001 // 0.5 kOhm resistor in CSy off time +#define IS31FL3746A_PUR_1K_OHM_CS_OFF 0b010 // 1 kOhm resistor in CSy off time +#define IS31FL3746A_PUR_2K_OHM_CS_OFF 0b011 // 2 kOhm resistor in CSy off time +#define IS31FL3746A_PUR_1K_OHM 0b100 // 1 kOhm resistor +#define IS31FL3746A_PUR_2K_OHM 0b101 // 2 kOhm resistor +#define IS31FL3746A_PUR_4K_OHM 0b110 // 4 kOhm resistor +#define IS31FL3746A_PUR_8K_OHM 0b111 // 8 kOhm resistor + +#define IS31FL3746A_PWM_FREQUENCY_29K_HZ 0b000 +#define IS31FL3746A_PWM_FREQUENCY_14K5_HZ 0b001 +#define IS31FL3746A_PWM_FREQUENCY_7K25_HZ 0b010 +#define IS31FL3746A_PWM_FREQUENCY_3K63_HZ 0b011 +#define IS31FL3746A_PWM_FREQUENCY_1K81_HZ 0b100 +#define IS31FL3746A_PWM_FREQUENCY_906_HZ 0b101 +#define IS31FL3746A_PWM_FREQUENCY_453_HZ 0b110 + +#define CS1_SW1 0x00 +#define CS2_SW1 0x01 +#define CS3_SW1 0x02 +#define CS4_SW1 0x03 +#define CS5_SW1 0x04 +#define CS6_SW1 0x05 +#define CS7_SW1 0x06 +#define CS8_SW1 0x07 +#define CS9_SW1 0x08 +#define CS10_SW1 0x09 +#define CS11_SW1 0x0A +#define CS12_SW1 0x0B +#define CS13_SW1 0x0C +#define CS14_SW1 0x0D +#define CS15_SW1 0x0E +#define CS16_SW1 0x0F +#define CS17_SW1 0x10 +#define CS18_SW1 0x11 + +#define CS1_SW2 0x12 +#define CS2_SW2 0x13 +#define CS3_SW2 0x14 +#define CS4_SW2 0x15 +#define CS5_SW2 0x16 +#define CS6_SW2 0x17 +#define CS7_SW2 0x18 +#define CS8_SW2 0x19 +#define CS9_SW2 0x1A +#define CS10_SW2 0x1B +#define CS11_SW2 0x1C +#define CS12_SW2 0x1D +#define CS13_SW2 0x1E +#define CS14_SW2 0x1F +#define CS15_SW2 0x20 +#define CS16_SW2 0x21 +#define CS17_SW2 0x22 +#define CS18_SW2 0x23 + +#define CS1_SW3 0x24 +#define CS2_SW3 0x25 +#define CS3_SW3 0x26 +#define CS4_SW3 0x27 +#define CS5_SW3 0x28 +#define CS6_SW3 0x29 +#define CS7_SW3 0x2A +#define CS8_SW3 0x2B +#define CS9_SW3 0x2C +#define CS10_SW3 0x2D +#define CS11_SW3 0x2E +#define CS12_SW3 0x2F +#define CS13_SW3 0x30 +#define CS14_SW3 0x31 +#define CS15_SW3 0x32 +#define CS16_SW3 0x33 +#define CS17_SW3 0x34 +#define CS18_SW3 0x35 + +#define CS1_SW4 0x36 +#define CS2_SW4 0x37 +#define CS3_SW4 0x38 +#define CS4_SW4 0x39 +#define CS5_SW4 0x3A +#define CS6_SW4 0x3B +#define CS7_SW4 0x3C +#define CS8_SW4 0x3D +#define CS9_SW4 0x3E +#define CS10_SW4 0x3F +#define CS11_SW4 0x40 +#define CS12_SW4 0x41 +#define CS13_SW4 0x42 +#define CS14_SW4 0x43 +#define CS15_SW4 0x44 +#define CS16_SW4 0x45 +#define CS17_SW4 0x46 +#define CS18_SW4 0x47 diff --git a/drivers/led/issi/is31fl3746a-simple.c b/drivers/led/issi/is31fl3746a-simple.c deleted file mode 100644 index 3a29c511cb..0000000000 --- a/drivers/led/issi/is31fl3746a-simple.c +++ /dev/null @@ -1,208 +0,0 @@ -#include "is31fl3746a-simple.h" -#include -#include "i2c_master.h" -#include "wait.h" - -#define IS31FL3746A_PWM_REGISTER_COUNT 72 -#define IS31FL3746A_SCALING_REGISTER_COUNT 72 - -#ifndef IS31FL3746A_I2C_TIMEOUT -# define IS31FL3746A_I2C_TIMEOUT 100 -#endif - -#ifndef IS31FL3746A_I2C_PERSISTENCE -# define IS31FL3746A_I2C_PERSISTENCE 0 -#endif - -#ifndef IS31FL3746A_CONFIGURATION -# define IS31FL3746A_CONFIGURATION 0x01 -#endif - -#ifndef IS31FL3746A_PWM_FREQUENCY -# define IS31FL3746A_PWM_FREQUENCY IS31FL3746A_PWM_FREQUENCY_29K_HZ -#endif - -#ifndef IS31FL3746A_SW_PULLDOWN -# define IS31FL3746A_SW_PULLDOWN IS31FL3746A_PDR_2K_OHM_SW_OFF -#endif - -#ifndef IS31FL3746A_CS_PULLUP -# define IS31FL3746A_CS_PULLUP IS31FL3746A_PUR_2K_OHM_CS_OFF -#endif - -#ifndef IS31FL3746A_GLOBAL_CURRENT -# define IS31FL3746A_GLOBAL_CURRENT 0xFF -#endif - -uint8_t i2c_transfer_buffer[20] = {0xFF}; - -uint8_t g_pwm_buffer[IS31FL3746A_DRIVER_COUNT][IS31FL3746A_PWM_REGISTER_COUNT]; -bool g_pwm_buffer_update_required[IS31FL3746A_DRIVER_COUNT] = {false}; -bool g_scaling_registers_update_required[IS31FL3746A_DRIVER_COUNT] = {false}; - -uint8_t g_scaling_registers[IS31FL3746A_DRIVER_COUNT][IS31FL3746A_SCALING_REGISTER_COUNT]; - -void is31fl3746a_write_register(uint8_t addr, uint8_t reg, uint8_t data) { - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if IS31FL3746A_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3746A_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3746A_I2C_TIMEOUT) == 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3746A_I2C_TIMEOUT); -#endif -} - -void is31fl3746a_select_page(uint8_t addr, uint8_t page) { - is31fl3746a_write_register(addr, IS31FL3746A_REG_COMMAND_WRITE_LOCK, IS31FL3746A_COMMAND_WRITE_LOCK_MAGIC); - is31fl3746a_write_register(addr, IS31FL3746A_REG_COMMAND, page); -} - -void is31fl3746a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // Assumes page 0 is already selected. - // If any of the transactions fails function returns false. - // Transmit PWM registers in 12 transfers of 16 bytes. - // i2c_transfer_buffer[] is 20 bytes - - // Iterate over the pwm_buffer contents at 16 byte intervals. - for (int i = 0; i < IS31FL3746A_PWM_REGISTER_COUNT; i += 16) { - i2c_transfer_buffer[0] = i + 1; - // Copy the data from i to i+15. - // Device will auto-increment register for data after the first byte - // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. - memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16); - -#if IS31FL3746A_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < IS31FL3746A_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3746A_I2C_TIMEOUT) != 0) break; - } -#else - i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3746A_I2C_TIMEOUT); -#endif - } -} - -void is31fl3746a_init_drivers(void) { - i2c_init(); - - is31fl3746a_init(IS31FL3746A_I2C_ADDRESS_1); -#if defined(IS31FL3746A_I2C_ADDRESS_2) - is31fl3746a_init(IS31FL3746A_I2C_ADDRESS_2); -# if defined(IS31FL3746A_I2C_ADDRESS_3) - is31fl3746a_init(IS31FL3746A_I2C_ADDRESS_3); -# if defined(IS31FL3746A_I2C_ADDRESS_4) - is31fl3746a_init(IS31FL3746A_I2C_ADDRESS_4); -# endif -# endif -#endif - - for (int i = 0; i < IS31FL3746A_LED_COUNT; i++) { - is31fl3746a_set_scaling_register(i, 0xFF); - } - - is31fl3746a_update_scaling_registers(IS31FL3746A_I2C_ADDRESS_1, 0); -#if defined(IS31FL3746A_I2C_ADDRESS_2) - is31fl3746a_update_scaling_registers(IS31FL3746A_I2C_ADDRESS_2, 1); -# if defined(IS31FL3746A_I2C_ADDRESS_3) - is31fl3746a_update_scaling_registers(IS31FL3746A_I2C_ADDRESS_3, 2); -# if defined(IS31FL3746A_I2C_ADDRESS_4) - is31fl3746a_update_scaling_registers(IS31FL3746A_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void is31fl3746a_init(uint8_t addr) { - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, shutdown is enabled last. - // Set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - - is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_SCALING); - - // Turn off all LEDs. - for (int i = 0; i < IS31FL3746A_SCALING_REGISTER_COUNT; i++) { - is31fl3746a_write_register(addr, i + 1, 0x00); - } - - is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_PWM); - - for (int i = 0; i < IS31FL3746A_PWM_REGISTER_COUNT; i++) { - is31fl3746a_write_register(addr, i + 1, 0x00); - } - - is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_FUNCTION); - - is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_PULLDOWNUP, (IS31FL3746A_SW_PULLDOWN << 4) | IS31FL3746A_CS_PULLUP); - is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3746A_GLOBAL_CURRENT); - is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_PWM_ENABLE, 0x01); - is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_PWM_FREQUENCY, IS31FL3746A_PWM_FREQUENCY); - is31fl3746a_write_register(addr, IS31FL3746A_FUNCTION_REG_CONFIGURATION, IS31FL3746A_CONFIGURATION); - - // Wait 10ms to ensure the device has woken up. - wait_ms(10); -} - -void is31fl3746a_set_color(int index, uint8_t value) { - is31fl3746a_led_t led; - if (index >= 0 && index < IS31FL3746A_LED_COUNT) { - memcpy_P(&led, (&g_is31fl3746a_leds[index]), sizeof(led)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - g_pwm_buffer_update_required[led.driver] = true; - g_pwm_buffer[led.driver][led.v] = value; - } -} - -void is31fl3746a_set_value_all(uint8_t value) { - for (int i = 0; i < IS31FL3746A_LED_COUNT; i++) { - is31fl3746a_set_value(i, value); - } -} - -void is31fl3746a_set_scaling_register(uint8_t index, uint8_t value) { - is31fl3746a_led_t led; - memcpy_P(&led, (&g_is31fl3746a_leds[index]), sizeof(led)); - - g_scaling_registers[led.driver][led.v] = value; - - g_scaling_registers_update_required[led.driver] = true; -} - -void is31fl3746a_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_PWM); - - is31fl3746a_write_pwm_buffer(addr, g_pwm_buffer[index]); - } - - g_pwm_buffer_update_required[index] = false; -} - -void is31fl3746a_update_scaling_registers(uint8_t addr, uint8_t index) { - if (g_scaling_registers_update_required[index]) { - is31fl3746a_select_page(addr, IS31FL3746A_COMMAND_SCALING); - - for (int i = 0; i < IS31FL3746A_SCALING_REGISTER_COUNT; i++) { - is31fl3746a_write_register(addr, i + 1, g_scaling_registers[index][i]); - } - g_scaling_registers_update_required[index] = false; - } -} - -void is31fl3746a_flush(void) { - is31fl3746a_update_pwm_buffers(IS31FL3746A_I2C_ADDRESS_1, 0); -#if defined(IS31FL3746A_I2C_ADDRESS_2) - is31fl3746a_update_pwm_buffers(IS31FL3746A_I2C_ADDRESS_2, 1); -# if defined(IS31FL3746A_I2C_ADDRESS_3) - is31fl3746a_update_pwm_buffers(IS31FL3746A_I2C_ADDRESS_3, 2); -# if defined(IS31FL3746A_I2C_ADDRESS_4) - is31fl3746a_update_pwm_buffers(IS31FL3746A_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} diff --git a/drivers/led/issi/is31fl3746a-simple.h b/drivers/led/issi/is31fl3746a-simple.h deleted file mode 100644 index eda644ad19..0000000000 --- a/drivers/led/issi/is31fl3746a-simple.h +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * Copyright 2018 Yiancar - * Copyright 2020 MelGeek - * Copyright 2021 MasterSpoon - * - * 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 . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -#define IS31FL3746A_REG_ID 0xFC - -#define IS31FL3746A_REG_COMMAND 0xFD - -#define IS31FL3746A_COMMAND_PWM 0x00 -#define IS31FL3746A_COMMAND_SCALING 0x01 -#define IS31FL3746A_COMMAND_FUNCTION 0x01 - -#define IS31FL3746A_FUNCTION_REG_CONFIGURATION 0x50 -#define IS31FL3746A_FUNCTION_REG_GLOBAL_CURRENT 0x51 -#define IS31FL3746A_FUNCTION_REG_PULLDOWNUP 0x52 -#define IS31FL3746A_FUNCTION_REG_TEMPERATURE 0x5F -#define IS31FL3746A_FUNCTION_REG_SPREAD_SPECTRUM 0x60 -#define IS31FL3746A_FUNCTION_REG_RESET 0x8F -#define IS31FL3746A_FUNCTION_REG_PWM_ENABLE 0xE0 -#define IS31FL3746A_FUNCTION_REG_PWM_FREQUENCY 0xE2 - -#define IS31FL3746A_REG_COMMAND_WRITE_LOCK 0xFE -#define IS31FL3746A_COMMAND_WRITE_LOCK_MAGIC 0xC5 - -#define IS31FL3746A_I2C_ADDRESS_GND_GND 0x60 -#define IS31FL3746A_I2C_ADDRESS_GND_SCL 0x61 -#define IS31FL3746A_I2C_ADDRESS_GND_SDA 0x62 -#define IS31FL3746A_I2C_ADDRESS_GND_VCC 0x63 -#define IS31FL3746A_I2C_ADDRESS_SCL_GND 0x64 -#define IS31FL3746A_I2C_ADDRESS_SCL_SCL 0x65 -#define IS31FL3746A_I2C_ADDRESS_SCL_SDA 0x66 -#define IS31FL3746A_I2C_ADDRESS_SCL_VCC 0x67 -#define IS31FL3746A_I2C_ADDRESS_SDA_GND 0x68 -#define IS31FL3746A_I2C_ADDRESS_SDA_SCL 0x69 -#define IS31FL3746A_I2C_ADDRESS_SDA_SDA 0x6A -#define IS31FL3746A_I2C_ADDRESS_SDA_VCC 0x6B -#define IS31FL3746A_I2C_ADDRESS_VCC_GND 0x6C -#define IS31FL3746A_I2C_ADDRESS_VCC_SCL 0x6D -#define IS31FL3746A_I2C_ADDRESS_VCC_SDA 0x6E -#define IS31FL3746A_I2C_ADDRESS_VCC_VCC 0x6F - -#if defined(LED_MATRIX_IS31FL3746A) -# define IS31FL3746A_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -typedef struct is31fl3746a_led_t { - uint8_t driver : 2; - uint8_t v; -} PACKED is31fl3746a_led_t; - -extern const is31fl3746a_led_t PROGMEM g_is31fl3746a_leds[IS31FL3746A_LED_COUNT]; - -void is31fl3746a_init_drivers(void); -void is31fl3746a_init(uint8_t addr, uint8_t sync); -void is31fl3746a_write_register(uint8_t addr, uint8_t reg, uint8_t data); -void is31fl3746a_select_page(uint8_t addr, uint8_t page); -void is31fl3746a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); - -void is31fl3746a_set_value(int index, uint8_t value); -void is31fl3746a_set_value_all(uint8_t value); - -void is31fl3746a_set_scaling_register(uint8_t index, uint8_t value); - -void is31fl3746a_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3746a_update_scaling_registers(uint8_t addr, uint8_t index); - -void is31fl3746a_flush(void); - -#define IS31FL3746A_PDR_0_OHM 0b000 // No pull-down resistor -#define IS31FL3746A_PDR_0K5_OHM_SW_OFF 0b001 // 0.5 kOhm resistor in SWx off time -#define IS31FL3746A_PDR_1K_OHM_SW_OFF 0b010 // 1 kOhm resistor in SWx off time -#define IS31FL3746A_PDR_2K_OHM_SW_OFF 0b011 // 2 kOhm resistor in SWx off time -#define IS31FL3746A_PDR_1K_OHM 0b100 // 1 kOhm resistor -#define IS31FL3746A_PDR_2K_OHM 0b101 // 2 kOhm resistor -#define IS31FL3746A_PDR_4K_OHM 0b110 // 4 kOhm resistor -#define IS31FL3746A_PDR_8K_OHM 0b111 // 8 kOhm resistor - -#define IS31FL3746A_PUR_0_OHM 0b000 // No pull-up resistor -#define IS31FL3746A_PUR_0K5_OHM_CS_OFF 0b001 // 0.5 kOhm resistor in CSy off time -#define IS31FL3746A_PUR_1K_OHM_CS_OFF 0b010 // 1 kOhm resistor in CSy off time -#define IS31FL3746A_PUR_2K_OHM_CS_OFF 0b011 // 2 kOhm resistor in CSy off time -#define IS31FL3746A_PUR_1K_OHM 0b100 // 1 kOhm resistor -#define IS31FL3746A_PUR_2K_OHM 0b101 // 2 kOhm resistor -#define IS31FL3746A_PUR_4K_OHM 0b110 // 4 kOhm resistor -#define IS31FL3746A_PUR_8K_OHM 0b111 // 8 kOhm resistor - -#define IS31FL3746A_PWM_FREQUENCY_29K_HZ 0b000 -#define IS31FL3746A_PWM_FREQUENCY_14K5_HZ 0b001 -#define IS31FL3746A_PWM_FREQUENCY_7K25_HZ 0b010 -#define IS31FL3746A_PWM_FREQUENCY_3K63_HZ 0b011 -#define IS31FL3746A_PWM_FREQUENCY_1K81_HZ 0b100 -#define IS31FL3746A_PWM_FREQUENCY_906_HZ 0b101 -#define IS31FL3746A_PWM_FREQUENCY_453_HZ 0b110 - -#define CS1_SW1 0x00 -#define CS2_SW1 0x01 -#define CS3_SW1 0x02 -#define CS4_SW1 0x03 -#define CS5_SW1 0x04 -#define CS6_SW1 0x05 -#define CS7_SW1 0x06 -#define CS8_SW1 0x07 -#define CS9_SW1 0x08 -#define CS10_SW1 0x09 -#define CS11_SW1 0x0A -#define CS12_SW1 0x0B -#define CS13_SW1 0x0C -#define CS14_SW1 0x0D -#define CS15_SW1 0x0E -#define CS16_SW1 0x0F -#define CS17_SW1 0x10 -#define CS18_SW1 0x11 - -#define CS1_SW2 0x12 -#define CS2_SW2 0x13 -#define CS3_SW2 0x14 -#define CS4_SW2 0x15 -#define CS5_SW2 0x16 -#define CS6_SW2 0x17 -#define CS7_SW2 0x18 -#define CS8_SW2 0x19 -#define CS9_SW2 0x1A -#define CS10_SW2 0x1B -#define CS11_SW2 0x1C -#define CS12_SW2 0x1D -#define CS13_SW2 0x1E -#define CS14_SW2 0x1F -#define CS15_SW2 0x20 -#define CS16_SW2 0x21 -#define CS17_SW2 0x22 -#define CS18_SW2 0x23 - -#define CS1_SW3 0x24 -#define CS2_SW3 0x25 -#define CS3_SW3 0x26 -#define CS4_SW3 0x27 -#define CS5_SW3 0x28 -#define CS6_SW3 0x29 -#define CS7_SW3 0x2A -#define CS8_SW3 0x2B -#define CS9_SW3 0x2C -#define CS10_SW3 0x2D -#define CS11_SW3 0x2E -#define CS12_SW3 0x2F -#define CS13_SW3 0x30 -#define CS14_SW3 0x31 -#define CS15_SW3 0x32 -#define CS16_SW3 0x33 -#define CS17_SW3 0x34 -#define CS18_SW3 0x35 - -#define CS1_SW4 0x36 -#define CS2_SW4 0x37 -#define CS3_SW4 0x38 -#define CS4_SW4 0x39 -#define CS5_SW4 0x3A -#define CS6_SW4 0x3B -#define CS7_SW4 0x3C -#define CS8_SW4 0x3D -#define CS9_SW4 0x3E -#define CS10_SW4 0x3F -#define CS11_SW4 0x40 -#define CS12_SW4 0x41 -#define CS13_SW4 0x42 -#define CS14_SW4 0x43 -#define CS15_SW4 0x44 -#define CS16_SW4 0x45 -#define CS17_SW4 0x46 -#define CS18_SW4 0x47 diff --git a/drivers/led/snled27351-mono.c b/drivers/led/snled27351-mono.c new file mode 100644 index 0000000000..4519243e0e --- /dev/null +++ b/drivers/led/snled27351-mono.c @@ -0,0 +1,272 @@ +/* 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 . + */ + +#include "snled27351-mono.h" +#include "i2c_master.h" + +#define SNLED27351_PWM_REGISTER_COUNT 192 +#define SNLED27351_LED_CONTROL_REGISTER_COUNT 24 + +#ifndef SNLED27351_I2C_TIMEOUT +# define SNLED27351_I2C_TIMEOUT 100 +#endif + +#ifndef SNLED27351_I2C_PERSISTENCE +# define SNLED27351_I2C_PERSISTENCE 0 +#endif + +#ifndef SNLED27351_PHASE_CHANNEL +# define SNLED27351_PHASE_CHANNEL SNLED27351_SCAN_PHASE_12_CHANNEL +#endif + +#ifndef SNLED27351_CURRENT_TUNE +# define SNLED27351_CURRENT_TUNE \ + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } +#endif + +uint8_t i2c_transfer_buffer[20]; + +// 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_register(uint8_t addr, uint8_t reg, uint8_t data) { + // If the transaction fails function returns false. + i2c_transfer_buffer[0] = reg; + i2c_transfer_buffer[1] = data; + +#if SNLED27351_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < SNLED27351_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) { + return false; + } +#endif + return true; +} + +void snled27351_select_page(uint8_t addr, uint8_t page) { + snled27351_write_register(addr, SNLED27351_REG_COMMAND, page); +} + +bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // Assumes PG1 is already selected. + // If any of the transactions fails function returns false. + // Transmit PWM registers in 12 transfers of 16 bytes. + // i2c_transfer_buffer[] is 20 bytes + + // Iterate over the pwm_buffer contents at 16 byte intervals. + for (int i = 0; i < SNLED27351_PWM_REGISTER_COUNT; i += 16) { + i2c_transfer_buffer[0] = i; + // Copy the data from i to i+15. + // Device will auto-increment register for data after the first byte + // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. + for (int j = 0; j < 16; j++) { + i2c_transfer_buffer[1 + j] = pwm_buffer[i + j]; + } + +#if SNLED27351_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < SNLED27351_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, SNLED27351_I2C_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, SNLED27351_I2C_TIMEOUT) != 0) { + return false; + } +#endif + } + return true; +} + +void snled27351_init_drivers(void) { + i2c_init(); + + snled27351_init(SNLED27351_I2C_ADDRESS_1); +#if defined(SNLED27351_I2C_ADDRESS_2) + snled27351_init(SNLED27351_I2C_ADDRESS_2); +# if defined(SNLED27351_I2C_ADDRESS_3) + snled27351_init(SNLED27351_I2C_ADDRESS_3); +# if defined(SNLED27351_I2C_ADDRESS_4) + snled27351_init(SNLED27351_I2C_ADDRESS_4); +# endif +# endif +#endif + + for (int i = 0; i < SNLED27351_LED_COUNT; i++) { + snled27351_set_led_control_register(i, true); + } + + snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_1, 0); +#if defined(SNLED27351_I2C_ADDRESS_2) + snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_2, 1); +# if defined(SNLED27351_I2C_ADDRESS_3) + snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_3, 2); +# if defined(SNLED27351_I2C_ADDRESS_4) + snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void snled27351_init(uint8_t addr) { + snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION); + + // Setting LED driver to shutdown mode + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN); + // Setting internal channel pulldown/pullup + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_PULLDOWNUP, SNLED27351_PULLDOWNUP_ALL_ENABLED); + // Select number of scan phase + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SCAN_PHASE, SNLED27351_PHASE_CHANNEL); + // Setting PWM Delay Phase + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_1, SNLED27351_SLEW_RATE_CONTROL_MODE_1_PDP_ENABLE); + // Setting Driving/Sinking Channel Slew Rate + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_2, SNLED27351_SLEW_RATE_CONTROL_MODE_2_DSL_ENABLE | SNLED27351_SLEW_RATE_CONTROL_MODE_2_SSL_ENABLE); + // Setting Iref + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP, 0); + + snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL); + + for (int i = 0; i < SNLED27351_LED_CONTROL_ON_OFF_LENGTH; i++) { + snled27351_write_register(addr, i, 0x00); + } + + snled27351_select_page(addr, SNLED27351_COMMAND_PWM); + + for (int i = 0; i < SNLED27351_LED_CURRENT_TUNE_LENGTH; i++) { + snled27351_write_register(addr, i, 0x00); + } + + snled27351_select_page(addr, SNLED27351_COMMAND_CURRENT_TUNE); + + uint8_t current_tune_reg_list[SNLED27351_LED_CURRENT_TUNE_LENGTH] = SNLED27351_CURRENT_TUNE; + for (int i = 0; i < SNLED27351_LED_CURRENT_TUNE_LENGTH; i++) { + snled27351_write_register(addr, i, current_tune_reg_list[i]); + } + + snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL); + + // Enable LEDs ON/OFF + for (int i = 0; i < SNLED27351_LED_CONTROL_ON_OFF_LENGTH; i++) { + snled27351_write_register(addr, i, 0xFF); + } + + snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION); + + // Setting LED driver to normal mode + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL); +} + +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)); + + if (g_pwm_buffer[led.driver][led.v] == value) { + return; + } + 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 addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + snled27351_select_page(addr, SNLED27351_COMMAND_PWM); + + // If any of the transactions fail we risk writing dirty PG0, + // refresh page 0 just in case. + if (!snled27351_write_pwm_buffer(addr, 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 addr, uint8_t index) { + if (g_led_control_registers_update_required[index]) { + snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL); + + for (int i = 0; i < SNLED27351_LED_CONTROL_REGISTER_COUNT; i++) { + snled27351_write_register(addr, i, g_led_control_registers[index][i]); + } + } + g_led_control_registers_update_required[index] = false; +} + +void snled27351_flush(void) { + snled27351_update_pwm_buffers(SNLED27351_I2C_ADDRESS_1, 0); +#if defined(SNLED27351_I2C_ADDRESS_2) + snled27351_update_pwm_buffers(SNLED27351_I2C_ADDRESS_2, 1); +# if defined(SNLED27351_I2C_ADDRESS_3) + snled27351_update_pwm_buffers(SNLED27351_I2C_ADDRESS_3, 2); +# if defined(SNLED27351_I2C_ADDRESS_4) + snled27351_update_pwm_buffers(SNLED27351_I2C_ADDRESS_4, 3); +# endif +# endif +#endif +} + +void snled27351_sw_return_normal(uint8_t addr) { + snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION); + + // Setting LED driver to normal mode + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL); +} + +void snled27351_sw_shutdown(uint8_t addr) { + snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION); + + // Setting LED driver to shutdown mode + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN); + // Write SW Sleep Register + snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP, SNLED27351_SOFTWARE_SLEEP_ENABLE); +} diff --git a/drivers/led/snled27351-mono.h b/drivers/led/snled27351-mono.h new file mode 100644 index 0000000000..0a4d2469f0 --- /dev/null +++ b/drivers/led/snled27351-mono.h @@ -0,0 +1,381 @@ +/* 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 . + */ + +#pragma once + +#include +#include +#include "progmem.h" +#include "util.h" + +// ======== DEPRECATED DEFINES - DO NOT USE ======== +#ifdef CKLED2001_TIMEOUT +# define SNLED27351_I2C_TIMEOUT CKLED2001_TIMEOUT +#endif +#ifdef CKLED2001_PERSISTENCE +# define SNLED27351_I2C_PERSISTENCE CKLED2001_PERSISTENCE +#endif +#ifdef PHASE_CHANNEL +# define SNLED27351_PHASE_CHANNEL PHASE_CHANNEL +#endif +#ifdef CKLED2001_CURRENT_TUNE +# define SNLED27351_CURRENT_TUNE CKLED2001_CURRENT_TUNE +#endif + +#define MSKPHASE_12CHANNEL SNLED27351_SCAN_PHASE_12_CHANNEL +#define MSKPHASE_11CHANNEL SNLED27351_SCAN_PHASE_11_CHANNEL +#define MSKPHASE_10CHANNEL SNLED27351_SCAN_PHASE_10_CHANNEL +#define MSKPHASE_9CHANNEL SNLED27351_SCAN_PHASE_9_CHANNEL +#define MSKPHASE_8CHANNEL SNLED27351_SCAN_PHASE_8_CHANNEL +#define MSKPHASE_7CHANNEL SNLED27351_SCAN_PHASE_7_CHANNEL +#define MSKPHASE_6CHANNEL SNLED27351_SCAN_PHASE_6_CHANNEL +#define MSKPHASE_5CHANNEL SNLED27351_SCAN_PHASE_5_CHANNEL +#define MSKPHASE_4CHANNEL SNLED27351_SCAN_PHASE_4_CHANNEL +#define MSKPHASE_3CHANNEL SNLED27351_SCAN_PHASE_3_CHANNEL +#define MSKPHASE_2CHANNEL SNLED27351_SCAN_PHASE_2_CHANNEL +#define MSKPHASE_1CHANNEL SNLED27351_SCAN_PHASE_1_CHANNEL + +#define ckled2001_led snled27351_led_t +#define g_ckled2001_leds g_snled27351_leds +// ======== + +#define SNLED27351_REG_COMMAND 0xFD +#define SNLED27351_COMMAND_LED_CONTROL 0x00 +#define SNLED27351_COMMAND_PWM 0x01 +#define SNLED27351_COMMAND_FUNCTION 0x03 +#define SNLED27351_COMMAND_CURRENT_TUNE 0x04 + +#define SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN 0x00 +#define SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN (0x0 << 0) +#define SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL (0x1 << 0) + +#define SNLED27351_FUNCTION_REG_ID 0x11 +#define SNLED27351_DRIVER_ID 0x8A + +#define SNLED27351_FUNCTION_REG_PULLDOWNUP 0x13 +#define SNLED27351_PULLDOWNUP_ALL_ENABLED 0xAA + +#define SNLED27351_FUNCTION_REG_SCAN_PHASE 0x14 +#define SNLED27351_SCAN_PHASE_12_CHANNEL 0x00 +#define SNLED27351_SCAN_PHASE_11_CHANNEL 0x01 +#define SNLED27351_SCAN_PHASE_10_CHANNEL 0x02 +#define SNLED27351_SCAN_PHASE_9_CHANNEL 0x03 +#define SNLED27351_SCAN_PHASE_8_CHANNEL 0x04 +#define SNLED27351_SCAN_PHASE_7_CHANNEL 0x05 +#define SNLED27351_SCAN_PHASE_6_CHANNEL 0x06 +#define SNLED27351_SCAN_PHASE_5_CHANNEL 0x07 +#define SNLED27351_SCAN_PHASE_4_CHANNEL 0x08 +#define SNLED27351_SCAN_PHASE_3_CHANNEL 0x09 +#define SNLED27351_SCAN_PHASE_2_CHANNEL 0x0A +#define SNLED27351_SCAN_PHASE_1_CHANNEL 0x0B + +#define SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_1 0x15 +#define SNLED27351_SLEW_RATE_CONTROL_MODE_1_PDP_ENABLE (0b1 << 2) + +#define SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_2 0x16 +#define SNLED27351_SLEW_RATE_CONTROL_MODE_2_SSL_ENABLE (0b1 << 6) +#define SNLED27351_SLEW_RATE_CONTROL_MODE_2_DSL_ENABLE (0b1 << 7) + +#define SNLED27351_FUNCTION_REG_OPEN_SHORT_ENABLE 0x17 +#define SNLED27351_OPEN_SHORT_ENABLE_SDS_ENABLE (0b1 << 6) +#define SNLED27351_OPEN_SHORT_ENABLE_ODS_ENABLE (0b1 << 7) + +#define SNLED27351_FUNCTION_REG_OPEN_SHORT_DUTY 0x18 + +#define SNLED27351_FUNCTION_REG_OPEN_SHORT_FLAG 0x19 +#define SNLED27351_OPEN_SHORT_FLAG_OSINT_ENABLE (0b1 << 6) +#define SNLED27351_OPEN_SHORT_FLAG_ODINT_ENABLE (0b1 << 7) + +#define SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP 0x1A +#define SNLED27351_SOFTWARE_SLEEP_ENABLE (0b1 << 1) + +// LED Control Registers +#define SNLED27351_LED_CONTROL_ON_OFF_FIRST_ADDR 0x0 +#define SNLED27351_LED_CONTROL_ON_OFF_LAST_ADDR 0x17 +#define SNLED27351_LED_CONTROL_ON_OFF_LENGTH ((SNLED27351_LED_CONTROL_ON_OFF_LAST_ADDR - SNLED27351_LED_CONTROL_ON_OFF_FIRST_ADDR) + 1) + +#define SNLED27351_LED_CONTROL_OPEN_FIRST_ADDR 0x18 +#define SNLED27351_LED_CONTROL_OPEN_LAST_ADDR 0x2F +#define SNLED27351_LED_CONTROL_OPEN_LENGTH ((SNLED27351_LED_CONTROL_OPEN_LAST_ADDR - SNLED27351_LED_CONTROL_OPEN_FIRST_ADDR) + 1) + +#define SNLED27351_LED_CONTROL_SHORT_FIRST_ADDR 0x30 +#define SNLED27351_LED_CONTROL_SHORT_LAST_ADDR 0x47 +#define SNLED27351_LED_CONTROL_SHORT_LENGTH ((SNLED27351_LED_CONTROL_SHORT_LAST_ADDR - SNLED27351_LED_CONTROL_SHORT_FIRST_ADDR) + 1) + +#define SNLED27351_LED_CONTROL_PAGE_LENGTH 0x48 + +// LED Control Registers +#define SNLED27351_LED_PWM_FIRST_ADDR 0x00 +#define SNLED27351_LED_PWM_LAST_ADDR 0xBF +#define SNLED27351_LED_PWM_LENGTH 0xC0 + +// Current Tune Registers +#define SNLED27351_LED_CURRENT_TUNE_FIRST_ADDR 0x00 +#define SNLED27351_LED_CURRENT_TUNE_LAST_ADDR 0x0B +#define SNLED27351_LED_CURRENT_TUNE_LENGTH 0x0C + +#define SNLED27351_I2C_ADDRESS_GND 0x74 +#define SNLED27351_I2C_ADDRESS_SCL 0x75 +#define SNLED27351_I2C_ADDRESS_SDA 0x76 +#define SNLED27351_I2C_ADDRESS_VDDIO 0x77 + +#if defined(LED_MATRIX_SNLED27351) +# define SNLED27351_LED_COUNT LED_MATRIX_LED_COUNT +#endif + +#if defined(SNLED27351_I2C_ADDRESS_4) +# define SNLED27351_DRIVER_COUNT 4 +#elif defined(SNLED27351_I2C_ADDRESS_3) +# define SNLED27351_DRIVER_COUNT 3 +#elif defined(SNLED27351_I2C_ADDRESS_2) +# define SNLED27351_DRIVER_COUNT 2 +#elif defined(SNLED27351_I2C_ADDRESS_1) +# define SNLED27351_DRIVER_COUNT 1 +#endif + +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 addr); +void snled27351_select_page(uint8_t addr, uint8_t page); +bool snled27351_write_register(uint8_t addr, uint8_t reg, uint8_t data); +bool snled27351_write_pwm_buffer(uint8_t addr, 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 addr, uint8_t index); +void snled27351_update_led_control_registers(uint8_t addr, uint8_t index); + +void snled27351_flush(void); + +void snled27351_sw_return_normal(uint8_t addr); +void snled27351_sw_shutdown(uint8_t addr); + +#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 diff --git a/drivers/led/snled27351-simple.c b/drivers/led/snled27351-simple.c deleted file mode 100644 index 7b7a82f90f..0000000000 --- a/drivers/led/snled27351-simple.c +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright 2021 @ Keychron (https://www.keychron.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "snled27351-simple.h" -#include "i2c_master.h" - -#define SNLED27351_PWM_REGISTER_COUNT 192 -#define SNLED27351_LED_CONTROL_REGISTER_COUNT 24 - -#ifndef SNLED27351_I2C_TIMEOUT -# define SNLED27351_I2C_TIMEOUT 100 -#endif - -#ifndef SNLED27351_I2C_PERSISTENCE -# define SNLED27351_I2C_PERSISTENCE 0 -#endif - -#ifndef SNLED27351_PHASE_CHANNEL -# define SNLED27351_PHASE_CHANNEL SNLED27351_SCAN_PHASE_12_CHANNEL -#endif - -#ifndef SNLED27351_CURRENT_TUNE -# define SNLED27351_CURRENT_TUNE \ - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } -#endif - -uint8_t i2c_transfer_buffer[20]; - -// 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_register(uint8_t addr, uint8_t reg, uint8_t data) { - // If the transaction fails function returns false. - i2c_transfer_buffer[0] = reg; - i2c_transfer_buffer[1] = data; - -#if SNLED27351_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < SNLED27351_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) { - return false; - } - } -#else - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, SNLED27351_I2C_TIMEOUT) != 0) { - return false; - } -#endif - return true; -} - -void snled27351_select_page(uint8_t addr, uint8_t page) { - snled27351_write_register(addr, SNLED27351_REG_COMMAND, page); -} - -bool snled27351_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { - // Assumes PG1 is already selected. - // If any of the transactions fails function returns false. - // Transmit PWM registers in 12 transfers of 16 bytes. - // i2c_transfer_buffer[] is 20 bytes - - // Iterate over the pwm_buffer contents at 16 byte intervals. - for (int i = 0; i < SNLED27351_PWM_REGISTER_COUNT; i += 16) { - i2c_transfer_buffer[0] = i; - // Copy the data from i to i+15. - // Device will auto-increment register for data after the first byte - // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. - for (int j = 0; j < 16; j++) { - i2c_transfer_buffer[1 + j] = pwm_buffer[i + j]; - } - -#if SNLED27351_I2C_PERSISTENCE > 0 - for (uint8_t i = 0; i < SNLED27351_I2C_PERSISTENCE; i++) { - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, SNLED27351_I2C_TIMEOUT) != 0) { - return false; - } - } -#else - if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, SNLED27351_I2C_TIMEOUT) != 0) { - return false; - } -#endif - } - return true; -} - -void snled27351_init_drivers(void) { - i2c_init(); - - snled27351_init(SNLED27351_I2C_ADDRESS_1); -#if defined(SNLED27351_I2C_ADDRESS_2) - snled27351_init(SNLED27351_I2C_ADDRESS_2); -# if defined(SNLED27351_I2C_ADDRESS_3) - snled27351_init(SNLED27351_I2C_ADDRESS_3); -# if defined(SNLED27351_I2C_ADDRESS_4) - snled27351_init(SNLED27351_I2C_ADDRESS_4); -# endif -# endif -#endif - - for (int i = 0; i < SNLED27351_LED_COUNT; i++) { - snled27351_set_led_control_register(i, true); - } - - snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_1, 0); -#if defined(SNLED27351_I2C_ADDRESS_2) - snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_2, 1); -# if defined(SNLED27351_I2C_ADDRESS_3) - snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_3, 2); -# if defined(SNLED27351_I2C_ADDRESS_4) - snled27351_update_led_control_registers(SNLED27351_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void snled27351_init(uint8_t addr) { - snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION); - - // Setting LED driver to shutdown mode - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN); - // Setting internal channel pulldown/pullup - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_PULLDOWNUP, SNLED27351_PULLDOWNUP_ALL_ENABLED); - // Select number of scan phase - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SCAN_PHASE, SNLED27351_PHASE_CHANNEL); - // Setting PWM Delay Phase - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_1, SNLED27351_SLEW_RATE_CONTROL_MODE_1_PDP_ENABLE); - // Setting Driving/Sinking Channel Slew Rate - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_2, SNLED27351_SLEW_RATE_CONTROL_MODE_2_DSL_ENABLE | SNLED27351_SLEW_RATE_CONTROL_MODE_2_SSL_ENABLE); - // Setting Iref - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP, 0); - - snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL); - - for (int i = 0; i < SNLED27351_LED_CONTROL_ON_OFF_LENGTH; i++) { - snled27351_write_register(addr, i, 0x00); - } - - snled27351_select_page(addr, SNLED27351_COMMAND_PWM); - - for (int i = 0; i < SNLED27351_LED_CURRENT_TUNE_LENGTH; i++) { - snled27351_write_register(addr, i, 0x00); - } - - snled27351_select_page(addr, SNLED27351_COMMAND_CURRENT_TUNE); - - uint8_t current_tune_reg_list[SNLED27351_LED_CURRENT_TUNE_LENGTH] = SNLED27351_CURRENT_TUNE; - for (int i = 0; i < SNLED27351_LED_CURRENT_TUNE_LENGTH; i++) { - snled27351_write_register(addr, i, current_tune_reg_list[i]); - } - - snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL); - - // Enable LEDs ON/OFF - for (int i = 0; i < SNLED27351_LED_CONTROL_ON_OFF_LENGTH; i++) { - snled27351_write_register(addr, i, 0xFF); - } - - snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION); - - // Setting LED driver to normal mode - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL); -} - -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)); - - if (g_pwm_buffer[led.driver][led.v] == value) { - return; - } - 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 addr, uint8_t index) { - if (g_pwm_buffer_update_required[index]) { - snled27351_select_page(addr, SNLED27351_COMMAND_PWM); - - // If any of the transactions fail we risk writing dirty PG0, - // refresh page 0 just in case. - if (!snled27351_write_pwm_buffer(addr, 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 addr, uint8_t index) { - if (g_led_control_registers_update_required[index]) { - snled27351_select_page(addr, SNLED27351_COMMAND_LED_CONTROL); - - for (int i = 0; i < SNLED27351_LED_CONTROL_REGISTER_COUNT; i++) { - snled27351_write_register(addr, i, g_led_control_registers[index][i]); - } - } - g_led_control_registers_update_required[index] = false; -} - -void snled27351_flush(void) { - snled27351_update_pwm_buffers(SNLED27351_I2C_ADDRESS_1, 0); -#if defined(SNLED27351_I2C_ADDRESS_2) - snled27351_update_pwm_buffers(SNLED27351_I2C_ADDRESS_2, 1); -# if defined(SNLED27351_I2C_ADDRESS_3) - snled27351_update_pwm_buffers(SNLED27351_I2C_ADDRESS_3, 2); -# if defined(SNLED27351_I2C_ADDRESS_4) - snled27351_update_pwm_buffers(SNLED27351_I2C_ADDRESS_4, 3); -# endif -# endif -#endif -} - -void snled27351_sw_return_normal(uint8_t addr) { - snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION); - - // Setting LED driver to normal mode - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL); -} - -void snled27351_sw_shutdown(uint8_t addr) { - snled27351_select_page(addr, SNLED27351_COMMAND_FUNCTION); - - // Setting LED driver to shutdown mode - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN, SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN); - // Write SW Sleep Register - snled27351_write_register(addr, SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP, SNLED27351_SOFTWARE_SLEEP_ENABLE); -} diff --git a/drivers/led/snled27351-simple.h b/drivers/led/snled27351-simple.h deleted file mode 100644 index 0a4d2469f0..0000000000 --- a/drivers/led/snled27351-simple.h +++ /dev/null @@ -1,381 +0,0 @@ -/* Copyright 2021 @ Keychron (https://www.keychron.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include -#include "progmem.h" -#include "util.h" - -// ======== DEPRECATED DEFINES - DO NOT USE ======== -#ifdef CKLED2001_TIMEOUT -# define SNLED27351_I2C_TIMEOUT CKLED2001_TIMEOUT -#endif -#ifdef CKLED2001_PERSISTENCE -# define SNLED27351_I2C_PERSISTENCE CKLED2001_PERSISTENCE -#endif -#ifdef PHASE_CHANNEL -# define SNLED27351_PHASE_CHANNEL PHASE_CHANNEL -#endif -#ifdef CKLED2001_CURRENT_TUNE -# define SNLED27351_CURRENT_TUNE CKLED2001_CURRENT_TUNE -#endif - -#define MSKPHASE_12CHANNEL SNLED27351_SCAN_PHASE_12_CHANNEL -#define MSKPHASE_11CHANNEL SNLED27351_SCAN_PHASE_11_CHANNEL -#define MSKPHASE_10CHANNEL SNLED27351_SCAN_PHASE_10_CHANNEL -#define MSKPHASE_9CHANNEL SNLED27351_SCAN_PHASE_9_CHANNEL -#define MSKPHASE_8CHANNEL SNLED27351_SCAN_PHASE_8_CHANNEL -#define MSKPHASE_7CHANNEL SNLED27351_SCAN_PHASE_7_CHANNEL -#define MSKPHASE_6CHANNEL SNLED27351_SCAN_PHASE_6_CHANNEL -#define MSKPHASE_5CHANNEL SNLED27351_SCAN_PHASE_5_CHANNEL -#define MSKPHASE_4CHANNEL SNLED27351_SCAN_PHASE_4_CHANNEL -#define MSKPHASE_3CHANNEL SNLED27351_SCAN_PHASE_3_CHANNEL -#define MSKPHASE_2CHANNEL SNLED27351_SCAN_PHASE_2_CHANNEL -#define MSKPHASE_1CHANNEL SNLED27351_SCAN_PHASE_1_CHANNEL - -#define ckled2001_led snled27351_led_t -#define g_ckled2001_leds g_snled27351_leds -// ======== - -#define SNLED27351_REG_COMMAND 0xFD -#define SNLED27351_COMMAND_LED_CONTROL 0x00 -#define SNLED27351_COMMAND_PWM 0x01 -#define SNLED27351_COMMAND_FUNCTION 0x03 -#define SNLED27351_COMMAND_CURRENT_TUNE 0x04 - -#define SNLED27351_FUNCTION_REG_SOFTWARE_SHUTDOWN 0x00 -#define SNLED27351_SOFTWARE_SHUTDOWN_SSD_SHUTDOWN (0x0 << 0) -#define SNLED27351_SOFTWARE_SHUTDOWN_SSD_NORMAL (0x1 << 0) - -#define SNLED27351_FUNCTION_REG_ID 0x11 -#define SNLED27351_DRIVER_ID 0x8A - -#define SNLED27351_FUNCTION_REG_PULLDOWNUP 0x13 -#define SNLED27351_PULLDOWNUP_ALL_ENABLED 0xAA - -#define SNLED27351_FUNCTION_REG_SCAN_PHASE 0x14 -#define SNLED27351_SCAN_PHASE_12_CHANNEL 0x00 -#define SNLED27351_SCAN_PHASE_11_CHANNEL 0x01 -#define SNLED27351_SCAN_PHASE_10_CHANNEL 0x02 -#define SNLED27351_SCAN_PHASE_9_CHANNEL 0x03 -#define SNLED27351_SCAN_PHASE_8_CHANNEL 0x04 -#define SNLED27351_SCAN_PHASE_7_CHANNEL 0x05 -#define SNLED27351_SCAN_PHASE_6_CHANNEL 0x06 -#define SNLED27351_SCAN_PHASE_5_CHANNEL 0x07 -#define SNLED27351_SCAN_PHASE_4_CHANNEL 0x08 -#define SNLED27351_SCAN_PHASE_3_CHANNEL 0x09 -#define SNLED27351_SCAN_PHASE_2_CHANNEL 0x0A -#define SNLED27351_SCAN_PHASE_1_CHANNEL 0x0B - -#define SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_1 0x15 -#define SNLED27351_SLEW_RATE_CONTROL_MODE_1_PDP_ENABLE (0b1 << 2) - -#define SNLED27351_FUNCTION_REG_SLEW_RATE_CONTROL_MODE_2 0x16 -#define SNLED27351_SLEW_RATE_CONTROL_MODE_2_SSL_ENABLE (0b1 << 6) -#define SNLED27351_SLEW_RATE_CONTROL_MODE_2_DSL_ENABLE (0b1 << 7) - -#define SNLED27351_FUNCTION_REG_OPEN_SHORT_ENABLE 0x17 -#define SNLED27351_OPEN_SHORT_ENABLE_SDS_ENABLE (0b1 << 6) -#define SNLED27351_OPEN_SHORT_ENABLE_ODS_ENABLE (0b1 << 7) - -#define SNLED27351_FUNCTION_REG_OPEN_SHORT_DUTY 0x18 - -#define SNLED27351_FUNCTION_REG_OPEN_SHORT_FLAG 0x19 -#define SNLED27351_OPEN_SHORT_FLAG_OSINT_ENABLE (0b1 << 6) -#define SNLED27351_OPEN_SHORT_FLAG_ODINT_ENABLE (0b1 << 7) - -#define SNLED27351_FUNCTION_REG_SOFTWARE_SLEEP 0x1A -#define SNLED27351_SOFTWARE_SLEEP_ENABLE (0b1 << 1) - -// LED Control Registers -#define SNLED27351_LED_CONTROL_ON_OFF_FIRST_ADDR 0x0 -#define SNLED27351_LED_CONTROL_ON_OFF_LAST_ADDR 0x17 -#define SNLED27351_LED_CONTROL_ON_OFF_LENGTH ((SNLED27351_LED_CONTROL_ON_OFF_LAST_ADDR - SNLED27351_LED_CONTROL_ON_OFF_FIRST_ADDR) + 1) - -#define SNLED27351_LED_CONTROL_OPEN_FIRST_ADDR 0x18 -#define SNLED27351_LED_CONTROL_OPEN_LAST_ADDR 0x2F -#define SNLED27351_LED_CONTROL_OPEN_LENGTH ((SNLED27351_LED_CONTROL_OPEN_LAST_ADDR - SNLED27351_LED_CONTROL_OPEN_FIRST_ADDR) + 1) - -#define SNLED27351_LED_CONTROL_SHORT_FIRST_ADDR 0x30 -#define SNLED27351_LED_CONTROL_SHORT_LAST_ADDR 0x47 -#define SNLED27351_LED_CONTROL_SHORT_LENGTH ((SNLED27351_LED_CONTROL_SHORT_LAST_ADDR - SNLED27351_LED_CONTROL_SHORT_FIRST_ADDR) + 1) - -#define SNLED27351_LED_CONTROL_PAGE_LENGTH 0x48 - -// LED Control Registers -#define SNLED27351_LED_PWM_FIRST_ADDR 0x00 -#define SNLED27351_LED_PWM_LAST_ADDR 0xBF -#define SNLED27351_LED_PWM_LENGTH 0xC0 - -// Current Tune Registers -#define SNLED27351_LED_CURRENT_TUNE_FIRST_ADDR 0x00 -#define SNLED27351_LED_CURRENT_TUNE_LAST_ADDR 0x0B -#define SNLED27351_LED_CURRENT_TUNE_LENGTH 0x0C - -#define SNLED27351_I2C_ADDRESS_GND 0x74 -#define SNLED27351_I2C_ADDRESS_SCL 0x75 -#define SNLED27351_I2C_ADDRESS_SDA 0x76 -#define SNLED27351_I2C_ADDRESS_VDDIO 0x77 - -#if defined(LED_MATRIX_SNLED27351) -# define SNLED27351_LED_COUNT LED_MATRIX_LED_COUNT -#endif - -#if defined(SNLED27351_I2C_ADDRESS_4) -# define SNLED27351_DRIVER_COUNT 4 -#elif defined(SNLED27351_I2C_ADDRESS_3) -# define SNLED27351_DRIVER_COUNT 3 -#elif defined(SNLED27351_I2C_ADDRESS_2) -# define SNLED27351_DRIVER_COUNT 2 -#elif defined(SNLED27351_I2C_ADDRESS_1) -# define SNLED27351_DRIVER_COUNT 1 -#endif - -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 addr); -void snled27351_select_page(uint8_t addr, uint8_t page); -bool snled27351_write_register(uint8_t addr, uint8_t reg, uint8_t data); -bool snled27351_write_pwm_buffer(uint8_t addr, 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 addr, uint8_t index); -void snled27351_update_led_control_registers(uint8_t addr, uint8_t index); - -void snled27351_flush(void); - -void snled27351_sw_return_normal(uint8_t addr); -void snled27351_sw_shutdown(uint8_t addr); - -#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 diff --git a/keyboards/fallacy/indicators.c b/keyboards/fallacy/indicators.c index b95786db41..41d27b0972 100755 --- a/keyboards/fallacy/indicators.c +++ b/keyboards/fallacy/indicators.c @@ -15,7 +15,7 @@ */ #include "indicators.h" -#include "drivers/led/issi/is31fl3731-simple.h" +#include "drivers/led/issi/is31fl3731-mono.h" #include "i2c_master.h" /* Set up IS31FL3731 for use in powering indicator LEDs. Absolutely overkill for this job but it was already in the design. diff --git a/keyboards/fallacy/rules.mk b/keyboards/fallacy/rules.mk index 7fa230bae2..ee1a36c910 100755 --- a/keyboards/fallacy/rules.mk +++ b/keyboards/fallacy/rules.mk @@ -13,5 +13,5 @@ AUDIO_ENABLE = no # Audio output # project specific files SRC += indicators.c \ - drivers/led/issi/is31fl3731-simple.c + drivers/led/issi/is31fl3731-mono.c I2C_DRIVER_REQUIRED = yes diff --git a/keyboards/wilba_tech/wt60_a/rules.mk b/keyboards/wilba_tech/wt60_a/rules.mk index 9ca8e8f973..f7482c7a2f 100644 --- a/keyboards/wilba_tech/wt60_a/rules.mk +++ b/keyboards/wilba_tech/wt60_a/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736-simple.c \ +SRC = drivers/led/issi/is31fl3736-mono.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ keyboards/wilba_tech/wt_main.c diff --git a/keyboards/wilba_tech/wt65_a/rules.mk b/keyboards/wilba_tech/wt65_a/rules.mk index 9ca8e8f973..f7482c7a2f 100644 --- a/keyboards/wilba_tech/wt65_a/rules.mk +++ b/keyboards/wilba_tech/wt65_a/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736-simple.c \ +SRC = drivers/led/issi/is31fl3736-mono.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ keyboards/wilba_tech/wt_main.c diff --git a/keyboards/wilba_tech/wt65_b/rules.mk b/keyboards/wilba_tech/wt65_b/rules.mk index 9ca8e8f973..f7482c7a2f 100644 --- a/keyboards/wilba_tech/wt65_b/rules.mk +++ b/keyboards/wilba_tech/wt65_b/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736-simple.c \ +SRC = drivers/led/issi/is31fl3736-mono.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ keyboards/wilba_tech/wt_main.c diff --git a/keyboards/wilba_tech/wt75_a/rules.mk b/keyboards/wilba_tech/wt75_a/rules.mk index 9ca8e8f973..f7482c7a2f 100644 --- a/keyboards/wilba_tech/wt75_a/rules.mk +++ b/keyboards/wilba_tech/wt75_a/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736-simple.c \ +SRC = drivers/led/issi/is31fl3736-mono.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ keyboards/wilba_tech/wt_main.c diff --git a/keyboards/wilba_tech/wt75_b/rules.mk b/keyboards/wilba_tech/wt75_b/rules.mk index 9ca8e8f973..f7482c7a2f 100644 --- a/keyboards/wilba_tech/wt75_b/rules.mk +++ b/keyboards/wilba_tech/wt75_b/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736-simple.c \ +SRC = drivers/led/issi/is31fl3736-mono.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ keyboards/wilba_tech/wt_main.c diff --git a/keyboards/wilba_tech/wt75_c/rules.mk b/keyboards/wilba_tech/wt75_c/rules.mk index 9ca8e8f973..f7482c7a2f 100644 --- a/keyboards/wilba_tech/wt75_c/rules.mk +++ b/keyboards/wilba_tech/wt75_c/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736-simple.c \ +SRC = drivers/led/issi/is31fl3736-mono.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ keyboards/wilba_tech/wt_main.c diff --git a/keyboards/wilba_tech/wt80_a/rules.mk b/keyboards/wilba_tech/wt80_a/rules.mk index 9ca8e8f973..f7482c7a2f 100644 --- a/keyboards/wilba_tech/wt80_a/rules.mk +++ b/keyboards/wilba_tech/wt80_a/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736-simple.c \ +SRC = drivers/led/issi/is31fl3736-mono.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ keyboards/wilba_tech/wt_main.c diff --git a/keyboards/wilba_tech/wt_mono_backlight.c b/keyboards/wilba_tech/wt_mono_backlight.c index e218f0af4b..c954ae7c03 100644 --- a/keyboards/wilba_tech/wt_mono_backlight.c +++ b/keyboards/wilba_tech/wt_mono_backlight.c @@ -33,7 +33,7 @@ #error VIA_EEPROM_CUSTOM_CONFIG_SIZE was not defined to store backlight_config struct #endif -#include "drivers/led/issi/is31fl3736-simple.h" +#include "drivers/led/issi/is31fl3736-mono.h" #define BACKLIGHT_EFFECT_MAX 3 diff --git a/quantum/led_matrix/led_matrix_drivers.h b/quantum/led_matrix/led_matrix_drivers.h index 79d3cebead..d792600e1f 100644 --- a/quantum/led_matrix/led_matrix_drivers.h +++ b/quantum/led_matrix/led_matrix_drivers.h @@ -6,27 +6,27 @@ #include #if defined(LED_MATRIX_IS31FL3218) -# include "is31fl3218-simple.h" +# include "is31fl3218-mono.h" #elif defined(LED_MATRIX_IS31FL3731) -# include "is31fl3731-simple.h" +# include "is31fl3731-mono.h" #elif defined(LED_MATRIX_IS31FL3733) -# include "is31fl3733-simple.h" +# include "is31fl3733-mono.h" #elif defined(LED_MATRIX_IS31FL3736) -# include "is31fl3736-simple.h" +# include "is31fl3736-mono.h" #elif defined(LED_MATRIX_IS31FL3737) -# include "is31fl3737-simple.h" +# include "is31fl3737-mono.h" #elif defined(LED_MATRIX_IS31FL3741) -# include "is31fl3741-simple.h" +# include "is31fl3741-mono.h" #elif defined(LED_MATRIX_IS31FL3742A) -# include "is31fl3742a-simple.h" +# include "is31fl3742a-mono.h" #elif defined(LED_MATRIX_IS31FL3743A) -# include "is31fl3743a-simple.h" +# include "is31fl3743a-mono.h" #elif defined(LED_MATRIX_IS31FL3745) -# include "is31fl3745-simple.h" +# include "is31fl3745-mono.h" #elif defined(LED_MATRIX_IS31FL3746A) -# include "is31fl3746a-simple.h" +# include "is31fl3746a-mono.h" #elif defined(LED_MATRIX_SNLED27351) -# include "snled27351-simple.h" +# include "snled27351-mono.h" #endif typedef struct { -- cgit v1.2.3