aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryiancar <yiangosyiangou@cytanet.com.cy>2019-11-25 20:33:52 +0000
committerJoel Challis <git@zvecr.com>2019-11-25 20:33:52 +0000
commitc0fe8dbfb4ea7b36cc2c5ba65d943c2cbec84244 (patch)
tree3fe648b223538ce54ad1f322f760a8610bd7a388
parentf0f161e5724375b7a289699703d86d6de2adae8d (diff)
downloadqmk_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.c50
-rw-r--r--drivers/issi/is31fl3733.h4
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};
80uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}, {0}}; 80uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}, {0}};
81bool g_led_control_registers_update_required[DRIVER_COUNT] = {false}; 81bool g_led_control_registers_update_required[DRIVER_COUNT] = {false};
82 82
83void IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) { 83bool 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
96void IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { 102bool 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
122void IS31FL3733_init(uint8_t addr, uint8_t sync) { 133void 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
214void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index) { 225void 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 {
32extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; 32extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
33 33
34void IS31FL3733_init(uint8_t addr, uint8_t sync); 34void IS31FL3733_init(uint8_t addr, uint8_t sync);
35void IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data); 35bool IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data);
36void IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer); 36bool IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
37 37
38void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); 38void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue);
39void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue); 39void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue);