]> git.donarmstrong.com Git - qmk_firmware.git/commitdiff
ISSI31FL3733 driver (#3679)
authoryiancar <yiangosyiangou@cytanet.com.cy>
Tue, 28 Aug 2018 13:03:11 +0000 (16:03 +0300)
committerJack Humbert <jack.humb@gmail.com>
Tue, 28 Aug 2018 13:03:11 +0000 (09:03 -0400)
* ISSI31FL3733 driver

- Addapted IS31 driver for the above driver

* fix my branch

* ISSI31FL3733 driver

- Inclusion of above ISSI led driver

* IS31fl3733 driver

- Added correct function for control registers

* Finalized support for ISSI31fl3733 led driver

- Finalized and tested driver.
- Modified i2c_master for arm due to declaration mistake.
- Fixed spaces/tabs in quantum.h file.
- Fixed spaces/tabs in common_features.mk file.
- Removed unnecessary includes from rgb_matrix.c file.
- Added local definitions for MIN and MAX macros in rgb_matrix.c file.
- Adjusted chevron effect.
- Added necessary define (RGB_3733_MATRIX_ENABLE) for makefile.
- Added necessary C define (ISSI3733) to aid with inclusion of the correct header file.
- Added documentation for the new driver.

* Driver structure update

- Changed rule includes to be more condensed (RGB_MATRIX_ENABLE = IS31FL3731) and (RGB_MATRIX_ENABLE = IS31FL3733)
- Updated documentation
- Reverted to the use of differently named functions for each driver and selecting the needed ones within rgb_matrix.c

* ISSI Drivers refractoring

- Moved issi drivers in a dedicated folder
- Updated documentation

* I2C library fix

I released the special pins incorrectly before. It is now fixed.

14 files changed:
common_features.mk
docs/feature_rgb_matrix.md
docs/hardware_drivers.md
drivers/arm/i2c_master.c
drivers/arm/i2c_master.h
drivers/is31fl3731.c [deleted file]
drivers/is31fl3731.h [deleted file]
drivers/issi/is31fl3731.c [new file with mode: 0644]
drivers/issi/is31fl3731.h [new file with mode: 0644]
drivers/issi/is31fl3733.c [new file with mode: 0644]
drivers/issi/is31fl3733.h [new file with mode: 0644]
quantum/quantum.h
quantum/rgb_matrix.c
quantum/rgb_matrix.h

index b78f04d2a8206a64092388784cdbe83692d59932..e0d4ca297cc1df090311f4a7bac5a4c93cbb3b65 100644 (file)
@@ -61,8 +61,8 @@ endif
 
 ifeq ($(strip $(STENO_ENABLE)), yes)
     OPT_DEFS += -DSTENO_ENABLE
-       VIRTSER_ENABLE := yes
-       SRC += $(QUANTUM_DIR)/process_keycode/process_steno.c
+    VIRTSER_ENABLE := yes
+    SRC += $(QUANTUM_DIR)/process_keycode/process_steno.c
 endif
 
 ifeq ($(strip $(VIRTSER_ENABLE)), yes)
@@ -75,9 +75,9 @@ ifeq ($(strip $(FAUXCLICKY_ENABLE)), yes)
 endif
 
 ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
-       OPT_DEFS += -DPOINTING_DEVICE_ENABLE
-       OPT_DEFS += -DMOUSE_ENABLE
-       SRC += $(QUANTUM_DIR)/pointing_device.c
+    OPT_DEFS += -DPOINTING_DEVICE_ENABLE
+    OPT_DEFS += -DMOUSE_ENABLE
+    SRC += $(QUANTUM_DIR)/pointing_device.c
 endif
 
 ifeq ($(strip $(UCIS_ENABLE)), yes)
@@ -110,12 +110,14 @@ ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
     ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes)
         OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER
     else
-           SRC += ws2812.c
+        SRC += ws2812.c
     endif
 endif
 
 ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
     OPT_DEFS += -DRGB_MATRIX_ENABLE
+    OPT_DEFS += -DIS31FL3731
+    COMMON_VPATH += $(DRIVER_PATH)/issi
     SRC += is31fl3731.c
     SRC += i2c_master.c
     SRC += $(QUANTUM_DIR)/color.c
@@ -123,6 +125,28 @@ ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
     CIE1931_CURVE = yes
 endif
 
+ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3731)
+    OPT_DEFS += -DRGB_MATRIX_ENABLE
+    OPT_DEFS += -DIS31FL3731
+    COMMON_VPATH += $(DRIVER_PATH)/issi
+    SRC += is31fl3731.c
+    SRC += i2c_master.c
+    SRC += $(QUANTUM_DIR)/color.c
+    SRC += $(QUANTUM_DIR)/rgb_matrix.c
+    CIE1931_CURVE = yes
+endif
+
+ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3733)
+    OPT_DEFS += -DRGB_MATRIX_ENABLE
+    OPT_DEFS += -DIS31FL3733
+    COMMON_VPATH += $(DRIVER_PATH)/issi
+    SRC += is31fl3733.c
+    SRC += i2c_master.c
+    SRC += $(QUANTUM_DIR)/color.c
+    SRC += $(QUANTUM_DIR)/rgb_matrix.c
+    CIE1931_CURVE = yes
+endif
+
 ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
     OPT_DEFS += -DTAP_DANCE_ENABLE
     SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c
@@ -169,7 +193,7 @@ ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
     ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
         CIE1931_CURVE = yes
     endif
-               ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
+        ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
         OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
     endif
 endif
@@ -200,7 +224,7 @@ endif
 
 ifeq ($(strip $(HD44780_ENABLE)), yes)
     SRC += drivers/avr/hd44780.c
-       OPT_DEFS += -DHD44780_ENABLE
+    OPT_DEFS += -DHD44780_ENABLE
 endif
 
 QUANTUM_SRC:= \
index ed33c7ea4ee912826bc3c1f1441f4d3576826d29..4f827f8dc9d94c6f35a8770282582b8bf3e0de42 100644 (file)
@@ -1,8 +1,12 @@
 # RGB Matrix Lighting
 
+## Driver configuration
+
+### IS31FL3731
+
 There is basic support for addressable RGB matrix lighting with the I2C IS31FL3731 RGB controller. To enable it, add this to your `rules.mk`:
 
-    RGB_MATRIX_ENABLE = yes
+    RGB_MATRIX_ENABLE = IS31FL3731
 
 Configure the hardware via your `config.h`:
 
@@ -36,7 +40,51 @@ Define these arrays listing all the LEDs in your `<keyboard>.c`:
            ....
        }
 
-Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](http://www.issi.com/WW/pdf/31FL3731.pdf). The `driver` is the index of the driver you defined in your `config.h` (`0` or `1` right now).
+Where `Cx_y` is the location of the LED in the matrix defined by [the datasheet](http://www.issi.com/WW/pdf/31FL3731.pdf) and the header file `drivers/issi/is31fl3731.h`. The `driver` is the index of the driver you defined in your `config.h` (`0` or `1` right now).
+
+###  IS31FL3733
+
+There is basic support for addressable RGB matrix lighting with the I2C IS31FL3733 RGB controller. To enable it, add this to your `rules.mk`:
+
+    RGB_MATRIX_ENABLE = IS31FL3733
+
+Configure the hardware via your `config.h`:
+
+       // This is a 7-bit address, that gets left-shifted and bit 0
+       // set to 0 for write, 1 for read (as per I2C protocol)
+       // The address will vary depending on your wiring:
+       // 00 <-> GND
+       // 01 <-> SCL
+       // 10 <-> SDA
+       // 11 <-> VCC
+       // ADDR1 represents A1:A0 of the 7-bit address.
+       // ADDR2 represents A3:A2 of the 7-bit address.
+       // The result is: 0b101(ADDR2)(ADDR1)
+       #define DRIVER_ADDR_1 0b1010000
+       #define DRIVER_ADDR_2 0b1010000 // this is here for compliancy reasons.
+
+       #define DRIVER_COUNT 1
+       #define DRIVER_1_LED_TOTAL 64
+       #define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL
+
+Currently only a single drivers is supported, but it would be trivial to support all 4 combinations. For now define `DRIVER_ADDR_2` as `DRIVER_ADDR_1`
+
+Define these arrays listing all the LEDs in your `<keyboard>.c`:
+
+       const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
+       /* Refer to IS31 manual for these locations
+        *   driver
+        *   |  R location
+        *   |  |       G location
+        *   |  |       |       B location
+        *   |  |       |       | */
+           {0, B_1,    A_1,    C_1},
+           ....
+       }
+
+Where `X_Y` is the location of the LED in the matrix defined by [the datasheet](http://www.issi.com/WW/pdf/31FL3733.pdf) and the header file `drivers/issi/is31fl3733.h`. The `driver` is the index of the driver you defined in your `config.h` (Only `0` right now).
+
+From this point forward the configuration is the same for all the drivers. 
 
        const rgb_led g_rgb_leds[DRIVER_LED_TOTAL] = {
        /* {row | col << 4}
index 336bc908ef3ed53bb73e13c351f34c45045f4c14..4c1266f2241e054f59307a8908b8e47184b22cff 100644 (file)
@@ -26,6 +26,10 @@ You can make use of uGFX within QMK to drive character and graphic LCD's, LED ar
 
 Support for WS2811/WS2812{a,b,c} LED's. For more information see the [RGB Light](feature_rgblight.md) page.
 
-## IS31FL3731 (AVR Only)
+## IS31FL3731
 
 Support for up to 2 drivers. Each driver impliments 2 charlieplex matrices to individually address LEDs using I2C. This allows up to 144 same color LEDs or 32 RGB LEDs. For more information on how to setup the driver see the [RGB Matrix](feature_rgb_matrix.md) page.
+
+## IS31FL3733
+
+Support for up to a single driver with room for expansion. Each driver can control 192 individual LEDs or 64 RGB LEDs. For more information on how to setup the driver see the [RGB Matrix](feature_rgb_matrix.md) page.
\ No newline at end of file
index 2fdd9f65e1cacf5f5f8affe2ba37314b9ea016f4..2a7badd351f29a8834410a0dd3385d260f297d68 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/* This library follows the convention of the AVR i2c_master library.
+/* This library is only valid for STM32 processors.
+ * This library follows the convention of the AVR i2c_master library.
  * As a result addresses are expected to be already shifted (addr << 1).
  * I2CD1 is the default driver which corresponds to pins B6 and B7. This
  * can be changed.
  * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that
- * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file.
+ * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. Pins B6 and B7 are used
+ * but using any other I2C pins should be trivial.
  */
 
 #include "i2c_master.h"
@@ -41,7 +43,7 @@ static const I2CConfig i2cconfig = {
 
 void i2c_init(void)
 {
-  palSetGroupMode(GPIOB,6,7, PAL_MODE_INPUT);       // Try releasing special pins for a short time
+  palSetGroupMode(GPIOB, GPIOB_PIN6 | GPIOB_PIN7, 0, PAL_MODE_INPUT); // Try releasing special pins for a short time
   chThdSleepMilliseconds(10);
 
   palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP);
@@ -82,12 +84,12 @@ uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t l
   {
     complete_packet[i+1] = data[i];
   }
-  complete_packet[0] = regaddr
+  complete_packet[0] = regaddr;
 
   return i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), complete_packet, length + 1, 0, 0, MS2ST(timeout));
 }
 
-uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
+uint8_t i2c_readReg(uint8_t devaddr, uint8_t* regaddr, uint8_t* data, uint16_t length, uint16_t timeout)
 {
   i2c_address = devaddr;
   i2cStart(&I2C_DRIVER, &i2cconfig);
@@ -97,7 +99,6 @@ uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t le
 // This is usually not needed. It releases the driver to allow pins to become GPIO again.
 uint8_t i2c_stop(uint16_t timeout)
 {
-  i2c_address = address;
   i2cStop(&I2C_DRIVER);
   return 0;
 }
index 9d51245be1d12dd3a8c070f71613f5866ef5d95d..591fa7f77d754aebe1251a97f79c80250e00c1db 100644 (file)
@@ -35,5 +35,5 @@ uint8_t i2c_start(uint8_t address);
 uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
 uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
 uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
-void i2c_stop(void);
+uint8_t i2c_readReg(uint8_t devaddr, uint8_t* regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
+uint8_t i2c_stop(uint16_t timeout);
diff --git a/drivers/is31fl3731.c b/drivers/is31fl3731.c
deleted file mode 100644 (file)
index 0524feb..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/* Copyright 2017 Jason Williams
- * Copyright 2018 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef __AVR__
-#include <avr/interrupt.h>
-#include <avr/io.h>
-#include <util/delay.h>
-#else
-#include "wait.h"
-#endif
-
-#include "is31fl3731.h"
-#include <string.h>
-#include "i2c_master.h"
-#include "progmem.h"
-
-// This is a 7-bit address, that gets left-shifted and bit 0
-// set to 0 for write, 1 for read (as per I2C protocol)
-// The address will vary depending on your wiring:
-// 0b1110100 AD <-> GND
-// 0b1110111 AD <-> VCC
-// 0b1110101 AD <-> SCL
-// 0b1110110 AD <-> SDA
-#define ISSI_ADDR_DEFAULT 0x74
-
-#define ISSI_REG_CONFIG  0x00
-#define ISSI_REG_CONFIG_PICTUREMODE 0x00
-#define ISSI_REG_CONFIG_AUTOPLAYMODE 0x08
-#define ISSI_REG_CONFIG_AUDIOPLAYMODE 0x18
-
-#define ISSI_CONF_PICTUREMODE 0x00
-#define ISSI_CONF_AUTOFRAMEMODE 0x04
-#define ISSI_CONF_AUDIOMODE 0x08
-
-#define ISSI_REG_PICTUREFRAME  0x01
-
-#define ISSI_REG_SHUTDOWN 0x0A
-#define ISSI_REG_AUDIOSYNC 0x06
-
-#define ISSI_COMMANDREGISTER 0xFD
-#define ISSI_BANK_FUNCTIONREG 0x0B    // helpfully called 'page nine'
-
-#ifndef ISSI_TIMEOUT
-  #define ISSI_TIMEOUT 100
-#endif
-
-#ifndef ISSI_PERSISTENCE
-  #define ISSI_PERSISTENCE 0
-#endif
-
-// Transfer buffer for TWITransmitData()
-uint8_t g_twi_transfer_buffer[20];
-
-// These buffers match the IS31FL3731 PWM registers 0x24-0xB3.
-// Storing them like this is optimal for I2C transfers to the registers.
-// We could optimize this and take out the unused registers from these
-// buffers and the transfers in IS31FL3731_write_pwm_buffer() but it's
-// probably not worth the extra complexity.
-uint8_t g_pwm_buffer[DRIVER_COUNT][144];
-bool g_pwm_buffer_update_required = false;
-
-uint8_t g_led_control_registers[DRIVER_COUNT][18] = { { 0 }, { 0 } };
-bool g_led_control_registers_update_required = false;
-
-// This is the bit pattern in the LED control registers
-// (for matrix A, add one to register for matrix B)
-//
-//  reg -  b7  b6  b5  b4  b3  b2  b1  b0
-// 0x00 - R08,R07,R06,R05,R04,R03,R02,R01
-// 0x02 - G08,G07,G06,G05,G04,G03,G02,R00
-// 0x04 - B08,B07,B06,B05,B04,B03,G01,G00
-// 0x06 -  - , - , - , - , - ,B02,B01,B00
-// 0x08 -  - , - , - , - , - , - , - , -
-// 0x0A - B17,B16,B15, - , - , - , - , -
-// 0x0C - G17,G16,B14,B13,B12,B11,B10,B09
-// 0x0E - R17,G15,G14,G13,G12,G11,G10,G09
-// 0x10 - R16,R15,R14,R13,R12,R11,R10,R09
-
-
-void IS31_write_register( uint8_t addr, uint8_t reg, uint8_t data )
-{
-    g_twi_transfer_buffer[0] = reg;
-    g_twi_transfer_buffer[1] = data;
-
-  #if ISSI_PERSISTENCE > 0
-    for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
-      if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0)
-        break;
-    }
-  #else
-    i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
-  #endif
-}
-
-void IS31_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
-{
-    // assumes bank is already selected
-
-    // transmit PWM registers in 9 transfers of 16 bytes
-    // g_twi_transfer_buffer[] is 20 bytes
-
-    // iterate over the pwm_buffer contents at 16 byte intervals
-    for ( int i = 0; i < 144; i += 16 ) {
-        // set the first register, e.g. 0x24, 0x34, 0x44, etc.
-        g_twi_transfer_buffer[0] = 0x24 + i;
-        // copy the data from i to i+15
-        // device will auto-increment register for data after the first byte
-        // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer
-        for ( int j = 0; j < 16; j++ ) {
-            g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
-        }
-
-    #if ISSI_PERSISTENCE > 0
-      for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
-        if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0)
-          break;
-      }
-    #else
-      i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT);
-    #endif
-    }
-}
-
-void IS31_init( uint8_t addr )
-{
-    // In order to avoid the LEDs being driven with garbage data
-    // in the LED driver's PWM registers, first enable software shutdown,
-    // then set up the mode and other settings, clear the PWM registers,
-    // then disable software shutdown.
-
-    // select "function register" bank
-    IS31_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG );
-
-    // enable software shutdown
-    IS31_write_register( addr, ISSI_REG_SHUTDOWN, 0x00 );
-    // this delay was copied from other drivers, might not be needed
-    #ifdef __AVR__
-    _delay_ms( 10 );
-    #else
-    wait_ms(10);
-    #endif
-
-    // picture mode
-    IS31_write_register( addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE );
-    // display frame 0
-    IS31_write_register( addr, ISSI_REG_PICTUREFRAME, 0x00 );
-    // audio sync off
-    IS31_write_register( addr, ISSI_REG_AUDIOSYNC, 0x00 );
-
-    // select bank 0
-    IS31_write_register( addr, ISSI_COMMANDREGISTER, 0 );
-
-    // turn off all LEDs in the LED control register
-    for ( int i = 0x00; i <= 0x11; i++ )
-    {
-        IS31_write_register( addr, i, 0x00 );
-    }
-
-    // turn off all LEDs in the blink control register (not really needed)
-    for ( int i = 0x12; i <= 0x23; i++ )
-    {
-        IS31_write_register( addr, i, 0x00 );
-    }
-
-    // set PWM on all LEDs to 0
-    for ( int i = 0x24; i <= 0xB3; i++ )
-    {
-        IS31_write_register( addr, i, 0x00 );
-    }
-
-    // select "function register" bank
-    IS31_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG );
-
-    // disable software shutdown
-    IS31_write_register( addr, ISSI_REG_SHUTDOWN, 0x01 );
-
-    // select bank 0 and leave it selected.
-    // most usage after initialization is just writing PWM buffers in bank 0
-    // as there's not much point in double-buffering
-    IS31_write_register( addr, ISSI_COMMANDREGISTER, 0 );
-
-}
-
-void IS31_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
-{
-    if ( index >= 0 && index < DRIVER_LED_TOTAL ) {
-        is31_led led = g_is31_leds[index];
-
-        // Subtract 0x24 to get the second index of g_pwm_buffer
-        g_pwm_buffer[led.driver][led.r - 0x24] = red;
-        g_pwm_buffer[led.driver][led.g - 0x24] = green;
-        g_pwm_buffer[led.driver][led.b - 0x24] = blue;
-        g_pwm_buffer_update_required = true;
-    }
-}
-
-void IS31_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
-{
-    for ( int i = 0; i < DRIVER_LED_TOTAL; i++ )
-    {
-        IS31_set_color( i, red, green, blue );
-    }
-}
-
-void IS31_set_led_control_register( uint8_t index, bool red, bool green, bool blue )
-{
-    is31_led led = g_is31_leds[index];
-
-  uint8_t control_register_r = (led.r - 0x24) / 8;
-  uint8_t control_register_g = (led.g - 0x24) / 8;
-  uint8_t control_register_b = (led.b - 0x24) / 8;
-  uint8_t bit_r = (led.r - 0x24) % 8;
-  uint8_t bit_g = (led.g - 0x24) % 8;
-  uint8_t bit_b = (led.b - 0x24) % 8;
-
-    if ( red ) {
-        g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
-    } else {
-        g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
-    }
-    if ( green ) {
-        g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
-    } else {
-        g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
-    }
-    if ( blue ) {
-        g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
-    } else {
-        g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
-    }
-
-    g_led_control_registers_update_required = true;
-
-}
-
-void IS31_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
-{
-    if ( g_pwm_buffer_update_required )
-    {
-        IS31_write_pwm_buffer( addr1, g_pwm_buffer[0] );
-        IS31_write_pwm_buffer( addr2, g_pwm_buffer[1] );
-    }
-    g_pwm_buffer_update_required = false;
-}
-
-void IS31_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
-{
-    if ( g_led_control_registers_update_required )
-    {
-        for ( int i=0; i<18; i++ )
-        {
-            IS31_write_register(addr1, i, g_led_control_registers[0][i] );
-            IS31_write_register(addr2, i, g_led_control_registers[1][i] );
-        }
-    }
-}
-
diff --git a/drivers/is31fl3731.h b/drivers/is31fl3731.h
deleted file mode 100644 (file)
index 9e195c2..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/* Copyright 2017 Jason Williams
- * Copyright 2018 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef IS31FL3731_DRIVER_H
-#define IS31FL3731_DRIVER_H
-
-#include <stdint.h>
-#include <stdbool.h>
-
-typedef struct is31_led {
-  uint8_t driver:2;
-  uint8_t r;
-  uint8_t g;
-  uint8_t b;
-} __attribute__((packed)) is31_led;
-
-extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
-
-void IS31_init( uint8_t addr );
-void IS31_write_register( uint8_t addr, uint8_t reg, uint8_t data );
-void IS31_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer );
-
-void IS31_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
-void IS31_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
-
-void IS31_set_led_control_register( uint8_t index, bool red, bool green, bool blue );
-
-// This should not be called from an interrupt
-// (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 IS31_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
-void IS31_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
-
-#define C1_1  0x24
-#define C1_2  0x25
-#define C1_3  0x26
-#define C1_4  0x27
-#define C1_5  0x28
-#define C1_6  0x29
-#define C1_7  0x2A
-#define C1_8  0x2B
-
-#define C1_9  0x2C
-#define C1_10 0x2D
-#define C1_11 0x2E
-#define C1_12 0x2F
-#define C1_13 0x30
-#define C1_14 0x31
-#define C1_15 0x32
-#define C1_16 0x33
-
-#define C2_1  0x34
-#define C2_2  0x35
-#define C2_3  0x36
-#define C2_4  0x37
-#define C2_5  0x38
-#define C2_6  0x39
-#define C2_7  0x3A
-#define C2_8  0x3B
-
-#define C2_9  0x3C
-#define C2_10 0x3D
-#define C2_11 0x3E
-#define C2_12 0x3F
-#define C2_13 0x40
-#define C2_14 0x41
-#define C2_15 0x42
-#define C2_16 0x43
-
-#define C3_1  0x44
-#define C3_2  0x45
-#define C3_3  0x46
-#define C3_4  0x47
-#define C3_5  0x48
-#define C3_6  0x49
-#define C3_7  0x4A
-#define C3_8  0x4B
-
-#define C3_9  0x4C
-#define C3_10 0x4D
-#define C3_11 0x4E
-#define C3_12 0x4F
-#define C3_13 0x50
-#define C3_14 0x51
-#define C3_15 0x52
-#define C3_16 0x53
-
-#define C4_1  0x54
-#define C4_2  0x55
-#define C4_3  0x56
-#define C4_4  0x57
-#define C4_5  0x58
-#define C4_6  0x59
-#define C4_7  0x5A
-#define C4_8  0x5B
-
-#define C4_9  0x5C
-#define C4_10 0x5D
-#define C4_11 0x5E
-#define C4_12 0x5F
-#define C4_13 0x60
-#define C4_14 0x61
-#define C4_15 0x62
-#define C4_16 0x63
-
-#define C5_1  0x64
-#define C5_2  0x65
-#define C5_3  0x66
-#define C5_4  0x67
-#define C5_5  0x68
-#define C5_6  0x69
-#define C5_7  0x6A
-#define C5_8  0x6B
-
-#define C5_9  0x6C
-#define C5_10 0x6D
-#define C5_11 0x6E
-#define C5_12 0x6F
-#define C5_13 0x70
-#define C5_14 0x71
-#define C5_15 0x72
-#define C5_16 0x73
-
-#define C6_1  0x74
-#define C6_2  0x75
-#define C6_3  0x76
-#define C6_4  0x77
-#define C6_5  0x78
-#define C6_6  0x79
-#define C6_7  0x7A
-#define C6_8  0x7B
-
-#define C6_9  0x7C
-#define C6_10 0x7D
-#define C6_11 0x7E
-#define C6_12 0x7F
-#define C6_13 0x80
-#define C6_14 0x81
-#define C6_15 0x82
-#define C6_16 0x83
-
-#define C7_1  0x84
-#define C7_2  0x85
-#define C7_3  0x86
-#define C7_4  0x87
-#define C7_5  0x88
-#define C7_6  0x89
-#define C7_7  0x8A
-#define C7_8  0x8B
-
-#define C7_9  0x8C
-#define C7_10 0x8D
-#define C7_11 0x8E
-#define C7_12 0x8F
-#define C7_13 0x90
-#define C7_14 0x91
-#define C7_15 0x92
-#define C7_16 0x93
-
-#define C8_1  0x94
-#define C8_2  0x95
-#define C8_3  0x96
-#define C8_4  0x97
-#define C8_5  0x98
-#define C8_6  0x99
-#define C8_7  0x9A
-#define C8_8  0x9B
-
-#define C8_9  0x9C
-#define C8_10 0x9D
-#define C8_11 0x9E
-#define C8_12 0x9F
-#define C8_13 0xA0
-#define C8_14 0xA1
-#define C8_15 0xA2
-#define C8_16 0xA3
-
-#define C9_1  0xA4
-#define C9_2  0xA5
-#define C9_3  0xA6
-#define C9_4  0xA7
-#define C9_5  0xA8
-#define C9_6  0xA9
-#define C9_7  0xAA
-#define C9_8  0xAB
-
-#define C9_9  0xAC
-#define C9_10 0xAD
-#define C9_11 0xAE
-#define C9_12 0xAF
-#define C9_13 0xB0
-#define C9_14 0xB1
-#define C9_15 0xB2
-#define C9_16 0xB3
-
-
-
-#endif // IS31FL3731_DRIVER_H
diff --git a/drivers/issi/is31fl3731.c b/drivers/issi/is31fl3731.c
new file mode 100644 (file)
index 0000000..4d0d6b8
--- /dev/null
@@ -0,0 +1,271 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef __AVR__
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#else
+#include "wait.h"
+#endif
+
+#include "is31fl3731.h"
+#include <string.h>
+#include "i2c_master.h"
+#include "progmem.h"
+
+// This is a 7-bit address, that gets left-shifted and bit 0
+// set to 0 for write, 1 for read (as per I2C protocol)
+// The address will vary depending on your wiring:
+// 0b1110100 AD <-> GND
+// 0b1110111 AD <-> VCC
+// 0b1110101 AD <-> SCL
+// 0b1110110 AD <-> SDA
+#define ISSI_ADDR_DEFAULT 0x74
+
+#define ISSI_REG_CONFIG  0x00
+#define ISSI_REG_CONFIG_PICTUREMODE 0x00
+#define ISSI_REG_CONFIG_AUTOPLAYMODE 0x08
+#define ISSI_REG_CONFIG_AUDIOPLAYMODE 0x18
+
+#define ISSI_CONF_PICTUREMODE 0x00
+#define ISSI_CONF_AUTOFRAMEMODE 0x04
+#define ISSI_CONF_AUDIOMODE 0x08
+
+#define ISSI_REG_PICTUREFRAME  0x01
+
+#define ISSI_REG_SHUTDOWN 0x0A
+#define ISSI_REG_AUDIOSYNC 0x06
+
+#define ISSI_COMMANDREGISTER 0xFD
+#define ISSI_BANK_FUNCTIONREG 0x0B    // helpfully called 'page nine'
+
+#ifndef ISSI_TIMEOUT
+  #define ISSI_TIMEOUT 100
+#endif
+
+#ifndef ISSI_PERSISTENCE
+  #define ISSI_PERSISTENCE 0
+#endif
+
+// Transfer buffer for TWITransmitData()
+uint8_t g_twi_transfer_buffer[20];
+
+// These buffers match the IS31FL3731 PWM registers 0x24-0xB3.
+// Storing them like this is optimal for I2C transfers to the registers.
+// We could optimize this and take out the unused registers from these
+// buffers and the transfers in IS31FL3731_write_pwm_buffer() but it's
+// probably not worth the extra complexity.
+uint8_t g_pwm_buffer[DRIVER_COUNT][144];
+bool g_pwm_buffer_update_required = false;
+
+uint8_t g_led_control_registers[DRIVER_COUNT][18] = { { 0 }, { 0 } };
+bool g_led_control_registers_update_required = false;
+
+// This is the bit pattern in the LED control registers
+// (for matrix A, add one to register for matrix B)
+//
+//  reg -  b7  b6  b5  b4  b3  b2  b1  b0
+// 0x00 - R08,R07,R06,R05,R04,R03,R02,R01
+// 0x02 - G08,G07,G06,G05,G04,G03,G02,R00
+// 0x04 - B08,B07,B06,B05,B04,B03,G01,G00
+// 0x06 -  - , - , - , - , - ,B02,B01,B00
+// 0x08 -  - , - , - , - , - , - , - , -
+// 0x0A - B17,B16,B15, - , - , - , - , -
+// 0x0C - G17,G16,B14,B13,B12,B11,B10,B09
+// 0x0E - R17,G15,G14,G13,G12,G11,G10,G09
+// 0x10 - R16,R15,R14,R13,R12,R11,R10,R09
+
+
+void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data )
+{
+    g_twi_transfer_buffer[0] = reg;
+    g_twi_transfer_buffer[1] = data;
+
+  #if ISSI_PERSISTENCE > 0
+    for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+      if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0)
+        break;
+    }
+  #else
+    i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
+  #endif
+}
+
+void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
+{
+    // assumes bank is already selected
+
+    // transmit PWM registers in 9 transfers of 16 bytes
+    // g_twi_transfer_buffer[] is 20 bytes
+
+    // iterate over the pwm_buffer contents at 16 byte intervals
+    for ( int i = 0; i < 144; i += 16 ) {
+        // set the first register, e.g. 0x24, 0x34, 0x44, etc.
+        g_twi_transfer_buffer[0] = 0x24 + i;
+        // copy the data from i to i+15
+        // device will auto-increment register for data after the first byte
+        // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer
+        for ( int j = 0; j < 16; j++ ) {
+            g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
+        }
+
+    #if ISSI_PERSISTENCE > 0
+      for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+        if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0)
+          break;
+      }
+    #else
+      i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT);
+    #endif
+    }
+}
+
+void IS31FL3731_init( uint8_t addr )
+{
+    // In order to avoid the LEDs being driven with garbage data
+    // in the LED driver's PWM registers, first enable software shutdown,
+    // then set up the mode and other settings, clear the PWM registers,
+    // then disable software shutdown.
+
+    // select "function register" bank
+    IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG );
+
+    // enable software shutdown
+    IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x00 );
+    // this delay was copied from other drivers, might not be needed
+    #ifdef __AVR__
+    _delay_ms( 10 );
+    #else
+    wait_ms(10);
+    #endif
+
+    // picture mode
+    IS31FL3731_write_register( addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE );
+    // display frame 0
+    IS31FL3731_write_register( addr, ISSI_REG_PICTUREFRAME, 0x00 );
+    // audio sync off
+    IS31FL3731_write_register( addr, ISSI_REG_AUDIOSYNC, 0x00 );
+
+    // select bank 0
+    IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, 0 );
+
+    // turn off all LEDs in the LED control register
+    for ( int i = 0x00; i <= 0x11; i++ )
+    {
+        IS31FL3731_write_register( addr, i, 0x00 );
+    }
+
+    // turn off all LEDs in the blink control register (not really needed)
+    for ( int i = 0x12; i <= 0x23; i++ )
+    {
+        IS31FL3731_write_register( addr, i, 0x00 );
+    }
+
+    // set PWM on all LEDs to 0
+    for ( int i = 0x24; i <= 0xB3; i++ )
+    {
+        IS31FL3731_write_register( addr, i, 0x00 );
+    }
+
+    // select "function register" bank
+    IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG );
+
+    // disable software shutdown
+    IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x01 );
+
+    // select bank 0 and leave it selected.
+    // most usage after initialization is just writing PWM buffers in bank 0
+    // as there's not much point in double-buffering
+    IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, 0 );
+
+}
+
+void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
+{
+    if ( index >= 0 && index < DRIVER_LED_TOTAL ) {
+        is31_led led = g_is31_leds[index];
+
+        // Subtract 0x24 to get the second index of g_pwm_buffer
+        g_pwm_buffer[led.driver][led.r - 0x24] = red;
+        g_pwm_buffer[led.driver][led.g - 0x24] = green;
+        g_pwm_buffer[led.driver][led.b - 0x24] = blue;
+        g_pwm_buffer_update_required = true;
+    }
+}
+
+void IS31FL3731_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
+{
+    for ( int i = 0; i < DRIVER_LED_TOTAL; i++ )
+    {
+        IS31FL3731_set_color( i, red, green, blue );
+    }
+}
+
+void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, bool blue )
+{
+    is31_led led = g_is31_leds[index];
+
+  uint8_t control_register_r = (led.r - 0x24) / 8;
+  uint8_t control_register_g = (led.g - 0x24) / 8;
+  uint8_t control_register_b = (led.b - 0x24) / 8;
+  uint8_t bit_r = (led.r - 0x24) % 8;
+  uint8_t bit_g = (led.g - 0x24) % 8;
+  uint8_t bit_b = (led.b - 0x24) % 8;
+
+    if ( red ) {
+        g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
+    } else {
+        g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
+    }
+    if ( green ) {
+        g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
+    } else {
+        g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
+    }
+    if ( blue ) {
+        g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
+    } else {
+        g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
+    }
+
+    g_led_control_registers_update_required = true;
+
+}
+
+void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
+{
+    if ( g_pwm_buffer_update_required )
+    {
+        IS31FL3731_write_pwm_buffer( addr1, g_pwm_buffer[0] );
+        IS31FL3731_write_pwm_buffer( addr2, g_pwm_buffer[1] );
+    }
+    g_pwm_buffer_update_required = false;
+}
+
+void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
+{
+    if ( g_led_control_registers_update_required )
+    {
+        for ( int i=0; i<18; i++ )
+        {
+            IS31FL3731_write_register(addr1, i, g_led_control_registers[0][i] );
+            IS31FL3731_write_register(addr2, i, g_led_control_registers[1][i] );
+        }
+    }
+}
+
diff --git a/drivers/issi/is31fl3731.h b/drivers/issi/is31fl3731.h
new file mode 100644 (file)
index 0000000..f354a12
--- /dev/null
@@ -0,0 +1,214 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef IS31FL3731_DRIVER_H
+#define IS31FL3731_DRIVER_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct is31_led {
+  uint8_t driver:2;
+  uint8_t r;
+  uint8_t g;
+  uint8_t b;
+} __attribute__((packed)) is31_led;
+
+extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+
+void IS31FL3731_init( uint8_t addr );
+void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data );
+void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer );
+
+void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
+void IS31FL3731_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
+
+void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, bool blue );
+
+// This should not be called from an interrupt
+// (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 IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
+void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
+
+#define C1_1  0x24
+#define C1_2  0x25
+#define C1_3  0x26
+#define C1_4  0x27
+#define C1_5  0x28
+#define C1_6  0x29
+#define C1_7  0x2A
+#define C1_8  0x2B
+
+#define C1_9  0x2C
+#define C1_10 0x2D
+#define C1_11 0x2E
+#define C1_12 0x2F
+#define C1_13 0x30
+#define C1_14 0x31
+#define C1_15 0x32
+#define C1_16 0x33
+
+#define C2_1  0x34
+#define C2_2  0x35
+#define C2_3  0x36
+#define C2_4  0x37
+#define C2_5  0x38
+#define C2_6  0x39
+#define C2_7  0x3A
+#define C2_8  0x3B
+
+#define C2_9  0x3C
+#define C2_10 0x3D
+#define C2_11 0x3E
+#define C2_12 0x3F
+#define C2_13 0x40
+#define C2_14 0x41
+#define C2_15 0x42
+#define C2_16 0x43
+
+#define C3_1  0x44
+#define C3_2  0x45
+#define C3_3  0x46
+#define C3_4  0x47
+#define C3_5  0x48
+#define C3_6  0x49
+#define C3_7  0x4A
+#define C3_8  0x4B
+
+#define C3_9  0x4C
+#define C3_10 0x4D
+#define C3_11 0x4E
+#define C3_12 0x4F
+#define C3_13 0x50
+#define C3_14 0x51
+#define C3_15 0x52
+#define C3_16 0x53
+
+#define C4_1  0x54
+#define C4_2  0x55
+#define C4_3  0x56
+#define C4_4  0x57
+#define C4_5  0x58
+#define C4_6  0x59
+#define C4_7  0x5A
+#define C4_8  0x5B
+
+#define C4_9  0x5C
+#define C4_10 0x5D
+#define C4_11 0x5E
+#define C4_12 0x5F
+#define C4_13 0x60
+#define C4_14 0x61
+#define C4_15 0x62
+#define C4_16 0x63
+
+#define C5_1  0x64
+#define C5_2  0x65
+#define C5_3  0x66
+#define C5_4  0x67
+#define C5_5  0x68
+#define C5_6  0x69
+#define C5_7  0x6A
+#define C5_8  0x6B
+
+#define C5_9  0x6C
+#define C5_10 0x6D
+#define C5_11 0x6E
+#define C5_12 0x6F
+#define C5_13 0x70
+#define C5_14 0x71
+#define C5_15 0x72
+#define C5_16 0x73
+
+#define C6_1  0x74
+#define C6_2  0x75
+#define C6_3  0x76
+#define C6_4  0x77
+#define C6_5  0x78
+#define C6_6  0x79
+#define C6_7  0x7A
+#define C6_8  0x7B
+
+#define C6_9  0x7C
+#define C6_10 0x7D
+#define C6_11 0x7E
+#define C6_12 0x7F
+#define C6_13 0x80
+#define C6_14 0x81
+#define C6_15 0x82
+#define C6_16 0x83
+
+#define C7_1  0x84
+#define C7_2  0x85
+#define C7_3  0x86
+#define C7_4  0x87
+#define C7_5  0x88
+#define C7_6  0x89
+#define C7_7  0x8A
+#define C7_8  0x8B
+
+#define C7_9  0x8C
+#define C7_10 0x8D
+#define C7_11 0x8E
+#define C7_12 0x8F
+#define C7_13 0x90
+#define C7_14 0x91
+#define C7_15 0x92
+#define C7_16 0x93
+
+#define C8_1  0x94
+#define C8_2  0x95
+#define C8_3  0x96
+#define C8_4  0x97
+#define C8_5  0x98
+#define C8_6  0x99
+#define C8_7  0x9A
+#define C8_8  0x9B
+
+#define C8_9  0x9C
+#define C8_10 0x9D
+#define C8_11 0x9E
+#define C8_12 0x9F
+#define C8_13 0xA0
+#define C8_14 0xA1
+#define C8_15 0xA2
+#define C8_16 0xA3
+
+#define C9_1  0xA4
+#define C9_2  0xA5
+#define C9_3  0xA6
+#define C9_4  0xA7
+#define C9_5  0xA8
+#define C9_6  0xA9
+#define C9_7  0xAA
+#define C9_8  0xAB
+
+#define C9_9  0xAC
+#define C9_10 0xAD
+#define C9_11 0xAE
+#define C9_12 0xAF
+#define C9_13 0xB0
+#define C9_14 0xB1
+#define C9_15 0xB2
+#define C9_16 0xB3
+
+
+
+#endif // IS31FL3731_DRIVER_H
diff --git a/drivers/issi/is31fl3733.c b/drivers/issi/is31fl3733.c
new file mode 100644 (file)
index 0000000..4098b54
--- /dev/null
@@ -0,0 +1,253 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2018 Yiancar
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef __AVR__
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#else
+#include "wait.h"
+#endif
+
+#include "is31fl3733.h"
+#include <string.h>
+#include "i2c_master.h"
+#include "progmem.h"
+
+// This is a 7-bit address, that gets left-shifted and bit 0
+// set to 0 for write, 1 for read (as per I2C protocol)
+// The address will vary depending on your wiring:
+// 00 <-> GND
+// 01 <-> SCL
+// 10 <-> SDA
+// 11 <-> VCC
+// ADDR1 represents A1:A0 of the 7-bit address.
+// ADDR2 represents A3:A2 of the 7-bit address.
+// The result is: 0b101(ADDR2)(ADDR1)
+#define ISSI_ADDR_DEFAULT 0x50
+
+#define ISSI_COMMANDREGISTER 0xFD
+#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE
+#define ISSI_INTERRUPTMASKREGISTER 0xF0
+#define ISSI_INTERRUPTSTATUSREGISTER 0xF1
+
+#define ISSI_PAGE_LEDCONTROL 0x00 //PG0
+#define ISSI_PAGE_PWM 0x01        //PG1
+#define ISSI_PAGE_AUTOBREATH 0x02 //PG2
+#define ISSI_PAGE_FUNCTION 0x03   //PG3
+
+#define ISSI_REG_CONFIGURATION 0x00 //PG3
+#define ISSI_REG_GLOBALCURRENT 0x01 //PG3
+#define ISSI_REG_RESET 0x11// PG3
+#define ISSI_REG_SWPULLUP 0x0F //PG3
+#define ISSI_REG_CSPULLUP 0x10 //PG3
+
+#ifndef ISSI_TIMEOUT
+  #define ISSI_TIMEOUT 100
+#endif
+
+#ifndef ISSI_PERSISTENCE
+  #define ISSI_PERSISTENCE 0
+#endif
+
+// Transfer buffer for TWITransmitData()
+uint8_t g_twi_transfer_buffer[20];
+
+// These buffers match the IS31FL3733 PWM registers.
+// The control buffers match the PG0 LED On/Off registers.
+// Storing them like this is optimal for I2C transfers to the registers.
+// We could optimize this and take out the unused registers from these
+// buffers and the transfers in IS31FL3733_write_pwm_buffer() but it's
+// probably not worth the extra complexity.
+uint8_t g_pwm_buffer[DRIVER_COUNT][192];
+bool g_pwm_buffer_update_required = false;
+
+uint8_t g_led_control_registers[DRIVER_COUNT][24] = { { 0 }, { 0 } };
+bool g_led_control_registers_update_required = false;
+
+void IS31FL3733_write_register( uint8_t addr, uint8_t reg, uint8_t data )
+{
+    g_twi_transfer_buffer[0] = reg;
+    g_twi_transfer_buffer[1] = data;
+
+  #if ISSI_PERSISTENCE > 0
+    for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+      if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) == 0)
+        break;
+    }
+  #else
+    i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
+  #endif
+}
+
+void IS31FL3733_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
+{
+    // assumes PG1 is already selected
+
+    // transmit PWM registers in 12 transfers of 16 bytes
+    // g_twi_transfer_buffer[] is 20 bytes
+
+    // iterate over the pwm_buffer contents at 16 byte intervals
+    for ( int i = 0; i < 192; i += 16 ) {
+        g_twi_transfer_buffer[0] = i;
+        // copy the data from i to i+15
+        // device will auto-increment register for data after the first byte
+        // thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer
+        for ( int j = 0; j < 16; j++ ) {
+            g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j];
+        }
+
+    #if ISSI_PERSISTENCE > 0
+      for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+        if (i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0)
+          break;
+      }
+    #else
+      i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT);
+    #endif
+    }
+}
+
+void IS31FL3733_init( uint8_t addr )
+{
+    // 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.
+
+    // Unlock the command register.
+    IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+    // Select PG0
+    IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL );
+    // Turn off all LEDs.
+    for ( int i = 0x00; i <= 0x17; i++ )
+    {
+        IS31FL3733_write_register( addr, i, 0x00 );
+    }
+
+    // Unlock the command register.
+    IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+    // Select PG1
+    IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM );
+    // Set PWM on all LEDs to 0
+    // No need to setup Breath registers to PWM as that is the default.
+    for ( int i = 0x00; i <= 0xBF; i++ )
+    {
+        IS31FL3733_write_register( addr, i, 0x00 );
+    }
+
+    // Unlock the command register.
+    IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+
+    // Select PG3
+    IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION );
+    // Set global current to maximum.
+    IS31FL3733_write_register( addr, ISSI_REG_GLOBALCURRENT, 0xFF );
+    // Disable software shutdown.
+    IS31FL3733_write_register( addr, ISSI_REG_CONFIGURATION, 0x01 );
+
+    // Wait 10ms to ensure the device has woken up.
+    #ifdef __AVR__
+    _delay_ms( 10 );
+    #else
+    wait_ms(10);
+    #endif
+}
+
+void IS31FL3733_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
+{
+    if ( index >= 0 && index < DRIVER_LED_TOTAL ) {
+        is31_led led = g_is31_leds[index];
+
+        g_pwm_buffer[led.driver][led.r] = red;
+        g_pwm_buffer[led.driver][led.g] = green;
+        g_pwm_buffer[led.driver][led.b] = blue;
+        g_pwm_buffer_update_required = true;
+    }
+}
+
+void IS31FL3733_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
+{
+    for ( int i = 0; i < DRIVER_LED_TOTAL; i++ )
+    {
+        IS31FL3733_set_color( i, red, green, blue );
+    }
+}
+
+void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, bool blue )
+{
+    is31_led led = g_is31_leds[index];
+
+  uint8_t control_register_r = led.r / 8;
+  uint8_t control_register_g = led.g / 8;
+  uint8_t control_register_b = led.b / 8;
+  uint8_t bit_r = led.r % 8;
+  uint8_t bit_g = led.g % 8;
+  uint8_t bit_b = led.b % 8;
+
+    if ( red ) {
+        g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r);
+    } else {
+        g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r);
+    }
+    if ( green ) {
+        g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g);
+    } else {
+        g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g);
+    }
+    if ( blue ) {
+        g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b);
+    } else {
+        g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
+    }
+
+    g_led_control_registers_update_required = true;
+
+}
+
+void IS31FL3733_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
+{
+    if ( g_pwm_buffer_update_required )
+    {
+        // Firstly we need to unlock the command register and select PG1
+        IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+        IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM );
+
+        IS31FL3733_write_pwm_buffer( addr1, g_pwm_buffer[0] );
+        //IS31FL3733_write_pwm_buffer( addr2, g_pwm_buffer[1] );
+    }
+    g_pwm_buffer_update_required = false;
+}
+
+void IS31FL3733_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
+{
+    if ( g_led_control_registers_update_required )
+    {
+        // Firstly we need to unlock the command register and select PG0
+        IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
+        IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL );
+        for ( int i=0; i<24; i++ )
+        {
+            IS31FL3733_write_register(addr1, i, g_led_control_registers[0][i] );
+            //IS31FL3733_write_register(addr2, i, g_led_control_registers[1][i] );
+        }
+    }
+}
+
diff --git a/drivers/issi/is31fl3733.h b/drivers/issi/is31fl3733.h
new file mode 100644 (file)
index 0000000..3d23b18
--- /dev/null
@@ -0,0 +1,255 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2018 Yiancar
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef IS31FL3733_DRIVER_H
+#define IS31FL3733_DRIVER_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct is31_led {
+  uint8_t driver:2;
+  uint8_t r;
+  uint8_t g;
+  uint8_t b;
+} __attribute__((packed)) is31_led;
+
+extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];
+
+void IS31FL3733_init( uint8_t addr );
+void IS31FL3733_write_register( uint8_t addr, uint8_t reg, uint8_t data );
+void IS31FL3733_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer );
+
+void IS31FL3733_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
+void IS31FL3733_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
+
+void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, bool blue );
+
+// This should not be called from an interrupt
+// (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 IS31FL3733_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
+void IS31FL3733_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
+
+#define A_1  0x00
+#define A_2  0x01
+#define A_3  0x02
+#define A_4  0x03
+#define A_5  0x04
+#define A_6  0x05
+#define A_7  0x06
+#define A_8  0x07
+#define A_9  0x08
+#define A_10  0x09
+#define A_11  0x0A
+#define A_12  0x0B
+#define A_13  0x0C
+#define A_14  0x0D
+#define A_15  0x0E
+#define A_16  0x0F
+
+#define B_1  0x10
+#define B_2  0x11
+#define B_3  0x12
+#define B_4  0x13
+#define B_5  0x14
+#define B_6  0x15
+#define B_7  0x16
+#define B_8  0x17
+#define B_9  0x18
+#define B_10  0x19
+#define B_11  0x1A
+#define B_12  0x1B
+#define B_13  0x1C
+#define B_14  0x1D
+#define B_15  0x1E
+#define B_16  0x1F
+
+#define C_1  0x20
+#define C_2  0x21
+#define C_3  0x22
+#define C_4  0x23
+#define C_5  0x24
+#define C_6  0x25
+#define C_7  0x26
+#define C_8  0x27
+#define C_9  0x28
+#define C_10  0x29
+#define C_11  0x2A
+#define C_12  0x2B
+#define C_13  0x2C
+#define C_14  0x2D
+#define C_15  0x2E
+#define C_16  0x2F
+
+#define D_1  0x30
+#define D_2  0x31
+#define D_3  0x32
+#define D_4  0x33
+#define D_5  0x34
+#define D_6  0x35
+#define D_7  0x36
+#define D_8  0x37
+#define D_9  0x38
+#define D_10  0x39
+#define D_11  0x3A
+#define D_12  0x3B
+#define D_13  0x3C
+#define D_14  0x3D
+#define D_15  0x3E
+#define D_16  0x3F
+
+#define E_1  0x40
+#define E_2  0x41
+#define E_3  0x42
+#define E_4  0x43
+#define E_5  0x44
+#define E_6  0x45
+#define E_7  0x46
+#define E_8  0x47
+#define E_9  0x48
+#define E_10  0x49
+#define E_11  0x4A
+#define E_12  0x4B
+#define E_13  0x4C
+#define E_14  0x4D
+#define E_15  0x4E
+#define E_16  0x4F
+
+#define F_1  0x50
+#define F_2  0x51
+#define F_3  0x52
+#define F_4  0x53
+#define F_5  0x54
+#define F_6  0x55
+#define F_7  0x56
+#define F_8  0x57
+#define F_9  0x58
+#define F_10  0x59
+#define F_11  0x5A
+#define F_12  0x5B
+#define F_13  0x5C
+#define F_14  0x5D
+#define F_15  0x5E
+#define F_16  0x5F
+
+#define G_1  0x60
+#define G_2  0x61
+#define G_3  0x62
+#define G_4  0x63
+#define G_5  0x64
+#define G_6  0x65
+#define G_7  0x66
+#define G_8  0x67
+#define G_9  0x68
+#define G_10  0x69
+#define G_11  0x6A
+#define G_12  0x6B
+#define G_13  0x6C
+#define G_14  0x6D
+#define G_15  0x6E
+#define G_16  0x6F
+
+#define H_1  0x70
+#define H_2  0x71
+#define H_3  0x72
+#define H_4  0x73
+#define H_5  0x74
+#define H_6  0x75
+#define H_7  0x76
+#define H_8  0x77
+#define H_9  0x78
+#define H_10  0x79
+#define H_11  0x7A
+#define H_12  0x7B
+#define H_13  0x7C
+#define H_14  0x7D
+#define H_15  0x7E
+#define H_16  0x7F
+
+#define I_1  0x80
+#define I_2  0x81
+#define I_3  0x82
+#define I_4  0x83
+#define I_5  0x84
+#define I_6  0x85
+#define I_7  0x86
+#define I_8  0x87
+#define I_9  0x88
+#define I_10  0x89
+#define I_11  0x8A
+#define I_12  0x8B
+#define I_13  0x8C
+#define I_14  0x8D
+#define I_15  0x8E
+#define I_16  0x8F
+
+#define J_1  0x90
+#define J_2  0x91
+#define J_3  0x92
+#define J_4  0x93
+#define J_5  0x94
+#define J_6  0x95
+#define J_7  0x96
+#define J_8  0x97
+#define J_9  0x98
+#define J_10  0x99
+#define J_11  0x9A
+#define J_12  0x9B
+#define J_13  0x9C
+#define J_14  0x9D
+#define J_15  0x9E
+#define J_16  0x9F
+
+#define K_1  0xA0
+#define K_2  0xA1
+#define K_3  0xA2
+#define K_4  0xA3
+#define K_5  0xA4
+#define K_6  0xA5
+#define K_7  0xA6
+#define K_8  0xA7
+#define K_9  0xA8
+#define K_10  0xA9
+#define K_11  0xAA
+#define K_12  0xAB
+#define K_13  0xAC
+#define K_14  0xAD
+#define K_15  0xAE
+#define K_16  0xAF
+
+#define L_1  0xB0
+#define L_2  0xB1
+#define L_3  0xB2
+#define L_4  0xB3
+#define L_5  0xB4
+#define L_6  0xB5
+#define L_7  0xB6
+#define L_8  0xB7
+#define L_9  0xB8
+#define L_10  0xB9
+#define L_11  0xBA
+#define L_12  0xBB
+#define L_13  0xBC
+#define L_14  0xBD
+#define L_15  0xBE
+#define L_16  0xBF
+
+#endif // IS31FL3733_DRIVER_H
index 1db9846f045836856186ab8458576ecf35adb67c..b4e4de1743f1d388828dc6d893b30cb551802e56 100644 (file)
@@ -28,7 +28,7 @@
     #include "backlight.h"
 #endif
 #if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE)
-       #include "rgb.h"
+    #include "rgb.h"
 #endif
 #ifdef RGBLIGHT_ENABLE
   #include "rgblight.h"
@@ -39,7 +39,7 @@
 #endif
 
 #ifdef RGB_MATRIX_ENABLE
-       #include "rgb_matrix.h"
+    #include "rgb_matrix.h"
 #endif
 
 #include "action_layer.h"
 extern uint32_t default_layer_state;
 
 #ifndef NO_ACTION_LAYER
-       extern uint32_t layer_state;
+    extern uint32_t layer_state;
 #endif
 
 #ifdef MIDI_ENABLE
 #ifdef MIDI_ADVANCED
-       #include "process_midi.h"
+    #include "process_midi.h"
 #endif
 #endif // MIDI_ENABLE
 
 #ifdef AUDIO_ENABLE
-       #include "audio.h"
-       #include "process_audio.h"
+    #include "audio.h"
+    #include "process_audio.h"
   #ifdef AUDIO_CLICKY
     #include "process_clicky.h"
   #endif // AUDIO_CLICKY
 #endif
 
 #ifdef STENO_ENABLE
-       #include "process_steno.h"
+    #include "process_steno.h"
 #endif
 
 #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
-       #include "process_music.h"
+    #include "process_music.h"
 #endif
 
 #ifndef DISABLE_LEADER
-       #include "process_leader.h"
+    #include "process_leader.h"
 #endif
 
 #define DISABLE_CHORDING
 #ifndef DISABLE_CHORDING
-       #include "process_chording.h"
+    #include "process_chording.h"
 #endif
 
 #ifdef UNICODE_ENABLE
-       #include "process_unicode.h"
+    #include "process_unicode.h"
 #endif
 
 #ifdef UCIS_ENABLE
-       #include "process_ucis.h"
+    #include "process_ucis.h"
 #endif
 
 #ifdef UNICODEMAP_ENABLE
-       #include "process_unicodemap.h"
+    #include "process_unicodemap.h"
 #endif
 
 #include "process_tap_dance.h"
 
 #ifdef PRINTING_ENABLE
-       #include "process_printer.h"
+    #include "process_printer.h"
 #endif
 
 #ifdef AUTO_SHIFT_ENABLE
-       #include "process_auto_shift.h"
+    #include "process_auto_shift.h"
 #endif
 
 #ifdef COMBO_ENABLE
-       #include "process_combo.h"
+    #include "process_combo.h"
 #endif
 
 #ifdef KEY_LOCK_ENABLE
-       #include "process_key_lock.h"
+    #include "process_key_lock.h"
 #endif
 
 #ifdef TERMINAL_ENABLE
-       #include "process_terminal.h"
+    #include "process_terminal.h"
 #else
-       #include "process_terminal_nop.h"
+    #include "process_terminal_nop.h"
 #endif
 
 #ifdef HD44780_ENABLE
-       #include "hd44780.h"
+    #include "hd44780.h"
 #endif
 
 #define STRINGIZE(z) #z
index 70ad1a17833dfd0ffb5ccdcb2c06aee4f127ae4a..197bc1ac5e054541d9538982172b35aa6b2da838 100644 (file)
@@ -1,5 +1,6 @@
 /* Copyright 2017 Jason Williams
  * Copyright 2017 Jack Humbert
+ * Copyright 2018 Yiancar
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 
 #include "rgb_matrix.h"
-#include <avr/io.h>
 #include "i2c_master.h"
-#include <util/delay.h>
-#include <avr/interrupt.h>
 #include "progmem.h"
 #include "config.h"
 #include "eeprom.h"
-#include "lufa.h"
 #include <math.h>
 
 rgb_config_t rgb_matrix_config;
 
+#ifndef MAX
+    #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+#endif
+
+#ifndef MIN
+    #define MIN(a,b) ((a) < (b)? (a): (b))
+#endif
+
 #ifndef RGB_DISABLE_AFTER_TIMEOUT
     #define RGB_DISABLE_AFTER_TIMEOUT 0
 #endif
@@ -106,16 +111,29 @@ void map_row_column_to_led( uint8_t row, uint8_t column, uint8_t *led_i, uint8_t
 }
 
 void rgb_matrix_update_pwm_buffers(void) {
-    IS31_update_pwm_buffers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
-    IS31_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+#ifdef IS31FL3731
+    IS31FL3731_update_pwm_buffers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+    IS31FL3731_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+#elif defined(IS31FL3733)
+    IS31FL3733_update_pwm_buffers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+    IS31FL3733_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+#endif
 }
 
 void rgb_matrix_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) {
-    IS31_set_color( index, red, green, blue );
+#ifdef IS31FL3731
+    IS31FL3731_set_color( index, red, green, blue );
+#elif defined(IS31FL3733)
+    IS31FL3733_set_color( index, red, green, blue );
+#endif
 }
 
 void rgb_matrix_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) {
-    IS31_set_color_all( red, green, blue );
+#ifdef IS31FL3731
+    IS31FL3731_set_color_all( red, green, blue );
+#elif defined(IS31FL3733)
+    IS31FL3733_set_color_all( red, green, blue );
+#endif
 }
 
 bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) {
@@ -460,7 +478,7 @@ void rgb_matrix_rainbow_moving_chevron(void) {
     for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
         led = g_rgb_leds[i];
         // uint8_t r = g_tick;
-        uint8_t r = 32;
+        uint8_t r = 128;
         hsv.h = (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * abs(led.point.y - 32.0)* sin(r * PI / 128) + (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (led.point.x - (g_tick / 256.0 * 224)) * cos(r * PI / 128) + rgb_matrix_config.hue;
         rgb = hsv_to_rgb( hsv );
         rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
@@ -752,16 +770,28 @@ void rgb_matrix_init(void) {
 void rgb_matrix_setup_drivers(void) {
   // Initialize TWI
   i2c_init();
-  IS31_init( DRIVER_ADDR_1 );
-  IS31_init( DRIVER_ADDR_2 );
+#ifdef IS31FL3731
+  IS31FL3731_init( DRIVER_ADDR_1 );
+  IS31FL3731_init( DRIVER_ADDR_2 );
+#elif defined (IS31FL3733)
+  IS31FL3733_init( DRIVER_ADDR_1 );
+#endif
 
   for ( int index = 0; index < DRIVER_LED_TOTAL; index++ ) {
     bool enabled = true;
     // This only caches it for later
-    IS31_set_led_control_register( index, enabled, enabled, enabled );
+#ifdef IS31FL3731
+    IS31FL3731_set_led_control_register( index, enabled, enabled, enabled );
+#elif defined (IS31FL3733)
+    IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
+#endif
   }
   // This actually updates the LED drivers
-  IS31_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+#ifdef IS31FL3731
+  IS31FL3731_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+#elif defined (IS31FL3733)
+  IS31FL3733_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+#endif
 }
 
 // Deals with the messy details of incrementing an integer
@@ -811,11 +841,19 @@ void rgb_matrix_test_led( uint8_t index, bool red, bool green, bool blue ) {
     {
         if ( i == index )
         {
-            IS31_set_led_control_register( i, red, green, blue );
+#ifdef IS31FL3731
+            IS31FL3731_set_led_control_register( i, red, green, blue );
+#elif defined (IS31FL3733)
+            IS31FL3733_set_led_control_register( i, red, green, blue );
+#endif
         }
         else
         {
-            IS31_set_led_control_register( i, false, false, false );
+#ifdef IS31FL3731
+            IS31FL3731_set_led_control_register( i, false, false, false );
+#elif defined (IS31FL3733)
+            IS31FL3733_set_led_control_register( i, false, false, false );
+#endif
         }
     }
 }
index 5769314002b50c792787e3e55f3b77ec5f6fb614..b91c9fba598c34bd550de4083bba116103086d95 100644 (file)
@@ -1,5 +1,6 @@
 /* Copyright 2017 Jason Williams
  * Copyright 2017 Jack Humbert
+ * Copyright 2018 Yiancar
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <stdint.h>
 #include <stdbool.h>
 #include "color.h"
-#include "is31fl3731.h"
 #include "quantum.h"
 
+#ifdef IS31FL3731
+    #include "is31fl3731.h"
+#elif defined (IS31FL3733)
+    #include "is31fl3733.h"
+#endif
+
 typedef struct Point {
        uint8_t x;
        uint8_t y;