Skip to content

Commit 36c3ef3

Browse files
committed
Commit Halo96 V2, add IS31FL3736 driver file, and make format adjustments for other projects
1 parent 70bd81b commit 36c3ef3

8 files changed

Lines changed: 621 additions & 4 deletions

File tree

builddefs/common_features.mk

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ LED_MATRIX_DRIVER := snled27351
340340
endif
341341

342342
LED_MATRIX_ENABLE ?= no
343-
VALID_LED_MATRIX_TYPES := is31fl3218 is31fl3236 is31fl3729 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 custom
343+
VALID_LED_MATRIX_TYPES := is31fl3218 is31fl3236 is31fl3729 is31fl3731 is31fl3733 is31fl3763 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 custom
344344

345345
ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
346346
ifeq ($(filter $(LED_MATRIX_DRIVER),$(VALID_LED_MATRIX_TYPES)),)
@@ -449,7 +449,7 @@ endif
449449

450450
RGB_MATRIX_ENABLE ?= no
451451

452-
VALID_RGB_MATRIX_TYPES := aw20216s is31fl3218 is31fl3236 is31fl3729 is31fl3731 is31fl3733 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 ws2812 custom
452+
VALID_RGB_MATRIX_TYPES := aw20216s is31fl3218 is31fl3236 is31fl3729 is31fl3731 is31fl3733 is31fl3763 is31fl3736 is31fl3737 is31fl3741 is31fl3742a is31fl3743a is31fl3745 is31fl3746a snled27351 ws2812 custom
453453
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
454454
ifeq ($(filter $(RGB_MATRIX_DRIVER),$(VALID_RGB_MATRIX_TYPES)),)
455455
$(call CATASTROPHIC_ERROR,Invalid RGB_MATRIX_DRIVER,RGB_MATRIX_DRIVER="$(RGB_MATRIX_DRIVER)" is not a valid matrix type)
@@ -498,6 +498,12 @@ ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
498498
SRC += is31fl3731.c
499499
endif
500500

501+
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3763)
502+
I2C_DRIVER_REQUIRED = yes
503+
COMMON_VPATH += $(DRIVER_PATH)/led/issi
504+
SRC += is31fl3763.c
505+
endif
506+
501507
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3733)
502508
I2C_DRIVER_REQUIRED = yes
503509
COMMON_VPATH += $(DRIVER_PATH)/led/issi

data/schemas/keyboard.jsonschema

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@
470470
"is31fl3729",
471471
"is31fl3731",
472472
"is31fl3733",
473+
"is31fl3763",
473474
"is31fl3736",
474475
"is31fl3737",
475476
"is31fl3741",
@@ -553,6 +554,7 @@
553554
"is31fl3729",
554555
"is31fl3731",
555556
"is31fl3733",
557+
"is31fl3763",
556558
"is31fl3736",
557559
"is31fl3737",
558560
"is31fl3741",

drivers/led/issi/is31fl3763.c

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
/* Copyright 2017 Jason Williams
2+
* Copyright 2018 Jack Humbert
3+
* Copyright 2018 Yiancar
4+
* Copyright 2021 Doni Crosby
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 "is31fl3763.h"
21+
#include "i2c_master.h"
22+
#include "gpio.h"
23+
#include "wait.h"
24+
25+
26+
#define ISSI_ADDR_DEFAULT 0x6C
27+
28+
#define ISSI_COMMANDREGISTER 0xFE
29+
#define ISSI_COMMANDREGISTER_WRITELOCK 0xFF
30+
#define ISSI_INTERRUPTMASKREGISTER 0xF0
31+
#define ISSI_INTERRUPTSTATUSREGISTER 0xF1
32+
33+
34+
#define ISSI_PAGE_PWM 0x00 // PG0
35+
#define ISSI_PAGE_PWM_CONTROL 0x01 // PG1
36+
37+
#define ISSI_PAGE_AUTOBREATH 0x02 // PG2
38+
#define ISSI_PAGE_FUNCTION 0x03 // PG3
39+
40+
#define ISSI_REG_CONFIGURATION 0x00 // PG3
41+
#define ISSI_REG_GLOBALCURRENT 0x01 // PG3
42+
#define ISSI_REG_RESET 0x11 // PG3
43+
#define ISSI_REG_SWPULLUP 0x0F // PG3
44+
#define ISSI_REG_CSPULLUP 0x10 // PG3
45+
46+
#ifndef ISSI_TIMEOUT
47+
# define ISSI_TIMEOUT 100
48+
#endif
49+
50+
#ifndef ISSI_PERSISTENCE
51+
# define ISSI_PERSISTENCE 0
52+
#endif
53+
54+
#ifndef ISSI_PWM_FREQUENCY
55+
# define ISSI_PWM_FREQUENCY 0b000
56+
#endif
57+
58+
#ifndef ISSI_SWPULLUP
59+
# define ISSI_SWPULLUP PUR_0R
60+
#endif
61+
62+
#ifndef ISSI_CSPULLUP
63+
# define ISSI_CSPULLUP PUR_0R
64+
#endif
65+
66+
#ifndef ISSI_GLOBALCURRENT
67+
# define ISSI_GLOBALCURRENT 0x80
68+
#endif
69+
70+
const uint8_t i2c_addresses[DRIVER_COUNT] = {
71+
DRIVER_ADDR_1,DRIVER_ADDR_2,
72+
};
73+
74+
// Transfer buffer for TWITransmitData()
75+
uint8_t g_twi_transfer_buffer[20];
76+
77+
// These buffers match the IS31FL3733 PWM registers.
78+
// The control buffers match the PG0 LED On/Off registers.
79+
// Storing them like this is optimal for I2C transfers to the registers.
80+
// We could optimize this and take out the unused registers from these
81+
// buffers and the transfers in is31fl3733_write_pwm_buffer() but it's
82+
// probably not worth the extra complexity.
83+
uint8_t g_pwm_buffer[DRIVER_COUNT][328];
84+
bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
85+
86+
uint8_t g_led_control_registers[DRIVER_COUNT][24] = {0};
87+
bool g_led_control_registers_update_required[DRIVER_COUNT] = {false};
88+
89+
90+
// I2C
91+
void is31fl3763_write_register(uint8_t index, uint8_t reg, uint8_t data) {
92+
// If the transaction fails function returns false.
93+
#if ISSI_PERSISTENCE > 0
94+
for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
95+
if (i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, ISSI_TIMEOUT) != 0) {
96+
return false;
97+
}
98+
}
99+
#else
100+
i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, ISSI_TIMEOUT);
101+
#endif
102+
}
103+
104+
uint8_t PWM_H_Tab[14][12] =
105+
{
106+
//sw 1 2 3 4 5 6 7 8 9 10 11 12
107+
{0x01,0x02,0x04,0x05,0x07,0x08,0x0A,0x0B,0X0D,0X0E,0X10,0X11}, //CS01 | CS15
108+
{0X13,0X14,0X16,0X17,0X19,0X1A,0X1C,0X1D,0X1F,0X20,0X22,0X23}, //CS02 | CS16
109+
{0X25,0X26,0X28,0X29,0X2B,0X2C,0X2E,0X2F,0X31,0X32,0X34,0X35}, //CS03 | CS17
110+
{0X37,0X38,0X3A,0X3B,0X3D,0X3E,0X40,0X41,0X43,0X44,0X46,0X47}, //CS04 | CS18
111+
{0X49,0X4A,0X4C,0X4D,0X4F,0X50,0X52,0X53,0X55,0X56,0X58,0X59}, //CS05
112+
{0X5B,0X5C,0X5E,0X5F,0X61,0X62,0X64,0X65,0X67,0X68,0X6A,0X6B}, //CS06
113+
{0X6D,0X6E,0X70,0X71,0X73,0X74,0X76,0X77,0X79,0X7A,0X7C,0X7D}, //CS07
114+
{0X7F,0X80,0X82,0X83,0X85,0X86,0X88,0X89,0X8B,0X8C,0X8E,0X8F}, //CS08
115+
{0x91,0x92,0x94,0x95,0x97,0x98,0x9A,0x9B,0X9D,0X9E,0XA0,0XA1}, //CS09
116+
{0XA3,0XA4,0XA6,0XA7,0XA9,0XAA,0XAC,0XAD,0XAF,0XB0,0XB2,0XB3}, //CS10
117+
{0XB5,0XB6,0XB8,0XB9,0XBB,0XBC,0XBE,0XBF,0XC1,0XC2,0XC4,0XC5}, //CS11
118+
{0XC7,0XC8,0XCA,0XCB,0XCD,0XCE,0XD0,0XD1,0XD3,0XD4,0XD6,0XD7}, //CS12
119+
{0XD9,0XDA,0XDC,0XDD,0XDF,0XE0,0XE2,0XE3,0XE5,0XE6,0XE8,0XE9}, //CS13
120+
{0XEB,0XEC,0XEE,0XEF,0XF1,0XF2,0XF4,0XF5,0XF7,0XF8,0XFA,0XFB} //CS14
121+
};
122+
123+
124+
void is31fl3763_write_pwm_buffer(uint8_t index) {
125+
126+
uint16_t addr_sart = 0;
127+
128+
for (int i = 0; i < 18; i += 1) {
129+
130+
if(i >= 14) {
131+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
132+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM_CONTROL);
133+
134+
addr_sart = ((i-14)*18);
135+
136+
i2c_write_register(i2c_addresses[index] << 1, addr_sart, &g_pwm_buffer[index][(addr_sart | 0X100)], 18, ISSI_TIMEOUT);
137+
138+
} else {
139+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
140+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
141+
142+
addr_sart = (i*18);
143+
144+
i2c_write_register(i2c_addresses[index] << 1, addr_sart, &g_pwm_buffer[index][(addr_sart)], 18, ISSI_TIMEOUT);
145+
}
146+
}
147+
148+
is31fl3763_write_register(index, 0xFD, 0x00);
149+
}
150+
151+
152+
153+
void is31fl3763_init_drivers(void) {
154+
i2c_init();
155+
156+
for (uint8_t i = 0; i < DRIVER_COUNT; i++) {
157+
is31fl3763_init(i);
158+
}
159+
160+
for (int i = 0; i < DRIVER_COUNT; i++) {
161+
is31fl3763_set_led_control_register(i, true, true, true);
162+
}
163+
164+
for (uint8_t i = 0; i < DRIVER_COUNT; i++) {
165+
is31fl3763_update_led_control_registers(i);
166+
}
167+
}
168+
169+
void is31fl3763_init(uint8_t index) {
170+
171+
uint8_t i, j;
172+
173+
// Unlock the command register.
174+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
175+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
176+
177+
// Turn off all LEDs.
178+
for(i = 0;i < 14;i++) {
179+
for(j = 0;j < 12; j++) {
180+
is31fl3763_write_register(index, PWM_H_Tab[i][j], 0X00);
181+
}
182+
}
183+
184+
// Unlock the command register.
185+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
186+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM_CONTROL);
187+
188+
// Turn off all LEDs.
189+
for(i = 0;i < 4;i++) {
190+
for(j = 0;j < 12; j++) {
191+
is31fl3763_write_register(index, PWM_H_Tab[i][j], 0X00);
192+
}
193+
}
194+
195+
// Unlock the command register.
196+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
197+
// Select PG1
198+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM_CONTROL);
199+
// Set de-ghost pull-up resistors (SWx)(CSx)
200+
is31fl3763_write_register(index, 0x62, 0x66); //
201+
// Set global current to maximum.
202+
is31fl3763_write_register(index, 0x61, ISSI_GLOBALCURRENT);
203+
// Disable software shutdown.
204+
is31fl3763_write_register(index, 0x60,0x09);
205+
206+
is31fl3763_write_register(index, 0x63, 0x00);
207+
208+
uint8_t SL_Set;
209+
for(SL_Set = 0x49;SL_Set <= 0x5A;SL_Set++) {
210+
is31fl3763_write_register(index, SL_Set, 0x80);
211+
}
212+
is31fl3763_write_register(index, 0xFD, 0x00); //update
213+
214+
// Wait 10ms to ensure the device has woken up.
215+
wait_ms(10);
216+
}
217+
218+
void is31fl3763_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
219+
is31_led led;
220+
if (index >= 0 && index < RGB_MATRIX_LED_COUNT) {
221+
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
222+
223+
g_pwm_buffer[led.driver][led.r] = red;
224+
g_pwm_buffer[led.driver][led.g] = green;
225+
g_pwm_buffer[led.driver][led.b] = blue;
226+
g_pwm_buffer_update_required[led.driver] = true;
227+
}
228+
}
229+
230+
void is31fl3763_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
231+
for (int i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
232+
is31fl3763_set_color(i, red, green, blue);
233+
}
234+
}
235+
236+
void is31fl3763_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
237+
is31_led led;
238+
memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
239+
240+
uint8_t control_register_r = led.r / 8;
241+
uint8_t control_register_g = led.g / 8;
242+
uint8_t control_register_b = led.b / 8;
243+
uint8_t bit_r = led.r % 8;
244+
uint8_t bit_g = led.g % 8;
245+
uint8_t bit_b = led.b % 8;
246+
247+
if (red) {
248+
g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
249+
} else {
250+
g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
251+
}
252+
if (green) {
253+
g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
254+
} else {
255+
g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
256+
}
257+
if (blue) {
258+
g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
259+
} else {
260+
g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
261+
}
262+
263+
g_led_control_registers_update_required[led.driver] = true;
264+
}
265+
266+
void is31fl3763_update_pwm_buffers(uint8_t index) {
267+
if (g_pwm_buffer_update_required[index]) {
268+
// Firstly we need to unlock the command register and select PG1.
269+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
270+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
271+
272+
is31fl3763_write_pwm_buffer(index);
273+
274+
g_pwm_buffer_update_required[index] = false;
275+
}
276+
}
277+
278+
279+
void is31fl3763_update_led_control_registers(uint8_t index) {
280+
if (g_led_control_registers_update_required[index]) {
281+
// Firstly we need to unlock the command register and select PG0
282+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
283+
is31fl3763_write_register(index, ISSI_COMMANDREGISTER, 0x01);
284+
for (int i = 0; i < 24; i++) {
285+
is31fl3763_write_register(index, i, g_led_control_registers[index][i]);
286+
}
287+
}
288+
g_led_control_registers_update_required[index] = false;
289+
}
290+
291+
void is31fl3763_flush(void) {
292+
for (uint8_t i = 0; i < DRIVER_COUNT; i++) {
293+
is31fl3763_update_pwm_buffers(i);
294+
}
295+
}

0 commit comments

Comments
 (0)