diff options
| -rw-r--r-- | docs/feature_rgb_matrix.md | 25 | ||||
| -rw-r--r-- | drivers/issi/is31fl3737.c | 43 | ||||
| -rw-r--r-- | quantum/rgb_matrix/rgb_matrix_drivers.c | 15 |
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 | |||
| 145 | RGB_MATRIX_ENABLE = yes | 145 | RGB_MATRIX_ENABLE = yes |
| 146 | RGB_MATRIX_DRIVER = IS31FL3737 | 146 | RGB_MATRIX_DRIVER = IS31FL3737 |
| 147 | ``` | 147 | ``` |
| 148 | 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. | ||
| 148 | 149 | ||
| 149 | Configure the hardware via your `config.h`: | 150 | Configure 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 | |||
| 162 | Here 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 | ||
| 169 | 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` | 184 | Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations. |
| 170 | 185 | ||
| 171 | Define these arrays listing all the LEDs in your `<keyboard>.c`: | 186 | Define 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 | ||
| 186 | 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). | 201 | 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). |
| 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 | |||
| 69 | uint8_t g_pwm_buffer[DRIVER_COUNT][192]; | 70 | uint8_t g_pwm_buffer[DRIVER_COUNT][192]; |
| 70 | bool g_pwm_buffer_update_required = false; | 71 | bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false}; |
| 71 | 72 | ||
| 72 | uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}}; | 73 | uint8_t g_led_control_registers[DRIVER_COUNT][24] = {0}; |
| 73 | bool g_led_control_registers_update_required = false; | 74 | bool g_led_control_registers_update_required[DRIVER_COUNT] = {false}; |
| 74 | 75 | ||
| 75 | void IS31FL3737_write_register(uint8_t addr, uint8_t reg, uint8_t data) { | 76 | void 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 | ||
| 205 | void IS31FL3737_update_pwm_buffers(uint8_t addr1, uint8_t addr2) { | 206 | void 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 | ||
| 217 | void IS31FL3737_update_led_control_registers(uint8_t addr1, uint8_t addr2) { | 217 | void 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) |
| 155 | static void flush(void) { IS31FL3737_update_pwm_buffers(DRIVER_ADDR_1, DRIVER_ADDR_2); } | 161 | static 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 | ||
| 157 | const rgb_matrix_driver_t rgb_matrix_driver = { | 168 | const rgb_matrix_driver_t rgb_matrix_driver = { |
| 158 | .init = init, | 169 | .init = init, |
