commit 597de0e29841aa6c738eb40454620bc30d44099a
parent 1bd9b9204d233ee48c5a3f39d70cbc93b084cb19
Author: Ryan <fauxpark@gmail.com>
Date: Thu, 4 Jan 2024 17:05:37 +1100
LED drivers: rename "simple" to "mono" (#22814)
Diffstat:
46 files changed, 2562 insertions(+), 2562 deletions(-)
diff --git 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
@@ -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
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+#include "is31fl3218-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3218-simple.c b/drivers/led/issi/is31fl3218-simple.c
@@ -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 <http://www.gnu.org/licenses/>.
- */
-#include "is31fl3218-simple.h"
-#include <string.h>
-#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/is31fl3731-mono.c 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "is31fl3731-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3731-simple.c b/drivers/led/issi/is31fl3731-simple.c
@@ -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 <http://www.gnu.org/licenses/>.
- */
-
-#include "is31fl3731-simple.h"
-#include <string.h>
-#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/is31fl3733-mono.c 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "is31fl3733-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3733-simple.c b/drivers/led/issi/is31fl3733-simple.c
@@ -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 <http://www.gnu.org/licenses/>.
- */
-
-#include "is31fl3733-simple.h"
-#include <string.h>
-#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/is31fl3736-mono.c 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "is31fl3736-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3736-simple.c b/drivers/led/issi/is31fl3736-simple.c
@@ -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 <http://www.gnu.org/licenses/>.
- */
-
-#include "is31fl3736-simple.h"
-#include <string.h>
-#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/is31fl3737-mono.c 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "is31fl3737-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3737-simple.c b/drivers/led/issi/is31fl3737-simple.c
@@ -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 <http://www.gnu.org/licenses/>.
- */
-
-#include "is31fl3737-simple.h"
-#include <string.h>
-#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/is31fl3741-mono.c 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "is31fl3741-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3741-simple.c b/drivers/led/issi/is31fl3741-simple.c
@@ -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 <http://www.gnu.org/licenses/>.
- */
-
-#include "is31fl3741-simple.h"
-#include <string.h>
-#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/is31fl3742a-mono.c b/drivers/led/issi/is31fl3742a-mono.c
@@ -0,0 +1,206 @@
+#include "is31fl3742a-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3742a-simple.c b/drivers/led/issi/is31fl3742a-simple.c
@@ -1,206 +0,0 @@
-#include "is31fl3742a-simple.h"
-#include <string.h>
-#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/is31fl3743a-mono.c b/drivers/led/issi/is31fl3743a-mono.c
@@ -0,0 +1,216 @@
+#include "is31fl3743a-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3743a-simple.c b/drivers/led/issi/is31fl3743a-simple.c
@@ -1,216 +0,0 @@
-#include "is31fl3743a-simple.h"
-#include <string.h>
-#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/is31fl3745-mono.c b/drivers/led/issi/is31fl3745-mono.c
@@ -0,0 +1,216 @@
+#include "is31fl3745-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3745-simple.c b/drivers/led/issi/is31fl3745-simple.c
@@ -1,216 +0,0 @@
-#include "is31fl3745-simple.h"
-#include <string.h>
-#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/is31fl3746a-mono.c b/drivers/led/issi/is31fl3746a-mono.c
@@ -0,0 +1,208 @@
+#include "is31fl3746a-mono.h"
+#include <string.h>
+#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-mono.h
diff --git a/drivers/led/issi/is31fl3746a-simple.c b/drivers/led/issi/is31fl3746a-simple.c
@@ -1,208 +0,0 @@
-#include "is31fl3746a-simple.h"
-#include <string.h>
-#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/snled27351-mono.c 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 <http://www.gnu.org/licenses/>.
+ */
+
+#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-simple.h b/drivers/led/snled27351-mono.h
diff --git a/drivers/led/snled27351-simple.c b/drivers/led/snled27351-simple.c
@@ -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 <http://www.gnu.org/licenses/>.
- */
-
-#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/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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -6,27 +6,27 @@
#include <stdint.h>
#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 {