aboutsummaryrefslogtreecommitdiff
path: root/drivers/issi/is31fl3733.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/issi/is31fl3733.c')
-rw-r--r--drivers/issi/is31fl3733.c177
1 files changed, 80 insertions, 97 deletions
diff --git a/drivers/issi/is31fl3733.c b/drivers/issi/is31fl3733.c
index aa247f4e8..968f072de 100644
--- a/drivers/issi/is31fl3733.c
+++ b/drivers/issi/is31fl3733.c
@@ -17,11 +17,11 @@
17 */ 17 */
18 18
19#ifdef __AVR__ 19#ifdef __AVR__
20#include <avr/interrupt.h> 20# include <avr/interrupt.h>
21#include <avr/io.h> 21# include <avr/io.h>
22#include <util/delay.h> 22# include <util/delay.h>
23#else 23#else
24#include "wait.h" 24# include "wait.h"
25#endif 25#endif
26 26
27#include "is31fl3733.h" 27#include "is31fl3733.h"
@@ -46,23 +46,23 @@
46#define ISSI_INTERRUPTMASKREGISTER 0xF0 46#define ISSI_INTERRUPTMASKREGISTER 0xF0
47#define ISSI_INTERRUPTSTATUSREGISTER 0xF1 47#define ISSI_INTERRUPTSTATUSREGISTER 0xF1
48 48
49#define ISSI_PAGE_LEDCONTROL 0x00 //PG0 49#define ISSI_PAGE_LEDCONTROL 0x00 // PG0
50#define ISSI_PAGE_PWM 0x01 //PG1 50#define ISSI_PAGE_PWM 0x01 // PG1
51#define ISSI_PAGE_AUTOBREATH 0x02 //PG2 51#define ISSI_PAGE_AUTOBREATH 0x02 // PG2
52#define ISSI_PAGE_FUNCTION 0x03 //PG3 52#define ISSI_PAGE_FUNCTION 0x03 // PG3
53 53
54#define ISSI_REG_CONFIGURATION 0x00 //PG3 54#define ISSI_REG_CONFIGURATION 0x00 // PG3
55#define ISSI_REG_GLOBALCURRENT 0x01 //PG3 55#define ISSI_REG_GLOBALCURRENT 0x01 // PG3
56#define ISSI_REG_RESET 0x11// PG3 56#define ISSI_REG_RESET 0x11 // PG3
57#define ISSI_REG_SWPULLUP 0x0F //PG3 57#define ISSI_REG_SWPULLUP 0x0F // PG3
58#define ISSI_REG_CSPULLUP 0x10 //PG3 58#define ISSI_REG_CSPULLUP 0x10 // PG3
59 59
60#ifndef ISSI_TIMEOUT 60#ifndef ISSI_TIMEOUT
61 #define ISSI_TIMEOUT 100 61# define ISSI_TIMEOUT 100
62#endif 62#endif
63 63
64#ifndef ISSI_PERSISTENCE 64#ifndef ISSI_PERSISTENCE
65 #define ISSI_PERSISTENCE 0 65# define ISSI_PERSISTENCE 0
66#endif 66#endif
67 67
68// Transfer buffer for TWITransmitData() 68// Transfer buffer for TWITransmitData()
@@ -75,56 +75,51 @@ uint8_t g_twi_transfer_buffer[20];
75// buffers and the transfers in IS31FL3733_write_pwm_buffer() but it's 75// buffers and the transfers in IS31FL3733_write_pwm_buffer() but it's
76// probably not worth the extra complexity. 76// probably not worth the extra complexity.
77uint8_t g_pwm_buffer[DRIVER_COUNT][192]; 77uint8_t g_pwm_buffer[DRIVER_COUNT][192];
78bool g_pwm_buffer_update_required[DRIVER_COUNT] = { false }; 78bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false};
79 79
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 ) 83void IS31FL3733_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
84{
85 g_twi_transfer_buffer[0] = reg; 84 g_twi_transfer_buffer[0] = reg;
86 g_twi_transfer_buffer[1] = data; 85 g_twi_transfer_buffer[1] = data;
87 86
88 #if ISSI_PERSISTENCE > 0 87#if ISSI_PERSISTENCE > 0
89 for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { 88 for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
90 if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0) 89 if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0) break;
91 break;
92 } 90 }
93 #else 91#else
94 i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT); 92 i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
95 #endif 93#endif
96} 94}
97 95
98void IS31FL3733_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) 96void IS31FL3733_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
99{
100 // assumes PG1 is already selected 97 // assumes PG1 is already selected
101 98
102 // transmit PWM registers in 12 transfers of 16 bytes 99 // transmit PWM registers in 12 transfers of 16 bytes
103 // g_twi_transfer_buffer[] is 20 bytes 100 // g_twi_transfer_buffer[] is 20 bytes
104 101
105 // iterate over the pwm_buffer contents at 16 byte intervals 102 // iterate over the pwm_buffer contents at 16 byte intervals
106 for ( int i = 0; i < 192; i += 16 ) { 103 for (int i = 0; i < 192; i += 16) {
107 g_twi_transfer_buffer[0] = i; 104 g_twi_transfer_buffer[0] = i;
108 // copy the data from i to i+15 105 // copy the data from i to i+15
109 // device will auto-increment register for data after the first byte 106 // device will auto-increment register for data after the first byte
110 // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer 107 // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer
111 for ( int j = 0; j < 16; j++ ) { 108 for (int j = 0; j < 16; j++) {
112 g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; 109 g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
113 } 110 }
114 111
115 #if ISSI_PERSISTENCE > 0 112#if ISSI_PERSISTENCE > 0
116 for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { 113 for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
117 if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0) 114 if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0) break;
118 break; 115 }
119 } 116#else
120 #else 117 i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT);
121 i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT); 118#endif
122 #endif
123 } 119 }
124} 120}
125 121
126void IS31FL3733_init( uint8_t addr, uint8_t sync) 122void IS31FL3733_init(uint8_t addr, uint8_t sync) {
127{
128 // In order to avoid the LEDs being driven with garbage data 123 // In order to avoid the LEDs being driven with garbage data
129 // in the LED driver's PWM registers, shutdown is enabled last. 124 // in the LED driver's PWM registers, shutdown is enabled last.
130 // Set up the mode and other settings, clear the PWM registers, 125 // Set up the mode and other settings, clear the PWM registers,
@@ -132,120 +127,108 @@ void IS31FL3733_init( uint8_t addr, uint8_t sync)
132 // Sync is passed so set it according to the datasheet. 127 // Sync is passed so set it according to the datasheet.
133 128
134 // Unlock the command register. 129 // Unlock the command register.
135 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); 130 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
136 131
137 // Select PG0 132 // Select PG0
138 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL ); 133 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
139 // Turn off all LEDs. 134 // Turn off all LEDs.
140 for ( int i = 0x00; i <= 0x17; i++ ) 135 for (int i = 0x00; i <= 0x17; i++) {
141 { 136 IS31FL3733_write_register(addr, i, 0x00);
142 IS31FL3733_write_register( addr, i, 0x00 );
143 } 137 }
144 138
145 // Unlock the command register. 139 // Unlock the command register.
146 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); 140 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
147 141
148 // Select PG1 142 // Select PG1
149 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM ); 143 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
150 // Set PWM on all LEDs to 0 144 // Set PWM on all LEDs to 0
151 // No need to setup Breath registers to PWM as that is the default. 145 // No need to setup Breath registers to PWM as that is the default.
152 for ( int i = 0x00; i <= 0xBF; i++ ) 146 for (int i = 0x00; i <= 0xBF; i++) {
153 { 147 IS31FL3733_write_register(addr, i, 0x00);
154 IS31FL3733_write_register( addr, i, 0x00 );
155 } 148 }
156 149
157 // Unlock the command register. 150 // Unlock the command register.
158 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); 151 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
159 152
160 // Select PG3 153 // Select PG3
161 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION ); 154 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION);
162 // Set global current to maximum. 155 // Set global current to maximum.
163 IS31FL3733_write_register( addr, ISSI_REG_GLOBALCURRENT, 0xFF ); 156 IS31FL3733_write_register(addr, ISSI_REG_GLOBALCURRENT, 0xFF);
164 // Disable software shutdown. 157 // Disable software shutdown.
165 IS31FL3733_write_register( addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01 ); 158 IS31FL3733_write_register(addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01);
166 159
167 // Wait 10ms to ensure the device has woken up. 160// Wait 10ms to ensure the device has woken up.
168 #ifdef __AVR__ 161#ifdef __AVR__
169 _delay_ms( 10 ); 162 _delay_ms(10);
170 #else 163#else
171 wait_ms(10); 164 wait_ms(10);
172 #endif 165#endif
173} 166}
174 167
175void IS31FL3733_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) 168void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
176{ 169 if (index >= 0 && index < DRIVER_LED_TOTAL) {
177 if ( index >= 0 && index < DRIVER_LED_TOTAL ) {
178 is31_led led = g_is31_leds[index]; 170 is31_led led = g_is31_leds[index];
179 171
180 g_pwm_buffer[led.driver][led.r] = red; 172 g_pwm_buffer[led.driver][led.r] = red;
181 g_pwm_buffer[led.driver][led.g] = green; 173 g_pwm_buffer[led.driver][led.g] = green;
182 g_pwm_buffer[led.driver][led.b] = blue; 174 g_pwm_buffer[led.driver][led.b] = blue;
183 g_pwm_buffer_update_required[led.driver] = true; 175 g_pwm_buffer_update_required[led.driver] = true;
184 } 176 }
185} 177}
186 178
187void IS31FL3733_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) 179void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
188{ 180 for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
189 for ( int i = 0; i < DRIVER_LED_TOTAL; i++ ) 181 IS31FL3733_set_color(i, red, green, blue);
190 {
191 IS31FL3733_set_color( i, red, green, blue );
192 } 182 }
193} 183}
194 184
195void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, bool blue ) 185void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
196{
197 is31_led led = g_is31_leds[index]; 186 is31_led led = g_is31_leds[index];
198 187
199 uint8_t control_register_r = led.r / 8; 188 uint8_t control_register_r = led.r / 8;
200 uint8_t control_register_g = led.g / 8; 189 uint8_t control_register_g = led.g / 8;
201 uint8_t control_register_b = led.b / 8; 190 uint8_t control_register_b = led.b / 8;
202 uint8_t bit_r = led.r % 8; 191 uint8_t bit_r = led.r % 8;
203 uint8_t bit_g = led.g % 8; 192 uint8_t bit_g = led.g % 8;
204 uint8_t bit_b = led.b % 8; 193 uint8_t bit_b = led.b % 8;
205 194
206 if ( red ) { 195 if (red) {
207 g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r); 196 g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
208 } else { 197 } else {
209 g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r); 198 g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
210 } 199 }
211 if ( green ) { 200 if (green) {
212 g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g); 201 g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
213 } else { 202 } else {
214 g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g); 203 g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
215 } 204 }
216 if ( blue ) { 205 if (blue) {
217 g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b); 206 g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
218 } else { 207 } else {
219 g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); 208 g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
220 } 209 }
221 210
222 g_led_control_registers_update_required[led.driver] = true; 211 g_led_control_registers_update_required[led.driver] = true;
223
224} 212}
225 213
226void IS31FL3733_update_pwm_buffers( uint8_t addr, uint8_t index ) 214void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index) {
227{ 215 if (g_pwm_buffer_update_required[index]) {
228 if ( g_pwm_buffer_update_required[index] )
229 {
230 // Firstly we need to unlock the command register and select PG1 216 // Firstly we need to unlock the command register and select PG1
231 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); 217 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
232 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM ); 218 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
233 219
234 IS31FL3733_write_pwm_buffer( addr, g_pwm_buffer[index] ); 220 IS31FL3733_write_pwm_buffer(addr, g_pwm_buffer[index]);
235 } 221 }
236 g_pwm_buffer_update_required[index] = false; 222 g_pwm_buffer_update_required[index] = false;
237} 223}
238 224
239void IS31FL3733_update_led_control_registers( uint8_t addr, uint8_t index ) 225void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index) {
240{ 226 if (g_led_control_registers_update_required[index]) {
241 if ( g_led_control_registers_update_required[index] )
242 {
243 // Firstly we need to unlock the command register and select PG0 227 // Firstly we need to unlock the command register and select PG0
244 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 ); 228 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
245 IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL ); 229 IS31FL3733_write_register(addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
246 for ( int i=0; i<24; i++ ) 230 for (int i = 0; i < 24; i++) {
247 { 231 IS31FL3733_write_register(addr, i, g_led_control_registers[index][i]);
248 IS31FL3733_write_register(addr, i, g_led_control_registers[index][i] );
249 } 232 }
250 } 233 }
251 g_led_control_registers_update_required[index] = false; 234 g_led_control_registers_update_required[index] = false;