Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complete RGB Matrix support for IS31FL3218 #22004

Merged
merged 5 commits into from
Sep 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion builddefs/common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ endif

RGB_MATRIX_ENABLE ?= no

VALID_RGB_MATRIX_TYPES := aw20216s is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 ws2812 custom
VALID_RGB_MATRIX_TYPES := aw20216s is31fl3218 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a ckled2001 ws2812 custom
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
$(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
Expand Down Expand Up @@ -444,6 +444,13 @@ endif
QUANTUM_LIB_SRC += spi_master.c
endif

ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3218)
OPT_DEFS += -DIS31FL3218 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
SRC += is31fl3218.c
QUANTUM_LIB_SRC += i2c_master.c
endif

ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3731)
OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
COMMON_VPATH += $(DRIVER_PATH)/led/issi
Expand Down
2 changes: 1 addition & 1 deletion docs/reference_info_json.md
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ Configures the [RGB Matrix](feature_rgb_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 `aw20216s`, `ckled2001`, `custom`, `is31fl3731`, `is31fl3733`, `is31fl3736`, `is31fl3737`, `is31fl3741`, `is31fl3742a`, `is31fl3743a`, `is31fl3745`, `is31fl3746a`, `ws2812`.
* The driver to use. Must be one of `aw20216s`, `ckled2001`, `custom`, `is31fl3218`, `is31fl3731`, `is31fl3733`, `is31fl3736`, `is31fl3737`, `is31fl3741`, `is31fl3742a`, `is31fl3743a`, `is31fl3745`, `is31fl3746a`, `ws2812`.
* `hue_steps`
* The number of hue adjustment steps.
* Default: `8`
Expand Down
96 changes: 79 additions & 17 deletions drivers/led/issi/is31fl3218.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,57 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "is31fl3218.h"
#include <string.h>
#include "i2c_master.h"

// This is the full 8-bit address
#define IS31FL3218_I2C_ADDRESS 0xA8

// These are the register addresses
#define IS31FL3218_REG_SHUTDOWN 0x00
#define IS31FL3218_REG_PWM 0x01
#define IS31FL3218_REG_CONTROL 0x13
#define IS31FL3218_REG_UPDATE 0x16
#define IS31FL3218_REG_RESET 0x17

// Default timeout if no I2C response
#define IS31FL3218_I2C_TIMEOUT 100
#ifndef IS31FL3218_I2C_TIMEOUT
# define IS31FL3218_I2C_TIMEOUT 100
#endif

#ifndef IS31FL3218_I2C_PERSISTENCE
# define IS31FL3218_I2C_PERSISTENCE 0
#endif

// Reusable buffer for transfers
uint8_t g_twi_transfer_buffer[20];

// IS31FL3218 has 18 PWM outputs and a fixed I2C address, so no chaining.
// If used as RGB LED driver, LEDs are assigned RGB,RGB,RGB,RGB,RGB,RGB
uint8_t g_pwm_buffer[18];
bool g_pwm_buffer_update_required = false;

uint8_t g_led_control_registers[3] = {0};
bool g_led_control_registers_update_required = false;

void is31fl3218_write_register(uint8_t reg, uint8_t data) {
g_twi_transfer_buffer[0] = reg;
g_twi_transfer_buffer[1] = data;
i2c_transmit(IS31FL3218_I2C_ADDRESS, g_twi_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT);
#if IS31FL3218_I2C_PERSISTENCE > 0
for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) {
if (i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT) == 0) break;
}
#else
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 2, IS31FL3218_I2C_TIMEOUT);
#endif
}

void is31fl3218_write_pwm_buffer(uint8_t *pwm_buffer) {
g_twi_transfer_buffer[0] = IS31FL3218_REG_PWM;
memcpy(g_twi_transfer_buffer + 1, pwm_buffer, 18);

i2c_transmit(IS31FL3218_I2C_ADDRESS, g_twi_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
#if IS31FL3218_I2C_PERSISTENCE > 0
for (uint8_t i = 0; i < IS31FL3218_I2C_PERSISTENCE; i++) {
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
}
#else
i2c_transmit(IS31FL3218_I2C_ADDRESS << 1, g_twi_transfer_buffer, 19, IS31FL3218_I2C_TIMEOUT);
#endif
}

void is31fl3218_init(void) {
Expand All @@ -62,36 +79,81 @@ void is31fl3218_init(void) {
is31fl3218_write_register(IS31FL3218_REG_PWM + i, 0x00);
}

// Enable all channels
// turn off all LEDs in the LED control register
for (uint8_t i = 0; i < 3; i++) {
is31fl3218_write_register(IS31FL3218_REG_CONTROL + i, 0b00111111);
is31fl3218_write_register(IS31FL3218_REG_CONTROL + i, 0x00);
}

// Load PWM registers and LED Control register data
is31fl3218_write_register(IS31FL3218_REG_UPDATE, 0x01);
}

void is31fl3218_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
if (g_pwm_buffer[index * 3 + 0] == red && g_pwm_buffer[index * 3 + 1] == green && g_pwm_buffer[index * 3 + 2] == blue) {
is31fl3218_led_t led;
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
memcpy_P(&led, (&g_is31fl3218_leds[index]), sizeof(led));
}
if (g_pwm_buffer[led.r - IS31FL3218_REG_PWM] == red && g_pwm_buffer[led.g - IS31FL3218_REG_PWM] == green && g_pwm_buffer[led.b - IS31FL3218_REG_PWM] == blue) {
return;
}
g_pwm_buffer[index * 3 + 0] = red;
g_pwm_buffer[index * 3 + 1] = green;
g_pwm_buffer[index * 3 + 2] = blue;
g_pwm_buffer_update_required = true;
g_pwm_buffer[led.r - IS31FL3218_REG_PWM] = red;
g_pwm_buffer[led.g - IS31FL3218_REG_PWM] = green;
g_pwm_buffer[led.b - IS31FL3218_REG_PWM] = blue;
g_pwm_buffer_update_required = true;
}

void is31fl3218_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
for (int i = 0; i < 6; i++) {
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
is31fl3218_set_color(i, red, green, blue);
}
}

void is31fl3218_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
is31fl3218_led_t led;
memcpy_P(&led, (&g_is31fl3218_leds[index]), sizeof(led));

uint8_t control_register_r = (led.r - IS31FL3218_REG_PWM) / 6;
uint8_t control_register_g = (led.g - IS31FL3218_REG_PWM) / 6;
uint8_t control_register_b = (led.b - IS31FL3218_REG_PWM) / 6;
uint8_t bit_r = (led.r - IS31FL3218_REG_PWM) % 6;
uint8_t bit_g = (led.g - IS31FL3218_REG_PWM) % 6;
uint8_t bit_b = (led.b - IS31FL3218_REG_PWM) % 6;

if (red) {
g_led_control_registers[control_register_r] |= (1 << bit_r);
} else {
g_led_control_registers[control_register_r] &= ~(1 << bit_r);
}
if (green) {
g_led_control_registers[control_register_g] |= (1 << bit_g);
} else {
g_led_control_registers[control_register_g] &= ~(1 << bit_g);
}
if (blue) {
g_led_control_registers[control_register_b] |= (1 << bit_b);
} else {
g_led_control_registers[control_register_b] &= ~(1 << bit_b);
}

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 < 3; i++) {
is31fl3218_write_register(IS31FL3218_REG_CONTROL + i, g_led_control_registers[i]);
}

g_led_control_registers_update_required = false;
}
g_pwm_buffer_update_required = false;
}
38 changes: 37 additions & 1 deletion drivers/led/issi/is31fl3218.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,45 @@

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "progmem.h"

#define IS31FL3218_I2C_ADDRESS 0x54

typedef struct is31fl3218_led_t {
uint8_t r;
uint8_t g;
uint8_t b;
} __attribute__((packed)) is31fl3218_led_t;

extern const is31fl3218_led_t PROGMEM g_is31fl3218_leds[RGB_MATRIX_LED_COUNT];

void is31fl3218_init(void);

void is31fl3218_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);

void is31fl3218_set_color_all(uint8_t red, uint8_t green, uint8_t blue);

void is31fl3218_set_led_control_register(uint8_t index, bool red, bool green, bool blue);

void is31fl3218_update_pwm_buffers(void);

void is31fl3218_update_led_control_registers(void);

#define OUT1 0x01
#define OUT2 0x02
#define OUT3 0x03
#define OUT4 0x04
#define OUT5 0x05
#define OUT6 0x06
#define OUT7 0x07
#define OUT8 0x08
#define OUT9 0x09
#define OUT10 0x0A
#define OUT11 0x0B
#define OUT12 0x0C
#define OUT13 0x0D
#define OUT14 0x0E
#define OUT15 0x0F
#define OUT16 0x10
#define OUT17 0x11
#define OUT18 0x12
4 changes: 1 addition & 3 deletions keyboards/wilba_tech/rama_works_m60_a/keymaps/zyber/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@

#pragma once
#undef PRODUCT
#define PRODUCT RAMA WORKS M60-A Seq2
#undef DESCRIPTION
#define DESCRIPTION RAMA WORKS M60-A Seq2
#define PRODUCT "RAMA WORKS M60-A Seq2"
2 changes: 2 additions & 0 deletions keyboards/wilba_tech/rama_works_m6_b/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE

#define RGB_MATRIX_LED_COUNT 6

#define RGB_BACKLIGHT_ENABLED 1

// This conditionally compiles the backlight code for M6-B specifics
Expand Down
20 changes: 19 additions & 1 deletion keyboards/wilba_tech/wt_rgb_backlight.c
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,14 @@ const is31_led PROGMEM g_is31_leds[RGB_MATRIX_LED_COUNT] = {
};

#elif defined(RGB_BACKLIGHT_M6_B)
// Driver has fixed mapping of index to the red, green and blue LEDs
const is31fl3218_led_t PROGMEM g_is31fl3218_leds[RGB_MATRIX_LED_COUNT] = {
{OUT1, OUT2, OUT3},
{OUT4, OUT5, OUT6},
{OUT7, OUT8, OUT9},
{OUT10, OUT11, OUT12},
{OUT13, OUT14, OUT15},
{OUT16, OUT17, OUT18}
};
#elif defined(RGB_BACKLIGHT_M10_C)
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
Expand Down Expand Up @@ -2915,6 +2922,17 @@ void backlight_init_drivers(void)

#if defined(RGB_BACKLIGHT_M6_B)
is31fl3218_init();

for ( int index = 0; index < RGB_MATRIX_LED_COUNT; index++ )
{
bool enabled = true;

// This only caches it for later
is31fl3218_set_led_control_register( index, enabled, enabled, enabled );
}

// This actually updates the LED drivers
is31fl3218_update_led_control_registers();
#elif defined(RGB_BACKLIGHT_HS60)
is31fl3733_init( ISSI_ADDR_1, 0 );

Expand Down
4 changes: 3 additions & 1 deletion quantum/rgb_matrix/rgb_matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
#include "color.h"
#include "keyboard.h"

#ifdef IS31FL3731
#if defined(IS31FL3218)
# include "is31fl3218.h"
#elif defined(IS31FL3731)
# include "is31fl3731.h"
#elif defined(IS31FL3733)
# include "is31fl3733.h"
Expand Down
36 changes: 28 additions & 8 deletions quantum/rgb_matrix/rgb_matrix_drivers.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* be here if shared between boards.
*/

#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3736) || defined(IS31FL3737) || defined(IS31FL3741) || defined(IS31FLCOMMON) || defined(CKLED2001)
#if defined(IS31FL3218) || defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FL3736) || defined(IS31FL3737) || defined(IS31FL3741) || defined(IS31FLCOMMON) || defined(CKLED2001)
# include "i2c_master.h"

// TODO: Remove this at some later date
Expand All @@ -37,7 +37,10 @@
static void init(void) {
i2c_init();

# if defined(IS31FL3731)
# if defined(IS31FL3218)
is31fl3218_init();

# elif defined(IS31FL3731)
is31fl3731_init(DRIVER_ADDR_1);
# if defined(DRIVER_ADDR_2)
is31fl3731_init(DRIVER_ADDR_2);
Expand Down Expand Up @@ -138,7 +141,9 @@ static void init(void) {
bool enabled = true;

// This only caches it for later
# if defined(IS31FL3731)
# if defined(IS31FL3218)
is31fl3218_set_led_control_register(index, enabled, enabled, enabled);
# elif defined(IS31FL3731)
is31fl3731_set_led_control_register(index, enabled, enabled, enabled);
# elif defined(IS31FL3733)
is31fl3733_set_led_control_register(index, enabled, enabled, enabled);
Expand All @@ -156,7 +161,10 @@ static void init(void) {
}

// This actually updates the LED drivers
# if defined(IS31FL3731)
# if defined(IS31FL3218)
is31fl3218_update_led_control_registers();

# elif defined(IS31FL3731)
is31fl3731_update_led_control_registers(DRIVER_ADDR_1, 0);
# if defined(DRIVER_ADDR_2)
is31fl3731_update_led_control_registers(DRIVER_ADDR_2, 1);
Expand Down Expand Up @@ -245,7 +253,19 @@ static void init(void) {
# endif
}

# if defined(IS31FL3731)
# if defined(IS31FL3218)
static void flush(void) {
is31fl3218_update_pwm_buffers();
}

const rgb_matrix_driver_t rgb_matrix_driver = {
.init = init,
.flush = flush,
.set_color = is31fl3218_set_color,
.set_color_all = is31fl3218_set_color_all,
};

# elif defined(IS31FL3731)
static void flush(void) {
is31fl3731_update_pwm_buffers(DRIVER_ADDR_1, 0);
# if defined(DRIVER_ADDR_2)
Expand All @@ -260,9 +280,9 @@ static void flush(void) {
}

const rgb_matrix_driver_t rgb_matrix_driver = {
.init = init,
.flush = flush,
.set_color = is31fl3731_set_color,
.init = init,
.flush = flush,
.set_color = is31fl3731_set_color,
.set_color_all = is31fl3731_set_color_all,
};

Expand Down