diff --git a/drivers/arm/i2c_master.c b/drivers/arm/i2c_master.c
index 50a30ebce7..2ef3f32314 100644
--- a/drivers/arm/i2c_master.c
+++ b/drivers/arm/i2c_master.c
@@ -65,11 +65,13 @@ uint8_t i2c_start(uint8_t address)
return 0;
}
-uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)
+int8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)
{
+ //xprintf("i2c_transmit(0x%x, 0x%x, %d, 0x%x) address:0x%x\n", address, data, length, timeout, address >> 1);
i2c_address = address;
i2cStart(&I2C_DRIVER, &i2cconfig);
- return i2cMasterTransmitTimeout(&I2C_DRIVER, (i2c_address >> 1), data, length, 0, 0, MS2ST(timeout));
+ int8_t result = i2cMasterTransmitTimeout(&I2C_DRIVER, i2c_address, data, length, 0, 0, MS2ST(timeout));
+ return result;
}
uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout)
diff --git a/drivers/arm/i2c_master.h b/drivers/arm/i2c_master.h
index 7a9eb32eb9..b8087b5a33 100644
--- a/drivers/arm/i2c_master.h
+++ b/drivers/arm/i2c_master.h
@@ -42,7 +42,7 @@
void i2c_init(void);
uint8_t i2c_start(uint8_t address);
-uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout);
+int8_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_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t * rx_body, uint16_t rx_length);
uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout);
diff --git a/drivers/issi/is31fl3235a.c b/drivers/issi/is31fl3235a.c
new file mode 100644
index 0000000000..ffaeeacb23
--- /dev/null
+++ b/drivers/issi/is31fl3235a.c
@@ -0,0 +1,227 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2019 Clueboard
+ *
+ * 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 .
+ */
+
+#ifdef __AVR__
+#include
+#include
+#include
+#else
+#include "wait.h"
+#endif
+
+#include
+#include
+#include
+#include "is31fl3235a.h"
+#include "i2c_master.h"
+#include "progmem.h"
+#include "print.h"
+
+
+#define ISSI_REG_CONFIG 0x00 // FIXME: Not on 3235?
+#define ISSI_REG_CONFIG_PICTUREMODE 0x00 // FIXME: Not on 3235?
+
+//#define ISSI_REG_AUDIOSYNC 0x06 // FIXME: Not on 3235?
+
+#define ISSI_COMMANDREGISTER 0xFD // FIXME: Not on 3235?
+#define ISSI_BANK_FUNCTIONREG 0x0B // FIXME: Not on 3235?
+
+#ifndef ISSI_TIMEOUT
+ #define ISSI_TIMEOUT 100
+#endif
+
+#ifndef ISSI_PERSISTENCE
+ #define ISSI_PERSISTENCE 0
+#endif
+
+// Transfer buffer for TWITransmitData()
+uint8_t g_3235a_transfer_buffer[20];
+
+// These buffers match the IS31FL3235A PWM registers 0x05-0x20.
+// 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 IS31FL3235A_write_pwm_buffer() but it's
+// probably not worth the extra complexity.
+uint8_t g_rgb7seg_buffer[IS31FL3235A_COUNT][IS31FL3235A_LED_MAX];
+bool g_rgb7seg_buffer_update_required = false;
+
+/* There's probably a better way to init this... */
+#if IS31FL3235A_COUNT == 1
+ uint8_t g_3235a_control_registers[IS31FL3235A_COUNT][18] = {{0}};
+#elif IS31FL3235A_COUNT == 2
+ uint8_t g_3235a_control_registers[IS31FL3235A_COUNT][18] = {{0}, {0}};
+#elif IS31FL3235A_COUNT == 3
+ uint8_t g_3235a_control_registers[IS31FL3235A_COUNT][18] = {{0}, {0}, {0}};
+#elif IS31FL3235A_COUNT == 4
+ uint8_t g_3235a_control_registers[IS31FL3235A_COUNT][18] = {{0}, {0}, {0}, {0}};
+#endif
+bool g_rgb7seg_control_registers_update_required = false;
+
+void IS31FL3235A_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
+ g_3235a_transfer_buffer[0] = reg;
+ g_3235a_transfer_buffer[1] = data;
+ xprintf("IS31FL3235A_write_register(0x%x, 0x%x, 0x%x); g_3235a_transfer_buffer:0x%x\n", addr, reg, data, g_3235a_transfer_buffer);
+
+ #if ISSI_PERSISTENCE > 0
+ for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) {
+ if (i2c_transmit(addr, g_3235a_transfer_buffer, 2, ISSI_TIMEOUT) == 0) {
+ break;
+ }
+ }
+ #else
+ if (i2c_transmit(addr, g_3235a_transfer_buffer, 2, ISSI_TIMEOUT) == -1) {
+ // When we encounter a timeout ChibiOS says the bus must be reset as it's in an unknown state
+ xprintf("i2c transmit timeout, resetting i2c bus!\n");
+ i2c_stop(ISSI_TIMEOUT);
+ wait_ms(5);
+ i2c_start(ISSI_TIMEOUT);
+ }
+ #endif
+}
+
+void IS31FL3235A_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_3235a_transfer_buffer[] is 20 bytes
+
+ // iterate over the pwm_buffer contents at 16 byte intervals
+ for (int i = 0; i < IS31FL3235A_LED_MAX; i += 16) {
+ // set the first register, e.g. 0x24, 0x34, 0x44, etc.
+ g_3235a_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_3235a_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_3235a_transfer_buffer, 17, ISSI_TIMEOUT) == 0)
+ break;
+ }
+ #else
+ if (i2c_transmit(addr << 1, g_3235a_transfer_buffer, 17, ISSI_TIMEOUT) == -1) {
+ // When we encounter a timeout ChibiOS says the bus must be reset as it's in an unknown state
+ xprintf("i2c transmit timeout, resetting i2c bus!\n");
+ i2c_stop(ISSI_TIMEOUT);
+ wait_ms(5);
+ i2c_start(ISSI_TIMEOUT);
+ }
+ #endif
+ }
+}
+
+void IS31FL3235A_init(uint8_t addr) {
+ wait_ms(2000); // Give QMK Toolbox time to attach
+ xprintf("IS31FS3235A_init(0x%x)\n", 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.
+
+ // Reset settings to default
+ //IS31FL3235A_write_register(addr, ISSI_REG_RESET_REG, 0);
+
+ // this delay was copied from other drivers, might not be needed
+ wait_ms(10);
+
+ // This is how the Arduino code does init...
+ uint8_t i = 0;
+
+ for (i=0x2A; i<=0x45; i++) {
+ IS31FL3235A_write_register(addr, i, 0xFF); // Turn off all LEDs
+ }
+
+ for (i=0x05; i<=0x20; i++) {
+ IS31FL3235A_write_register(addr, i, 0x00); // Write all PWM set 0x00
+ }
+
+ IS31FL3235A_write_register(addr, 0x25, 0x00); //update PWM&Control registers
+ IS31FL3235A_write_register(addr, 0x4B, 0x01); //frequency setting 22KHz
+ IS31FL3235A_write_register(addr, 0x00, 0x01); //normal operation
+
+ // This is how the Arduino code does LED turn on
+ IS31FL3235A_write_register(addr, 0x05, 0xFF); // set PWM
+ IS31FL3235A_write_register(addr, 0x25, 0x00); // update PWM&Control registers
+ IS31FL3235A_write_register(addr, 0x08, 0xFF); // set PWM
+ IS31FL3235A_write_register(addr, 0x25, 0x00); // update PWM&Control registers
+ IS31FL3235A_write_register(addr, 0x12, 0xFF); // set PWM
+ IS31FL3235A_write_register(addr, 0x25, 0x00); // update PWM&Control registers
+
+ // FIXME: This is for testing, turn on OUT1 at full brightness
+ //IS31FL3235A_write_register(addr, 0x2A, 0xFF);
+ //IS31FL3235A_write_register(addr, 0x05, 0x00);
+
+ // I think this finally turns it on?
+ //IS31FL3235A_write_register(addr, 0x25, 0x00); //update PWM&Control registers
+ //IS31FL3235A_write_register(addr, 0x4B, 0x01); //frequency setting 22KHz
+ //IS31FL3235A_write_register(addr, 0x00, 0x01); //normal operation
+}
+
+void IS31FL3235A_set_value(int index, uint8_t value) {
+/*
+ if (index >= 0 && index < IS31FL3235A_LED_COUNT) {
+ is31_led led = g_is31_leds[index];
+
+ // Subtract 0x24 to get the second index of g_rgb7seg_buffer
+ g_rgb7seg_buffer[led.driver][led.v - 0x24] = value;
+ g_rgb7seg_buffer_update_required = true;
+ }
+*/
+}
+
+void IS31FL3235A_set_value_all(uint8_t value) {
+ for (int i = 0; i < IS31FL3235A_LED_COUNT; i++) {
+ IS31FL3235A_set_value(i, value);
+ }
+}
+
+void IS31FL3235A_set_led_control_register(uint8_t index, bool value) {
+/*
+ is31_led led = g_is31_leds[index];
+
+ uint8_t control_register = (led.v - 0x24) / 8;
+ uint8_t bit_value = (led.v - 0x24) % 8;
+
+ if (value) {
+ g_3235a_control_registers[led.driver][control_register] |= (1 << bit_value);
+ } else {
+ g_3235a_control_registers[led.driver][control_register] &= ~(1 << bit_value);
+ }
+
+ g_rgb7seg_control_registers_update_required = true;
+*/
+}
+
+void IS31FL3235A_update_pwm_buffers(uint8_t addr, uint8_t index) {
+ //xprintf("IS31FS3235A_update_pwm_buffers(0x%x, %d)\n", addr, index);
+ if (g_rgb7seg_buffer_update_required) {
+ IS31FL3235A_write_pwm_buffer(addr, g_rgb7seg_buffer[index]);
+ g_rgb7seg_buffer_update_required = false;
+ }
+}
+
+void IS31FL3235A_update_led_control_registers(uint8_t addr, uint8_t index) {
+ if (g_rgb7seg_control_registers_update_required) {
+ for (int i=0; i<18; i++) {
+ IS31FL3235A_write_register(addr, i, g_3235a_control_registers[index][i]);
+ }
+ }
+}
diff --git a/drivers/issi/is31fl3235a.h b/drivers/issi/is31fl3235a.h
new file mode 100644
index 0000000000..6c53c73a50
--- /dev/null
+++ b/drivers/issi/is31fl3235a.h
@@ -0,0 +1,141 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2018 Jack Humbert
+ * Copyright 2019 Clueboard
+ *
+ * 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 .
+ */
+
+
+#ifndef IS31FL3235A_DRIVER_H
+#define IS31FL3235A_DRIVER_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:
+// 0b0111111 AD <-> VCC
+// 0b0111110 AD <-> SDA
+// 0b0111101 AD <-> SCL
+// 0b0111100 AD <-> GND
+#ifndef IS31FL3235A_COUNT
+ #define IS31FL3235A_COUNT 1
+#endif
+#ifndef IS31FL3235A_DRIVER_ADDR_1
+ #define IS31FL3235A_DRIVER_ADDR_1 0b0111111
+ //#define IS31FL3235A_DRIVER_ADDR_1 0x7E
+#endif
+#ifndef IS31FL3235A_DRIVER_ADDR_2
+ #define IS31FL3235A_DRIVER_ADDR_2 0b0111110
+#endif
+#ifndef IS31FL3235A_DRIVER_ADDR_3
+ #define IS31FL3235A_DRIVER_ADDR_3 0b0111101
+#endif
+#ifndef IS31FL3235A_DRIVER_ADDR_4
+ #define IS31FL3235A_DRIVER_ADDR_4 0b0111100
+#endif
+
+// This is the max number of LEDs this driver supports per IC
+#define IS31FL3235A_LED_MAX 28
+#ifndef IS31FL3235A_LED_COUNT
+ #define IS31FL3235A_LED_COUNT IS31FL3235A_LED_MAX
+#endif
+
+// Registers we will need to write to
+#define ISSI_REG_SHUTDOWN 0x00 // Control the software shutdown state of the controller
+#define ISSI_REG_GLOBAL_CONTROL 0x4A // Write 0 for normal operation, 1 to shutdown all LEDs
+#define ISSI_REG_OUTPUT_FREQ 0x4B // Write 0 for 3kHz PWM, 1 for 22kHz
+#define ISSI_REG_RESET_REG 0x4F // Write 0 to reset all registers to default value
+
+
+void IS31FL3235A_init(uint8_t addr);
+void IS31FL3235A_write_register(uint8_t addr, uint8_t reg, uint8_t data);
+void IS31FL3235A_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer);
+
+void IS31FL3235A_set_value(int index, uint8_t value);
+void IS31FL3235A_set_value_all(uint8_t value);
+
+void IS31FL3235A_set_led_control_register(uint8_t index, bool value);
+
+// 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 IS31FL3235A_update_pwm_buffers(uint8_t addr, uint8_t index);
+void IS31FL3235A_update_led_control_registers(uint8_t addr, uint8_t index);
+
+// The address for each LED in the is31fl3235a's Control Register
+enum control_register {
+ CR_OUT1 = 0x2A,
+ CR_OUT2,
+ CR_OUT3,
+ CR_OUT4,
+ CR_OUT5,
+ CR_OUT6,
+ CR_OUT7,
+ CR_OUT8,
+ CR_OUT9,
+ CR_OUT10,
+ CR_OUT11,
+ CR_OUT12,
+ CR_OUT13,
+ CR_OUT14,
+ CR_OUT15,
+ CR_OUT16,
+ CR_OUT17,
+ CR_OUT18,
+ CR_OUT19,
+ CR_OUT20,
+ CR_OUT21,
+ CR_OUT22,
+ CR_OUT23,
+ CR_OUT24,
+ CR_OUT25,
+ CR_OUT26,
+ CR_OUT27,
+ CR_OUT28
+};
+
+// The address for each LED in the is31fl3235a's PWM Register
+enum pwm_register {
+ OUT1 = 0x05,
+ OUT2,
+ OUT3,
+ OUT4,
+ OUT5,
+ OUT6,
+ OUT7,
+ OUT8,
+ OUT9,
+ OUT10,
+ OUT11,
+ OUT12,
+ OUT13,
+ OUT14,
+ OUT15,
+ OUT16,
+ OUT17,
+ OUT18,
+ OUT19,
+ OUT20,
+ OUT21,
+ OUT22,
+ OUT23,
+ OUT24,
+ OUT25,
+ OUT26,
+ OUT27,
+ OUT28
+};
+
+#endif // IS31FL3235A_DRIVER_H
diff --git a/drivers/qwiic/qwiic.c b/drivers/qwiic/qwiic.c
index 9047919927..d9eb13afbb 100644
--- a/drivers/qwiic/qwiic.c
+++ b/drivers/qwiic/qwiic.c
@@ -22,10 +22,16 @@ void qwiic_init(void) {
#ifdef QWIIC_MICRO_OLED_ENABLE
micro_oled_init();
#endif
+ #ifdef QWIIC_RGB7SEG_ENABLE
+ rgb7seg_init();
+ #endif
}
void qwiic_task(void) {
#ifdef QWIIC_JOYSTIIC_ENABLE
joystiic_task();
#endif
+ #ifdef QWIIC_RGB7SEG_ENABLE
+ rgb7seg_task();
+ #endif
}
diff --git a/drivers/qwiic/qwiic.h b/drivers/qwiic/qwiic.h
index 160fb28dfd..a0662d7a21 100644
--- a/drivers/qwiic/qwiic.h
+++ b/drivers/qwiic/qwiic.h
@@ -23,6 +23,9 @@
#ifdef QWIIC_MICRO_OLED_ENABLE
#include "micro_oled.h"
#endif
+#ifdef QWIIC_RGB7SEG_ENABLE
+ #include "rgb7seg.h"
+#endif
void qwiic_init(void);
void qwiic_task(void);
diff --git a/drivers/qwiic/qwiic.mk b/drivers/qwiic/qwiic.mk
index 4ae2d78e3e..cd5524a60a 100644
--- a/drivers/qwiic/qwiic.mk
+++ b/drivers/qwiic/qwiic.mk
@@ -16,3 +16,9 @@ ifneq ($(filter MICRO_OLED, $(QWIIC_ENABLE)),)
OPT_DEFS += -DQWIIC_MICRO_OLED_ENABLE
SRC += micro_oled.c
endif
+
+ifneq ($(filter RGB7SEG, $(QWIIC_ENABLE)),)
+ COMMON_VPATH += $(DRIVER_PATH)/issi
+ OPT_DEFS += -DQWIIC_RGB7SEG_ENABLE
+ SRC += rgb7seg.c is31fl3235a.c
+endif
diff --git a/drivers/qwiic/rgb7seg.c b/drivers/qwiic/rgb7seg.c
new file mode 100644
index 0000000000..2249382696
--- /dev/null
+++ b/drivers/qwiic/rgb7seg.c
@@ -0,0 +1,168 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2017 Jack Humbert
+ * Copyright 2018 Yiancar
+ * Copyright 2019 Clueboard
+ *
+ * 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 .
+ */
+
+#include
+#include
+#include "quantum.h"
+#include "rgb7seg.h"
+#include "is31fl3235a.h"
+#include "progmem.h"
+#include "config.h"
+#include "eeprom.h"
+#include
+#include
+
+#ifndef MAX
+ #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+#endif
+
+#ifndef MIN
+ #define MIN(a,b) ((a) < (b)? (a): (b))
+#endif
+
+// State variables
+uint32_t g7_tick = 0; // Global tick at 20 Hz
+bool rgb7seg_enabled = 0; // Whether or not the display is turned on
+
+/*
+const rgb7seg_led g_rgb7seg_leds[IS31FL3235A_COUNT * 8][4] = {
+/ * Refer to IS31 manual for these locations
+ * driver
+ * | R LED address
+ * | | G LED address
+ * | | | B LED address
+ * | | | | * /
+ {0, OUT17, OUT16, OUT15}, // A, top middle
+ {0, OUT22, OUT21, OUT20}, // B, top right
+ {0, OUT26, OUT27, OUT28}, // C, bottom right
+ {0, OUT1, OUT2, OUT3}, // D, bottom center
+ {0, OUT23, OUT24, OUT25}, // DP, dot
+ {0, OUT4, OUT5, OUT6}, // E, bottom left
+ {0, OUT9, OUT7, OUT8}, // F, top left
+ {0, OUT14, OUT13, OUT12}, // G, center
+ #if IS31FL3235A_COUNT > 1
+ {1, OUT17, OUT16, OUT15}, // A, top middle
+ {1, OUT22, OUT21, OUT20}, // B, top right
+ {1, OUT26, OUT27, OUT28}, // C, bottom right
+ {1, OUT1, OUT2, OUT3}, // D, bottom center
+ {1, OUT23, OUT24, OUT25}, // DP, dot
+ {1, OUT4, OUT5, OUT6}, // E, bottom left
+ {1, OUT9, OUT7, OUT8}, // F, top left
+ {1, OUT14, OUT13, OUT12}, // G, center
+ #endif
+ #if IS31FL3235A_COUNT > 2
+ {2, OUT17, OUT16, OUT15}, // A, top middle
+ {2, OUT17, OUT16, OUT15}, // A, top middle
+ {2, OUT22, OUT21, OUT20}, // B, top right
+ {2, OUT26, OUT27, OUT28}, // C, bottom right
+ {2, OUT1, OUT2, OUT3}, // D, bottom center
+ {2, OUT23, OUT24, OUT25}, // DP, dot
+ {2, OUT4, OUT5, OUT6}, // E, bottom left
+ {2, OUT9, OUT7, OUT8}, // F, top left
+ {2, OUT14, OUT13, OUT12}, // G, center
+ #endif
+ #if IS31FL3235A_COUNT > 3
+ {3, OUT17, OUT16, OUT15}, // A, top middle
+ {3, OUT22, OUT21, OUT20}, // B, top right
+ {3, OUT26, OUT27, OUT28}, // C, bottom right
+ {3, OUT1, OUT2, OUT3}, // D, bottom center
+ {3, OUT23, OUT24, OUT25}, // DP, dot
+ {3, OUT4, OUT5, OUT6}, // E, bottom left
+ {3, OUT9, OUT7, OUT8}, // F, top left
+ {3, OUT14, OUT13, OUT12}, // G, center
+ {3, OUT22, OUT21, OUT20}, // B, top right
+ #endif
+};
+*/
+
+// API
+void rgb7seg_flush(void) {
+ IS31FL3235A_update_pwm_buffers(IS31FL3235A_DRIVER_ADDR_1, 0);
+ #if IS31FL3235A_COUNT > 1
+ IS31FL3235A_update_pwm_buffers(IS31FL3235A_DRIVER_ADDR_2, 1);
+ #endif
+ #if IS31FL3235A_COUNT > 2
+ IS31FL3235A_update_pwm_buffers(IS31FL3235A_DRIVER_ADDR_3, 2);
+ #endif
+ #if IS31FL3235A_COUNT > 3
+ IS31FL3235A_update_pwm_buffers(IS31FL3235A_DRIVER_ADDR_4, 3);
+ #endif
+}
+
+void rgb7seg_set_index_value(int index, uint8_t value) {
+ IS31FL3235A_set_value(index, value);
+}
+
+void rgb7seg_set_index_value_all(uint8_t value) {
+ IS31FL3235A_set_value_all(value);
+}
+
+// All LEDs off
+void rgb7seg_off(void) {
+ rgb7seg_set_index_value_all(0);
+}
+
+void rgb7seg_task(void) {
+ g7_tick++;
+
+ // Do something here?
+
+ // Tell the LED driver to update its state
+ rgb7seg_flush();
+}
+
+void rgb7seg_init(void) {
+ IS31FL3235A_init(IS31FL3235A_DRIVER_ADDR_1);
+ #if IS31FL3235A_COUNT > 1
+ IS31FL3235A_init(IS31FL3235A_DRIVER_ADDR_2);
+ #endif
+ #if IS31FL3235A_COUNT > 2
+ IS31FL3235A_init(IS31FL3235A_DRIVER_ADDR_3);
+ #endif
+ #if IS31FL3235A_COUNT > 3
+ IS31FL3235A_init(IS31FL3235A_DRIVER_ADDR_4);
+ #endif
+
+ // Wait half a second for the driver to finish initializing
+ wait_ms(500);
+}
+
+uint32_t rgb7seg_get_tick(void) {
+ return g7_tick;
+}
+
+void rgb7seg_toggle(void) {
+ rgb7seg_enabled ^= 1;
+}
+
+void rgb7seg_enable(void) {
+ rgb7seg_enabled = 1;
+}
+
+void rgb7seg_disable(void) {
+ rgb7seg_enabled = 0;
+}
+
+void rgb7seg_increase_val(void) {
+ // FIXME: Implement
+}
+
+void rgb7seg_decrease_val(void) {
+ // FIXME: Implement
+}
diff --git a/drivers/qwiic/rgb7seg.h b/drivers/qwiic/rgb7seg.h
new file mode 100644
index 0000000000..a87d7decf6
--- /dev/null
+++ b/drivers/qwiic/rgb7seg.h
@@ -0,0 +1,60 @@
+/* Copyright 2017 Jason Williams
+ * Copyright 2017 Jack Humbert
+ * Copyright 2018 Yiancar
+ * Copyright 2019 Clueboard
+ *
+ * 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 .
+ */
+
+#ifndef LED_MATRIX_H
+#define LED_MATRIX_H
+
+#include "is31fl3235a.h"
+
+#ifndef BACKLIGHT_ENABLE
+ #error You must define BACKLIGHT_ENABLE with LED_MATRIX_ENABLE
+#endif
+
+
+void rgb7seg_task(void);
+void rgb7seg_init(void);
+
+// 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 rgb7seg_flush(void);
+
+uint32_t rgb7seg_get_tick(void);
+
+void rgb7seg_off(void);
+void rgb7seg_set_index_value(int index, uint8_t value);
+void rgb7seg_set_index_value_all(uint8_t value);
+
+void rgb7seg_toggle(void);
+void rgb7seg_enable(void);
+void rgb7seg_disable(void);
+void rgb7seg_increase_val(void);
+void rgb7seg_decrease_val(void);
+
+typedef struct rgb7seg_led {
+ uint8_t driver;
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} __attribute__((packed)) rgb7seg_led;
+
+extern const rgb7seg_led g_rgb7seg_leds[IS31FL3235A_COUNT * 8];
+
+#endif
diff --git a/keyboards/clueboard/60/config.h b/keyboards/clueboard/60/config.h
index aa544c70bb..f0e157ff14 100644
--- a/keyboards/clueboard/60/config.h
+++ b/keyboards/clueboard/60/config.h
@@ -47,7 +47,7 @@
*
*/
#define MATRIX_ROW_PINS { B0, B1, B2, A15, A10 }
-#define MATRIX_COL_PINS { A2, A3, A6, B14, B15, A8, A9, A7, B3, B4, C14, C15, C13, B5, B6 }
+#define MATRIX_COL_PINS { A2, A3, A6, B14, B15, A8, A9, A7, B3, B4, C15, C14, C13, B5, B6 }
#define UNUSED_PINS { A0, A1, A9, B7, B8, B9, B10, B11, B12, B13 }
#define DIODE_DIRECTION COL2ROW
diff --git a/keyboards/clueboard/66/rev4/config.h b/keyboards/clueboard/66/rev4/config.h
index 540b387220..bc616ce20e 100644
--- a/keyboards/clueboard/66/rev4/config.h
+++ b/keyboards/clueboard/66/rev4/config.h
@@ -37,6 +37,17 @@
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+#define IS31FL3235A_COUNT 1
+//#define I2C_DRIVER I2CD1
+#define I2C1_BANK GPIOB
+#define I2C1_SCL 8
+#define I2C1_SDA 9
+
/*
* Feature disable options
* These options are also useful to firmware size reduction.
diff --git a/keyboards/clueboard/66/rev4/halconf.h b/keyboards/clueboard/66/rev4/halconf.h
index e617fdffc7..eda293c49b 100644
--- a/keyboards/clueboard/66/rev4/halconf.h
+++ b/keyboards/clueboard/66/rev4/halconf.h
@@ -76,7 +76,7 @@
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
-#define HAL_USE_I2C FALSE
+#define HAL_USE_I2C TRUE
#endif
/**
diff --git a/keyboards/clueboard/66/rev4/mcuconf.h b/keyboards/clueboard/66/rev4/mcuconf.h
index 94cb540ec9..226da48d59 100644
--- a/keyboards/clueboard/66/rev4/mcuconf.h
+++ b/keyboards/clueboard/66/rev4/mcuconf.h
@@ -154,7 +154,7 @@
/*
* I2C driver system settings.
*/
-#define STM32_I2C_USE_I2C1 FALSE
+#define STM32_I2C_USE_I2C1 TRUE
#define STM32_I2C_USE_I2C2 FALSE
#define STM32_I2C_BUSY_TIMEOUT 50
#define STM32_I2C_I2C1_IRQ_PRIORITY 10
diff --git a/keyboards/clueboard/66/rev4/rules.mk b/keyboards/clueboard/66/rev4/rules.mk
index 846b1eee0b..28b8a4bf68 100644
--- a/keyboards/clueboard/66/rev4/rules.mk
+++ b/keyboards/clueboard/66/rev4/rules.mk
@@ -17,6 +17,8 @@ DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave
# Build Options
# comment out to disable the options.
#
+QWIIC_ENABLE = RGB7SEG
+
BACKLIGHT_ENABLE = yes
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
diff --git a/keyboards/clueboard/66_hotswap/gen1/config.h b/keyboards/clueboard/66_hotswap/gen1/config.h
index 6b0cfb60b5..516248fa5c 100644
--- a/keyboards/clueboard/66_hotswap/gen1/config.h
+++ b/keyboards/clueboard/66_hotswap/gen1/config.h
@@ -130,6 +130,15 @@
*/
#define BACKLIGHT_LEVELS 10
+// For the rgb7seg
+#define IS31FL3235A_COUNT 1
+/*
+#define I2C_DRIVER I2CD2
+#define I2C1_BANK GPIOA
+#define I2C1_SCL 9
+#define I2C1_SDA 10
+*/
+
// 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:
@@ -138,6 +147,9 @@
// 0b1110101 AD <-> SCL
// 0b1110110 AD <-> SDA
#define LED_DRIVER_ADDR_1 0b1110100
+
+/* For the LED driver
+ */
#define I2C1_BANK GPIOB
#define I2C1_SCL 8
#define I2C1_SDA 9
diff --git a/keyboards/clueboard/66_hotswap/gen1/gen1.c b/keyboards/clueboard/66_hotswap/gen1/gen1.c
index c70f223756..484015885a 100644
--- a/keyboards/clueboard/66_hotswap/gen1/gen1.c
+++ b/keyboards/clueboard/66_hotswap/gen1/gen1.c
@@ -14,7 +14,6 @@
* along with this program. If not, see .
*/
#include "gen1.h"
-#include "is31fl3731-simple.h"
void matrix_init_kb(void) {
}
@@ -23,6 +22,8 @@ void matrix_scan_kb(void) {
}
#ifdef LED_MATRIX_ENABLE
+#include "is31fl3731-simple.h"
+
const is31_led g_is31_leds[LED_DRIVER_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
@@ -102,7 +103,6 @@ const is31_led g_is31_leds[LED_DRIVER_LED_COUNT] = {
};
const led_matrix g_leds[LED_DRIVER_LED_COUNT] = {
-
/*{row | col << 4}
| LED_ROW_COL(row, col)
| | modifier
diff --git a/keyboards/clueboard/66_hotswap/gen1/mcuconf.h b/keyboards/clueboard/66_hotswap/gen1/mcuconf.h
index 226da48d59..40fbeb76cf 100644
--- a/keyboards/clueboard/66_hotswap/gen1/mcuconf.h
+++ b/keyboards/clueboard/66_hotswap/gen1/mcuconf.h
@@ -155,7 +155,7 @@
* I2C driver system settings.
*/
#define STM32_I2C_USE_I2C1 TRUE
-#define STM32_I2C_USE_I2C2 FALSE
+#define STM32_I2C_USE_I2C2 TRUE
#define STM32_I2C_BUSY_TIMEOUT 50
#define STM32_I2C_I2C1_IRQ_PRIORITY 10
#define STM32_I2C_I2C2_IRQ_PRIORITY 10
diff --git a/keyboards/clueboard/66_hotswap/gen1/rules.mk b/keyboards/clueboard/66_hotswap/gen1/rules.mk
index 6b1ee92c18..0c7ada11dc 100644
--- a/keyboards/clueboard/66_hotswap/gen1/rules.mk
+++ b/keyboards/clueboard/66_hotswap/gen1/rules.mk
@@ -41,6 +41,9 @@ DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave
# LED Configuration
LED_MATRIX_ENABLE = IS31FL3731
+# QWIIC Devices
+#QWIIC_ENABLE = RGB7SEG
+
# Build Options
# comment out to disable the options.
#
diff --git a/keyboards/clueboard/66_hotswap/prototype/prototype.h b/keyboards/clueboard/66_hotswap/prototype/prototype.h
index b1d483b408..2d0a9d3977 100644
--- a/keyboards/clueboard/66_hotswap/prototype/prototype.h
+++ b/keyboards/clueboard/66_hotswap/prototype/prototype.h
@@ -28,7 +28,7 @@
// The first section contains all of the arguments
// The second converts the arguments into a two-dimensional array
-#define LAYOUT_all( \
+#define LAYOUT( \
k00, k01, k02, k03, k04, k05, k06, k07, k50, k51, k52, k53, k54, k56, k57, \
k10, k11, k12, k13, k14, k15, k16, k17, k60, k61, k62, k63, k64, k65, k67, \
k20, k21, k22, k23, k24, k25, k26, k27, k70, k71, k72, k73, k75, \
@@ -47,25 +47,6 @@
{ k90, KC_NO, k92, k93, k94, k95, k96, k97 } \
}
-#define LAYOUT( \
- k00, k01, k02, k03, k04, k05, k06, k07, k50, k51, k52, k53, k54, k56, k57, \
- k10, k11, k12, k13, k14, k15, k16, k17, k60, k61, k62, k63, k64, k65, k67, \
- k20, k21, k22, k23, k24, k25, k26, k27, k70, k71, k72, k73, k75, \
- k30, k32, k33, k34, k35, k36, k37, k80, k81, k82, k83, k85, k86, \
- k40, k41, k42, k45, k46, k90, k92, k93, k94, k95, k96, k97 \
-) { \
- { k00, k01, k02, k03, k04, k05, k06, k07 }, \
- { k10, k11, k12, k13, k14, k15, k16, k17 }, \
- { k20, k21, k22, k23, k24, k25, k26, k27 }, \
- { k30, KC_NO, k32, k33, k34, k35, k36, k37 }, \
- { k40, k41, k42, KC_NO, KC_NO, k45, k46, KC_NO }, \
- { k50, k51, k52, k53, k54, KC_NO, k56, k57 }, \
- { k60, k61, k62, k63, k64, k65, KC_NO, k67 }, \
- { k70, k71, k72, k73, KC_NO, k75, KC_NO, KC_NO }, \
- { k80, k81, k82, k83, KC_NO, k85, k86, KC_NO }, \
- { k90, KC_NO, k92, k93, k94, k95, k96, k97 } \
-}
-
#define LAYOUT_66_ansi( \
k00, k01, k02, k03, k04, k05, k06, k07, k50, k51, k52, k53, k54, k56, k57, \
k10, k11, k12, k13, k14, k15, k16, k17, k60, k61, k62, k63, k64, k65, k67, \