From c371cb3bc4c42694a6b8a2325af45f83fb07da47 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 22 Feb 2024 17:51:49 +1100 Subject: [PATCH] IS31FL3729 updates (#23109) --- drivers/led/issi/is31fl3729-mono.c | 117 +++++----- drivers/led/issi/is31fl3729-mono.h | 339 +++++++++++++++-------------- drivers/led/issi/is31fl3729.c | 117 +++++----- drivers/led/issi/is31fl3729.h | 339 +++++++++++++++-------------- 4 files changed, 462 insertions(+), 450 deletions(-) diff --git a/drivers/led/issi/is31fl3729-mono.c b/drivers/led/issi/is31fl3729-mono.c index 1617dd40a7..13d5146877 100644 --- a/drivers/led/issi/is31fl3729-mono.c +++ b/drivers/led/issi/is31fl3729-mono.c @@ -18,6 +18,7 @@ #include "is31fl3729-mono.h" #include "i2c_master.h" +#include "gpio.h" #include "wait.h" #define IS31FL3729_PWM_REGISTER_COUNT 143 @@ -39,26 +40,43 @@ # define IS31FL3729_GLOBAL_CURRENT 0x40 #endif -#ifndef IS31FL3729_PULLDOWNUP -# define IS31FL3729_PULLDOWNUP 0x33 +#ifndef IS31FL3729_SW_PULLDOWN +# define IS31FL3729_SW_PULLDOWN IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF +#endif + +#ifndef IS31FL3729_CS_PULLUP +# define IS31FL3729_CS_PULLUP IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF #endif #ifndef IS31FL3729_SPREAD_SPECTRUM -# define IS31FL3729_SPREAD_SPECTRUM IS31FL3729_SSP_DISABLE +# define IS31FL3729_SPREAD_SPECTRUM IS31FL3729_SPREAD_SPECTRUM_DISABLE #endif #ifndef IS31FL3729_SPREAD_SPECTRUM_RANGE -# define IS31FL3729_SPREAD_SPECTRUM_RANGE IS31FL3729_RNG_5_PERCENT +# define IS31FL3729_SPREAD_SPECTRUM_RANGE IS31FL3729_SPREAD_SPECTRUM_RANGE_5_PERCENT #endif #ifndef IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME -# define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME IS31FL3729_CLT_1980_US +# define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1980_US #endif #ifndef IS31FL3729_PWM_FREQUENCY # define IS31FL3729_PWM_FREQUENCY IS31FL3729_PWM_FREQUENCY_32K_HZ #endif +const uint8_t i2c_addresses[IS31FL3729_DRIVER_COUNT] = { + IS31FL3729_I2C_ADDRESS_1, +#ifdef IS31FL3729_I2C_ADDRESS_2 + IS31FL3729_I2C_ADDRESS_2, +# ifdef IS31FL3729_I2C_ADDRESS_3 + IS31FL3729_I2C_ADDRESS_3, +# ifdef IS31FL3729_I2C_ADDRESS_4 + IS31FL3729_I2C_ADDRESS_4, +# endif +# endif +#endif +}; + // These buffers match the PWM & scaling registers. // Storing them like this is optimal for I2C transfers to the registers. typedef struct is31fl3729_driver_t { @@ -75,27 +93,27 @@ is31fl3729_driver_t driver_buffers[IS31FL3729_DRIVER_COUNT] = {{ .scaling_buffer_dirty = false, }}; -void is31fl3729_write_register(uint8_t addr, uint8_t reg, uint8_t data) { +void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data) { #if IS31FL3729_I2C_PERSISTENCE > 0 for (uint8_t i = 0; i < IS31FL3729_I2C_PERSISTENCE; i++) { - if (i2c_write_register(addr << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; + if (i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; } #else - i2c_write_register(addr << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT); + i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT); #endif } -void is31fl3729_write_pwm_buffer(uint8_t addr, uint8_t index) { - // Transmit PWM registers in 9 transfers of 16 bytes. +void is31fl3729_write_pwm_buffer(uint8_t index) { + // Transmit PWM registers in 11 transfers of 13 bytes. - // Iterate over the pwm_buffer contents at 16 byte intervals. - for (uint8_t i = 0; i <= IS31FL3729_PWM_REGISTER_COUNT; i += 16) { + // Iterate over the pwm_buffer contents at 13 byte intervals. + for (uint8_t i = 0; i <= IS31FL3729_PWM_REGISTER_COUNT; i += 13) { #if IS31FL3729_I2C_PERSISTENCE > 0 for (uint8_t j = 0; j < IS31FL3729_I2C_PERSISTENCE; j++) { - if (i2c_write_register(addr << 1, i, driver_buffers[index].pwm_buffer + i, 16, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; + if (i2c_write_register(i2c_addresses[index] << 1, IS31FL3729_REG_PWM + i, driver_buffers[index].pwm_buffer + i, 13, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; } #else - i2c_write_register(addr << 1, i, driver_buffers[index].pwm_buffer + i, 16, IS31FL3729_I2C_TIMEOUT); + i2c_write_register(i2c_addresses[index] << 1, IS31FL3729_REG_PWM + i, driver_buffers[index].pwm_buffer + i, 13, IS31FL3729_I2C_TIMEOUT); #endif } } @@ -103,53 +121,35 @@ void is31fl3729_write_pwm_buffer(uint8_t addr, uint8_t index) { void is31fl3729_init_drivers(void) { i2c_init(); - is31fl3729_init(IS31FL3729_I2C_ADDRESS_1); -#if defined(IS31FL3729_I2C_ADDRESS_2) - is31fl3729_init(IS31FL3729_I2C_ADDRESS_2); -# if defined(IS31FL3729_I2C_ADDRESS_3) - is31fl3729_init(IS31FL3729_I2C_ADDRESS_3); -# if defined(IS31FL3729_I2C_ADDRESS_4) - is31fl3729_init(IS31FL3729_I2C_ADDRESS_4); -# endif -# endif +#if defined(IS31FL3729_SDB_PIN) + gpio_set_pin_output(IS31FL3729_SDB_PIN); + gpio_write_pin_high(IS31FL3729_SDB_PIN); #endif + for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) { + is31fl3729_init(i); + } + for (int i = 0; i < IS31FL3729_LED_COUNT; i++) { is31fl3729_set_scaling_register(i, 0xFF); } - is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_1, 0); -#if defined(IS31FL3729_I2C_ADDRESS_2) - is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_2, 1); -# if defined(IS31FL3729_I2C_ADDRESS_3) - is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_3, 2); -# if defined(IS31FL3729_I2C_ADDRESS_4) - is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_4, 3); -# endif -# endif -#endif + for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) { + is31fl3729_update_scaling_registers(i); + } } -void is31fl3729_init(uint8_t addr) { +void is31fl3729_init(uint8_t index) { // In order to avoid the LEDs being driven with garbage data // in the LED driver's PWM registers, shutdown is enabled last. // Set up the mode and other settings, clear the PWM registers, // then disable software shutdown. - // Set Pull up & Down for SWx CSy - is31fl3729_write_register(addr, IS31FL3729_REG_PULLDOWNUP, IS31FL3729_PULLDOWNUP); - - // Set Spread Spectrum Register if applicable - is31fl3729_write_register(addr, IS31FL3729_REG_SPREAD_SPECTRUM, ((IS31FL3729_SPREAD_SPECTRUM & 0b1) << 4) | ((IS31FL3729_SPREAD_SPECTRUM_RANGE & 0b11) << 2) | (IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME & 0b11)); - - // Set PWM Frequency Register if applicable - is31fl3729_write_register(addr, IS31FL3729_REG_PWM_FREQUENCY, IS31FL3729_PWM_FREQUENCY); - - // Set Golbal Current Control Register - is31fl3729_write_register(addr, IS31FL3729_REG_GLOBAL_CURRENT, IS31FL3729_GLOBAL_CURRENT); - - // Set to Normal operation - is31fl3729_write_register(addr, IS31FL3729_REG_CONFIGURATION, IS31FL3729_CONFIGURATION); + is31fl3729_write_register(index, IS31FL3729_REG_PULLDOWNUP, ((IS31FL3729_SW_PULLDOWN & 0b111) << 4) | (IS31FL3729_CS_PULLUP & 0b111)); + is31fl3729_write_register(index, IS31FL3729_REG_SPREAD_SPECTRUM, ((IS31FL3729_SPREAD_SPECTRUM & 0b1) << 4) | ((IS31FL3729_SPREAD_SPECTRUM_RANGE & 0b11) << 2) | (IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME & 0b11)); + is31fl3729_write_register(index, IS31FL3729_REG_PWM_FREQUENCY, IS31FL3729_PWM_FREQUENCY); + is31fl3729_write_register(index, IS31FL3729_REG_GLOBAL_CURRENT, IS31FL3729_GLOBAL_CURRENT); + is31fl3729_write_register(index, IS31FL3729_REG_CONFIGURATION, IS31FL3729_CONFIGURATION); // Wait 10ms to ensure the device has woken up. wait_ms(10); @@ -188,18 +188,18 @@ void is31fl3729_set_scaling_register(uint8_t index, uint8_t value) { driver_buffers[led.driver].scaling_buffer_dirty = true; } -void is31fl3729_update_pwm_buffers(uint8_t addr, uint8_t index) { +void is31fl3729_update_pwm_buffers(uint8_t index) { if (driver_buffers[index].pwm_buffer_dirty) { - is31fl3729_write_pwm_buffer(addr, index); + is31fl3729_write_pwm_buffer(index); driver_buffers[index].pwm_buffer_dirty = false; } } -void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index) { +void is31fl3729_update_scaling_registers(uint8_t index) { if (driver_buffers[index].scaling_buffer_dirty) { for (uint8_t i = 0; i < IS31FL3729_SCALING_REGISTER_COUNT; i++) { - is31fl3729_write_register(addr, IS31FL3729_REG_SCALING + i, driver_buffers[index].scaling_buffer[i]); + is31fl3729_write_register(index, IS31FL3729_REG_SCALING + i, driver_buffers[index].scaling_buffer[i]); } driver_buffers[index].scaling_buffer_dirty = false; @@ -207,14 +207,7 @@ void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index) { } void is31fl3729_flush(void) { - is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_1, 0); -#if defined(IS31FL3729_I2C_ADDRESS_2) - is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_2, 1); -# if defined(IS31FL3729_I2C_ADDRESS_3) - is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_3, 2); -# if defined(IS31FL3729_I2C_ADDRESS_4) - is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_4, 3); -# endif -# endif -#endif + for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) { + is31fl3729_update_pwm_buffers(i); + } } diff --git a/drivers/led/issi/is31fl3729-mono.h b/drivers/led/issi/is31fl3729-mono.h index 815c200fd9..9afcde84b3 100644 --- a/drivers/led/issi/is31fl3729-mono.h +++ b/drivers/led/issi/is31fl3729-mono.h @@ -23,6 +23,7 @@ #include "progmem.h" #include "util.h" +#define IS31FL3729_REG_PWM 0x01 #define IS31FL3729_REG_SCALING 0x90 #define IS31FL3729_REG_CONFIGURATION 0xA0 #define IS31FL3729_REG_GLOBAL_CURRENT 0xA1 @@ -58,8 +59,8 @@ typedef struct is31fl3729_led_t { extern const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT]; void is31fl3729_init_drivers(void); -void is31fl3729_init(uint8_t addr); -void is31fl3729_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3729_init(uint8_t index); +void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data); void is31fl3729_set_value(int index, uint8_t value); void is31fl3729_set_value_all(uint8_t value); @@ -70,26 +71,42 @@ void is31fl3729_set_scaling_register(uint8_t index, uint8_t value); // (eg. from a timer interrupt). // Call this while idle (in between matrix scans). // If the buffer is dirty, it will update the driver with the buffer. -void is31fl3729_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index); +void is31fl3729_update_pwm_buffers(uint8_t index); +void is31fl3729_update_scaling_registers(uint8_t index); void is31fl3729_flush(void); -// Noise reduction using Spread Spectrum register -#define IS31FL3729_SSP_DISABLE 0b0 -#define IS31FL3729_SSP_ENABLE 0b1 +#define IS31FL3729_SW_PULLDOWN_0_OHM 0b000 +#define IS31FL3729_SW_PULLDOWN_0K5_OHM_SW_OFF 0b001 +#define IS31FL3729_SW_PULLDOWN_1K_OHM_SW_OFF 0b010 +#define IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF 0b011 +#define IS31FL3729_SW_PULLDOWN_1K_OHM 0b100 +#define IS31FL3729_SW_PULLDOWN_2K_OHM 0b101 +#define IS31FL3729_SW_PULLDOWN_4K_OHM 0b110 +#define IS31FL3729_SW_PULLDOWN_8K_OHM 0b111 -#define IS31FL3729_RNG_5_PERCENT 0b00 -#define IS31FL3729_RNG_15_PERCENT 0b01 -#define IS31FL3729_RNG_24_PERCENT 0b10 -#define IS31FL3729_RNG_34_PERCENT 0b11 +#define IS31FL3729_CS_PULLUP_0_OHM 0b000 +#define IS31FL3729_CS_PULLUP_0K5_OHM_CS_OFF 0b001 +#define IS31FL3729_CS_PULLUP_1K_OHM_CS_OFF 0b010 +#define IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF 0b011 +#define IS31FL3729_CS_PULLUP_1K_OHM 0b100 +#define IS31FL3729_CS_PULLUP_2K_OHM 0b101 +#define IS31FL3729_CS_PULLUP_4K_OHM 0b110 +#define IS31FL3729_CS_PULLUP_8K_OHM 0b111 -#define IS31FL3729_CLT_1980_US 0b00 -#define IS31FL3729_CLT_1200_US 0b01 -#define IS31FL3729_CLT_820_US 0b10 -#define IS31FL3729_CLT_660_US 0b11 +#define IS31FL3729_SPREAD_SPECTRUM_DISABLE 0b0 +#define IS31FL3729_SPREAD_SPECTRUM_ENABLE 0b1 + +#define IS31FL3729_SPREAD_SPECTRUM_RANGE_5_PERCENT 0b00 +#define IS31FL3729_SPREAD_SPECTRUM_RANGE_15_PERCENT 0b01 +#define IS31FL3729_SPREAD_SPECTRUM_RANGE_24_PERCENT 0b10 +#define IS31FL3729_SPREAD_SPECTRUM_RANGE_34_PERCENT 0b11 + +#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1980_US 0b00 +#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1200_US 0b01 +#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_820_US 0b10 +#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_660_US 0b11 -// Noise reduction using PWM Frequency register #define IS31FL3729_PWM_FREQUENCY_55K_HZ 0b000 #define IS31FL3729_PWM_FREQUENCY_32K_HZ 0b001 #define IS31FL3729_PWM_FREQUENCY_4K_HZ 0b010 @@ -99,7 +116,6 @@ void is31fl3729_flush(void); #define IS31FL3729_PWM_FREQUENCY_250_HZ 0b110 #define IS31FL3729_PWM_FREQUENCY_80K_HZ 0b111 -// Change SWx Setting using Configuration register #define IS31FL3729_CONFIG_SWS_15_9 0x01 // 15 CS x 9 SW matrix #define IS31FL3729_CONFIG_SWS_16_8 0x11 // 16 CS x 8 SW matrix #define IS31FL3729_CONFIG_SWS_16_7 0x21 // 16 CS x 7 SW matrix @@ -109,157 +125,154 @@ void is31fl3729_flush(void); #define IS31FL3729_CONFIG_SWS_16_3 0x61 // 16 CS x 3 SW matrix #define IS31FL3729_CONFIG_SWS_16_2 0x71 // 16 CS x 2 SW matrix -// Map CS SW locations to order in PWM / Scaling buffers -// This matches the ORDER in the Datasheet Register not the POSITION -// It will always count from 0x01 to (ISSI_MAX_LEDS - 1) -#define SW1_CS1 0x01 -#define SW1_CS2 0x02 -#define SW1_CS3 0x03 -#define SW1_CS4 0x04 -#define SW1_CS5 0x05 -#define SW1_CS6 0x06 -#define SW1_CS7 0x07 -#define SW1_CS8 0x08 -#define SW1_CS9 0x09 -#define SW1_CS10 0x0A -#define SW1_CS11 0x0B -#define SW1_CS12 0x0C -#define SW1_CS13 0x0D -#define SW1_CS14 0x0E -#define SW1_CS15 0x0F -#define SW1_CS16 0x10 +#define SW1_CS1 0x00 +#define SW1_CS2 0x01 +#define SW1_CS3 0x02 +#define SW1_CS4 0x03 +#define SW1_CS5 0x04 +#define SW1_CS6 0x05 +#define SW1_CS7 0x06 +#define SW1_CS8 0x07 +#define SW1_CS9 0x08 +#define SW1_CS10 0x09 +#define SW1_CS11 0x0A +#define SW1_CS12 0x0B +#define SW1_CS13 0x0C +#define SW1_CS14 0x0D +#define SW1_CS15 0x0E +#define SW1_CS16 0x0F -#define SW2_CS1 0x11 -#define SW2_CS2 0x12 -#define SW2_CS3 0x13 -#define SW2_CS4 0x14 -#define SW2_CS5 0x15 -#define SW2_CS6 0x16 -#define SW2_CS7 0x17 -#define SW2_CS8 0x18 -#define SW2_CS9 0x19 -#define SW2_CS10 0x1A -#define SW2_CS11 0x1B -#define SW2_CS12 0x1C -#define SW2_CS13 0x1D -#define SW2_CS14 0x1E -#define SW2_CS15 0x1F -#define SW2_CS16 0x20 +#define SW2_CS1 0x10 +#define SW2_CS2 0x11 +#define SW2_CS3 0x12 +#define SW2_CS4 0x13 +#define SW2_CS5 0x14 +#define SW2_CS6 0x15 +#define SW2_CS7 0x16 +#define SW2_CS8 0x17 +#define SW2_CS9 0x18 +#define SW2_CS10 0x19 +#define SW2_CS11 0x1A +#define SW2_CS12 0x1B +#define SW2_CS13 0x1C +#define SW2_CS14 0x1D +#define SW2_CS15 0x1E +#define SW2_CS16 0x1F -#define SW3_CS1 0x21 -#define SW3_CS2 0x22 -#define SW3_CS3 0x23 -#define SW3_CS4 0x24 -#define SW3_CS5 0x25 -#define SW3_CS6 0x26 -#define SW3_CS7 0x27 -#define SW3_CS8 0x28 -#define SW3_CS9 0x29 -#define SW3_CS10 0x2A -#define SW3_CS11 0x2B -#define SW3_CS12 0x2C -#define SW3_CS13 0x2D -#define SW3_CS14 0x2E -#define SW3_CS15 0x2F -#define SW3_CS16 0x30 +#define SW3_CS1 0x20 +#define SW3_CS2 0x21 +#define SW3_CS3 0x22 +#define SW3_CS4 0x23 +#define SW3_CS5 0x24 +#define SW3_CS6 0x25 +#define SW3_CS7 0x26 +#define SW3_CS8 0x27 +#define SW3_CS9 0x28 +#define SW3_CS10 0x29 +#define SW3_CS11 0x2A +#define SW3_CS12 0x2B +#define SW3_CS13 0x2C +#define SW3_CS14 0x2D +#define SW3_CS15 0x2E +#define SW3_CS16 0x2F -#define SW4_CS1 0x31 -#define SW4_CS2 0x32 -#define SW4_CS3 0x33 -#define SW4_CS4 0x34 -#define SW4_CS5 0x35 -#define SW4_CS6 0x36 -#define SW4_CS7 0x37 -#define SW4_CS8 0x38 -#define SW4_CS9 0x39 -#define SW4_CS10 0x3A -#define SW4_CS11 0x3B -#define SW4_CS12 0x3C -#define SW4_CS13 0x3D -#define SW4_CS14 0x3E -#define SW4_CS15 0x3F -#define SW4_CS16 0x40 +#define SW4_CS1 0x30 +#define SW4_CS2 0x31 +#define SW4_CS3 0x32 +#define SW4_CS4 0x33 +#define SW4_CS5 0x34 +#define SW4_CS6 0x35 +#define SW4_CS7 0x36 +#define SW4_CS8 0x37 +#define SW4_CS9 0x38 +#define SW4_CS10 0x39 +#define SW4_CS11 0x3A +#define SW4_CS12 0x3B +#define SW4_CS13 0x3C +#define SW4_CS14 0x3D +#define SW4_CS15 0x3E +#define SW4_CS16 0x3F -#define SW5_CS1 0x41 -#define SW5_CS2 0x42 -#define SW5_CS3 0x43 -#define SW5_CS4 0x44 -#define SW5_CS5 0x45 -#define SW5_CS6 0x46 -#define SW5_CS7 0x47 -#define SW5_CS8 0x48 -#define SW5_CS9 0x49 -#define SW5_CS10 0x4A -#define SW5_CS11 0x4B -#define SW5_CS12 0x4C -#define SW5_CS13 0x4D -#define SW5_CS14 0x4E -#define SW5_CS15 0x4F -#define SW5_CS16 0x50 +#define SW5_CS1 0x40 +#define SW5_CS2 0x41 +#define SW5_CS3 0x42 +#define SW5_CS4 0x43 +#define SW5_CS5 0x44 +#define SW5_CS6 0x45 +#define SW5_CS7 0x46 +#define SW5_CS8 0x47 +#define SW5_CS9 0x48 +#define SW5_CS10 0x49 +#define SW5_CS11 0x4A +#define SW5_CS12 0x4B +#define SW5_CS13 0x4C +#define SW5_CS14 0x4D +#define SW5_CS15 0x4E +#define SW5_CS16 0x4F -#define SW6_CS1 0x51 -#define SW6_CS2 0x52 -#define SW6_CS3 0x53 -#define SW6_CS4 0x54 -#define SW6_CS5 0x55 -#define SW6_CS6 0x56 -#define SW6_CS7 0x57 -#define SW6_CS8 0x58 -#define SW6_CS9 0x59 -#define SW6_CS10 0x5A -#define SW6_CS11 0x5B -#define SW6_CS12 0x5C -#define SW6_CS13 0x5D -#define SW6_CS14 0x5E -#define SW6_CS15 0x5F -#define SW6_CS16 0x60 +#define SW6_CS1 0x50 +#define SW6_CS2 0x51 +#define SW6_CS3 0x52 +#define SW6_CS4 0x53 +#define SW6_CS5 0x54 +#define SW6_CS6 0x55 +#define SW6_CS7 0x56 +#define SW6_CS8 0x57 +#define SW6_CS9 0x58 +#define SW6_CS10 0x59 +#define SW6_CS11 0x5A +#define SW6_CS12 0x5B +#define SW6_CS13 0x5C +#define SW6_CS14 0x5D +#define SW6_CS15 0x5E +#define SW6_CS16 0x5F -#define SW7_CS1 0x61 -#define SW7_CS2 0x62 -#define SW7_CS3 0x63 -#define SW7_CS4 0x64 -#define SW7_CS5 0x65 -#define SW7_CS6 0x66 -#define SW7_CS7 0x67 -#define SW7_CS8 0x68 -#define SW7_CS9 0x69 -#define SW7_CS10 0x6A -#define SW7_CS11 0x6B -#define SW7_CS12 0x6C -#define SW7_CS13 0x6D -#define SW7_CS14 0x6E -#define SW7_CS15 0x6F -#define SW7_CS16 0x70 +#define SW7_CS1 0x60 +#define SW7_CS2 0x61 +#define SW7_CS3 0x62 +#define SW7_CS4 0x63 +#define SW7_CS5 0x64 +#define SW7_CS6 0x65 +#define SW7_CS7 0x66 +#define SW7_CS8 0x67 +#define SW7_CS9 0x68 +#define SW7_CS10 0x69 +#define SW7_CS11 0x6A +#define SW7_CS12 0x6B +#define SW7_CS13 0x6C +#define SW7_CS14 0x6D +#define SW7_CS15 0x6E +#define SW7_CS16 0x6F -#define SW8_CS1 0x71 -#define SW8_CS2 0x72 -#define SW8_CS3 0x73 -#define SW8_CS4 0x74 -#define SW8_CS5 0x75 -#define SW8_CS6 0x76 -#define SW8_CS7 0x77 -#define SW8_CS8 0x78 -#define SW8_CS9 0x79 -#define SW8_CS10 0x7A -#define SW8_CS11 0x7B -#define SW8_CS12 0x7C -#define SW8_CS13 0x7D -#define SW8_CS14 0x7E -#define SW8_CS15 0x7F -#define SW8_CS16 0x80 +#define SW8_CS1 0x70 +#define SW8_CS2 0x71 +#define SW8_CS3 0x72 +#define SW8_CS4 0x73 +#define SW8_CS5 0x74 +#define SW8_CS6 0x75 +#define SW8_CS7 0x76 +#define SW8_CS8 0x77 +#define SW8_CS9 0x78 +#define SW8_CS10 0x79 +#define SW8_CS11 0x7A +#define SW8_CS12 0x7B +#define SW8_CS13 0x7C +#define SW8_CS14 0x7D +#define SW8_CS15 0x7E +#define SW8_CS16 0x7F -#define SW9_CS1 0x81 -#define SW9_CS2 0x82 -#define SW9_CS3 0x83 -#define SW9_CS4 0x84 -#define SW9_CS5 0x85 -#define SW9_CS6 0x86 -#define SW9_CS7 0x87 -#define SW9_CS8 0x88 -#define SW9_CS9 0x89 -#define SW9_CS10 0x8A -#define SW9_CS11 0x8B -#define SW9_CS12 0x8C -#define SW9_CS13 0x8D -#define SW9_CS14 0x8E -#define SW9_CS15 0x8F +#define SW9_CS1 0x80 +#define SW9_CS2 0x81 +#define SW9_CS3 0x82 +#define SW9_CS4 0x83 +#define SW9_CS5 0x84 +#define SW9_CS6 0x85 +#define SW9_CS7 0x86 +#define SW9_CS8 0x87 +#define SW9_CS9 0x88 +#define SW9_CS10 0x89 +#define SW9_CS11 0x8A +#define SW9_CS12 0x8B +#define SW9_CS13 0x8C +#define SW9_CS14 0x8D +#define SW9_CS15 0x8E diff --git a/drivers/led/issi/is31fl3729.c b/drivers/led/issi/is31fl3729.c index 06f2d168d0..80acb22fa2 100644 --- a/drivers/led/issi/is31fl3729.c +++ b/drivers/led/issi/is31fl3729.c @@ -18,6 +18,7 @@ #include "is31fl3729.h" #include "i2c_master.h" +#include "gpio.h" #include "wait.h" #define IS31FL3729_PWM_REGISTER_COUNT 143 @@ -39,26 +40,43 @@ # define IS31FL3729_GLOBAL_CURRENT 0x40 #endif -#ifndef IS31FL3729_PULLDOWNUP -# define IS31FL3729_PULLDOWNUP 0x33 +#ifndef IS31FL3729_SW_PULLDOWN +# define IS31FL3729_SW_PULLDOWN IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF +#endif + +#ifndef IS31FL3729_CS_PULLUP +# define IS31FL3729_CS_PULLUP IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF #endif #ifndef IS31FL3729_SPREAD_SPECTRUM -# define IS31FL3729_SPREAD_SPECTRUM IS31FL3729_SSP_DISABLE +# define IS31FL3729_SPREAD_SPECTRUM IS31FL3729_SPREAD_SPECTRUM_DISABLE #endif #ifndef IS31FL3729_SPREAD_SPECTRUM_RANGE -# define IS31FL3729_SPREAD_SPECTRUM_RANGE IS31FL3729_RNG_5_PERCENT +# define IS31FL3729_SPREAD_SPECTRUM_RANGE IS31FL3729_SPREAD_SPECTRUM_RANGE_5_PERCENT #endif #ifndef IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME -# define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME IS31FL3729_CLT_1980_US +# define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1980_US #endif #ifndef IS31FL3729_PWM_FREQUENCY # define IS31FL3729_PWM_FREQUENCY IS31FL3729_PWM_FREQUENCY_32K_HZ #endif +const uint8_t i2c_addresses[IS31FL3729_DRIVER_COUNT] = { + IS31FL3729_I2C_ADDRESS_1, +#ifdef IS31FL3729_I2C_ADDRESS_2 + IS31FL3729_I2C_ADDRESS_2, +# ifdef IS31FL3729_I2C_ADDRESS_3 + IS31FL3729_I2C_ADDRESS_3, +# ifdef IS31FL3729_I2C_ADDRESS_4 + IS31FL3729_I2C_ADDRESS_4, +# endif +# endif +#endif +}; + // These buffers match the PWM & scaling registers. // Storing them like this is optimal for I2C transfers to the registers. typedef struct is31fl3729_driver_t { @@ -75,27 +93,27 @@ is31fl3729_driver_t driver_buffers[IS31FL3729_DRIVER_COUNT] = {{ .scaling_buffer_dirty = false, }}; -void is31fl3729_write_register(uint8_t addr, uint8_t reg, uint8_t data) { +void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data) { #if IS31FL3729_I2C_PERSISTENCE > 0 for (uint8_t i = 0; i < IS31FL3729_I2C_PERSISTENCE; i++) { - if (i2c_write_register(addr << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; + if (i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; } #else - i2c_write_register(addr << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT); + i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3729_I2C_TIMEOUT); #endif } -void is31fl3729_write_pwm_buffer(uint8_t addr, uint8_t index) { - // Transmit PWM registers in 9 transfers of 16 bytes. +void is31fl3729_write_pwm_buffer(uint8_t index) { + // Transmit PWM registers in 11 transfers of 13 bytes. - // Iterate over the pwm_buffer contents at 16 byte intervals. - for (uint8_t i = 0; i <= IS31FL3729_PWM_REGISTER_COUNT; i += 16) { + // Iterate over the pwm_buffer contents at 13 byte intervals. + for (uint8_t i = 0; i <= IS31FL3729_PWM_REGISTER_COUNT; i += 13) { #if IS31FL3729_I2C_PERSISTENCE > 0 for (uint8_t j = 0; j < IS31FL3729_I2C_PERSISTENCE; j++) { - if (i2c_write_register(addr << 1, i, driver_buffers[index].pwm_buffer + i, 16, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; + if (i2c_write_register(i2c_addresses[index] << 1, IS31FL3729_REG_PWM + i, driver_buffers[index].pwm_buffer + i, 13, IS31FL3729_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break; } #else - i2c_write_register(addr << 1, i, driver_buffers[index].pwm_buffer + i, 16, IS31FL3729_I2C_TIMEOUT); + i2c_write_register(i2c_addresses[index] << 1, IS31FL3729_REG_PWM + i, driver_buffers[index].pwm_buffer + i, 13, IS31FL3729_I2C_TIMEOUT); #endif } } @@ -103,53 +121,35 @@ void is31fl3729_write_pwm_buffer(uint8_t addr, uint8_t index) { void is31fl3729_init_drivers(void) { i2c_init(); - is31fl3729_init(IS31FL3729_I2C_ADDRESS_1); -#if defined(IS31FL3729_I2C_ADDRESS_2) - is31fl3729_init(IS31FL3729_I2C_ADDRESS_2); -# if defined(IS31FL3729_I2C_ADDRESS_3) - is31fl3729_init(IS31FL3729_I2C_ADDRESS_3); -# if defined(IS31FL3729_I2C_ADDRESS_4) - is31fl3729_init(IS31FL3729_I2C_ADDRESS_4); -# endif -# endif +#if defined(IS31FL3729_SDB_PIN) + gpio_set_pin_output(IS31FL3729_SDB_PIN); + gpio_write_pin_high(IS31FL3729_SDB_PIN); #endif + for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) { + is31fl3729_init(i); + } + for (int i = 0; i < IS31FL3729_LED_COUNT; i++) { is31fl3729_set_scaling_register(i, 0xFF, 0xFF, 0xFF); } - is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_1, 0); -#if defined(IS31FL3729_I2C_ADDRESS_2) - is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_2, 1); -# if defined(IS31FL3729_I2C_ADDRESS_3) - is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_3, 2); -# if defined(IS31FL3729_I2C_ADDRESS_4) - is31fl3729_update_scaling_registers(IS31FL3729_I2C_ADDRESS_4, 3); -# endif -# endif -#endif + for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) { + is31fl3729_update_scaling_registers(i); + } } -void is31fl3729_init(uint8_t addr) { +void is31fl3729_init(uint8_t index) { // In order to avoid the LEDs being driven with garbage data // in the LED driver's PWM registers, shutdown is enabled last. // Set up the mode and other settings, clear the PWM registers, // then disable software shutdown. - // Set Pull up & Down for SWx CSy - is31fl3729_write_register(addr, IS31FL3729_REG_PULLDOWNUP, IS31FL3729_PULLDOWNUP); - - // Set Spread Spectrum Register if applicable - is31fl3729_write_register(addr, IS31FL3729_REG_SPREAD_SPECTRUM, ((IS31FL3729_SPREAD_SPECTRUM & 0b1) << 4) | ((IS31FL3729_SPREAD_SPECTRUM_RANGE & 0b11) << 2) | (IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME & 0b11)); - - // Set PWM Frequency Register if applicable - is31fl3729_write_register(addr, IS31FL3729_REG_PWM_FREQUENCY, IS31FL3729_PWM_FREQUENCY); - - // Set Golbal Current Control Register - is31fl3729_write_register(addr, IS31FL3729_REG_GLOBAL_CURRENT, IS31FL3729_GLOBAL_CURRENT); - - // Set to Normal operation - is31fl3729_write_register(addr, IS31FL3729_REG_CONFIGURATION, IS31FL3729_CONFIGURATION); + is31fl3729_write_register(index, IS31FL3729_REG_PULLDOWNUP, ((IS31FL3729_SW_PULLDOWN & 0b111) << 4) | (IS31FL3729_CS_PULLUP & 0b111)); + is31fl3729_write_register(index, IS31FL3729_REG_SPREAD_SPECTRUM, ((IS31FL3729_SPREAD_SPECTRUM & 0b1) << 4) | ((IS31FL3729_SPREAD_SPECTRUM_RANGE & 0b11) << 2) | (IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME & 0b11)); + is31fl3729_write_register(index, IS31FL3729_REG_PWM_FREQUENCY, IS31FL3729_PWM_FREQUENCY); + is31fl3729_write_register(index, IS31FL3729_REG_GLOBAL_CURRENT, IS31FL3729_GLOBAL_CURRENT); + is31fl3729_write_register(index, IS31FL3729_REG_CONFIGURATION, IS31FL3729_CONFIGURATION); // Wait 10ms to ensure the device has woken up. wait_ms(10); @@ -194,18 +194,18 @@ void is31fl3729_set_scaling_register(uint8_t index, uint8_t red, uint8_t green, driver_buffers[led.driver].scaling_buffer_dirty = true; } -void is31fl3729_update_pwm_buffers(uint8_t addr, uint8_t index) { +void is31fl3729_update_pwm_buffers(uint8_t index) { if (driver_buffers[index].pwm_buffer_dirty) { - is31fl3729_write_pwm_buffer(addr, index); + is31fl3729_write_pwm_buffer(index); driver_buffers[index].pwm_buffer_dirty = false; } } -void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index) { +void is31fl3729_update_scaling_registers(uint8_t index) { if (driver_buffers[index].scaling_buffer_dirty) { for (uint8_t i = 0; i < IS31FL3729_SCALING_REGISTER_COUNT; i++) { - is31fl3729_write_register(addr, IS31FL3729_REG_SCALING + i, driver_buffers[index].scaling_buffer[i]); + is31fl3729_write_register(index, IS31FL3729_REG_SCALING + i, driver_buffers[index].scaling_buffer[i]); } driver_buffers[index].scaling_buffer_dirty = false; @@ -213,14 +213,7 @@ void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index) { } void is31fl3729_flush(void) { - is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_1, 0); -#if defined(IS31FL3729_I2C_ADDRESS_2) - is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_2, 1); -# if defined(IS31FL3729_I2C_ADDRESS_3) - is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_3, 2); -# if defined(IS31FL3729_I2C_ADDRESS_4) - is31fl3729_update_pwm_buffers(IS31FL3729_I2C_ADDRESS_4, 3); -# endif -# endif -#endif + for (uint8_t i = 0; i < IS31FL3729_DRIVER_COUNT; i++) { + is31fl3729_update_pwm_buffers(i); + } } diff --git a/drivers/led/issi/is31fl3729.h b/drivers/led/issi/is31fl3729.h index 6f2672b6a3..865c462f05 100644 --- a/drivers/led/issi/is31fl3729.h +++ b/drivers/led/issi/is31fl3729.h @@ -23,6 +23,7 @@ #include "progmem.h" #include "util.h" +#define IS31FL3729_REG_PWM 0x01 #define IS31FL3729_REG_SCALING 0x90 #define IS31FL3729_REG_CONFIGURATION 0xA0 #define IS31FL3729_REG_GLOBAL_CURRENT 0xA1 @@ -60,8 +61,8 @@ typedef struct is31fl3729_led_t { extern const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT]; void is31fl3729_init_drivers(void); -void is31fl3729_init(uint8_t addr); -void is31fl3729_write_register(uint8_t addr, uint8_t reg, uint8_t data); +void is31fl3729_init(uint8_t index); +void is31fl3729_write_register(uint8_t index, uint8_t reg, uint8_t data); void is31fl3729_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); void is31fl3729_set_color_all(uint8_t red, uint8_t green, uint8_t blue); @@ -72,26 +73,42 @@ void is31fl3729_set_scaling_register(uint8_t index, uint8_t red, uint8_t green, // (eg. from a timer interrupt). // Call this while idle (in between matrix scans). // If the buffer is dirty, it will update the driver with the buffer. -void is31fl3729_update_pwm_buffers(uint8_t addr, uint8_t index); -void is31fl3729_update_scaling_registers(uint8_t addr, uint8_t index); +void is31fl3729_update_pwm_buffers(uint8_t index); +void is31fl3729_update_scaling_registers(uint8_t index); void is31fl3729_flush(void); -// Noise reduction using Spread Spectrum register -#define IS31FL3729_SSP_DISABLE 0b0 -#define IS31FL3729_SSP_ENABLE 0b1 +#define IS31FL3729_SW_PULLDOWN_0_OHM 0b000 +#define IS31FL3729_SW_PULLDOWN_0K5_OHM_SW_OFF 0b001 +#define IS31FL3729_SW_PULLDOWN_1K_OHM_SW_OFF 0b010 +#define IS31FL3729_SW_PULLDOWN_2K_OHM_SW_OFF 0b011 +#define IS31FL3729_SW_PULLDOWN_1K_OHM 0b100 +#define IS31FL3729_SW_PULLDOWN_2K_OHM 0b101 +#define IS31FL3729_SW_PULLDOWN_4K_OHM 0b110 +#define IS31FL3729_SW_PULLDOWN_8K_OHM 0b111 -#define IS31FL3729_RNG_5_PERCENT 0b00 -#define IS31FL3729_RNG_15_PERCENT 0b01 -#define IS31FL3729_RNG_24_PERCENT 0b10 -#define IS31FL3729_RNG_34_PERCENT 0b11 +#define IS31FL3729_CS_PULLUP_0_OHM 0b000 +#define IS31FL3729_CS_PULLUP_0K5_OHM_CS_OFF 0b001 +#define IS31FL3729_CS_PULLUP_1K_OHM_CS_OFF 0b010 +#define IS31FL3729_CS_PULLUP_2K_OHM_CS_OFF 0b011 +#define IS31FL3729_CS_PULLUP_1K_OHM 0b100 +#define IS31FL3729_CS_PULLUP_2K_OHM 0b101 +#define IS31FL3729_CS_PULLUP_4K_OHM 0b110 +#define IS31FL3729_CS_PULLUP_8K_OHM 0b111 -#define IS31FL3729_CLT_1980_US 0b00 -#define IS31FL3729_CLT_1200_US 0b01 -#define IS31FL3729_CLT_820_US 0b10 -#define IS31FL3729_CLT_660_US 0b11 +#define IS31FL3729_SPREAD_SPECTRUM_DISABLE 0b0 +#define IS31FL3729_SPREAD_SPECTRUM_ENABLE 0b1 + +#define IS31FL3729_SPREAD_SPECTRUM_RANGE_5_PERCENT 0b00 +#define IS31FL3729_SPREAD_SPECTRUM_RANGE_15_PERCENT 0b01 +#define IS31FL3729_SPREAD_SPECTRUM_RANGE_24_PERCENT 0b10 +#define IS31FL3729_SPREAD_SPECTRUM_RANGE_34_PERCENT 0b11 + +#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1980_US 0b00 +#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_1200_US 0b01 +#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_820_US 0b10 +#define IS31FL3729_SPREAD_SPECTRUM_CYCLE_TIME_660_US 0b11 -// Noise reduction using PWM Frequency register #define IS31FL3729_PWM_FREQUENCY_55K_HZ 0b000 #define IS31FL3729_PWM_FREQUENCY_32K_HZ 0b001 #define IS31FL3729_PWM_FREQUENCY_4K_HZ 0b010 @@ -101,7 +118,6 @@ void is31fl3729_flush(void); #define IS31FL3729_PWM_FREQUENCY_250_HZ 0b110 #define IS31FL3729_PWM_FREQUENCY_80K_HZ 0b111 -// Change SWx Setting using Configuration register #define IS31FL3729_CONFIG_SWS_15_9 0x01 // 15 CS x 9 SW matrix #define IS31FL3729_CONFIG_SWS_16_8 0x11 // 16 CS x 8 SW matrix #define IS31FL3729_CONFIG_SWS_16_7 0x21 // 16 CS x 7 SW matrix @@ -111,157 +127,154 @@ void is31fl3729_flush(void); #define IS31FL3729_CONFIG_SWS_16_3 0x61 // 16 CS x 3 SW matrix #define IS31FL3729_CONFIG_SWS_16_2 0x71 // 16 CS x 2 SW matrix -// Map CS SW locations to order in PWM / Scaling buffers -// This matches the ORDER in the Datasheet Register not the POSITION -// It will always count from 0x01 to (ISSI_MAX_LEDS - 1) -#define SW1_CS1 0x01 -#define SW1_CS2 0x02 -#define SW1_CS3 0x03 -#define SW1_CS4 0x04 -#define SW1_CS5 0x05 -#define SW1_CS6 0x06 -#define SW1_CS7 0x07 -#define SW1_CS8 0x08 -#define SW1_CS9 0x09 -#define SW1_CS10 0x0A -#define SW1_CS11 0x0B -#define SW1_CS12 0x0C -#define SW1_CS13 0x0D -#define SW1_CS14 0x0E -#define SW1_CS15 0x0F -#define SW1_CS16 0x10 +#define SW1_CS1 0x00 +#define SW1_CS2 0x01 +#define SW1_CS3 0x02 +#define SW1_CS4 0x03 +#define SW1_CS5 0x04 +#define SW1_CS6 0x05 +#define SW1_CS7 0x06 +#define SW1_CS8 0x07 +#define SW1_CS9 0x08 +#define SW1_CS10 0x09 +#define SW1_CS11 0x0A +#define SW1_CS12 0x0B +#define SW1_CS13 0x0C +#define SW1_CS14 0x0D +#define SW1_CS15 0x0E +#define SW1_CS16 0x0F -#define SW2_CS1 0x11 -#define SW2_CS2 0x12 -#define SW2_CS3 0x13 -#define SW2_CS4 0x14 -#define SW2_CS5 0x15 -#define SW2_CS6 0x16 -#define SW2_CS7 0x17 -#define SW2_CS8 0x18 -#define SW2_CS9 0x19 -#define SW2_CS10 0x1A -#define SW2_CS11 0x1B -#define SW2_CS12 0x1C -#define SW2_CS13 0x1D -#define SW2_CS14 0x1E -#define SW2_CS15 0x1F -#define SW2_CS16 0x20 +#define SW2_CS1 0x10 +#define SW2_CS2 0x11 +#define SW2_CS3 0x12 +#define SW2_CS4 0x13 +#define SW2_CS5 0x14 +#define SW2_CS6 0x15 +#define SW2_CS7 0x16 +#define SW2_CS8 0x17 +#define SW2_CS9 0x18 +#define SW2_CS10 0x19 +#define SW2_CS11 0x1A +#define SW2_CS12 0x1B +#define SW2_CS13 0x1C +#define SW2_CS14 0x1D +#define SW2_CS15 0x1E +#define SW2_CS16 0x1F -#define SW3_CS1 0x21 -#define SW3_CS2 0x22 -#define SW3_CS3 0x23 -#define SW3_CS4 0x24 -#define SW3_CS5 0x25 -#define SW3_CS6 0x26 -#define SW3_CS7 0x27 -#define SW3_CS8 0x28 -#define SW3_CS9 0x29 -#define SW3_CS10 0x2A -#define SW3_CS11 0x2B -#define SW3_CS12 0x2C -#define SW3_CS13 0x2D -#define SW3_CS14 0x2E -#define SW3_CS15 0x2F -#define SW3_CS16 0x30 +#define SW3_CS1 0x20 +#define SW3_CS2 0x21 +#define SW3_CS3 0x22 +#define SW3_CS4 0x23 +#define SW3_CS5 0x24 +#define SW3_CS6 0x25 +#define SW3_CS7 0x26 +#define SW3_CS8 0x27 +#define SW3_CS9 0x28 +#define SW3_CS10 0x29 +#define SW3_CS11 0x2A +#define SW3_CS12 0x2B +#define SW3_CS13 0x2C +#define SW3_CS14 0x2D +#define SW3_CS15 0x2E +#define SW3_CS16 0x2F -#define SW4_CS1 0x31 -#define SW4_CS2 0x32 -#define SW4_CS3 0x33 -#define SW4_CS4 0x34 -#define SW4_CS5 0x35 -#define SW4_CS6 0x36 -#define SW4_CS7 0x37 -#define SW4_CS8 0x38 -#define SW4_CS9 0x39 -#define SW4_CS10 0x3A -#define SW4_CS11 0x3B -#define SW4_CS12 0x3C -#define SW4_CS13 0x3D -#define SW4_CS14 0x3E -#define SW4_CS15 0x3F -#define SW4_CS16 0x40 +#define SW4_CS1 0x30 +#define SW4_CS2 0x31 +#define SW4_CS3 0x32 +#define SW4_CS4 0x33 +#define SW4_CS5 0x34 +#define SW4_CS6 0x35 +#define SW4_CS7 0x36 +#define SW4_CS8 0x37 +#define SW4_CS9 0x38 +#define SW4_CS10 0x39 +#define SW4_CS11 0x3A +#define SW4_CS12 0x3B +#define SW4_CS13 0x3C +#define SW4_CS14 0x3D +#define SW4_CS15 0x3E +#define SW4_CS16 0x3F -#define SW5_CS1 0x41 -#define SW5_CS2 0x42 -#define SW5_CS3 0x43 -#define SW5_CS4 0x44 -#define SW5_CS5 0x45 -#define SW5_CS6 0x46 -#define SW5_CS7 0x47 -#define SW5_CS8 0x48 -#define SW5_CS9 0x49 -#define SW5_CS10 0x4A -#define SW5_CS11 0x4B -#define SW5_CS12 0x4C -#define SW5_CS13 0x4D -#define SW5_CS14 0x4E -#define SW5_CS15 0x4F -#define SW5_CS16 0x50 +#define SW5_CS1 0x40 +#define SW5_CS2 0x41 +#define SW5_CS3 0x42 +#define SW5_CS4 0x43 +#define SW5_CS5 0x44 +#define SW5_CS6 0x45 +#define SW5_CS7 0x46 +#define SW5_CS8 0x47 +#define SW5_CS9 0x48 +#define SW5_CS10 0x49 +#define SW5_CS11 0x4A +#define SW5_CS12 0x4B +#define SW5_CS13 0x4C +#define SW5_CS14 0x4D +#define SW5_CS15 0x4E +#define SW5_CS16 0x4F -#define SW6_CS1 0x51 -#define SW6_CS2 0x52 -#define SW6_CS3 0x53 -#define SW6_CS4 0x54 -#define SW6_CS5 0x55 -#define SW6_CS6 0x56 -#define SW6_CS7 0x57 -#define SW6_CS8 0x58 -#define SW6_CS9 0x59 -#define SW6_CS10 0x5A -#define SW6_CS11 0x5B -#define SW6_CS12 0x5C -#define SW6_CS13 0x5D -#define SW6_CS14 0x5E -#define SW6_CS15 0x5F -#define SW6_CS16 0x60 +#define SW6_CS1 0x50 +#define SW6_CS2 0x51 +#define SW6_CS3 0x52 +#define SW6_CS4 0x53 +#define SW6_CS5 0x54 +#define SW6_CS6 0x55 +#define SW6_CS7 0x56 +#define SW6_CS8 0x57 +#define SW6_CS9 0x58 +#define SW6_CS10 0x59 +#define SW6_CS11 0x5A +#define SW6_CS12 0x5B +#define SW6_CS13 0x5C +#define SW6_CS14 0x5D +#define SW6_CS15 0x5E +#define SW6_CS16 0x5F -#define SW7_CS1 0x61 -#define SW7_CS2 0x62 -#define SW7_CS3 0x63 -#define SW7_CS4 0x64 -#define SW7_CS5 0x65 -#define SW7_CS6 0x66 -#define SW7_CS7 0x67 -#define SW7_CS8 0x68 -#define SW7_CS9 0x69 -#define SW7_CS10 0x6A -#define SW7_CS11 0x6B -#define SW7_CS12 0x6C -#define SW7_CS13 0x6D -#define SW7_CS14 0x6E -#define SW7_CS15 0x6F -#define SW7_CS16 0x70 +#define SW7_CS1 0x60 +#define SW7_CS2 0x61 +#define SW7_CS3 0x62 +#define SW7_CS4 0x63 +#define SW7_CS5 0x64 +#define SW7_CS6 0x65 +#define SW7_CS7 0x66 +#define SW7_CS8 0x67 +#define SW7_CS9 0x68 +#define SW7_CS10 0x69 +#define SW7_CS11 0x6A +#define SW7_CS12 0x6B +#define SW7_CS13 0x6C +#define SW7_CS14 0x6D +#define SW7_CS15 0x6E +#define SW7_CS16 0x6F -#define SW8_CS1 0x71 -#define SW8_CS2 0x72 -#define SW8_CS3 0x73 -#define SW8_CS4 0x74 -#define SW8_CS5 0x75 -#define SW8_CS6 0x76 -#define SW8_CS7 0x77 -#define SW8_CS8 0x78 -#define SW8_CS9 0x79 -#define SW8_CS10 0x7A -#define SW8_CS11 0x7B -#define SW8_CS12 0x7C -#define SW8_CS13 0x7D -#define SW8_CS14 0x7E -#define SW8_CS15 0x7F -#define SW8_CS16 0x80 +#define SW8_CS1 0x70 +#define SW8_CS2 0x71 +#define SW8_CS3 0x72 +#define SW8_CS4 0x73 +#define SW8_CS5 0x74 +#define SW8_CS6 0x75 +#define SW8_CS7 0x76 +#define SW8_CS8 0x77 +#define SW8_CS9 0x78 +#define SW8_CS10 0x79 +#define SW8_CS11 0x7A +#define SW8_CS12 0x7B +#define SW8_CS13 0x7C +#define SW8_CS14 0x7D +#define SW8_CS15 0x7E +#define SW8_CS16 0x7F -#define SW9_CS1 0x81 -#define SW9_CS2 0x82 -#define SW9_CS3 0x83 -#define SW9_CS4 0x84 -#define SW9_CS5 0x85 -#define SW9_CS6 0x86 -#define SW9_CS7 0x87 -#define SW9_CS8 0x88 -#define SW9_CS9 0x89 -#define SW9_CS10 0x8A -#define SW9_CS11 0x8B -#define SW9_CS12 0x8C -#define SW9_CS13 0x8D -#define SW9_CS14 0x8E -#define SW9_CS15 0x8F +#define SW9_CS1 0x80 +#define SW9_CS2 0x81 +#define SW9_CS3 0x82 +#define SW9_CS4 0x83 +#define SW9_CS5 0x84 +#define SW9_CS6 0x85 +#define SW9_CS7 0x86 +#define SW9_CS8 0x87 +#define SW9_CS9 0x88 +#define SW9_CS10 0x89 +#define SW9_CS11 0x8A +#define SW9_CS12 0x8B +#define SW9_CS13 0x8C +#define SW9_CS14 0x8D +#define SW9_CS15 0x8E