diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index 973cfba394..edc6f30d64 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -354,7 +354,7 @@ LED_MATRIX_DRIVER := aw20216s endif LED_MATRIX_ENABLE ?= no -VALID_LED_MATRIX_TYPES := is31fl3731 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 custom +VALID_LED_MATRIX_TYPES := is31fl3731 is31fl3736 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 custom # TODO: is31fl3733 is31fl3737 is31fl3741 ifeq ($(strip $(LED_MATRIX_ENABLE)), yes) @@ -384,6 +384,13 @@ endif QUANTUM_LIB_SRC += i2c_master.c endif + ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3736) + OPT_DEFS += -DHAL_USE_I2C=TRUE + COMMON_VPATH += $(DRIVER_PATH)/led/issi + SRC += is31fl3736-simple.c + QUANTUM_LIB_SRC += i2c_master.c + endif + ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3742a) OPT_DEFS += -DIS31FLCOMMON -DHAL_USE_I2C=TRUE COMMON_VPATH += $(DRIVER_PATH)/led/issi diff --git a/docs/reference_info_json.md b/docs/reference_info_json.md index 001d80ddab..3ea85932af 100644 --- a/docs/reference_info_json.md +++ b/docs/reference_info_json.md @@ -329,7 +329,7 @@ Configures the [LED Matrix](feature_led_matrix.md) feature. * The centroid (geometric center) of the LEDs. Used for certain effects. * Default: `[112, 32]` * `driver` (Required) - * The driver to use. Must be one of `ckled2001`, `custom`, `is31fl3731`, `is31fl3742a`, `is31fl3743a`, `is31fl3745`, `is31fl3746a`. + * The driver to use. Must be one of `ckled2001`, `custom`, `is31fl3731`, `is31fl3736`, `is31fl3742a`, `is31fl3743a`, `is31fl3745`, `is31fl3746a`. * `layout` (Required) * List of LED configuration dictionaries. Each dictionary contains: * `flags` (Required) diff --git a/drivers/led/issi/is31fl3736-simple.c b/drivers/led/issi/is31fl3736-simple.c new file mode 100644 index 0000000000..cd4038ac2c --- /dev/null +++ b/drivers/led/issi/is31fl3736-simple.c @@ -0,0 +1,222 @@ +/* Copyright 2018 Jason Williams (Wilba) + * Copyright 2021 Doni Crosby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "is31fl3736-simple.h" +#include +#include "i2c_master.h" +#include "wait.h" + +#define IS31FL3736_COMMANDREGISTER 0xFD +#define IS31FL3736_COMMANDREGISTER_WRITELOCK 0xFE +#define IS31FL3736_INTERRUPTMASKREGISTER 0xF0 +#define IS31FL3736_INTERRUPTSTATUSREGISTER 0xF1 + +#define IS31FL3736_PAGE_LEDCONTROL 0x00 // PG0 +#define IS31FL3736_PAGE_PWM 0x01 // PG1 +#define IS31FL3736_PAGE_AUTOBREATH 0x02 // PG2 +#define IS31FL3736_PAGE_FUNCTION 0x03 // PG3 + +#define IS31FL3736_REG_CONFIGURATION 0x00 // PG3 +#define IS31FL3736_REG_GLOBALCURRENT 0x01 // PG3 +#define IS31FL3736_REG_RESET 0x11 // PG3 +#define IS31FL3736_REG_SWPULLUP 0x0F // PG3 +#define IS31FL3736_REG_CSPULLUP 0x10 // PG3 + +#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_SWPULLUP +# define IS31FL3736_SWPULLUP IS31FL3736_PUR_0R +#endif + +#ifndef IS31FL3736_CSPULLUP +# define IS31FL3736_CSPULLUP IS31FL3736_PUR_0R +#endif + +#ifndef IS31FL3736_GLOBALCURRENT +# define IS31FL3736_GLOBALCURRENT 0xFF +#endif + +// Transfer buffer for TWITransmitData() +uint8_t g_twi_transfer_buffer[20]; + +// These buffers match the IS31FL3736 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 is31fl3736_write_pwm_buffer() but it's +// probably not worth the extra complexity. +uint8_t g_pwm_buffer[IS31FL3736_DRIVER_COUNT][192]; +bool g_pwm_buffer_update_required[IS31FL3736_DRIVER_COUNT] = {false}; + +uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][24] = {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) { + g_twi_transfer_buffer[0] = reg; + g_twi_transfer_buffer[1] = data; + +#if IS31FL3736_I2C_PERSISTENCE > 0 + for (uint8_t i = 0; i < IS31FL3736_I2C_PERSISTENCE; i++) { + if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, IS31FL3736_I2C_TIMEOUT); +#endif +} + +void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { + // assumes PG1 is already selected + + // transmit PWM registers in 12 transfers of 16 bytes + // g_twi_transfer_buffer[] is 20 bytes + + // iterate over the pwm_buffer contents at 16 byte intervals + for (int i = 0; i < 192; i += 16) { + g_twi_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(g_twi_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, g_twi_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT) == 0) break; + } +#else + i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, IS31FL3736_I2C_TIMEOUT); +#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. + + // Unlock the command register. + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5); + + // Select PG0 + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_LEDCONTROL); + // Turn off all LEDs. + for (int i = 0x00; i <= 0x17; i++) { + is31fl3736_write_register(addr, i, 0x00); + } + + // Unlock the command register. + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5); + + // Select PG1 + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_PWM); + // Set PWM on all LEDs to 0 + // No need to setup Breath registers to PWM as that is the default. + for (int i = 0x00; i <= 0xBF; i++) { + is31fl3736_write_register(addr, i, 0x00); + } + + // Unlock the command register. + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5); + + // Select PG3 + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_FUNCTION); + // Set de-ghost pull-up resistors (SWx) + is31fl3736_write_register(addr, IS31FL3736_REG_SWPULLUP, IS31FL3736_SWPULLUP); + // Set de-ghost pull-down resistors (CSx) + is31fl3736_write_register(addr, IS31FL3736_REG_CSPULLUP, IS31FL3736_CSPULLUP); + // Set global current to maximum. + is31fl3736_write_register(addr, IS31FL3736_REG_GLOBALCURRENT, IS31FL3736_GLOBALCURRENT); + // Disable software shutdown. + is31fl3736_write_register(addr, IS31FL3736_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) { + is31_led led; + if (index >= 0 && index < LED_MATRIX_LED_COUNT) { + memcpy_P(&led, (&g_is31_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 < LED_MATRIX_LED_COUNT; i++) { + is31fl3736_set_value(i, value); + } +} + +void is31fl3736_set_led_control_register(uint8_t index, bool value) { + is31_led led; + memcpy_P(&led, (&g_is31_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]) { + // Firstly we need to unlock the command register and select PG1 + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5); + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_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]) { + // Firstly we need to unlock the command register and select PG0 + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5); + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_LEDCONTROL); + for (int i = 0; i < 24; i++) { + is31fl3736_write_register(addr, i, g_led_control_registers[index][i]); + } + g_led_control_registers_update_required[index] = false; + } +} diff --git a/drivers/led/issi/is31fl3736-simple.h b/drivers/led/issi/is31fl3736-simple.h new file mode 100644 index 0000000000..9f8056af5b --- /dev/null +++ b/drivers/led/issi/is31fl3736-simple.h @@ -0,0 +1,215 @@ +/* Copyright 2018 Jason Williams (Wilba) + * Copyright 2021 Doni Crosby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include "progmem.h" + +// ======== DEPRECATED DEFINES - DO NOT USE ======== +#ifdef DRIVER_COUNT +# define IS31FL3736_DRIVER_COUNT DRIVER_COUNT +#endif +#ifdef ISSI_TIMEOUT +# define IS31FL3736_I2C_TIMEOUT ISSI_TIMEOUT +#endif +#ifdef ISSI_PERSISTENCE +# define IS31FL3736_I2C_PERSISTENCE ISSI_PERSISTENCE +#endif +#ifdef ISSI_SWPULLUP +# define IS31FL3736_SWPULLUP ISSI_SWPULLUP +#endif +#ifdef ISSI_CSPULLUP +# define IS31FL3736_CSPULLUP ISSI_CSPULLUP +#endif +#ifdef ISSI_GLOBALCURRENT +# define IS31FL3736_GLOBALCURRENT ISSI_GLOBALCURRENT +#endif + +#define PUR_0R IS31FL3736_PUR_0R +#define PUR_05KR IS31FL3736_PUR_05KR +#define PUR_1KR IS31FL3736_PUR_1KR +#define PUR_2KR IS31FL3736_PUR_2KR +#define PUR_4KR IS31FL3736_PUR_4KR +#define PUR_8KR IS31FL3736_PUR_8KR +#define PUR_16KR IS31FL3736_PUR_16KR +#define PUR_32KR IS31FL3736_PUR_32KR +// ======== + +#define IS31FL3736_I2C_ADDRESS_GND_GND 0x50 +#define IS31FL3736_I2C_ADDRESS_GND_SCL 0x51 +#define IS31FL3736_I2C_ADDRESS_GND_SDA 0x52 +#define IS31FL3736_I2C_ADDRESS_GND_VCC 0x53 +#define IS31FL3736_I2C_ADDRESS_SCL_GND 0x54 +#define IS31FL3736_I2C_ADDRESS_SCL_SCL 0x55 +#define IS31FL3736_I2C_ADDRESS_SCL_SDA 0x56 +#define IS31FL3736_I2C_ADDRESS_SCL_VCC 0x57 +#define IS31FL3736_I2C_ADDRESS_SDA_GND 0x58 +#define IS31FL3736_I2C_ADDRESS_SDA_SCL 0x59 +#define IS31FL3736_I2C_ADDRESS_SDA_SDA 0x5A +#define IS31FL3736_I2C_ADDRESS_SDA_VCC 0x5B +#define IS31FL3736_I2C_ADDRESS_VCC_GND 0x5C +#define IS31FL3736_I2C_ADDRESS_VCC_SCL 0x5D +#define IS31FL3736_I2C_ADDRESS_VCC_SDA 0x5E +#define IS31FL3736_I2C_ADDRESS_VCC_VCC 0x5F + +typedef struct is31_led { + uint8_t driver : 2; + uint8_t v; +} __attribute__((packed)) is31_led; + +extern const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT]; + +void is31fl3736_init(uint8_t addr); +void is31fl3736_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3736_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); + +void is31fl3736_set_value(int index, uint8_t value); +void is31fl3736_set_value_all(uint8_t value); + +void is31fl3736_set_led_control_register(uint8_t index, bool value); + +// This should not be called from an interrupt +// (eg. from a timer interrupt). +// Call this while idle (in between matrix scans). +// If the buffer is dirty, it will update the driver with the buffer. +void is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index); +void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index); + +#define IS31FL3736_PUR_0R 0x00 // No PUR resistor +#define IS31FL3736_PUR_05KR 0x01 // 0.5k Ohm resistor +#define IS31FL3736_PUR_1KR 0x02 // 1.0k Ohm resistor +#define IS31FL3736_PUR_2KR 0x03 // 2.0k Ohm resistor +#define IS31FL3736_PUR_4KR 0x04 // 4.0k Ohm resistor +#define IS31FL3736_PUR_8KR 0x05 // 8.0k Ohm resistor +#define IS31FL3736_PUR_16KR 0x06 // 16k Ohm resistor +#define IS31FL3736_PUR_32KR 0x07 // 32k Ohm resistor + +#define IS31FL3736_PWM_FREQUENCY_8K4_HZ 0b000 +#define IS31FL3736_PWM_FREQUENCY_4K2_HZ 0b001 +#define IS31FL3736_PWM_FREQUENCY_26K7_HZ 0b010 +#define IS31FL3736_PWM_FREQUENCY_2K1_HZ 0b011 +#define IS31FL3736_PWM_FREQUENCY_1K05_HZ 0b100 + +#define A_1 0x00 +#define A_2 0x02 +#define A_3 0x04 +#define A_4 0x06 +#define A_5 0x08 +#define A_6 0x0A +#define A_7 0x0C +#define A_8 0x0E + +#define B_1 0x10 +#define B_2 0x12 +#define B_3 0x14 +#define B_4 0x16 +#define B_5 0x18 +#define B_6 0x1A +#define B_7 0x1C +#define B_8 0x1E + +#define C_1 0x20 +#define C_2 0x22 +#define C_3 0x24 +#define C_4 0x26 +#define C_5 0x28 +#define C_6 0x2A +#define C_7 0x2C +#define C_8 0x2E + +#define D_1 0x30 +#define D_2 0x32 +#define D_3 0x34 +#define D_4 0x36 +#define D_5 0x38 +#define D_6 0x3A +#define D_7 0x3C +#define D_8 0x3E + +#define E_1 0x40 +#define E_2 0x42 +#define E_3 0x44 +#define E_4 0x46 +#define E_5 0x48 +#define E_6 0x4A +#define E_7 0x4C +#define E_8 0x4E + +#define F_1 0x50 +#define F_2 0x52 +#define F_3 0x54 +#define F_4 0x56 +#define F_5 0x58 +#define F_6 0x5A +#define F_7 0x5C +#define F_8 0x5E + +#define G_1 0x60 +#define G_2 0x62 +#define G_3 0x64 +#define G_4 0x66 +#define G_5 0x68 +#define G_6 0x6A +#define G_7 0x6C +#define G_8 0x6E + +#define H_1 0x70 +#define H_2 0x72 +#define H_3 0x74 +#define H_4 0x76 +#define H_5 0x78 +#define H_6 0x7A +#define H_7 0x7C +#define H_8 0x7E + +#define I_1 0x80 +#define I_2 0x82 +#define I_3 0x84 +#define I_4 0x86 +#define I_5 0x88 +#define I_6 0x8A +#define I_7 0x8C +#define I_8 0x8E + +#define J_1 0x90 +#define J_2 0x92 +#define J_3 0x94 +#define J_4 0x96 +#define J_5 0x98 +#define J_6 0x9A +#define J_7 0x9C +#define J_8 0x9E + +#define K_1 0xA0 +#define K_2 0xA2 +#define K_3 0xA4 +#define K_4 0xA6 +#define K_5 0xA8 +#define K_6 0xAA +#define K_7 0xAC +#define K_8 0xAE + +#define L_1 0xB0 +#define L_2 0xB2 +#define L_3 0xB4 +#define L_4 0xB6 +#define L_5 0xB8 +#define L_6 0xBA +#define L_7 0xBC +#define L_8 0xBE diff --git a/drivers/led/issi/is31fl3736.c b/drivers/led/issi/is31fl3736.c index 7f50411f1f..23ff0637a6 100644 --- a/drivers/led/issi/is31fl3736.c +++ b/drivers/led/issi/is31fl3736.c @@ -72,8 +72,8 @@ uint8_t g_twi_transfer_buffer[20]; uint8_t g_pwm_buffer[IS31FL3736_DRIVER_COUNT][192]; bool g_pwm_buffer_update_required[IS31FL3736_DRIVER_COUNT] = {false}; -uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][24] = {{0}, {0}}; -bool g_led_control_registers_update_required = false; +uint8_t g_led_control_registers[IS31FL3736_DRIVER_COUNT][24] = {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) { g_twi_transfer_buffer[0] = reg; @@ -182,18 +182,11 @@ void is31fl3736_set_led_control_register(uint8_t index, bool red, bool green, bo is31_led led; memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); - // IS31FL3733 - // The PWM register for a matrix position (0x00 to 0xBF) can be - // divided by 8 to get the LED control register (0x00 to 0x17), - // then mod 8 to get the bit position within that register. - - // IS31FL3736 // 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 - // So, the same math applies. uint8_t control_register_r = led.r / 8; uint8_t control_register_g = led.g / 8; @@ -219,41 +212,7 @@ void is31fl3736_set_led_control_register(uint8_t index, bool red, bool green, bo g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); } - g_led_control_registers_update_required = true; -} - -void is31fl3736_mono_set_brightness(int index, uint8_t value) { - if (index >= 0 && index < 96) { - // Index in range 0..95 -> A1..A8, B1..B8, etc. - // Map index 0..95 to registers 0x00..0xBE (interleaved) - uint8_t pwm_register = index * 2; - g_pwm_buffer[0][pwm_register] = value; - g_pwm_buffer_update_required[0] = true; - } -} - -void is31fl3736_mono_set_brightness_all(uint8_t value) { - for (int i = 0; i < 96; i++) { - is31fl3736_mono_set_brightness(i, value); - } -} - -void is31fl3736_mono_set_led_control_register(uint8_t index, bool enabled) { - // Index in range 0..95 -> A1..A8, B1..B8, etc. - - // Map index 0..95 to registers 0x00..0xBE (interleaved) - uint8_t pwm_register = index * 2; - // Map register 0x00..0xBE (interleaved) into control register and bit - uint8_t control_register = pwm_register / 8; - uint8_t bit = pwm_register % 8; - - if (enabled) { - g_led_control_registers[0][control_register] |= (1 << bit); - } else { - g_led_control_registers[0][control_register] &= ~(1 << bit); - } - - g_led_control_registers_update_required = true; + g_led_control_registers_update_required[led.driver] = true; } void is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index) { @@ -267,15 +226,14 @@ void is31fl3736_update_pwm_buffers(uint8_t addr, uint8_t index) { } } -void is31fl3736_update_led_control_registers(uint8_t addr1, uint8_t addr2) { - if (g_led_control_registers_update_required) { +void is31fl3736_update_led_control_registers(uint8_t addr, uint8_t index) { + if (g_led_control_registers_update_required[index]) { // Firstly we need to unlock the command register and select PG0 - is31fl3736_write_register(addr1, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5); - is31fl3736_write_register(addr1, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_LEDCONTROL); + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER_WRITELOCK, 0xC5); + is31fl3736_write_register(addr, IS31FL3736_COMMANDREGISTER, IS31FL3736_PAGE_LEDCONTROL); for (int i = 0; i < 24; i++) { - is31fl3736_write_register(addr1, i, g_led_control_registers[0][i]); - // is31fl3736_write_register(addr2, i, g_led_control_registers[1][i]); + is31fl3736_write_register(addr, i, g_led_control_registers[index][i]); } - g_led_control_registers_update_required = false; + g_led_control_registers_update_required[index] = false; } } diff --git a/drivers/led/issi/is31fl3736.h b/drivers/led/issi/is31fl3736.h index baf200f8ad..f263b131fd 100644 --- a/drivers/led/issi/is31fl3736.h +++ b/drivers/led/issi/is31fl3736.h @@ -86,10 +86,6 @@ void is31fl3736_set_color_all(uint8_t red, uint8_t green, uint8_t blue); void is31fl3736_set_led_control_register(uint8_t index, bool red, bool green, bool blue); -void is31fl3736_mono_set_brightness(int index, uint8_t value); -void is31fl3736_mono_set_brightness_all(uint8_t value); -void is31fl3736_mono_set_led_control_register(uint8_t index, bool enabled); - // This should not be called from an interrupt // (eg. from a timer interrupt). // Call this while idle (in between matrix scans). diff --git a/keyboards/wilba_tech/wt60_a/config.h b/keyboards/wilba_tech/wt60_a/config.h index 54f68e9aaf..ec3f1abf30 100644 --- a/keyboards/wilba_tech/wt60_a/config.h +++ b/keyboards/wilba_tech/wt60_a/config.h @@ -62,5 +62,5 @@ // dynamic keymaps start after this. #define VIA_EEPROM_CUSTOM_CONFIG_SIZE 7 -#define IS31FL3736_DRIVER_COUNT 2 -#define RGB_MATRIX_LED_COUNT 96 +#define IS31FL3736_DRIVER_COUNT 1 +#define LED_MATRIX_LED_COUNT 96 diff --git a/keyboards/wilba_tech/wt60_a/rules.mk b/keyboards/wilba_tech/wt60_a/rules.mk index 4a53424c53..3a552128d8 100644 --- a/keyboards/wilba_tech/wt60_a/rules.mk +++ b/keyboards/wilba_tech/wt60_a/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736.c \ +SRC = drivers/led/issi/is31fl3736-simple.c \ i2c_master.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ diff --git a/keyboards/wilba_tech/wt65_a/config.h b/keyboards/wilba_tech/wt65_a/config.h index 8b30dd6cde..bddeb8397c 100644 --- a/keyboards/wilba_tech/wt65_a/config.h +++ b/keyboards/wilba_tech/wt65_a/config.h @@ -62,5 +62,5 @@ // dynamic keymaps start after this. #define VIA_EEPROM_CUSTOM_CONFIG_SIZE 7 -#define IS31FL3736_DRIVER_COUNT 2 -#define RGB_MATRIX_LED_COUNT 96 +#define IS31FL3736_DRIVER_COUNT 1 +#define LED_MATRIX_LED_COUNT 96 diff --git a/keyboards/wilba_tech/wt65_a/rules.mk b/keyboards/wilba_tech/wt65_a/rules.mk index 4a53424c53..3a552128d8 100644 --- a/keyboards/wilba_tech/wt65_a/rules.mk +++ b/keyboards/wilba_tech/wt65_a/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736.c \ +SRC = drivers/led/issi/is31fl3736-simple.c \ i2c_master.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ diff --git a/keyboards/wilba_tech/wt65_b/config.h b/keyboards/wilba_tech/wt65_b/config.h index 0a2a7526d9..f0aec12b06 100644 --- a/keyboards/wilba_tech/wt65_b/config.h +++ b/keyboards/wilba_tech/wt65_b/config.h @@ -62,5 +62,5 @@ // dynamic keymaps start after this. #define VIA_EEPROM_CUSTOM_CONFIG_SIZE 7 -#define IS31FL3736_DRIVER_COUNT 2 -#define RGB_MATRIX_LED_COUNT 96 +#define IS31FL3736_DRIVER_COUNT 1 +#define LED_MATRIX_LED_COUNT 96 diff --git a/keyboards/wilba_tech/wt65_b/rules.mk b/keyboards/wilba_tech/wt65_b/rules.mk index 4a53424c53..3a552128d8 100644 --- a/keyboards/wilba_tech/wt65_b/rules.mk +++ b/keyboards/wilba_tech/wt65_b/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736.c \ +SRC = drivers/led/issi/is31fl3736-simple.c \ i2c_master.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ diff --git a/keyboards/wilba_tech/wt75_a/config.h b/keyboards/wilba_tech/wt75_a/config.h index e987252e44..b2d20e3351 100644 --- a/keyboards/wilba_tech/wt75_a/config.h +++ b/keyboards/wilba_tech/wt75_a/config.h @@ -62,5 +62,5 @@ // dynamic keymaps start after this. #define VIA_EEPROM_CUSTOM_CONFIG_SIZE 7 -#define IS31FL3736_DRIVER_COUNT 2 -#define RGB_MATRIX_LED_COUNT 96 +#define IS31FL3736_DRIVER_COUNT 1 +#define LED_MATRIX_LED_COUNT 96 diff --git a/keyboards/wilba_tech/wt75_a/rules.mk b/keyboards/wilba_tech/wt75_a/rules.mk index 4a53424c53..3a552128d8 100644 --- a/keyboards/wilba_tech/wt75_a/rules.mk +++ b/keyboards/wilba_tech/wt75_a/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736.c \ +SRC = drivers/led/issi/is31fl3736-simple.c \ i2c_master.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ diff --git a/keyboards/wilba_tech/wt75_b/config.h b/keyboards/wilba_tech/wt75_b/config.h index 9d6dfb9585..cd6aa96577 100644 --- a/keyboards/wilba_tech/wt75_b/config.h +++ b/keyboards/wilba_tech/wt75_b/config.h @@ -62,5 +62,5 @@ // dynamic keymaps start after this. #define VIA_EEPROM_CUSTOM_CONFIG_SIZE 7 -#define IS31FL3736_DRIVER_COUNT 2 -#define RGB_MATRIX_LED_COUNT 96 +#define IS31FL3736_DRIVER_COUNT 1 +#define LED_MATRIX_LED_COUNT 96 diff --git a/keyboards/wilba_tech/wt75_b/rules.mk b/keyboards/wilba_tech/wt75_b/rules.mk index 4a53424c53..3a552128d8 100644 --- a/keyboards/wilba_tech/wt75_b/rules.mk +++ b/keyboards/wilba_tech/wt75_b/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736.c \ +SRC = drivers/led/issi/is31fl3736-simple.c \ i2c_master.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ diff --git a/keyboards/wilba_tech/wt75_c/config.h b/keyboards/wilba_tech/wt75_c/config.h index c4f9170872..f2cebdc7aa 100644 --- a/keyboards/wilba_tech/wt75_c/config.h +++ b/keyboards/wilba_tech/wt75_c/config.h @@ -62,5 +62,5 @@ // dynamic keymaps start after this. #define VIA_EEPROM_CUSTOM_CONFIG_SIZE 7 -#define IS31FL3736_DRIVER_COUNT 2 -#define RGB_MATRIX_LED_COUNT 96 +#define IS31FL3736_DRIVER_COUNT 1 +#define LED_MATRIX_LED_COUNT 96 diff --git a/keyboards/wilba_tech/wt75_c/rules.mk b/keyboards/wilba_tech/wt75_c/rules.mk index 4a53424c53..3a552128d8 100644 --- a/keyboards/wilba_tech/wt75_c/rules.mk +++ b/keyboards/wilba_tech/wt75_c/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736.c \ +SRC = drivers/led/issi/is31fl3736-simple.c \ i2c_master.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ diff --git a/keyboards/wilba_tech/wt80_a/config.h b/keyboards/wilba_tech/wt80_a/config.h index b33d797bdf..6b424a649f 100644 --- a/keyboards/wilba_tech/wt80_a/config.h +++ b/keyboards/wilba_tech/wt80_a/config.h @@ -62,5 +62,5 @@ // dynamic keymaps start after this. #define VIA_EEPROM_CUSTOM_CONFIG_SIZE 7 -#define IS31FL3736_DRIVER_COUNT 2 -#define RGB_MATRIX_LED_COUNT 96 +#define IS31FL3736_DRIVER_COUNT 1 +#define LED_MATRIX_LED_COUNT 96 diff --git a/keyboards/wilba_tech/wt80_a/rules.mk b/keyboards/wilba_tech/wt80_a/rules.mk index 4a53424c53..3a552128d8 100644 --- a/keyboards/wilba_tech/wt80_a/rules.mk +++ b/keyboards/wilba_tech/wt80_a/rules.mk @@ -11,7 +11,7 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality AUDIO_ENABLE = no # Audio output # project specific files -SRC = drivers/led/issi/is31fl3736.c \ +SRC = drivers/led/issi/is31fl3736-simple.c \ i2c_master.c \ quantum/color.c \ keyboards/wilba_tech/wt_mono_backlight.c \ diff --git a/keyboards/wilba_tech/wt_mono_backlight.c b/keyboards/wilba_tech/wt_mono_backlight.c index 28ee5fae81..57610f5b98 100644 --- a/keyboards/wilba_tech/wt_mono_backlight.c +++ b/keyboards/wilba_tech/wt_mono_backlight.c @@ -33,7 +33,7 @@ #error VIA_EEPROM_CUSTOM_CONFIG_SIZE was not defined to store backlight_config struct #endif -#include "drivers/led/issi/is31fl3736.h" +#include "drivers/led/issi/is31fl3736-simple.h" #define ISSI_ADDR_DEFAULT 0x50 @@ -52,6 +52,116 @@ backlight_config g_config = { .color_1 = MONO_BACKLIGHT_COLOR_1, }; +const is31_led PROGMEM g_is31_leds[LED_MATRIX_LED_COUNT] = { + {0, A_1}, + {0, A_2}, + {0, A_3}, + {0, A_4}, + {0, A_5}, + {0, A_6}, + {0, A_7}, + {0, A_8}, + + {0, B_1}, + {0, B_2}, + {0, B_3}, + {0, B_4}, + {0, B_5}, + {0, B_6}, + {0, B_7}, + {0, B_8}, + + {0, C_1}, + {0, C_2}, + {0, C_3}, + {0, C_4}, + {0, C_5}, + {0, C_6}, + {0, C_7}, + {0, C_8}, + + {0, D_1}, + {0, D_2}, + {0, D_3}, + {0, D_4}, + {0, D_5}, + {0, D_6}, + {0, D_7}, + {0, D_8}, + + {0, E_1}, + {0, E_2}, + {0, E_3}, + {0, E_4}, + {0, E_5}, + {0, E_6}, + {0, E_7}, + {0, E_8}, + + {0, F_1}, + {0, F_2}, + {0, F_3}, + {0, F_4}, + {0, F_5}, + {0, F_6}, + {0, F_7}, + {0, F_8}, + + {0, G_1}, + {0, G_2}, + {0, G_3}, + {0, G_4}, + {0, G_5}, + {0, G_6}, + {0, G_7}, + {0, G_8}, + + {0, H_1}, + {0, H_2}, + {0, H_3}, + {0, H_4}, + {0, H_5}, + {0, H_6}, + {0, H_7}, + {0, H_8}, + + {0, I_1}, + {0, I_2}, + {0, I_3}, + {0, I_4}, + {0, I_5}, + {0, I_6}, + {0, I_7}, + {0, I_8}, + + {0, J_1}, + {0, J_2}, + {0, J_3}, + {0, J_4}, + {0, J_5}, + {0, J_6}, + {0, J_7}, + {0, J_8}, + + {0, K_1}, + {0, K_2}, + {0, K_3}, + {0, K_4}, + {0, K_5}, + {0, K_6}, + {0, K_7}, + {0, K_8}, + + {0, L_1}, + {0, L_2}, + {0, L_3}, + {0, L_4}, + {0, L_5}, + {0, L_6}, + {0, L_7}, + {0, L_8} +}; + bool g_suspend_state = false; // Global tick at 20 Hz @@ -67,9 +177,9 @@ void backlight_init_drivers(void) is31fl3736_init( ISSI_ADDR_DEFAULT ); for ( uint8_t index = 0; index < 96; index++ ) { - is31fl3736_mono_set_led_control_register( index, true ); + is31fl3736_set_led_control_register( index, true ); } - is31fl3736_update_led_control_registers( ISSI_ADDR_DEFAULT, 0x00 ); + is31fl3736_update_led_control_registers( ISSI_ADDR_DEFAULT, 0 ); } void backlight_set_key_hit(uint8_t row, uint8_t column) @@ -119,17 +229,17 @@ void backlight_set_suspend_state(bool state) void backlight_set_brightness_all( uint8_t value ) { - is31fl3736_mono_set_brightness_all( value ); + is31fl3736_set_value_all( value ); } void backlight_effect_all_off(void) { - is31fl3736_mono_set_brightness_all( 0 ); + is31fl3736_set_value_all( 0 ); } void backlight_effect_all_on(void) { - is31fl3736_mono_set_brightness_all( g_config.brightness ); + is31fl3736_set_value_all( g_config.brightness ); } void backlight_effect_raindrops(bool initialize) @@ -143,7 +253,7 @@ void backlight_effect_raindrops(bool initialize) // If not, all but one will stay the same as before. if ( initialize || i == led_to_change ) { - is31fl3736_mono_set_brightness(i, rand() & 0xFF ); + is31fl3736_set_value(i, rand() & 0xFF ); } } } @@ -165,9 +275,9 @@ void backlight_effect_indicators(void) // SW7,CS8 = (6*8+7) = 55 // SW8,CS8 = (7*8+7) = 63 // SW9,CS8 = (8*8+7) = 71 - is31fl3736_mono_set_brightness(55, rgb.r); - is31fl3736_mono_set_brightness(63, rgb.g); - is31fl3736_mono_set_brightness(71, rgb.b); + is31fl3736_set_value(55, rgb.r); + is31fl3736_set_value(63, rgb.g); + is31fl3736_set_value(71, rgb.b); #endif // MONO_BACKLIGHT_WT75_A // This pairs with "All Off" already setting zero brightness, @@ -181,19 +291,19 @@ defined(MONO_BACKLIGHT_WT75_C) || \ defined(MONO_BACKLIGHT_WT80_A) if ( host_keyboard_led_state().caps_lock ) { // SW3,CS1 = (2*8+0) = 16 - is31fl3736_mono_set_brightness(16, 255); + is31fl3736_set_value(16, 255); } #endif #if defined(MONO_BACKLIGHT_WT80_A) if ( host_keyboard_led_state().scroll_lock ) { // SW7,CS7 = (6*8+6) = 54 - is31fl3736_mono_set_brightness(54, 255); + is31fl3736_set_value(54, 255); } #endif #if defined(MONO_BACKLIGHT_WT75_C) if ( host_keyboard_led_state().scroll_lock ) { // SW7,CS8 = (6*8+7) = 55 - is31fl3736_mono_set_brightness(55, 255); + is31fl3736_set_value(55, 255); } #endif } @@ -361,7 +471,7 @@ void backlight_config_save(void) void backlight_update_pwm_buffers(void) { - is31fl3736_update_pwm_buffers(ISSI_ADDR_DEFAULT,0x00); + is31fl3736_update_pwm_buffers(ISSI_ADDR_DEFAULT, 0); } bool process_record_backlight(uint16_t keycode, keyrecord_t *record) diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h index d654fd5757..2b41f11bbf 100644 --- a/quantum/led_matrix/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h @@ -27,12 +27,16 @@ #ifdef LED_MATRIX_IS31FL3731 # include "is31fl3731-simple.h" -#elif defined(IS31FLCOMMON) -# include "is31flcommon.h" #endif #ifdef LED_MATRIX_IS31FL3733 # include "is31fl3733-simple.h" #endif +#ifdef LED_MATRIX_IS31FL3736 +# include "is31fl3736-simple.h" +#endif +#if defined(IS31FLCOMMON) +# include "is31flcommon.h" +#endif #ifdef LED_MATRIX_CKLED2001 # include "ckled2001-simple.h" #endif diff --git a/quantum/led_matrix/led_matrix_drivers.c b/quantum/led_matrix/led_matrix_drivers.c index 77c5aa3d0a..7ca0c7958f 100644 --- a/quantum/led_matrix/led_matrix_drivers.c +++ b/quantum/led_matrix/led_matrix_drivers.c @@ -25,7 +25,7 @@ * in their own files. */ -#if defined(LED_MATRIX_IS31FL3731) || defined(LED_MATRIX_IS31FL3733) || defined(IS31FLCOMMON) || defined(LED_MATRIX_CKLED2001) +#if defined(LED_MATRIX_IS31FL3731) || defined(LED_MATRIX_IS31FL3733) || defined(LED_MATRIX_IS31FL3736) || defined(IS31FLCOMMON) || defined(LED_MATRIX_CKLED2001) # include "i2c_master.h" static void init(void) { @@ -67,6 +67,18 @@ static void init(void) { # endif # endif +# elif defined(LED_MATRIX_IS31FL3736) + is31fl3736_init(LED_DRIVER_ADDR_1); +# if defined(LED_DRIVER_ADDR_2) + is31fl3736_init(LED_DRIVER_ADDR_2); +# if defined(LED_DRIVER_ADDR_3) + is31fl3736_init(LED_DRIVER_ADDR_3); +# if defined(LED_DRIVER_ADDR_4) + is31fl3736_init(LED_DRIVER_ADDR_4); +# endif +# endif +# endif + # elif defined(IS31FLCOMMON) IS31FL_common_init(DRIVER_ADDR_1, ISSI_SSR_1); # if defined(LED_DRIVER_ADDR_2) @@ -101,6 +113,8 @@ static void init(void) { is31fl3731_set_led_control_register(index, true); # elif defined(LED_MATRIX_IS31FL3733) is31fl3733_set_led_control_register(index, true); +# elif defined(LED_MATRIX_IS31FL3736) + is31fl3736_set_led_control_register(index, true); # elif defined(IS31FLCOMMON) IS31FL_simple_set_scaling_buffer(index, true); # elif defined(LED_MATRIX_CKLED2001) @@ -133,6 +147,18 @@ static void init(void) { # endif # endif +# elif defined(LED_MATRIX_IS31FL3736) + is31fl3736_update_led_control_registers(LED_DRIVER_ADDR_1, 0); +# if defined(LED_DRIVER_ADDR_2) + is31fl3736_update_led_control_registers(LED_DRIVER_ADDR_2, 1); +# if defined(LED_DRIVER_ADDR_3) + is31fl3736_update_led_control_registers(LED_DRIVER_ADDR_3, 2); +# if defined(LED_DRIVER_ADDR_4) + is31fl3736_update_led_control_registers(LED_DRIVER_ADDR_4, 3); +# endif +# endif +# endif + # elif defined(IS31FLCOMMON) # ifdef ISSI_MANUAL_SCALING IS31FL_set_manual_scaling_buffer(); @@ -203,6 +229,27 @@ const led_matrix_driver_t led_matrix_driver = { .set_value_all = is31fl3733_set_value_all, }; +# elif defined(LED_MATRIX_IS31FL3736) +static void flush(void) { + is31fl3736_update_pwm_buffers(LED_DRIVER_ADDR_1, 0); +# if defined(LED_DRIVER_ADDR_2) + is31fl3736_update_pwm_buffers(LED_DRIVER_ADDR_2, 1); +# if defined(LED_DRIVER_ADDR_3) + is31fl3736_update_pwm_buffers(LED_DRIVER_ADDR_3, 2); +# if defined(LED_DRIVER_ADDR_4) + is31fl3736_update_pwm_buffers(LED_DRIVER_ADDR_4, 3); +# endif +# endif +# endif +} + +const led_matrix_driver_t led_matrix_driver = { + .init = init, + .flush = flush, + .set_value = is31fl3736_set_value, + .set_value_all = is31fl3736_set_value_all, +}; + # elif defined(IS31FLCOMMON) static void flush(void) { IS31FL_common_update_pwm_register(DRIVER_ADDR_1, 0);