Skip to content

Commit e1c0bd8

Browse files
authored
LED drivers: extract IS31FL3742A from IS31COMMON (qmk#22620)
1 parent 709d07a commit e1c0bd8

10 files changed

+816
-87
lines changed

builddefs/common_features.mk

+2-4
Original file line numberDiff line numberDiff line change
@@ -396,10 +396,9 @@ ifeq ($(strip $(LED_MATRIX_ENABLE)), yes)
396396
endif
397397

398398
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3742a)
399-
OPT_DEFS += -DIS31FLCOMMON
400399
I2C_DRIVER_REQUIRED = yes
401400
COMMON_VPATH += $(DRIVER_PATH)/led/issi
402-
SRC += is31flcommon.c
401+
SRC += is31fl3742a-simple.c
403402
endif
404403

405404
ifeq ($(strip $(LED_MATRIX_DRIVER)), is31fl3743a)
@@ -503,10 +502,9 @@ ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
503502
endif
504503

505504
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3742a)
506-
OPT_DEFS += -DIS31FLCOMMON
507505
I2C_DRIVER_REQUIRED = yes
508506
COMMON_VPATH += $(DRIVER_PATH)/led/issi
509-
SRC += is31flcommon.c
507+
SRC += is31fl3742a.c
510508
endif
511509

512510
ifeq ($(strip $(RGB_MATRIX_DRIVER)), is31fl3743a)

drivers/led/issi/is31fl3742a-simple.c

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
#include "is31fl3742a-simple.h"
2+
#include <string.h>
3+
#include "i2c_master.h"
4+
#include "wait.h"
5+
6+
#define IS31FL3742A_PWM_REGISTER_COUNT 180
7+
#define IS31FL3742A_SCALING_REGISTER_COUNT 180
8+
9+
#ifndef IS31FL3742A_I2C_TIMEOUT
10+
# define IS31FL3742A_I2C_TIMEOUT 100
11+
#endif
12+
13+
#ifndef IS31FL3742A_I2C_PERSISTENCE
14+
# define IS31FL3742A_I2C_PERSISTENCE 0
15+
#endif
16+
17+
#ifndef IS31FL3742A_CONFIGURATION
18+
# define IS31FL3742A_CONFIGURATION 0x31
19+
#endif
20+
21+
#ifndef IS31FL3742A_PWM_FREQUENCY
22+
# define IS31FL3742A_PWM_FREQUENCY IS31FL3742A_PWM_FREQUENCY_29K_HZ
23+
#endif
24+
25+
#ifndef IS31FL3742A_SW_PULLDOWN
26+
# define IS31FL3742A_SW_PULLDOWN IS31FL3742A_PDR_8K_OHM
27+
#endif
28+
29+
#ifndef IS31FL3742A_CS_PULLUP
30+
# define IS31FL3742A_CS_PULLUP IS31FL3742A_PUR_8K_OHM
31+
#endif
32+
33+
#ifndef IS31FL3742A_GLOBAL_CURRENT
34+
# define IS31FL3742A_GLOBAL_CURRENT 0xFF
35+
#endif
36+
37+
uint8_t i2c_transfer_buffer[20] = {0xFF};
38+
39+
uint8_t g_pwm_buffer[IS31FL3742A_DRIVER_COUNT][IS31FL3742A_PWM_REGISTER_COUNT];
40+
bool g_pwm_buffer_update_required[IS31FL3742A_DRIVER_COUNT] = {false};
41+
bool g_scaling_registers_update_required[IS31FL3742A_DRIVER_COUNT] = {false};
42+
43+
uint8_t g_scaling_registers[IS31FL3742A_DRIVER_COUNT][IS31FL3742A_SCALING_REGISTER_COUNT];
44+
45+
void is31fl3742a_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
46+
i2c_transfer_buffer[0] = reg;
47+
i2c_transfer_buffer[1] = data;
48+
49+
#if IS31FL3742A_I2C_PERSISTENCE > 0
50+
for (uint8_t i = 0; i < IS31FL3742A_I2C_PERSISTENCE; i++) {
51+
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3742A_I2C_TIMEOUT) == 0) break;
52+
}
53+
#else
54+
i2c_transmit(addr << 1, i2c_transfer_buffer, 2, IS31FL3742A_I2C_TIMEOUT);
55+
#endif
56+
}
57+
58+
void is31fl3742a_select_page(uint8_t addr, uint8_t page) {
59+
is31fl3742a_write_register(addr, IS31FL3742A_REG_COMMAND_WRITE_LOCK, IS31FL3742A_COMMAND_WRITE_LOCK_MAGIC);
60+
is31fl3742a_write_register(addr, IS31FL3742A_REG_COMMAND, page);
61+
}
62+
63+
void is31fl3742a_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
64+
// Assumes page 0 is already selected.
65+
// If any of the transactions fails function returns false.
66+
// Transmit PWM registers in 12 transfers of 16 bytes.
67+
// i2c_transfer_buffer[] is 20 bytes
68+
69+
// Iterate over the pwm_buffer contents at 16 byte intervals.
70+
for (int i = 0; i < IS31FL3742A_PWM_REGISTER_COUNT; i += 16) {
71+
i2c_transfer_buffer[0] = i;
72+
// Copy the data from i to i+15.
73+
// Device will auto-increment register for data after the first byte
74+
// Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer.
75+
memcpy(i2c_transfer_buffer + 1, pwm_buffer + i, 16);
76+
77+
#if IS31FL3742A_I2C_PERSISTENCE > 0
78+
for (uint8_t i = 0; i < IS31FL3742A_I2C_PERSISTENCE; i++) {
79+
if (i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3742A_I2C_TIMEOUT) != 0) break;
80+
}
81+
#else
82+
i2c_transmit(addr << 1, i2c_transfer_buffer, 17, IS31FL3742A_I2C_TIMEOUT);
83+
#endif
84+
}
85+
}
86+
87+
void is31fl3742a_init_drivers(void) {
88+
i2c_init();
89+
90+
is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_1);
91+
#if defined(IS31FL3742A_I2C_ADDRESS_2)
92+
is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_2);
93+
# if defined(IS31FL3742A_I2C_ADDRESS_3)
94+
is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_3);
95+
# if defined(IS31FL3742A_I2C_ADDRESS_4)
96+
is31fl3742a_init(IS31FL3742A_I2C_ADDRESS_4);
97+
# endif
98+
# endif
99+
#endif
100+
101+
for (int i = 0; i < IS31FL3742A_LED_COUNT; i++) {
102+
is31fl3742a_set_scaling_register(i, 0xFF);
103+
}
104+
105+
is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_1, 0);
106+
#if defined(IS31FL3742A_I2C_ADDRESS_2)
107+
is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_2, 1);
108+
# if defined(IS31FL3742A_I2C_ADDRESS_3)
109+
is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_3, 2);
110+
# if defined(IS31FL3742A_I2C_ADDRESS_4)
111+
is31fl3742a_update_scaling_registers(IS31FL3742A_I2C_ADDRESS_4, 3);
112+
# endif
113+
# endif
114+
#endif
115+
}
116+
117+
void is31fl3742a_init(uint8_t addr) {
118+
// In order to avoid the LEDs being driven with garbage data
119+
// in the LED driver's PWM registers, shutdown is enabled last.
120+
// Set up the mode and other settings, clear the PWM registers,
121+
// then disable software shutdown.
122+
123+
is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_SCALING);
124+
125+
// Turn off all LEDs.
126+
for (int i = 0; i < IS31FL3742A_SCALING_REGISTER_COUNT; i++) {
127+
is31fl3742a_write_register(addr, i, 0x00);
128+
}
129+
130+
is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_PWM);
131+
132+
for (int i = 0; i < IS31FL3742A_PWM_REGISTER_COUNT; i++) {
133+
is31fl3742a_write_register(addr, i, 0x00);
134+
}
135+
136+
is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_FUNCTION);
137+
138+
is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_PULLDOWNUP, (IS31FL3742A_SW_PULLDOWN << 4) | IS31FL3742A_CS_PULLUP);
139+
is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_GLOBAL_CURRENT, IS31FL3742A_GLOBAL_CURRENT);
140+
is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_PWM_FREQUENCY, (IS31FL3742A_PWM_FREQUENCY & 0b0111));
141+
is31fl3742a_write_register(addr, IS31FL3742A_FUNCTION_REG_CONFIGURATION, IS31FL3742A_CONFIGURATION);
142+
143+
// Wait 10ms to ensure the device has woken up.
144+
wait_ms(10);
145+
}
146+
147+
void is31fl3742a_set_value(int index, uint8_t value) {
148+
is31fl3742a_led_t led;
149+
if (index >= 0 && index < IS31FL3742A_LED_COUNT) {
150+
memcpy_P(&led, (&g_is31fl3742a_leds[index]), sizeof(led));
151+
152+
if (g_pwm_buffer[led.driver][led.v] == value) {
153+
return;
154+
}
155+
g_pwm_buffer[led.driver][led.v] = value;
156+
g_pwm_buffer_update_required[led.driver] = true;
157+
}
158+
}
159+
160+
void is31fl3742a_set_value_all(uint8_t value) {
161+
for (int i = 0; i < IS31FL3742A_LED_COUNT; i++) {
162+
is31fl3742a_set_value(i, value);
163+
}
164+
}
165+
166+
void is31fl3742a_set_scaling_register(uint8_t index, uint8_t value) {
167+
is31fl3742a_led_t led;
168+
memcpy_P(&led, (&g_is31fl3742a_leds[index]), sizeof(led));
169+
170+
g_scaling_registers[led.driver][led.v] = value;
171+
172+
g_scaling_registers_update_required[led.driver] = true;
173+
}
174+
175+
void is31fl3742a_update_pwm_buffers(uint8_t addr, uint8_t index) {
176+
if (g_pwm_buffer_update_required[index]) {
177+
is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_PWM);
178+
179+
is31fl3742a_write_pwm_buffer(addr, g_pwm_buffer[index]);
180+
g_pwm_buffer_update_required[index] = false;
181+
}
182+
}
183+
184+
void is31fl3742a_update_scaling_registers(uint8_t addr, uint8_t index) {
185+
if (g_scaling_registers_update_required[index]) {
186+
is31fl3742a_select_page(addr, IS31FL3742A_COMMAND_SCALING);
187+
188+
for (int i = 0; i < IS31FL3742A_SCALING_REGISTER_COUNT; i++) {
189+
is31fl3742a_write_register(addr, i, g_scaling_registers[index][i]);
190+
}
191+
g_scaling_registers_update_required[index] = false;
192+
}
193+
}
194+
195+
void is31fl3742a_flush(void) {
196+
is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_1, 0);
197+
#if defined(IS31FL3742A_I2C_ADDRESS_2)
198+
is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_2, 1);
199+
# if defined(IS31FL3742A_I2C_ADDRESS_3)
200+
is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_3, 2);
201+
# if defined(IS31FL3742A_I2C_ADDRESS_4)
202+
is31fl3742a_update_pwm_buffers(IS31FL3742A_I2C_ADDRESS_4, 3);
203+
# endif
204+
# endif
205+
#endif
206+
}

0 commit comments

Comments
 (0)