aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Cullin <chris@miplace.com>2021-07-16 07:52:05 +1000
committerGitHub <noreply@github.com>2021-07-15 22:52:05 +0100
commit70267b35c357f2744262300db03eafe642159734 (patch)
tree954f0ed828294d30c4beed4c02a00cb7ad507c60
parente07401bb5ac4f0e23aac8c943d9f03fa257834a3 (diff)
downloadqmk_firmware-70267b35c357f2744262300db03eafe642159734.tar.gz
qmk_firmware-70267b35c357f2744262300db03eafe642159734.zip
Dual RGB Matrix IS31FL3737 driver support to address #13442 (#13457)
* initial commit * removed changes to write_pwm_buffer * backward compatbility added * fixed issue with backward compatibility * documentation update * removed unneccessary comment. branched from master * updated per comments #13457 * removed blank line * cformat on diff files
-rw-r--r--docs/feature_rgb_matrix.md25
-rw-r--r--drivers/issi/is31fl3737.c43
-rw-r--r--quantum/rgb_matrix/rgb_matrix_drivers.c15
3 files changed, 54 insertions, 29 deletions
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index be763ee02..f3e25f2f1 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -145,9 +145,22 @@ There is basic support for addressable RGB matrix lighting with the I2C IS31FL37
145RGB_MATRIX_ENABLE = yes 145RGB_MATRIX_ENABLE = yes
146RGB_MATRIX_DRIVER = IS31FL3737 146RGB_MATRIX_DRIVER = IS31FL3737
147``` 147```
148You 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.
148 149
149Configure the hardware via your `config.h`: 150Configure the hardware via your `config.h`:
150 151
152| Variable | Description | Default |
153|----------|-------------|---------|
154| `ISSI_TIMEOUT` | (Optional) How long to wait for i2c messages, in milliseconds | 100 |
155| `ISSI_PERSISTENCE` | (Optional) Retry failed messages this many times | 0 |
156| `DRIVER_COUNT` | (Required) How many RGB driver IC's are present | |
157| `DRIVER_LED_TOTAL` | (Required) How many RGB lights are present across all drivers | |
158| `DRIVER_ADDR_1` | (Required) Address for the first RGB driver | |
159| `DRIVER_ADDR_2` | (Optional) Address for the second RGB driver | |
160
161
162Here is an example using 2 drivers.
163
151```c 164```c
152// This is a 7-bit address, that gets left-shifted and bit 0 165// This is a 7-bit address, that gets left-shifted and bit 0
153// set to 0 for write, 1 for read (as per I2C protocol) 166// set to 0 for write, 1 for read (as per I2C protocol)
@@ -159,14 +172,16 @@ Configure the hardware via your `config.h`:
159// ADDR represents A3:A0 of the 7-bit address. 172// ADDR represents A3:A0 of the 7-bit address.
160// The result is: 0b101(ADDR) 173// The result is: 0b101(ADDR)
161#define DRIVER_ADDR_1 0b1010000 174#define DRIVER_ADDR_1 0b1010000
162#define DRIVER_ADDR_2 0b1010000 // this is here for compliancy reasons. 175#define DRIVER_ADDR_2 0b1010001
163 176
164#define DRIVER_COUNT 2 177#define DRIVER_COUNT 2
165#define DRIVER_1_LED_TOTAL 64 178#define DRIVER_1_LED_TOTAL 30
166#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL 179#define DRIVER_2_LED_TOTAL 36
180#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
167``` 181```
182!> 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`.
168 183
169Currently 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` 184Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
170 185
171Define these arrays listing all the LEDs in your `<keyboard>.c`: 186Define these arrays listing all the LEDs in your `<keyboard>.c`:
172 187
@@ -183,7 +198,7 @@ const is31_led PROGMEM g_is31_leds[DRIVER_LED_TOTAL] = {
183} 198}
184``` 199```
185 200
186Where `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). 201Where `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).
187 202
188--- 203---
189 204
diff --git a/drivers/issi/is31fl3737.c b/drivers/issi/is31fl3737.c
index e40bfa0d7..30906b484 100644
--- a/drivers/issi/is31fl3737.c
+++ b/drivers/issi/is31fl3737.c
@@ -66,11 +66,12 @@ uint8_t g_twi_transfer_buffer[20];
66// We could optimize this and take out the unused registers from these 66// We could optimize this and take out the unused registers from these
67// buffers and the transfers in IS31FL3737_write_pwm_buffer() but it's 67// buffers and the transfers in IS31FL3737_write_pwm_buffer() but it's
68// probably not worth the extra complexity. 68// probably not worth the extra complexity.
69
69uint8_t g_pwm_buffer[DRIVER_COUNT][192]; 70uint8_t g_pwm_buffer[DRIVER_COUNT][192];
70bool g_pwm_buffer_update_required = false; 71bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
71 72
72uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}}; 73uint8_t g_led_control_registers[DRIVER_COUNT][24] = {0};
73bool g_led_control_registers_update_required = false; 74bool g_led_control_registers_update_required[DRIVER_COUNT] = {false};
74 75
75void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) { 76void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
76 g_twi_transfer_buffer[0] = reg; 77 g_twi_transfer_buffer[0] = reg;
@@ -158,10 +159,10 @@ void IS31FL3737_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
158 is31_led led; 159 is31_led led;
159 memcpy_P(&led, (&g_is31_leds[index]), sizeof(led)); 160 memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
160 161
161 g_pwm_buffer[led.driver][led.r] = red; 162 g_pwm_buffer[led.driver][led.r] = red;
162 g_pwm_buffer[led.driver][led.g] = green; 163 g_pwm_buffer[led.driver][led.g] = green;
163 g_pwm_buffer[led.driver][led.b] = blue; 164 g_pwm_buffer[led.driver][led.b] = blue;
164 g_pwm_buffer_update_required = true; 165 g_pwm_buffer_update_required[led.driver] = true;
165 } 166 }
166} 167}
167 168
@@ -199,30 +200,28 @@ void IS31FL3737_set_led_control_register(uint8_t index, bool red, bool green, bo
199 g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); 200 g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
200 } 201 }
201 202
202 g_led_control_registers_update_required = true; 203 g_led_control_registers_update_required[led.driver] = true;
203} 204}
204 205
205void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2) { 206void IS31FL3737_update_pwm_buffers(uint8_t addr, uint8_t index) {
206 if (g_pwm_buffer_update_required) { 207 if (g_pwm_buffer_update_required[index]) {
207 // Firstly we need to unlock the command register and select PG1 208 // Firstly we need to unlock the command register and select PG1
208 IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); 209 IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
209 IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM); 210 IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
210 211
211 IS31FL3737_write_pwm_buffer(addr1, g_pwm_buffer[0]); 212 IS31FL3737_write_pwm_buffer(addr, g_pwm_buffer[index]);
212 // IS31FL3737_write_pwm_buffer(addr2, g_pwm_buffer[1]);
213 } 213 }
214 g_pwm_buffer_update_required = false; 214 g_pwm_buffer_update_required[index] = false;
215} 215}
216 216
217void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2) { 217void IS31FL3737_update_led_control_registers(uint8_t addr, uint8_t index) {
218 if (g_led_control_registers_update_required) { 218 if (g_led_control_registers_update_required[index]) {
219 // Firstly we need to unlock the command register and select PG0 219 // Firstly we need to unlock the command register and select PG0
220 IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); 220 IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
221 IS31FL3737_write_register(addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL); 221 IS31FL3737_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
222 for (int i = 0; i < 24; i++) { 222 for (int i = 0; i < 24; i++) {
223 IS31FL3737_write_register(addr1, i, g_led_control_registers[0][i]); 223 IS31FL3737_write_register(addr, i, g_led_control_registers[index][i]);
224 // IS31FL3737_write_register(addr2, i, g_led_control_registers[1][i]);
225 } 224 }
226 g_led_control_registers_update_required = false;
227 } 225 }
226 g_led_control_registers_update_required[index] = false;
228} 227}
diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c
index 6a11d4791..dfdf45219 100644
--- a/quantum/rgb_matrix/rgb_matrix_drivers.c
+++ b/quantum/rgb_matrix/rgb_matrix_drivers.c
@@ -65,6 +65,9 @@ static void init(void) {
65# endif 65# endif
66# elif defined(IS31FL3737) 66# elif defined(IS31FL3737)
67 IS31FL3737_init(DRIVER_ADDR_1); 67 IS31FL3737_init(DRIVER_ADDR_1);
68# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
69 IS31FL3737_init(DRIVER_ADDR_2);
70# endif
68# else 71# else
69 IS31FL3741_init(DRIVER_ADDR_1); 72 IS31FL3741_init(DRIVER_ADDR_1);
70# endif 73# endif
@@ -105,7 +108,10 @@ static void init(void) {
105 IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3); 108 IS31FL3733_update_led_control_registers(DRIVER_ADDR_4, 3);
106# endif 109# endif
107# elif defined(IS31FL3737) 110# elif defined(IS31FL3737)
108 IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, DRIVER_ADDR_2); 111 IS31FL3737_update_led_control_registers(DRIVER_ADDR_1, 0);
112# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
113 IS31FL3737_update_led_control_registers(DRIVER_ADDR_2, 1);
114# endif
109# else 115# else
110 IS31FL3741_update_led_control_registers(DRIVER_ADDR_1, 0); 116 IS31FL3741_update_led_control_registers(DRIVER_ADDR_1, 0);
111# endif 117# endif
@@ -152,7 +158,12 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
152 .set_color_all = IS31FL3733_set_color_all, 158 .set_color_all = IS31FL3733_set_color_all,
153}; 159};
154# elif defined(IS31FL3737) 160# elif defined(IS31FL3737)
155static void flush(void) { IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, DRIVER_ADDR_2); } 161static void flush(void) {
162 IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, 0);
163# if defined(DRIVER_ADDR_2) && (DRIVER_ADDR_2 != DRIVER_ADDR_1) // provides backward compatibility
164 IS31FL3737_update_pwm_buffers(DRIVER_ADDR_2, 1);
165# endif
166}
156 167
157const rgb_matrix_driver_t rgb_matrix_driver = { 168const rgb_matrix_driver_t rgb_matrix_driver = {
158 .init = init, 169 .init = init,