aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common_features.mk20
-rw-r--r--docs/feature_led_matrix.md217
-rw-r--r--drivers/issi/is31fl3731-simple.c240
-rw-r--r--drivers/issi/is31fl3731-simple.h209
-rw-r--r--quantum/led_matrix.c404
-rw-r--r--quantum/led_matrix.h142
-rw-r--r--quantum/led_matrix_drivers.c147
-rw-r--r--quantum/rgb_matrix.h12
8 files changed, 1380 insertions, 11 deletions
diff --git a/common_features.mk b/common_features.mk
index 8c3361732..8c7043cb7 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -114,8 +114,26 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
114 endif 114 endif
115endif 115endif
116 116
117RGB_MATRIX_ENABLE ?= no
118VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 custom 117VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 custom
118
119LED_MATRIX_ENABLE ?= no
120ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
121ifeq ($(filter $(LED_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),)
122 $(error LED_MATRIX_ENABLE="$(LED_MATRIX_ENABLE)" is not a valid matrix type)
123endif
124 OPT_DEFS += -DLED_MATRIX_ENABLE
125 SRC += $(QUANTUM_DIR)/led_matrix.c
126 SRC += $(QUANTUM_DIR)/led_matrix_drivers.c
127endif
128
129ifeq ($(strip $(LED_MATRIX_ENABLE)), IS31FL3731)
130 OPT_DEFS += -DIS31FL3731
131 COMMON_VPATH += $(DRIVER_PATH)/issi
132 SRC += is31fl3731-simple.c
133 SRC += i2c_master.c
134endif
135
136RGB_MATRIX_ENABLE ?= no
119ifneq ($(strip $(RGB_MATRIX_ENABLE)), no) 137ifneq ($(strip $(RGB_MATRIX_ENABLE)), no)
120ifeq ($(filter $(RGB_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),) 138ifeq ($(filter $(RGB_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),)
121 $(error RGB_MATRIX_ENABLE="$(RGB_MATRIX_ENABLE)" is not a valid matrix type) 139 $(error RGB_MATRIX_ENABLE="$(RGB_MATRIX_ENABLE)" is not a valid matrix type)
diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md
new file mode 100644
index 000000000..5a62cc530
--- /dev/null
+++ b/docs/feature_led_matrix.md
@@ -0,0 +1,217 @@
1# RGB Matrix Lighting
2
3## Driver configuration
4
5### IS31FL3731
6
7There is basic support for addressable RGB matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your `rules.mk`:
8
9 LED_MATRIX_ENABLE = IS31FL3731
10
11Configure the hardware via your `config.h`:
12
13 // This is a 7-bit address, that gets left-shifted and bit 0
14 // set to 0 for write, 1 for read (as per I2C protocol)
15 // The address will vary depending on your wiring:
16 // 0b1110100 AD <-> GND
17 // 0b1110111 AD <-> VCC
18 // 0b1110101 AD <-> SCL
19 // 0b1110110 AD <-> SDA
20 #define LED_DRIVER_ADDR_1 0b1110100
21 #define LED_DRIVER_ADDR_2 0b1110110
22
23 #define LED_DRIVER_COUNT 2
24 #define LED_DRIVER_1_LED_TOTAL 25
25 #define LED_DRIVER_2_LED_TOTAL 24
26 #define LED_DRIVER_LED_TOTAL LED_DRIVER_1_LED_TOTAL + LED_DRIVER_2_LED_TOTAL
27
28Currently only 2 drivers are supported, but it would be trivial to support all 4 combinations.
29
30Define these arrays listing all the LEDs in your `<keyboard>.c`:
31
32 const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
33 /* Refer to IS31 manual for these locations
34 * driver
35 * | R location
36 * | | G location
37 * | | | B location
38 * | | | | */
39 {0, C1_3, C2_3, C3_3},
40 ....
41 }
42
43Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](http://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/issi/is31fl3731.h`. The `driver` is the index of the driver you defined in your `config.h` (`0` or `1` right now).
44
45### IS31FL3733
46
47There is basic support for addressable RGB matrix lighting with the I2C IS31FL3733 RGB controller. To enable it, add this to your `rules.mk`:
48
49 RGB_MATRIX_ENABLE = IS31FL3733
50
51Configure the hardware via your `config.h`:
52
53 // This is a 7-bit address, that gets left-shifted and bit 0
54 // set to 0 for write, 1 for read (as per I2C protocol)
55 // The address will vary depending on your wiring:
56 // 00 <-> GND
57 // 01 <-> SCL
58 // 10 <-> SDA
59 // 11 <-> VCC
60 // ADDR1 represents A1:A0 of the 7-bit address.
61 // ADDR2 represents A3:A2 of the 7-bit address.
62 // The result is: 0b101(ADDR2)(ADDR1)
63 #define DRIVER_ADDR_1 0b1010000
64 #define DRIVER_ADDR_2 0b1010000 // this is here for compliancy reasons.
65
66 #define DRIVER_COUNT 1
67 #define DRIVER_1_LED_TOTAL 64
68 #define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL
69
70Currently 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`
71
72Define these arrays listing all the LEDs in your `<keyboard>.c`:
73
74 const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
75 /* Refer to IS31 manual for these locations
76 * driver
77 * | R location
78 * | | G location
79 * | | | B location
80 * | | | | */
81 {0, B_1, A_1, C_1},
82 ....
83 }
84
85Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](http://www.issi.com/WW/pdf/31FL3733.pdf) and the header file `drivers/issi/is31fl3733.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0` right now).
86
87From this point forward the configuration is the same for all the drivers.
88
89 const rgb_led g_rgb_leds[DRIVER_LED_TOTAL] = {
90 /* {row | col << 4}
91 * | {x=0..224, y=0..64}
92 * | | modifier
93 * | | | */
94 {{0|(0<<4)}, {20.36*0, 21.33*0}, 1},
95 {{0|(1<<4)}, {20.36*1, 21.33*0}, 1},
96 ....
97 }
98
99The format for the matrix position used in this array is `{row | (col << 4)}`. The `x` is between (inclusive) 0-224, and `y` is between (inclusive) 0-64. The easiest way to calculate these positions is:
100
101 x = 224 / ( NUMBER_OF_ROWS - 1 ) * ROW_POSITION
102 y = 64 / (NUMBER_OF_COLS - 1 ) * COL_POSITION
103
104Where all variables are decimels/floats.
105
106`modifier` is a boolean, whether or not a certain key is considered a modifier (used in some effects).
107
108## Keycodes
109
110All RGB keycodes are currently shared with the RGBLIGHT system:
111
112 * `RGB_TOG` - toggle
113 * `RGB_MOD` - cycle through modes
114 * `RGB_HUI` - increase hue
115 * `RGB_HUD` - decrease hue
116 * `RGB_SAI` - increase saturation
117 * `RGB_SAD` - decrease saturation
118 * `RGB_VAI` - increase value
119 * `RGB_VAD` - decrease value
120 * `RGB_SPI` - increase speed effect (no EEPROM support)
121 * `RGB_SPD` - decrease speed effect (no EEPROM support)
122
123
124 * `RGB_MODE_*` keycodes will generally work, but are not currently mapped to the correct effects for the RGB Matrix system
125
126## RGB Matrix Effects
127
128These are the effects that are currently available:
129
130 enum rgb_matrix_effects {
131 RGB_MATRIX_SOLID_COLOR = 1,
132 RGB_MATRIX_ALPHAS_MODS,
133 RGB_MATRIX_DUAL_BEACON,
134 RGB_MATRIX_GRADIENT_UP_DOWN,
135 RGB_MATRIX_RAINDROPS,
136 RGB_MATRIX_CYCLE_ALL,
137 RGB_MATRIX_CYCLE_LEFT_RIGHT,
138 RGB_MATRIX_CYCLE_UP_DOWN,
139 RGB_MATRIX_RAINBOW_BEACON,
140 RGB_MATRIX_RAINBOW_PINWHEELS,
141 RGB_MATRIX_RAINBOW_MOVING_CHEVRON,
142 RGB_MATRIX_JELLYBEAN_RAINDROPS,
143 RGB_MATRIX_DIGITAL_RAIN,
144 #ifdef RGB_MATRIX_KEYPRESSES
145 RGB_MATRIX_SOLID_REACTIVE,
146 RGB_MATRIX_SPLASH,
147 RGB_MATRIX_MULTISPLASH,
148 RGB_MATRIX_SOLID_SPLASH,
149 RGB_MATRIX_SOLID_MULTISPLASH,
150 #endif
151 RGB_MATRIX_EFFECT_MAX
152 };
153
154You can disable a single effect by defining `DISABLE_[EFFECT_NAME]` in your `config.h`:
155
156
157|Define |Description |
158|---------------------------------------------------|--------------------------------------------|
159|`#define DISABLE_RGB_MATRIX_ALPHAS_MODS` |Disables `RGB_MATRIX_ALPHAS_MODS` |
160|`#define DISABLE_RGB_MATRIX_DUAL_BEACON` |Disables `RGB_MATRIX_DUAL_BEACON` |
161|`#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN` |Disables `RGB_MATRIX_GRADIENT_UP_DOWN` |
162|`#define DISABLE_RGB_MATRIX_RAINDROPS` |Disables `RGB_MATRIX_RAINDROPS` |
163|`#define DISABLE_RGB_MATRIX_CYCLE_ALL` |Disables `RGB_MATRIX_CYCLE_ALL` |
164|`#define DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT` |Disables `RGB_MATRIX_CYCLE_LEFT_RIGHT` |
165|`#define DISABLE_RGB_MATRIX_CYCLE_UP_DOWN` |Disables `RGB_MATRIX_CYCLE_UP_DOWN` |
166|`#define DISABLE_RGB_MATRIX_RAINBOW_BEACON` |Disables `RGB_MATRIX_RAINBOW_BEACON` |
167|`#define DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS` |Disables `RGB_MATRIX_RAINBOW_PINWHEELS` |
168|`#define DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON`|Disables `RGB_MATRIX_RAINBOW_MOVING_CHEVRON`|
169|`#define DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS` |Disables `RGB_MATRIX_JELLYBEAN_RAINDROPS` |
170|`#define DISABLE_RGB_MATRIX_DIGITAL_RAIN` |Disables `RGB_MATRIX_DIGITAL_RAIN` |
171|`#define DISABLE_RGB_MATRIX_SOLID_REACTIVE` |Disables `RGB_MATRIX_SOLID_REACTIVE` |
172|`#define DISABLE_RGB_MATRIX_SPLASH` |Disables `RGB_MATRIX_SPLASH` |
173|`#define DISABLE_RGB_MATRIX_MULTISPLASH` |Disables `RGB_MATRIX_MULTISPLASH` |
174|`#define DISABLE_RGB_MATRIX_SOLID_SPLASH` |Disables `RGB_MATRIX_SOLID_SPLASH` |
175|`#define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH` |Disables `RGB_MATRIX_SOLID_MULTISPLASH` |
176
177
178## Custom layer effects
179
180Custom layer effects can be done by defining this in your `<keyboard>.c`:
181
182 void rgb_matrix_indicators_kb(void) {
183 rgb_matrix_set_color(index, red, green, blue);
184 }
185
186A similar function works in the keymap as `rgb_matrix_indicators_user`.
187
188## Additional `config.h` Options
189
190 #define RGB_MATRIX_KEYPRESSES // reacts to keypresses (will slow down matrix scan by a lot)
191 #define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (not recommened)
192 #define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
193 #define RGB_DISABLE_WHEN_USB_SUSPENDED false // turn off effects when suspended
194 #define RGB_MATRIX_SKIP_FRAMES 1 // number of frames to skip when displaying animations (0 is full effect) if not defined defaults to 1
195 #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
196
197## EEPROM storage
198
199The EEPROM for it is currently shared with the RGBLIGHT system (it's generally assumed only one RGB would be used at a time), but could be configured to use its own 32bit address with:
200
201 #define EECONFIG_RGB_MATRIX (uint32_t *)16
202
203Where `16` is an unused index from `eeconfig.h`.
204
205## Suspended state
206
207To use the suspend feature, add this to your `<keyboard>.c`:
208
209 void suspend_power_down_kb(void)
210 {
211 rgb_matrix_set_suspend_state(true);
212 }
213
214 void suspend_wakeup_init_kb(void)
215 {
216 rgb_matrix_set_suspend_state(false);
217 }
diff --git a/drivers/issi/is31fl3731-simple.c b/drivers/issi/is31fl3731-simple.c
new file mode 100644
index 000000000..46d51dac7
--- /dev/null
+++ b/drivers/issi/is31fl3731-simple.c
@@ -0,0 +1,240 @@
1/* Copyright 2017 Jason Williams
2 * Copyright 2018 Jack Humbert
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifdef __AVR__
19#include <avr/interrupt.h>
20#include <avr/io.h>
21#include <util/delay.h>
22#else
23#include "wait.h"
24#endif
25
26#include <stdint.h>
27#include <stdbool.h>
28#include <string.h>
29#include "is31fl3731-simple.h"
30#include "i2c_master.h"
31#include "progmem.h"
32
33// This is a 7-bit address, that gets left-shifted and bit 0
34// set to 0 for write, 1 for read (as per I2C protocol)
35// The address will vary depending on your wiring:
36// 0b1110100 AD <-> GND
37// 0b1110111 AD <-> VCC
38// 0b1110101 AD <-> SCL
39// 0b1110110 AD <-> SDA
40#define ISSI_ADDR_DEFAULT 0x74
41
42#define ISSI_REG_CONFIG 0x00
43#define ISSI_REG_CONFIG_PICTUREMODE 0x00
44#define ISSI_REG_CONFIG_AUTOPLAYMODE 0x08
45#define ISSI_REG_CONFIG_AUDIOPLAYMODE 0x18
46
47#define ISSI_CONF_PICTUREMODE 0x00
48#define ISSI_CONF_AUTOFRAMEMODE 0x04
49#define ISSI_CONF_AUDIOMODE 0x08
50
51#define ISSI_REG_PICTUREFRAME 0x01
52
53#define ISSI_REG_SHUTDOWN 0x0A
54#define ISSI_REG_AUDIOSYNC 0x06
55
56#define ISSI_COMMANDREGISTER 0xFD
57#define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine'
58
59#ifndef ISSI_TIMEOUT
60 #define ISSI_TIMEOUT 100
61#endif
62
63#ifndef ISSI_PERSISTENCE
64 #define ISSI_PERSISTENCE 0
65#endif
66
67// Transfer buffer for TWITransmitData()
68uint8_t g_twi_transfer_buffer[20];
69
70// These buffers match the IS31FL3731 PWM registers 0x24-0xB3.
71// Storing them like this is optimal for I2C transfers to the registers.
72// We could optimize this and take out the unused registers from these
73// buffers and the transfers in IS31FL3731_write_pwm_buffer() but it's
74// probably not worth the extra complexity.
75uint8_t g_pwm_buffer[DRIVER_COUNT][144];
76bool g_pwm_buffer_update_required = false;
77
78uint8_t g_led_control_registers[DRIVER_COUNT][18] = { { 0 }, { 0 } };
79bool g_led_control_registers_update_required = false;
80
81// This is the bit pattern in the LED control registers
82// (for matrix A, add one to register for matrix B)
83//
84// reg - b7 b6 b5 b4 b3 b2 b1 b0
85// 0x00 - R08,R07,R06,R05,R04,R03,R02,R01
86// 0x02 - G08,G07,G06,G05,G04,G03,G02,R00
87// 0x04 - B08,B07,B06,B05,B04,B03,G01,G00
88// 0x06 - - , - , - , - , - ,B02,B01,B00
89// 0x08 - - , - , - , - , - , - , - , -
90// 0x0A - B17,B16,B15, - , - , - , - , -
91// 0x0C - G17,G16,B14,B13,B12,B11,B10,B09
92// 0x0E - R17,G15,G14,G13,G12,G11,G10,G09
93// 0x10 - R16,R15,R14,R13,R12,R11,R10,R09
94
95
96void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
97 g_twi_transfer_buffer[0] = reg;
98 g_twi_transfer_buffer[1] = data;
99
100 #if ISSI_PERSISTENCE > 0
101 for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
102 if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0) {
103 break;
104 }
105 }
106 #else
107 i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
108 #endif
109}
110
111void IS31FL3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
112 // assumes bank is already selected
113
114 // transmit PWM registers in 9 transfers of 16 bytes
115 // g_twi_transfer_buffer[] is 20 bytes
116
117 // iterate over the pwm_buffer contents at 16 byte intervals
118 for (int i = 0; i < 144; i += 16) {
119 // set the first register, e.g. 0x24, 0x34, 0x44, etc.
120 g_twi_transfer_buffer[0] = 0x24 + i;
121 // copy the data from i to i+15
122 // device will auto-increment register for data after the first byte
123 // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer
124 for (int j = 0; j < 16; j++) {
125 g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
126 }
127
128 #if ISSI_PERSISTENCE > 0
129 for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
130 if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0)
131 break;
132 }
133 #else
134 i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT);
135 #endif
136 }
137}
138
139void IS31FL3731_init(uint8_t addr) {
140 // In order to avoid the LEDs being driven with garbage data
141 // in the LED driver's PWM registers, first enable software shutdown,
142 // then set up the mode and other settings, clear the PWM registers,
143 // then disable software shutdown.
144
145 // select "function register" bank
146 IS31FL3731_write_register(addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG);
147
148 // enable software shutdown
149 IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00);
150 // this delay was copied from other drivers, might not be needed
151 // FIXME: Don't we have a wrapper for this already?
152 #ifdef __AVR__
153 _delay_ms(10);
154 #else
155 wait_ms(10);
156 #endif
157
158 // picture mode
159 IS31FL3731_write_register(addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE);
160 // display frame 0
161 IS31FL3731_write_register(addr, ISSI_REG_PICTUREFRAME, 0x00);
162 // audio sync off
163 IS31FL3731_write_register(addr, ISSI_REG_AUDIOSYNC, 0x00);
164
165 // select bank 0
166 IS31FL3731_write_register(addr, ISSI_COMMANDREGISTER, 0);
167
168 // turn off all LEDs in the LED control register
169 for (int i = 0x00; i <= 0x11; i++) {
170 IS31FL3731_write_register(addr, i, 0x00);
171 }
172
173 // turn off all LEDs in the blink control register (not really needed)
174 for (int i = 0x12; i <= 0x23; i++) {
175 IS31FL3731_write_register(addr, i, 0x00);
176 }
177
178 // set PWM on all LEDs to 0
179 for (int i = 0x24; i <= 0xB3; i++) {
180 IS31FL3731_write_register(addr, i, 0x00);
181 }
182
183 // select "function register" bank
184 IS31FL3731_write_register(addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG);
185
186 // disable software shutdown
187 IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x01);
188
189 // select bank 0 and leave it selected.
190 // most usage after initialization is just writing PWM buffers in bank 0
191 // as there's not much point in double-buffering
192 IS31FL3731_write_register(addr, ISSI_COMMANDREGISTER, 0);
193
194}
195
196void IS31FL3731_set_value(int index, uint8_t value) {
197 if (index >= 0 && index < DRIVER_LED_TOTAL) {
198 is31_led led = g_is31_leds[index];
199
200 // Subtract 0x24 to get the second index of g_pwm_buffer
201 g_pwm_buffer[led.driver][led.v - 0x24] = value;
202 g_pwm_buffer_update_required = true;
203 }
204}
205
206void IS31FL3731_set_value_all(uint8_t value) {
207 for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
208 IS31FL3731_set_value(i, value);
209 }
210}
211
212void IS31FL3731_set_led_control_register(uint8_t index, bool value) {
213 is31_led led = g_is31_leds[index];
214
215 uint8_t control_register = (led.v - 0x24) / 8;
216 uint8_t bit_value = (led.v - 0x24) % 8;
217
218 if (value) {
219 g_led_control_registers[led.driver][control_register] |= (1 << bit_value);
220 } else {
221 g_led_control_registers[led.driver][control_register] &= ~(1 << bit_value);
222 }
223
224 g_led_control_registers_update_required = true;
225}
226
227void IS31FL3731_update_pwm_buffers(uint8_t addr, uint8_t index) {
228 if (g_pwm_buffer_update_required) {
229 IS31FL3731_write_pwm_buffer(addr, g_pwm_buffer[index]);
230 g_pwm_buffer_update_required = false;
231 }
232}
233
234void IS31FL3731_update_led_control_registers(uint8_t addr, uint8_t index) {
235 if (g_led_control_registers_update_required) {
236 for (int i=0; i<18; i++) {
237 IS31FL3731_write_register(addr, i, g_led_control_registers[index][i]);
238 }
239 }
240}
diff --git a/drivers/issi/is31fl3731-simple.h b/drivers/issi/is31fl3731-simple.h
new file mode 100644
index 000000000..c102837a3
--- /dev/null
+++ b/drivers/issi/is31fl3731-simple.h
@@ -0,0 +1,209 @@
1/* Copyright 2017 Jason Williams
2 * Copyright 2018 Jack Humbert
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19#ifndef IS31FL3731_DRIVER_H
20#define IS31FL3731_DRIVER_H
21
22
23typedef struct is31_led {
24 uint8_t driver:2;
25 uint8_t v;
26} __attribute__((packed)) is31_led;
27
28extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
29
30void IS31FL3731_init(uint8_t addr);
31void IS31FL3731_write_register(uint8_t addr, uint8_t reg, uint8_t data);
32void IS31FL3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
33
34void IS31FL3731_set_value(int index, uint8_t value);
35void IS31FL3731_set_value_all(uint8_t value);
36
37void IS31FL3731_set_led_control_register(uint8_t index, bool value);
38
39// This should not be called from an interrupt
40// (eg. from a timer interrupt).
41// Call this while idle (in between matrix scans).
42// If the buffer is dirty, it will update the driver with the buffer.
43void IS31FL3731_update_pwm_buffers(uint8_t addr, uint8_t index);
44void IS31FL3731_update_led_control_registers(uint8_t addr, uint8_t index);
45
46#define C1_1 0x24
47#define C1_2 0x25
48#define C1_3 0x26
49#define C1_4 0x27
50#define C1_5 0x28
51#define C1_6 0x29
52#define C1_7 0x2A
53#define C1_8 0x2B
54
55#define C1_9 0x2C
56#define C1_10 0x2D
57#define C1_11 0x2E
58#define C1_12 0x2F
59#define C1_13 0x30
60#define C1_14 0x31
61#define C1_15 0x32
62#define C1_16 0x33
63
64#define C2_1 0x34
65#define C2_2 0x35
66#define C2_3 0x36
67#define C2_4 0x37
68#define C2_5 0x38
69#define C2_6 0x39
70#define C2_7 0x3A
71#define C2_8 0x3B
72
73#define C2_9 0x3C
74#define C2_10 0x3D
75#define C2_11 0x3E
76#define C2_12 0x3F
77#define C2_13 0x40
78#define C2_14 0x41
79#define C2_15 0x42
80#define C2_16 0x43
81
82#define C3_1 0x44
83#define C3_2 0x45
84#define C3_3 0x46
85#define C3_4 0x47
86#define C3_5 0x48
87#define C3_6 0x49
88#define C3_7 0x4A
89#define C3_8 0x4B
90
91#define C3_9 0x4C
92#define C3_10 0x4D
93#define C3_11 0x4E
94#define C3_12 0x4F
95#define C3_13 0x50
96#define C3_14 0x51
97#define C3_15 0x52
98#define C3_16 0x53
99
100#define C4_1 0x54
101#define C4_2 0x55
102#define C4_3 0x56
103#define C4_4 0x57
104#define C4_5 0x58
105#define C4_6 0x59
106#define C4_7 0x5A
107#define C4_8 0x5B
108
109#define C4_9 0x5C
110#define C4_10 0x5D
111#define C4_11 0x5E
112#define C4_12 0x5F
113#define C4_13 0x60
114#define C4_14 0x61
115#define C4_15 0x62
116#define C4_16 0x63
117
118#define C5_1 0x64
119#define C5_2 0x65
120#define C5_3 0x66
121#define C5_4 0x67
122#define C5_5 0x68
123#define C5_6 0x69
124#define C5_7 0x6A
125#define C5_8 0x6B
126
127#define C5_9 0x6C
128#define C5_10 0x6D
129#define C5_11 0x6E
130#define C5_12 0x6F
131#define C5_13 0x70
132#define C5_14 0x71
133#define C5_15 0x72
134#define C5_16 0x73
135
136#define C6_1 0x74
137#define C6_2 0x75
138#define C6_3 0x76
139#define C6_4 0x77
140#define C6_5 0x78
141#define C6_6 0x79
142#define C6_7 0x7A
143#define C6_8 0x7B
144
145#define C6_9 0x7C
146#define C6_10 0x7D
147#define C6_11 0x7E
148#define C6_12 0x7F
149#define C6_13 0x80
150#define C6_14 0x81
151#define C6_15 0x82
152#define C6_16 0x83
153
154#define C7_1 0x84
155#define C7_2 0x85
156#define C7_3 0x86
157#define C7_4 0x87
158#define C7_5 0x88
159#define C7_6 0x89
160#define C7_7 0x8A
161#define C7_8 0x8B
162
163#define C7_9 0x8C
164#define C7_10 0x8D
165#define C7_11 0x8E
166#define C7_12 0x8F
167#define C7_13 0x90
168#define C7_14 0x91
169#define C7_15 0x92
170#define C7_16 0x93
171
172#define C8_1 0x94
173#define C8_2 0x95
174#define C8_3 0x96
175#define C8_4 0x97
176#define C8_5 0x98
177#define C8_6 0x99
178#define C8_7 0x9A
179#define C8_8 0x9B
180
181#define C8_9 0x9C
182#define C8_10 0x9D
183#define C8_11 0x9E
184#define C8_12 0x9F
185#define C8_13 0xA0
186#define C8_14 0xA1
187#define C8_15 0xA2
188#define C8_16 0xA3
189
190#define C9_1 0xA4
191#define C9_2 0xA5
192#define C9_3 0xA6
193#define C9_4 0xA7
194#define C9_5 0xA8
195#define C9_6 0xA9
196#define C9_7 0xAA
197#define C9_8 0xAB
198
199#define C9_9 0xAC
200#define C9_10 0xAD
201#define C9_11 0xAE
202#define C9_12 0xAF
203#define C9_13 0xB0
204#define C9_14 0xB1
205#define C9_15 0xB2
206#define C9_16 0xB3
207
208
209#endif // IS31FL3731_DRIVER_H
diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c
new file mode 100644
index 000000000..9a0aa6acd
--- /dev/null
+++ b/quantum/led_matrix.c
@@ -0,0 +1,404 @@
1/* Copyright 2017 Jason Williams
2 * Copyright 2017 Jack Humbert
3 * Copyright 2018 Yiancar
4 * Copyright 2019 Clueboard
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <stdint.h>
21#include <stdbool.h>
22#include "quantum.h"
23#include "led_matrix.h"
24#include "progmem.h"
25#include "config.h"
26#include "eeprom.h"
27#include <string.h>
28#include <math.h>
29
30led_config_t led_matrix_config;
31
32#ifndef MAX
33 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
34#endif
35
36#ifndef MIN
37 #define MIN(a,b) ((a) < (b)? (a): (b))
38#endif
39
40#ifndef LED_DISABLE_AFTER_TIMEOUT
41 #define LED_DISABLE_AFTER_TIMEOUT 0
42#endif
43
44#ifndef LED_DISABLE_WHEN_USB_SUSPENDED
45 #define LED_DISABLE_WHEN_USB_SUSPENDED false
46#endif
47
48#ifndef EECONFIG_LED_MATRIX
49 #define EECONFIG_LED_MATRIX EECONFIG_RGBLIGHT
50#endif
51
52#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > 255
53 #define LED_MATRIX_MAXIMUM_BRIGHTNESS 255
54#endif
55
56bool g_suspend_state = false;
57
58// Global tick at 20 Hz
59uint32_t g_tick = 0;
60
61// Ticks since this key was last hit.
62uint8_t g_key_hit[DRIVER_LED_TOTAL];
63
64// Ticks since any key was last hit.
65uint32_t g_any_key_hit = 0;
66
67uint32_t eeconfig_read_led_matrix(void) {
68 return eeprom_read_dword(EECONFIG_LED_MATRIX);
69}
70void eeconfig_update_led_matrix(uint32_t config_value) {
71 eeprom_update_dword(EECONFIG_LED_MATRIX, config_value);
72}
73void eeconfig_update_led_matrix_default(void) {
74 dprintf("eeconfig_update_led_matrix_default\n");
75 led_matrix_config.enable = 1;
76 led_matrix_config.mode = LED_MATRIX_UNIFORM_BRIGHTNESS;
77 led_matrix_config.val = 128;
78 led_matrix_config.speed = 0;
79 eeconfig_update_led_matrix(led_matrix_config.raw);
80}
81void eeconfig_debug_led_matrix(void) {
82 dprintf("led_matrix_config eprom\n");
83 dprintf("led_matrix_config.enable = %d\n", led_matrix_config.enable);
84 dprintf("led_matrix_config.mode = %d\n", led_matrix_config.mode);
85 dprintf("led_matrix_config.val = %d\n", led_matrix_config.val);
86 dprintf("led_matrix_config.speed = %d\n", led_matrix_config.speed);
87}
88
89// Last led hit
90#define LED_HITS_TO_REMEMBER 8
91uint8_t g_last_led_hit[LED_HITS_TO_REMEMBER] = {255};
92uint8_t g_last_led_count = 0;
93
94void map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i, uint8_t *led_count) {
95 led_matrix led;
96 *led_count = 0;
97
98 for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
99 // map_index_to_led(i, &led);
100 led = g_leds[i];
101 if (row == led.matrix_co.row && column == led.matrix_co.col) {
102 led_i[*led_count] = i;
103 (*led_count)++;
104 }
105 }
106}
107
108void led_matrix_update_pwm_buffers(void) {
109 led_matrix_driver.flush();
110}
111
112void led_matrix_set_index_value(int index, uint8_t value) {
113 led_matrix_driver.set_value(index, value);
114}
115
116void led_matrix_set_index_value_all(uint8_t value) {
117 led_matrix_driver.set_value_all(value);
118}
119
120bool process_led_matrix(uint16_t keycode, keyrecord_t *record) {
121 if (record->event.pressed) {
122 uint8_t led[8], led_count;
123 map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count);
124 if (led_count > 0) {
125 for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) {
126 g_last_led_hit[i - 1] = g_last_led_hit[i - 2];
127 }
128 g_last_led_hit[0] = led[0];
129 g_last_led_count = MIN(LED_HITS_TO_REMEMBER, g_last_led_count + 1);
130 }
131 for(uint8_t i = 0; i < led_count; i++)
132 g_key_hit[led[i]] = 0;
133 g_any_key_hit = 0;
134 } else {
135 #ifdef LED_MATRIX_KEYRELEASES
136 uint8_t led[8], led_count;
137 map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count);
138 for(uint8_t i = 0; i < led_count; i++)
139 g_key_hit[led[i]] = 255;
140
141 g_any_key_hit = 255;
142 #endif
143 }
144 return true;
145}
146
147void led_matrix_set_suspend_state(bool state) {
148 g_suspend_state = state;
149}
150
151// All LEDs off
152void led_matrix_all_off(void) {
153 led_matrix_set_index_value_all(0);
154}
155
156// Uniform brightness
157void led_matrix_uniform_brightness(void) {
158 led_matrix_set_index_value_all(led_matrix_config.val);
159}
160
161void led_matrix_custom(void) {}
162
163void led_matrix_task(void) {
164 #ifdef TRACK_PREVIOUS_EFFECT
165 static uint8_t toggle_enable_last = 255;
166 #endif
167 if (!led_matrix_config.enable) {
168 led_matrix_all_off();
169 led_matrix_indicators();
170 #ifdef TRACK_PREVIOUS_EFFECT
171 toggle_enable_last = led_matrix_config.enable;
172 #endif
173 return;
174 }
175
176 // delay 1 second before driving LEDs or doing anything else
177 // FIXME: Can't we use wait_ms() here?
178 static uint8_t startup_tick = 0;
179 if (startup_tick < 20) {
180 startup_tick++;
181 return;
182 }
183
184 g_tick++;
185
186 if (g_any_key_hit < 0xFFFFFFFF) {
187 g_any_key_hit++;
188 }
189
190 for (int led = 0; led < DRIVER_LED_TOTAL; led++) {
191 if (g_key_hit[led] < 255) {
192 if (g_key_hit[led] == 254)
193 g_last_led_count = MAX(g_last_led_count - 1, 0);
194 g_key_hit[led]++;
195 }
196 }
197
198 // Factory default magic value
199 if (led_matrix_config.mode == 255) {
200 led_matrix_uniform_brightness();
201 return;
202 }
203
204 // Ideally we would also stop sending zeros to the LED driver PWM buffers
205 // while suspended and just do a software shutdown. This is a cheap hack for now.
206 bool suspend_backlight = ((g_suspend_state && LED_DISABLE_WHEN_USB_SUSPENDED) ||
207 (LED_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > LED_DISABLE_AFTER_TIMEOUT * 60 * 20));
208 uint8_t effect = suspend_backlight ? 0 : led_matrix_config.mode;
209
210 #ifdef TRACK_PREVIOUS_EFFECT
211 // Keep track of the effect used last time,
212 // detect change in effect, so each effect can
213 // have an optional initialization.
214
215 static uint8_t effect_last = 255;
216 bool initialize = (effect != effect_last) || (led_matrix_config.enable != toggle_enable_last);
217 effect_last = effect;
218 toggle_enable_last = led_matrix_config.enable;
219 #endif
220
221 // this gets ticked at 20 Hz.
222 // each effect can opt to do calculations
223 // and/or request PWM buffer updates.
224 switch (effect) {
225 case LED_MATRIX_UNIFORM_BRIGHTNESS:
226 led_matrix_uniform_brightness();
227 break;
228 default:
229 led_matrix_custom();
230 break;
231 }
232
233 if (! suspend_backlight) {
234 led_matrix_indicators();
235 }
236
237}
238
239void led_matrix_indicators(void) {
240 led_matrix_indicators_kb();
241 led_matrix_indicators_user();
242}
243
244__attribute__((weak))
245void led_matrix_indicators_kb(void) {}
246
247__attribute__((weak))
248void led_matrix_indicators_user(void) {}
249
250
251// void led_matrix_set_indicator_index(uint8_t *index, uint8_t row, uint8_t column)
252// {
253// if (row >= MATRIX_ROWS)
254// {
255// // Special value, 255=none, 254=all
256// *index = row;
257// }
258// else
259// {
260// // This needs updated to something like
261// // uint8_t led[8], led_count;
262// // map_row_column_to_led(row,column,led,&led_count);
263// // for(uint8_t i = 0; i < led_count; i++)
264// map_row_column_to_led(row, column, index);
265// }
266// }
267
268void led_matrix_init(void) {
269 led_matrix_driver.init();
270
271 // TODO: put the 1 second startup delay here?
272
273 // clear the key hits
274 for (int led=0; led<DRIVER_LED_TOTAL; led++) {
275 g_key_hit[led] = 255;
276 }
277
278
279 if (!eeconfig_is_enabled()) {
280 dprintf("led_matrix_init_drivers eeconfig is not enabled.\n");
281 eeconfig_init();
282 eeconfig_update_led_matrix_default();
283 }
284 led_matrix_config.raw = eeconfig_read_led_matrix();
285 if (!led_matrix_config.mode) {
286 dprintf("led_matrix_init_drivers led_matrix_config.mode = 0. Write default values to EEPROM.\n");
287 eeconfig_update_led_matrix_default();
288 led_matrix_config.raw = eeconfig_read_led_matrix();
289 }
290 eeconfig_debug_led_matrix(); // display current eeprom values
291}
292
293// Deals with the messy details of incrementing an integer
294static uint8_t increment(uint8_t value, uint8_t step, uint8_t min, uint8_t max) {
295 int16_t new_value = value;
296 new_value += step;
297 return MIN(MAX( new_value, min), max );
298}
299
300static uint8_t decrement(uint8_t value, uint8_t step, uint8_t min, uint8_t max) {
301 int16_t new_value = value;
302 new_value -= step;
303 return MIN(MAX( new_value, min), max );
304}
305
306// void *backlight_get_custom_key_value_eeprom_address(uint8_t led) {
307// // 3 bytes per value
308// return EECONFIG_LED_MATRIX + (led * 3);
309// }
310
311// void backlight_get_key_value(uint8_t led, uint8_t *value) {
312// void *address = backlight_get_custom_key_value_eeprom_address(led);
313// value = eeprom_read_byte(address);
314// }
315
316// void backlight_set_key_value(uint8_t row, uint8_t column, uint8_t value) {
317// uint8_t led[8], led_count;
318// map_row_column_to_led(row,column,led,&led_count);
319// for(uint8_t i = 0; i < led_count; i++) {
320// if (led[i] < DRIVER_LED_TOTAL) {
321// void *address = backlight_get_custom_key_value_eeprom_address(led[i]);
322// eeprom_update_byte(address, value);
323// }
324// }
325// }
326
327uint32_t led_matrix_get_tick(void) {
328 return g_tick;
329}
330
331void led_matrix_toggle(void) {
332 led_matrix_config.enable ^= 1;
333 eeconfig_update_led_matrix(led_matrix_config.raw);
334}
335
336void led_matrix_enable(void) {
337 led_matrix_config.enable = 1;
338 eeconfig_update_led_matrix(led_matrix_config.raw);
339}
340
341void led_matrix_enable_noeeprom(void) {
342 led_matrix_config.enable = 1;
343}
344
345void led_matrix_disable(void) {
346 led_matrix_config.enable = 0;
347 eeconfig_update_led_matrix(led_matrix_config.raw);
348}
349
350void led_matrix_disable_noeeprom(void) {
351 led_matrix_config.enable = 0;
352}
353
354void led_matrix_step(void) {
355 led_matrix_config.mode++;
356 if (led_matrix_config.mode >= LED_MATRIX_EFFECT_MAX)
357 led_matrix_config.mode = 1;
358 eeconfig_update_led_matrix(led_matrix_config.raw);
359}
360
361void led_matrix_step_reverse(void) {
362 led_matrix_config.mode--;
363 if (led_matrix_config.mode < 1)
364 led_matrix_config.mode = LED_MATRIX_EFFECT_MAX - 1;
365 eeconfig_update_led_matrix(led_matrix_config.raw);
366}
367
368void led_matrix_increase_val(void) {
369 led_matrix_config.val = increment(led_matrix_config.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS);
370 eeconfig_update_led_matrix(led_matrix_config.raw);
371}
372
373void led_matrix_decrease_val(void) {
374 led_matrix_config.val = decrement(led_matrix_config.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS);
375 eeconfig_update_led_matrix(led_matrix_config.raw);
376}
377
378void led_matrix_increase_speed(void) {
379 led_matrix_config.speed = increment(led_matrix_config.speed, 1, 0, 3);
380 eeconfig_update_led_matrix(led_matrix_config.raw);//EECONFIG needs to be increased to support this
381}
382
383void led_matrix_decrease_speed(void) {
384 led_matrix_config.speed = decrement(led_matrix_config.speed, 1, 0, 3);
385 eeconfig_update_led_matrix(led_matrix_config.raw);//EECONFIG needs to be increased to support this
386}
387
388void led_matrix_mode(uint8_t mode, bool eeprom_write) {
389 led_matrix_config.mode = mode;
390 if (eeprom_write) {
391 eeconfig_update_led_matrix(led_matrix_config.raw);
392 }
393}
394
395uint8_t led_matrix_get_mode(void) {
396 return led_matrix_config.mode;
397}
398
399void led_matrix_set_value(uint8_t val, bool eeprom_write) {
400 led_matrix_config.val = val;
401 if (eeprom_write) {
402 eeconfig_update_led_matrix(led_matrix_config.raw);
403 }
404}
diff --git a/quantum/led_matrix.h b/quantum/led_matrix.h
new file mode 100644
index 000000000..20f2e73c6
--- /dev/null
+++ b/quantum/led_matrix.h
@@ -0,0 +1,142 @@
1/* Copyright 2017 Jason Williams
2 * Copyright 2017 Jack Humbert
3 * Copyright 2018 Yiancar
4 * Copyright 2019 Clueboard
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef LED_MATRIX_H
21#define LED_MATRIX_H
22
23
24typedef struct Point {
25 uint8_t x;
26 uint8_t y;
27} __attribute__((packed)) Point;
28
29typedef struct led_matrix {
30 union {
31 uint8_t raw;
32 struct {
33 uint8_t row:4; // 16 max
34 uint8_t col:4; // 16 max
35 };
36 } matrix_co;
37 Point point;
38 uint8_t modifier:1;
39} __attribute__((packed)) led_matrix;
40
41extern const led_matrix g_leds[DRIVER_LED_TOTAL];
42
43typedef struct {
44 uint8_t index;
45 uint8_t value;
46} led_indicator;
47
48typedef union {
49 uint32_t raw;
50 struct {
51 bool enable :1;
52 uint8_t mode :6;
53 uint8_t hue :8; // Unused by led_matrix
54 uint8_t sat :8; // Unused by led_matrix
55 uint8_t val :8;
56 uint8_t speed :8;//EECONFIG needs to be increased to support this
57 };
58} led_config_t;
59
60enum led_matrix_effects {
61 LED_MATRIX_UNIFORM_BRIGHTNESS = 1,
62 // All new effects go above this line
63 LED_MATRIX_EFFECT_MAX
64};
65
66void led_matrix_set_index_value(int index, uint8_t value);
67void led_matrix_set_index_value_all(uint8_t value);
68
69// This runs after another backlight effect and replaces
70// colors already set
71void led_matrix_indicators(void);
72void led_matrix_indicators_kb(void);
73void led_matrix_indicators_user(void);
74
75void led_matrix_init(void);
76void led_matrix_setup_drivers(void);
77
78void led_matrix_set_suspend_state(bool state);
79void led_matrix_set_indicator_state(uint8_t state);
80
81void led_matrix_task(void);
82
83// This should not be called from an interrupt
84// (eg. from a timer interrupt).
85// Call this while idle (in between matrix scans).
86// If the buffer is dirty, it will update the driver with the buffer.
87void led_matrix_update_pwm_buffers(void);
88
89bool process_led_matrix(uint16_t keycode, keyrecord_t *record);
90
91uint32_t led_matrix_get_tick(void);
92
93void led_matrix_toggle(void);
94void led_matrix_enable(void);
95void led_matrix_enable_noeeprom(void);
96void led_matrix_disable(void);
97void led_matrix_disable_noeeprom(void);
98void led_matrix_step(void);
99void led_matrix_step_reverse(void);
100void led_matrix_increase_val(void);
101void led_matrix_decrease_val(void);
102void led_matrix_increase_speed(void);
103void led_matrix_decrease_speed(void);
104void led_matrix_mode(uint8_t mode, bool eeprom_write);
105void led_matrix_mode_noeeprom(uint8_t mode);
106uint8_t led_matrix_get_mode(void);
107void led_matrix_set_value(uint8_t mode, bool eeprom_write);
108
109#ifndef BACKLIGHT_ENABLE
110#define backlight_toggle() backlight_matrix_toggle()
111#define backlight_enable() backlight_matrix_enable()
112#define backlight_enable_noeeprom() backlight_matrix_enable_noeeprom()
113#define backlight_disable() backlight_matrix_disable()
114#define backlight_disable_noeeprom() backlight_matrix_disable_noeeprom()
115#define backlight_step() backlight_matrix_step()
116#define backlight_set_value(val) backlight_matrix_set_value(val)
117#define backlight_set_value_noeeprom(val) backlight_matrix_set_value_noeeprom(val)
118#define backlight_step_reverse() backlight_matrix_step_reverse()
119#define backlight_increase_val() backlight_matrix_increase_val()
120#define backlight_decrease_val() backlight_matrix_decrease_val()
121#define backlight_increase_speed() backlight_matrix_increase_speed()
122#define backlight_decrease_speed() backlight_matrix_decrease_speed()
123#define backlight_mode(mode) backlight_matrix_mode(mode)
124#define backlight_mode_noeeprom(mode) backlight_matrix_mode_noeeprom(mode)
125#define backlight_get_mode() backlight_matrix_get_mode()
126#endif
127
128typedef struct {
129 /* Perform any initialisation required for the other driver functions to work. */
130 void (*init)(void);
131
132 /* Set the brightness of a single LED in the buffer. */
133 void (*set_value)(int index, uint8_t value);
134 /* Set the brightness of all LEDS on the keyboard in the buffer. */
135 void (*set_value_all)(uint8_t value);
136 /* Flush any buffered changes to the hardware. */
137 void (*flush)(void);
138} led_matrix_driver_t;
139
140extern const led_matrix_driver_t led_matrix_driver;
141
142#endif
diff --git a/quantum/led_matrix_drivers.c b/quantum/led_matrix_drivers.c
new file mode 100644
index 000000000..f00f4f366
--- /dev/null
+++ b/quantum/led_matrix_drivers.c
@@ -0,0 +1,147 @@
1/* Copyright 2018 Clueboard
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <stdint.h>
18#include <stdbool.h>
19#include "quantum.h"
20#include "led_matrix.h"
21
22/* Each driver needs to define a struct:
23 *
24 * const led_matrix_driver_t led_matrix_driver;
25 *
26 * All members must be provided. Keyboard custom drivers must define this
27 * in their own files.
28 */
29
30#if defined(IS31FL3731) || defined(IS31FL3733)
31
32#if defined(IS31FL3731)
33 #include "is31fl3731-simple.h"
34#endif
35
36#include "i2c_master.h"
37
38static void init(void) {
39 i2c_init();
40 #ifdef IS31FL3731
41 #ifdef LED_DRIVER_ADDR_1
42 IS31FL3731_init(DRIVER_ADDR_1);
43 #endif
44 #ifdef LED_DRIVER_ADDR_2
45 IS31FL3731_init(DRIVER_ADDR_2);
46 #endif
47 #ifdef LED_DRIVER_ADDR_3
48 IS31FL3731_init(DRIVER_ADDR_3);
49 #endif
50 #ifdef LED_DRIVER_ADDR_4
51 IS31FL3731_init(DRIVER_ADDR_4);
52 #endif
53 #else
54 #ifdef LED_DRIVER_ADDR_1
55 IS31FL3733_init(DRIVER_ADDR_1);
56 #endif
57 #ifdef LED_DRIVER_ADDR_2
58 IS31FL3733_init(DRIVER_ADDR_2);
59 #endif
60 #ifdef LED_DRIVER_ADDR_3
61 IS31FL3733_init(DRIVER_ADDR_3);
62 #endif
63 #ifdef LED_DRIVER_ADDR_4
64 IS31FL3733_init(DRIVER_ADDR_4);
65 #endif
66 #endif
67 for (int index = 0; index < DRIVER_LED_TOTAL; index++) {
68 #ifdef IS31FL3731
69 IS31FL3731_set_led_control_register(index, true);
70 #else
71 IS31FL3733_set_led_control_register(index, true);
72 #endif
73 }
74 // This actually updates the LED drivers
75 #ifdef IS31FL3731
76 #ifdef LED_DRIVER_ADDR_1
77 IS31FL3731_update_led_control_registers(DRIVER_ADDR_1);
78 #endif
79 #ifdef LED_DRIVER_ADDR_2
80 IS31FL3731_update_led_control_registers(DRIVER_ADDR_2);
81 #endif
82 #ifdef LED_DRIVER_ADDR_3
83 IS31FL3731_update_led_control_registers(DRIVER_ADDR_3);
84 #endif
85 #ifdef LED_DRIVER_ADDR_4
86 IS31FL3731_update_led_control_registers(DRIVER_ADDR_4);
87 #endif
88 #else
89 #ifdef LED_DRIVER_ADDR_1
90 IS31FL3733_update_led_control_registers(DRIVER_ADDR_1);
91 #endif
92 #ifdef LED_DRIVER_ADDR_2
93 IS31FL3733_update_led_control_registers(DRIVER_ADDR_2);
94 #endif
95 #ifdef LED_DRIVER_ADDR_3
96 IS31FL3733_update_led_control_registers(DRIVER_ADDR_3);
97 #endif
98 #ifdef LED_DRIVER_ADDR_4
99 IS31FL3733_update_led_control_registers(DRIVER_ADDR_4);
100 #endif
101 #endif
102}
103
104static void flush(void) {
105 #ifdef IS31FL3731
106 #ifdef LED_DRIVER_ADDR_1
107 IS31FL3731_update_pwm_buffers(DRIVER_ADDR_1);
108 #endif
109 #ifdef LED_DRIVER_ADDR_2
110 IS31FL3731_update_pwm_buffers(DRIVER_ADDR_2);
111 #endif
112 #ifdef LED_DRIVER_ADDR_3
113 IS31FL3731_update_pwm_buffers(DRIVER_ADDR_3);
114 #endif
115 #ifdef LED_DRIVER_ADDR_4
116 IS31FL3731_update_pwm_buffers(DRIVER_ADDR_4);
117 #endif
118 #else
119 #ifdef LED_DRIVER_ADDR_1
120 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_1);
121 #endif
122 #ifdef LED_DRIVER_ADDR_2
123 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_2);
124 #endif
125 #ifdef LED_DRIVER_ADDR_3
126 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_3);
127 #endif
128 #ifdef LED_DRIVER_ADDR_4
129 IS31FL3733_update_pwm_buffers(DRIVER_ADDR_4);
130 #endif
131 #endif
132}
133
134const led_matrix_driver_t led_matrix_driver = {
135 .init = init,
136 .flush = flush,
137#ifdef IS31FL3731
138 .set_value = IS31FL3731_set_value,
139 .set_value_all = IS31FL3731_set_value_all,
140#else
141 .set_value = IS31FL3733_set_value,
142 .set_value_all = IS31FL3733_set_value_all,
143#endif
144};
145
146
147#endif
diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h
index e43532d11..b64ddec07 100644
--- a/quantum/rgb_matrix.h
+++ b/quantum/rgb_matrix.h
@@ -50,25 +50,17 @@ typedef struct rgb_led {
50 50
51extern const rgb_led g_rgb_leds[DRIVER_LED_TOTAL]; 51extern const rgb_led g_rgb_leds[DRIVER_LED_TOTAL];
52 52
53typedef struct
54{
55 HSV color;
56 uint8_t index;
57} rgb_indicator;
58
59typedef union { 53typedef union {
60 uint32_t raw; 54 uint32_t raw;
61 struct { 55 struct {
62 bool enable :1; 56 bool enable :1;
63 uint8_t mode :6; 57 uint8_t mode :6;
64 uint16_t hue :9;
65 uint8_t sat :8;
66 uint8_t val :8; 58 uint8_t val :8;
67 uint8_t speed :8;//EECONFIG needs to be increased to support this 59 uint8_t speed :8;//EECONFIG needs to be increased to support this
68 }; 60 };
69} rgb_config_t; 61} led_config_t;
70 62
71enum rgb_matrix_effects { 63enum _matrix_effects {
72 RGB_MATRIX_SOLID_COLOR = 1, 64 RGB_MATRIX_SOLID_COLOR = 1,
73#ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS 65#ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS
74 RGB_MATRIX_ALPHAS_MODS, 66 RGB_MATRIX_ALPHAS_MODS,