Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

is31fl3741: split PWM and scaling buffers #23049

Merged
merged 3 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 65 additions & 38 deletions drivers/led/issi/is31fl3741-mono.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
#include "i2c_master.h"
#include "wait.h"

#define IS31FL3741_PWM_REGISTER_COUNT 351
#define IS31FL3741_SCALING_REGISTER_COUNT 351
#define IS31FL3741_PWM_0_REGISTER_COUNT 180
#define IS31FL3741_PWM_1_REGISTER_COUNT 171
#define IS31FL3741_SCALING_0_REGISTER_COUNT 180
#define IS31FL3741_SCALING_1_REGISTER_COUNT 171

#ifndef IS31FL3741_I2C_TIMEOUT
# define IS31FL3741_I2C_TIMEOUT 100
Expand Down Expand Up @@ -72,16 +74,20 @@ const uint8_t i2c_addresses[IS31FL3741_DRIVER_COUNT] = {
// buffers and the transfers in is31fl3741_write_pwm_buffer() but it's
// probably not worth the extra complexity.
typedef struct is31fl3741_driver_t {
uint8_t pwm_buffer[IS31FL3741_PWM_REGISTER_COUNT];
uint8_t pwm_buffer_0[IS31FL3741_PWM_0_REGISTER_COUNT];
uint8_t pwm_buffer_1[IS31FL3741_PWM_1_REGISTER_COUNT];
bool pwm_buffer_dirty;
uint8_t scaling_buffer[IS31FL3741_SCALING_REGISTER_COUNT];
uint8_t scaling_buffer_0[IS31FL3741_SCALING_0_REGISTER_COUNT];
uint8_t scaling_buffer_1[IS31FL3741_SCALING_1_REGISTER_COUNT];
bool scaling_buffer_dirty;
} PACKED is31fl3741_driver_t;

is31fl3741_driver_t driver_buffers[IS31FL3741_DRIVER_COUNT] = {{
.pwm_buffer = {0},
.pwm_buffer_0 = {0},
.pwm_buffer_1 = {0},
.pwm_buffer_dirty = false,
.scaling_buffer = {0},
.scaling_buffer_0 = {0},
.scaling_buffer_1 = {0},
.scaling_buffer_dirty = false,
}};

Expand All @@ -101,30 +107,35 @@ void is31fl3741_select_page(uint8_t index, uint8_t page) {
}

void is31fl3741_write_pwm_buffer(uint8_t index) {
// Assume page 0 is already selected
is31fl3741_select_page(index, IS31FL3741_COMMAND_PWM_0);

for (uint16_t i = 0; i < 342; i += 18) {
if (i == 180) {
is31fl3741_select_page(index, IS31FL3741_COMMAND_PWM_1);
}
// Transmit PWM0 registers in 6 transfers of 30 bytes.

// Iterate over the pwm_buffer_0 contents at 30 byte intervals.
for (uint8_t i = 0; i < IS31FL3741_PWM_0_REGISTER_COUNT; i += 30) {
#if IS31FL3741_I2C_PERSISTENCE > 0
for (uint8_t j = 0; j < IS31FL3741_I2C_PERSISTENCE; j++) {
if (i2c_write_register(i2c_addresses[index] << 1, i % 180, driver_buffers[index].pwm_buffer + i, 18, IS31FL3741_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
if (i2c_write_register(i2c_addresses[index] << 1, i, driver_buffers[index].pwm_buffer_0 + i, 30, IS31FL3741_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
}
#else
i2c_write_register(i2c_addresses[index] << 1, i % 180, driver_buffers[index].pwm_buffer + i, 18, IS31FL3741_I2C_TIMEOUT);
i2c_write_register(i2c_addresses[index] << 1, i, driver_buffers[index].pwm_buffer_0 + i, 30, IS31FL3741_I2C_TIMEOUT);
#endif
}

// transfer the left cause the total number is 351
is31fl3741_select_page(index, IS31FL3741_COMMAND_PWM_1);

// Transmit PWM1 registers in 9 transfers of 19 bytes.

// Iterate over the pwm_buffer_1 contents at 19 byte intervals.
for (uint8_t i = 0; i < IS31FL3741_PWM_1_REGISTER_COUNT; i += 19) {
#if IS31FL3741_I2C_PERSISTENCE > 0
for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) {
if (i2c_write_register(i2c_addresses[index] << 1, 162, driver_buffers[index].pwm_buffer + 342, 9, IS31FL3741_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
}
for (uint8_t i = 0; i < IS31FL3741_I2C_PERSISTENCE; i++) {
if (i2c_write_register(i2c_addresses[index] << 1, i, driver_buffers[index].pwm_buffer_1 + i, 19, IS31FL3741_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
}
#else
i2c_write_register(i2c_addresses[index] << 1, 162, driver_buffers[index].pwm_buffer + 342, 9, IS31FL3741_I2C_TIMEOUT);
i2c_write_register(i2c_addresses[index] << 1, i, driver_buffers[index].pwm_buffer_1 + i, 19, IS31FL3741_I2C_TIMEOUT);
#endif
}
}

void is31fl3741_init_drivers(void) {
Expand Down Expand Up @@ -168,18 +179,34 @@ void is31fl3741_init(uint8_t index) {
wait_ms(10);
}

uint8_t get_pwm_value(uint8_t driver, uint16_t reg) {
if (reg & 0x100) {
return driver_buffers[driver].pwm_buffer_1[reg & 0xFF];
} else {
return driver_buffers[driver].pwm_buffer_0[reg];
}
}

void set_pwm_value(uint8_t driver, uint16_t reg, uint8_t value) {
if (reg & 0x100) {
driver_buffers[driver].pwm_buffer_1[reg & 0xFF] = value;
} else {
driver_buffers[driver].pwm_buffer_0[reg] = value;
}
}

void is31fl3741_set_value(int index, uint8_t value) {
is31fl3741_led_t led;

if (index >= 0 && index < IS31FL3741_LED_COUNT) {
memcpy_P(&led, (&g_is31fl3741_leds[index]), sizeof(led));

if (driver_buffers[led.driver].pwm_buffer[led.v] == value) {
if (get_pwm_value(led.driver, led.v) == value) {
return;
}

driver_buffers[led.driver].pwm_buffer[led.v] = value;
driver_buffers[led.driver].pwm_buffer_dirty = true;
set_pwm_value(led.driver, led.v, value);
driver_buffers[led.driver].pwm_buffer_dirty = true;
}
}

Expand All @@ -189,57 +216,57 @@ void is31fl3741_set_value_all(uint8_t value) {
}
}

void set_scaling_value(uint8_t driver, uint16_t reg, uint8_t value) {
if (reg & 0x100) {
driver_buffers[driver].scaling_buffer_1[reg & 0xFF] = value;
} else {
driver_buffers[driver].scaling_buffer_0[reg] = value;
}
}

void is31fl3741_set_led_control_register(uint8_t index, bool value) {
is31fl3741_led_t led;
memcpy_P(&led, (&g_is31fl3741_leds[index]), sizeof(led));

if (value) {
driver_buffers[led.driver].scaling_buffer[led.v] = 0xFF;
} else {
driver_buffers[led.driver].scaling_buffer[led.v] = 0x00;
}
set_scaling_value(led.driver, led.v, value ? 0xFF : 0x00);

driver_buffers[led.driver].scaling_buffer_dirty = true;
}

void is31fl3741_update_pwm_buffers(uint8_t index) {
if (driver_buffers[index].pwm_buffer_dirty) {
is31fl3741_select_page(index, IS31FL3741_COMMAND_PWM_0);

is31fl3741_write_pwm_buffer(index);

driver_buffers[index].pwm_buffer_dirty = false;
}
}

void is31fl3741_set_pwm_buffer(const is31fl3741_led_t *pled, uint8_t value) {
driver_buffers[pled->driver].pwm_buffer[pled->v] = value;
driver_buffers[pled->driver].pwm_buffer_dirty = true;
set_pwm_value(pled->driver, pled->v, value);
driver_buffers[pled->driver].pwm_buffer_dirty = true;
}

void is31fl3741_update_led_control_registers(uint8_t index) {
if (driver_buffers[index].scaling_buffer_dirty) {
is31fl3741_select_page(index, IS31FL3741_COMMAND_SCALING_0);

// CS1_SW1 to CS30_SW6 are on page 2
for (int i = CS1_SW1; i <= CS30_SW6; ++i) {
is31fl3741_write_register(index, i, driver_buffers[index].scaling_buffer[i]);
for (uint8_t i = 0; i < IS31FL3741_SCALING_0_REGISTER_COUNT; i++) {
is31fl3741_write_register(index, i, driver_buffers[index].scaling_buffer_0[i]);
}

is31fl3741_select_page(index, IS31FL3741_COMMAND_SCALING_1);

// CS1_SW7 to CS39_SW9 are on page 3
for (int i = CS1_SW7; i <= CS39_SW9; ++i) {
is31fl3741_write_register(index, i - CS1_SW7, driver_buffers[index].scaling_buffer[i]);
for (uint8_t i = 0; i < IS31FL3741_SCALING_1_REGISTER_COUNT; i++) {
is31fl3741_write_register(index, i, driver_buffers[index].scaling_buffer_1[i]);
}

driver_buffers[index].scaling_buffer_dirty = false;
}
}

void is31fl3741_set_scaling_registers(const is31fl3741_led_t *pled, uint8_t value) {
driver_buffers[pled->driver].scaling_buffer[pled->v] = value;
driver_buffers[pled->driver].scaling_buffer_dirty = true;
set_scaling_value(pled->driver, pled->v, value);
driver_buffers[pled->driver].scaling_buffer_dirty = true;
}

void is31fl3741_flush(void) {
Expand Down
Loading
Loading