diff options
author | yiancar <yiangosyiangou@cytanet.com.cy> | 2019-11-25 20:33:52 +0000 |
---|---|---|
committer | Joel Challis <git@zvecr.com> | 2019-11-25 20:33:52 +0000 |
commit | c0fe8dbfb4ea7b36cc2c5ba65d943c2cbec84244 (patch) | |
tree | 3fe648b223538ce54ad1f322f760a8610bd7a388 | |
parent | f0f161e5724375b7a289699703d86d6de2adae8d (diff) | |
download | qmk_firmware-c0fe8dbfb4ea7b36cc2c5ba65d943c2cbec84244.tar.gz qmk_firmware-c0fe8dbfb4ea7b36cc2c5ba65d943c2cbec84244.zip |
IS31FL3733 Dirty page fix (#7079)
* IS31FL3733 Dirty page fix
Function IS31FL3733_update_led_control_registers was never setting update register to false. As a result the led on/off page was being written every transaction even when it was not modified. This is ineficient and causes lots of bandwidth use.
-> Fix the IS31FL3733_update_led_control_registers.
-> After testing it was evident that failed I2C transactions could corrupt the Led on/off register.
-> Update IS31FL3733_write_pwm_buffer and IS31FL3733_write_register functions to return 0 upon succesful tranmission and 1 if any of the transmitions within the function fail.
-> Modify IS31FL3733_update_pwm_buffers function so if any of the IS31FL3733_write_pwm_buffer transuction fails, the g_led_control_registers_update_required register is set to true forcing a rewrite of the led on/off register in case it was corrupted.
* Minor comment update
* Upsie:)
* Update is31fl3733.c
* Return fix
* more return fix
* type change
* more boolian logic reversal:)
-rw-r--r-- | drivers/issi/is31fl3733.c | 50 | ||||
-rw-r--r-- | drivers/issi/is31fl3733.h | 4 |
2 files changed, 34 insertions, 20 deletions
diff --git a/drivers/issi/is31fl3733.c b/drivers/issi/is31fl3733.c index cc2d895ef..e60f0e878 100644 --- a/drivers/issi/is31fl3733.c +++ b/drivers/issi/is31fl3733.c | |||
@@ -24,10 +24,10 @@ | |||
24 | # include "wait.h" | 24 | # include "wait.h" |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #include "is31fl3733.h" | ||
28 | #include <string.h> | 27 | #include <string.h> |
29 | #include "i2c_master.h" | 28 | #include "i2c_master.h" |
30 | #include "progmem.h" | 29 | #include "progmem.h" |
30 | #include "is31fl3733.h" | ||
31 | 31 | ||
32 | // This is a 7-bit address, that gets left-shifted and bit 0 | 32 | // This is a 7-bit address, that gets left-shifted and bit 0 |
33 | // set to 0 for write, 1 for read (as per I2C protocol) | 33 | // set to 0 for write, 1 for read (as per I2C protocol) |
@@ -80,43 +80,54 @@ bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false}; | |||
80 | uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}, {0}}; | 80 | uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}, {0}}; |
81 | bool g_led_control_registers_update_required[DRIVER_COUNT] = {false}; | 81 | bool g_led_control_registers_update_required[DRIVER_COUNT] = {false}; |
82 | 82 | ||
83 | void IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) { | 83 | bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) { |
84 | // If the transaction fails function returns false. | ||
84 | g_twi_transfer_buffer[0] = reg; | 85 | g_twi_transfer_buffer[0] = reg; |
85 | g_twi_transfer_buffer[1] = data; | 86 | g_twi_transfer_buffer[1] = data; |
86 | 87 | ||
87 | #if ISSI_PERSISTENCE > 0 | 88 | #if ISSI_PERSISTENCE > 0 |
88 | for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { | 89 | for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { |
89 | if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0) break; | 90 | if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) != 0) { |
91 | return false; | ||
92 | } | ||
90 | } | 93 | } |
91 | #else | 94 | #else |
92 | i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT); | 95 | if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) != 0) { |
96 | return false; | ||
97 | } | ||
93 | #endif | 98 | #endif |
99 | return true; | ||
94 | } | 100 | } |
95 | 101 | ||
96 | void IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { | 102 | bool IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { |
97 | // assumes PG1 is already selected | 103 | // Assumes PG1 is already selected. |
98 | 104 | // If any of the transactions fails function returns false. | |
99 | // transmit PWM registers in 12 transfers of 16 bytes | 105 | // Transmit PWM registers in 12 transfers of 16 bytes. |
100 | // g_twi_transfer_buffer[] is 20 bytes | 106 | // g_twi_transfer_buffer[] is 20 bytes |
101 | 107 | ||
102 | // iterate over the pwm_buffer contents at 16 byte intervals | 108 | // Iterate over the pwm_buffer contents at 16 byte intervals. |
103 | for (int i = 0; i < 192; i += 16) { | 109 | for (int i = 0; i < 192; i += 16) { |
104 | g_twi_transfer_buffer[0] = i; | 110 | g_twi_transfer_buffer[0] = i; |
105 | // copy the data from i to i+15 | 111 | // Copy the data from i to i+15. |
106 | // device will auto-increment register for data after the first byte | 112 | // Device will auto-increment register for data after the first byte |
107 | // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer | 113 | // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. |
108 | for (int j = 0; j < 16; j++) { | 114 | for (int j = 0; j < 16; j++) { |
109 | g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; | 115 | g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; |
110 | } | 116 | } |
111 | 117 | ||
112 | #if ISSI_PERSISTENCE > 0 | 118 | #if ISSI_PERSISTENCE > 0 |
113 | for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { | 119 | for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { |
114 | if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0) break; | 120 | if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) != 0) { |
121 | return false; | ||
122 | } | ||
115 | } | 123 | } |
116 | #else | 124 | #else |
117 | i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT); | 125 | if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) != 0) { |
126 | return false; | ||
127 | } | ||
118 | #endif | 128 | #endif |
119 | } | 129 | } |
130 | return true; | ||
120 | } | 131 | } |
121 | 132 | ||
122 | void IS31FL3733_init(uint8_t addr, uint8_t sync) { | 133 | void IS31FL3733_init(uint8_t addr, uint8_t sync) { |
@@ -213,11 +224,15 @@ void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bo | |||
213 | 224 | ||
214 | void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index) { | 225 | void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index) { |
215 | if (g_pwm_buffer_update_required[index]) { | 226 | if (g_pwm_buffer_update_required[index]) { |
216 | // Firstly we need to unlock the command register and select PG1 | 227 | // Firstly we need to unlock the command register and select PG1. |
217 | IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); | 228 | IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); |
218 | IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM); | 229 | IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM); |
219 | 230 | ||
220 | IS31FL3733_write_pwm_buffer(addr, g_pwm_buffer[index]); | 231 | // If any of the transactions fail we risk writing dirty PG0, |
232 | // refresh page 0 just in case. | ||
233 | if (!IS31FL3733_write_pwm_buffer(addr, g_pwm_buffer[index])){ | ||
234 | g_led_control_registers_update_required[index] = true; | ||
235 | } | ||
221 | } | 236 | } |
222 | g_pwm_buffer_update_required[index] = false; | 237 | g_pwm_buffer_update_required[index] = false; |
223 | } | 238 | } |
@@ -231,6 +246,5 @@ void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index) { | |||
231 | IS31FL3733_write_register(addr, i, g_led_control_registers[index][i]); | 246 | IS31FL3733_write_register(addr, i, g_led_control_registers[index][i]); |
232 | } | 247 | } |
233 | } | 248 | } |
234 | // This seems counter intuitive but sometimes this page can get corrupted. So update it every time. | 249 | g_led_control_registers_update_required[index] = false; |
235 | // g_led_control_registers_update_required[index] = false; | ||
236 | } | 250 | } |
diff --git a/drivers/issi/is31fl3733.h b/drivers/issi/is31fl3733.h index 5b3283e03..4cf186733 100644 --- a/drivers/issi/is31fl3733.h +++ b/drivers/issi/is31fl3733.h | |||
@@ -32,8 +32,8 @@ typedef struct is31_led { | |||
32 | extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; | 32 | extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; |
33 | 33 | ||
34 | void IS31FL3733_init(uint8_t addr, uint8_t sync); | 34 | void IS31FL3733_init(uint8_t addr, uint8_t sync); |
35 | void IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data); | 35 | bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data); |
36 | void IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); | 36 | bool IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); |
37 | 37 | ||
38 | void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); | 38 | void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); |
39 | void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue); | 39 | void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue); |