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

Dual RGB Matrix IS31FL3737 driver support to address #13442 #13457

Merged
merged 9 commits into from
Jul 15, 2021
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
25 changes: 20 additions & 5 deletions docs/feature_rgb_matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,22 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
RGB_MATRIX_ENABLE = yes
RGB_MATRIX_DRIVER = IS31FL3737
```
You can use between 1 and 2 IS31FL3737 IC's. Do not specify `DRIVER_ADDR_2` define for second IC if not present on your keyboard.

Configure the hardware via your `config.h`:

| Variable | Description | Default |
|----------|-------------|---------|
| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |


Here is an example using 2 drivers.

```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 All @@ -159,14 +172,16 @@ Configure the hardware via your `config.h`:
// ADDR represents A3:A0 of the 7-bit address.
// The result is: 0b101(ADDR)
#define DRIVER_ADDR_1 0b1010000
#define DRIVER_ADDR_2 0b1010000 // this is here for compliancy reasons.
#define DRIVER_ADDR_2 0b1010001

#define DRIVER_COUNT 2
#define DRIVER_1_LED_TOTAL 64
#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL
#define DRIVER_1_LED_TOTAL 30
#define DRIVER_2_LED_TOTAL 36
#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
```
!> Note the parentheses, this is so when `DRIVER_LED_TOTAL` is used in code and expanded, the values are added together before any additional math is applied to them. As an example, `rand() % (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)` will give very different results than `rand() % DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL`.

Currently only a single drivers is supported, but it would be trivial to support all 4 combinations. For now define `DRIVER_ADDR_2` as `DRIVER_ADDR_1`
Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.

Define these arrays listing all the LEDs in your `<keyboard>.c`:

Expand All @@ -183,7 +198,7 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
}
```

Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3737.pdf) and the header file `drivers/issi/is31fl3737.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0` right now).
Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](https://www.issi.com/WW/pdf/31FL3737.pdf) and the header file `drivers/issi/is31fl3737.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0`, `1` for now).

---

Expand Down
43 changes: 21 additions & 22 deletions drivers/issi/is31fl3737.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ uint8_t g_twi_transfer_buffer[20];
// 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[DRIVER_COUNT][192];
bool g_pwm_buffer_update_required = false;
bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};

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

void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
g_twi_transfer_buffer[0] = reg;
Expand Down Expand Up @@ -155,10 +156,10 @@ void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
if (index >= 0 && index < DRIVER_LED_TOTAL) {
is31_led led = g_is31_leds[index];

g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green;
g_pwm_buffer[led.driver][led.b] = blue;
g_pwm_buffer_update_required = true;
g_pwm_buffer[led.driver][led.r] = red;
g_pwm_buffer[led.driver][led.g] = green;
g_pwm_buffer[led.driver][led.b] = blue;
g_pwm_buffer_update_required[led.driver] = true;
}
}

Expand Down Expand Up @@ -194,30 +195,28 @@ void IS31FL3737_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;
g_led_control_registers_update_required[led.driver] = true;
}

void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2) {
if (g_pwm_buffer_update_required) {
void IS31FL3737_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
IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);

IS31FL3737_write_pwm_buffer(addr1, g_pwm_buffer[0]);
// IS31FL3737_write_pwm_buffer(addr2, g_pwm_buffer[1]);
IS31FL3737_write_pwm_buffer(addr, g_pwm_buffer[index]);
}
g_pwm_buffer_update_required = false;
g_pwm_buffer_update_required[index] = false;
}

void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2) {
if (g_led_control_registers_update_required) {
void IS31FL3737_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
IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
for (int i = 0; i < 24; i++) {
IS31FL3737_write_register(addr1, i, g_led_control_registers[0][i]);
// IS31FL3737_write_register(addr2, i, g_led_control_registers[1][i]);
IS31FL3737_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;
}
15 changes: 13 additions & 2 deletions quantum/rgb_matrix/rgb_matrix_drivers.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ static void init(void) {
# endif
# elif defined(IS31FL3737)
IS31FL3737_init(DRIVER_ADDR_1);
# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
IS31FL3737_init(DRIVER_ADDR_2);
# endif
# else
IS31FL3741_init(DRIVER_ADDR_1);
# endif
Expand Down Expand Up @@ -105,7 +108,10 @@ static void init(void) {
IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3);
# endif
# elif defined(IS31FL3737)
IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, DRIVER_ADDR_2);
IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, 0);
# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
IS31FL3737_update_led_control_registers(DRIVER_ADDR_2, 1);
# endif
# else
IS31FL3741_update_led_control_registers(DRIVER_ADDR_1, 0);
# endif
Expand Down Expand Up @@ -152,7 +158,12 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
.set_color_all = IS31FL3733_set_color_all,
};
# elif defined(IS31FL3737)
static void flush(void) { IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, DRIVER_ADDR_2); }
static void flush(void) {
IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, 0);
# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
IS31FL3737_update_pwm_buffers(DRIVER_ADDR_2, 1);
# endif
}

const rgb_matrix_driver_t rgb_matrix_driver = {
.init = init,
Expand Down