From ef8de0e6f0ffa4854ed7364caa73cf9c1fe19e7e Mon Sep 17 00:00:00 2001 From: skullY Date: Tue, 29 Jan 2019 10:13:12 -0800 Subject: [PATCH] wip --- drivers/issi/is31fl3235a.c | 196 +++----- drivers/issi/is31fl3235a.h | 302 +++++------- drivers/qwiic/qwiic.c | 6 + drivers/qwiic/qwiic.h | 3 + drivers/qwiic/qwiic.mk | 6 + drivers/qwiic/rgb7seg.c | 441 +++++------------- drivers/qwiic/rgb7seg.h | 109 +---- keyboards/clueboard/66_hotswap/gen1/config.h | 10 + keyboards/clueboard/66_hotswap/gen1/gen1.c | 3 +- keyboards/clueboard/66_hotswap/gen1/mcuconf.h | 2 +- keyboards/clueboard/66_hotswap/gen1/rules.mk | 5 +- 11 files changed, 350 insertions(+), 733 deletions(-) diff --git a/drivers/issi/is31fl3235a.c b/drivers/issi/is31fl3235a.c index a7faa9c38c0..a6102d19cc8 100644 --- a/drivers/issi/is31fl3235a.c +++ b/drivers/issi/is31fl3235a.c @@ -27,36 +27,19 @@ #include #include #include -#include "is31fl3731-simple.h" +#include "is31fl3235a.h" #include "i2c_master.h" #include "progmem.h" #include "print.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_REG_CONFIG 0x00 // FIXME: Not on 3235? +#define ISSI_REG_CONFIG_PICTUREMODE 0x00 // FIXME: Not on 3235? -#define ISSI_CONF_PICTUREMODE 0x00 -#define ISSI_CONF_AUTOFRAMEMODE 0x04 -#define ISSI_CONF_AUDIOMODE 0x08 +//#define ISSI_REG_AUDIOSYNC 0x06 // FIXME: Not on 3235? -#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' +#define ISSI_COMMANDREGISTER 0xFD // FIXME: Not on 3235? +#define ISSI_BANK_FUNCTIONREG 0x0B // FIXME: Not on 3235? #ifndef ISSI_TIMEOUT #define ISSI_TIMEOUT 100 @@ -67,180 +50,145 @@ #endif // Transfer buffer for TWITransmitData() -uint8_t g_twi_transfer_buffer[20]; +uint8_t g_3235a_transfer_buffer[20]; -// These buffers match the IS31FL3731 PWM registers 0x24-0xB3. +// 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 IS31FL3731_write_pwm_buffer() but it's +// buffers and the transfers in IS31FL3235A_write_pwm_buffer() but it's // probably not worth the extra complexity. -uint8_t g_pwm_buffer[LED_DRIVER_COUNT][144]; -bool g_pwm_buffer_update_required = false; +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 LED_DRIVER_COUNT == 1 - uint8_t g_led_control_registers[LED_DRIVER_COUNT][18] = {{0}}; -#elif LED_DRIVER_COUNT == 2 - uint8_t g_led_control_registers[LED_DRIVER_COUNT][18] = {{0}, {0}}; -#elif LED_DRIVER_COUNT == 3 - uint8_t g_led_control_registers[LED_DRIVER_COUNT][18] = {{0}, {0}, {0}}; -#elif LED_DRIVER_COUNT == 4 - uint8_t g_led_control_registers[LED_DRIVER_COUNT][18] = {{0}, {0}, {0}, {0}}; +#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_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; +bool g_rgb7seg_control_registers_update_required = false; + +void IS31FL3235A_write_register(uint8_t addr, uint8_t reg, uint8_t data) { + xprintf("IS31FL3235A_write_register(0x%x, 0x%x, 0x%x);\n", addr, reg, data); + g_3235a_transfer_buffer[0] = reg; + g_3235a_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) { + if (i2c_transmit(addr << 1, g_3235a_transfer_buffer, 2, ISSI_TIMEOUT) == 0) { break; } } #else - i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT); + i2c_transmit(addr << 1, g_3235a_transfer_buffer, 2, ISSI_TIMEOUT); #endif } -void IS31FL3731_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) { +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_twi_transfer_buffer[] is 20 bytes + // g_3235a_transfer_buffer[] is 20 bytes // iterate over the pwm_buffer contents at 16 byte intervals - for (int i = 0; i < 144; i += 16) { + for (int i = 0; i < IS31FL3235A_LED_MAX; i += 16) { // set the first register, e.g. 0x24, 0x34, 0x44, etc. - g_twi_transfer_buffer[0] = 0x24 + i; + 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_twi_transfer_buffer[1 + j] = pwm_buffer[i + 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_twi_transfer_buffer, 17, ISSI_TIMEOUT) == 0) + if (i2c_transmit(addr << 1, g_3235a_transfer_buffer, 17, ISSI_TIMEOUT) == 0) break; } #else - i2c_transmit(addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT); + if (!i2c_transmit(addr << 1, g_3235a_transfer_buffer, 17, ISSI_TIMEOUT)) { + xprintf("Could not contact i2c device 0x%x!\n", addr << 1); + } #endif } } -void IS31FL3731_init(uint8_t addr) { +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. - // select "function register" bank - IS31FL3731_write_register(addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG); + // Reset settings to default + //IS31FL3235A_write_register(addr, ISSI_REG_RESET_REG, 0); - // enable software shutdown - IS31FL3731_write_register(addr, ISSI_REG_SHUTDOWN, 0x00); // this delay was copied from other drivers, might not be needed wait_ms(10); - // 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); + // 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 IS31FL3731_set_value(int index, uint8_t value) { - if (index >= 0 && index < LED_DRIVER_LED_COUNT) { +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_pwm_buffer - g_pwm_buffer[led.driver][led.v - 0x24] = value; - g_pwm_buffer_update_required = true; + // 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 IS31FL3731_set_value_all(uint8_t value) { - for (int i = 0; i < LED_DRIVER_LED_COUNT; i++) { - IS31FL3731_set_value(i, value); +void IS31FL3235A_set_value_all(uint8_t value) { + for (int i = 0; i < IS31FL3235A_LED_COUNT; i++) { + IS31FL3235A_set_value(i, value); } } -void IS31FL3731_set_led_control_register(uint8_t index, bool 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_led_control_registers[led.driver][control_register] |= (1 << bit_value); + g_3235a_control_registers[led.driver][control_register] |= (1 << bit_value); } else { - g_led_control_registers[led.driver][control_register] &= ~(1 << bit_value); + g_3235a_control_registers[led.driver][control_register] &= ~(1 << bit_value); } - g_led_control_registers_update_required = true; + g_rgb7seg_control_registers_update_required = true; +*/ } -void IS31FL3731_update_pwm_buffers(uint8_t addr, uint8_t index) { - if (g_pwm_buffer_update_required) { - IS31FL3731_write_pwm_buffer(addr, g_pwm_buffer[index]); - g_pwm_buffer_update_required = false; +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 IS31FL3731_update_led_control_registers(uint8_t addr, uint8_t index) { - if (g_led_control_registers_update_required) { +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++) { - IS31FL3731_write_register(addr, i, g_led_control_registers[index][i]); + IS31FL3235A_write_register(addr, i, g_3235a_control_registers[index][i]); } } } diff --git a/drivers/issi/is31fl3235a.h b/drivers/issi/is31fl3235a.h index dbe49828179..af96808d1d9 100644 --- a/drivers/issi/is31fl3235a.h +++ b/drivers/issi/is31fl3235a.h @@ -17,194 +17,124 @@ */ -#ifndef IS31FL3731_DRIVER_H -#define IS31FL3731_DRIVER_H - - -typedef struct is31_led { - uint8_t driver:2; - uint8_t v; -} __attribute__((packed)) is31_led; - -extern const is31_led g_is31_leds[LED_DRIVER_LED_COUNT]; - -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_value(int index, uint8_t value); -void IS31FL3731_set_value_all(uint8_t value); - -void IS31FL3731_set_led_control_register(uint8_t index, bool value); +#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 +#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 IS31FL3731_update_pwm_buffers(uint8_t addr, uint8_t index); -void IS31FL3731_update_led_control_registers(uint8_t addr, uint8_t index); - -#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 +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 9047919927e..d9eb13afbbc 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 160fb28dfde..a0662d7a21b 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 4ae2d78e3e7..cd5524a60a4 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 index 8ef8abe712b..f9eff00788c 100644 --- a/drivers/qwiic/rgb7seg.c +++ b/drivers/qwiic/rgb7seg.c @@ -20,15 +20,14 @@ #include #include #include "quantum.h" -#include "ledmatrix.h" +#include "rgb7seg.h" +#include "is31fl3235a.h" #include "progmem.h" #include "config.h" #include "eeprom.h" #include #include -led_config_t led_matrix_config; - #ifndef MAX #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) #endif @@ -37,355 +36,135 @@ led_config_t led_matrix_config; #define MIN(a,b) ((a) < (b)? (a): (b)) #endif -#ifndef LED_DISABLE_AFTER_TIMEOUT - #define LED_DISABLE_AFTER_TIMEOUT 0 -#endif - -#ifndef LED_DISABLE_WHEN_USB_SUSPENDED - #define LED_DISABLE_WHEN_USB_SUSPENDED false -#endif - -#ifndef EECONFIG_LED_MATRIX - #define EECONFIG_LED_MATRIX EECONFIG_RGBLIGHT -#endif - -#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > 255 - #define LED_MATRIX_MAXIMUM_BRIGHTNESS 255 -#endif - -bool g_suspend_state = false; - -// Global tick at 20 Hz -uint32_t g_tick = 0; - -// Ticks since this key was last hit. -uint8_t g_key_hit[LED_DRIVER_LED_COUNT]; - -// Ticks since any key was last hit. -uint32_t g_any_key_hit = 0; - -uint32_t eeconfig_read_led_matrix(void) { - return eeprom_read_dword(EECONFIG_LED_MATRIX); -} - -void eeconfig_update_led_matrix(uint32_t config_value) { - eeprom_update_dword(EECONFIG_LED_MATRIX, config_value); -} - -void eeconfig_update_led_matrix_default(void) { - dprintf("eeconfig_update_led_matrix_default\n"); - led_matrix_config.enable = 1; - led_matrix_config.mode = LED_MATRIX_UNIFORM_BRIGHTNESS; - led_matrix_config.val = 128; - led_matrix_config.speed = 0; - eeconfig_update_led_matrix(led_matrix_config.raw); -} - -void eeconfig_debug_led_matrix(void) { - dprintf("led_matrix_config eeprom\n"); - dprintf("led_matrix_config.enable = %d\n", led_matrix_config.enable); - dprintf("led_matrix_config.mode = %d\n", led_matrix_config.mode); - dprintf("led_matrix_config.val = %d\n", led_matrix_config.val); - dprintf("led_matrix_config.speed = %d\n", led_matrix_config.speed); -} - -// Last led hit -#ifndef LED_HITS_TO_REMEMBER - #define LED_HITS_TO_REMEMBER 8 -#endif -uint8_t g_last_led_hit[LED_HITS_TO_REMEMBER] = {255}; -uint8_t g_last_led_count = 0; - -void map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i, uint8_t *led_count) { - led_matrix led; - *led_count = 0; - - for (uint8_t i = 0; i < LED_DRIVER_LED_COUNT; i++) { - // map_index_to_led(i, &led); - led = g_leds[i]; - if (row == led.matrix_co.row && column == led.matrix_co.col) { - led_i[*led_count] = i; - (*led_count)++; - } - } -} - -void led_matrix_update_pwm_buffers(void) { - led_matrix_driver.flush(); -} - -void led_matrix_set_index_value(int index, uint8_t value) { - led_matrix_driver.set_value(index, value); -} - -void led_matrix_set_index_value_all(uint8_t value) { - led_matrix_driver.set_value_all(value); -} - -bool process_led_matrix(uint16_t keycode, keyrecord_t *record) { - if (record->event.pressed) { - uint8_t led[8], led_count; - map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count); - if (led_count > 0) { - for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) { - g_last_led_hit[i - 1] = g_last_led_hit[i - 2]; - } - g_last_led_hit[0] = led[0]; - g_last_led_count = MIN(LED_HITS_TO_REMEMBER, g_last_led_count + 1); - } - for(uint8_t i = 0; i < led_count; i++) - g_key_hit[led[i]] = 0; - g_any_key_hit = 0; - } else { - #ifdef LED_MATRIX_KEYRELEASES - uint8_t led[8], led_count; - map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count); - for(uint8_t i = 0; i < led_count; i++) - g_key_hit[led[i]] = 255; - - g_any_key_hit = 255; - #endif - } - return true; -} - -void led_matrix_set_suspend_state(bool state) { - g_suspend_state = state; +// 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 led_matrix_all_off(void) { - led_matrix_set_index_value_all(0); +void rgb7seg_off(void) { + rgb7seg_set_index_value_all(0); } -// Uniform brightness -void led_matrix_uniform_brightness(void) { - led_matrix_set_index_value_all(LED_MATRIX_MAXIMUM_BRIGHTNESS / BACKLIGHT_LEVELS * led_matrix_config.val); -} - -void led_matrix_custom(void) {} - -void led_matrix_task(void) { - if (!led_matrix_config.enable) { - led_matrix_all_off(); - led_matrix_indicators(); - return; - } - - g_tick++; - - if (g_any_key_hit < 0xFFFFFFFF) { - g_any_key_hit++; - } - - for (int led = 0; led < LED_DRIVER_LED_COUNT; led++) { - if (g_key_hit[led] < 255) { - if (g_key_hit[led] == 254) - g_last_led_count = MAX(g_last_led_count - 1, 0); - g_key_hit[led]++; - } - } - - // Ideally we would also stop sending zeros to the LED driver PWM buffers - // while suspended and just do a software shutdown. This is a cheap hack for now. - bool suspend_backlight = ((g_suspend_state && LED_DISABLE_WHEN_USB_SUSPENDED) || - (LED_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > LED_DISABLE_AFTER_TIMEOUT * 60 * 20)); - uint8_t effect = suspend_backlight ? 0 : led_matrix_config.mode; - - // this gets ticked at 20 Hz. - // each effect can opt to do calculations - // and/or request PWM buffer updates. - switch (effect) { - case LED_MATRIX_UNIFORM_BRIGHTNESS: - led_matrix_uniform_brightness(); - break; - default: - led_matrix_custom(); - break; - } +void rgb7seg_task(void) { + g7_tick++; - if (!suspend_backlight) { - led_matrix_indicators(); - } + // Do something here? // Tell the LED driver to update its state - led_matrix_driver.flush(); -} - -void led_matrix_indicators(void) { - led_matrix_indicators_kb(); - led_matrix_indicators_user(); -} - -__attribute__((weak)) -void led_matrix_indicators_kb(void) {} - -__attribute__((weak)) -void led_matrix_indicators_user(void) {} - - -// void led_matrix_set_indicator_index(uint8_t *index, uint8_t row, uint8_t column) -// { -// if (row >= MATRIX_ROWS) -// { -// // Special value, 255=none, 254=all -// *index = row; -// } -// else -// { -// // This needs updated to something like -// // uint8_t led[8], led_count; -// // map_row_column_to_led(row,column,led,&led_count); -// // for(uint8_t i = 0; i < led_count; i++) -// map_row_column_to_led(row, column, index); -// } -// } - -void led_matrix_init(void) { - led_matrix_driver.init(); + rgb7seg_flush(); +} + +void rgb7seg_init(void) { + #ifdef IS31FL3235A_DRIVER_ADDR_1 + IS31FL3235A_init(IS31FL3235A_DRIVER_ADDR_1); + #endif + #ifdef IS31FL3235A_DRIVER_ADDR_2 + IS31FL3235A_init(IS31FL3235A_DRIVER_ADDR_2); + #endif + #ifdef IS31FL3235A_DRIVER_ADDR_3 + IS31FL3235A_init(IS31FL3235A_DRIVER_ADDR_3); + #endif + #ifdef IS31FL3235A_DRIVER_ADDR_4 + IS31FL3235A_init(IS31FL3235A_DRIVER_ADDR_4); + #endif // Wait half a second for the driver to finish initializing wait_ms(500); - - // clear the key hits - for (int led=0; led= LED_MATRIX_EFFECT_MAX) { - led_matrix_config.mode = 1; - } - eeconfig_update_led_matrix(led_matrix_config.raw); -} - -void led_matrix_step_reverse(void) { - led_matrix_config.mode--; - if (led_matrix_config.mode < 1) { - led_matrix_config.mode = LED_MATRIX_EFFECT_MAX - 1; - } - eeconfig_update_led_matrix(led_matrix_config.raw); -} - -void led_matrix_increase_val(void) { - led_matrix_config.val = increment(led_matrix_config.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); - eeconfig_update_led_matrix(led_matrix_config.raw); -} - -void led_matrix_decrease_val(void) { - led_matrix_config.val = decrement(led_matrix_config.val, 8, 0, LED_MATRIX_MAXIMUM_BRIGHTNESS); - eeconfig_update_led_matrix(led_matrix_config.raw); -} - -void led_matrix_increase_speed(void) { - led_matrix_config.speed = increment(led_matrix_config.speed, 1, 0, 3); - eeconfig_update_led_matrix(led_matrix_config.raw);//EECONFIG needs to be increased to support this } -void led_matrix_decrease_speed(void) { - led_matrix_config.speed = decrement(led_matrix_config.speed, 1, 0, 3); - eeconfig_update_led_matrix(led_matrix_config.raw);//EECONFIG needs to be increased to support this +uint32_t rgb7seg_get_tick(void) { + return g7_tick; } -void led_matrix_mode(uint8_t mode, bool eeprom_write) { - led_matrix_config.mode = mode; - if (eeprom_write) { - eeconfig_update_led_matrix(led_matrix_config.raw); - } +void rgb7seg_toggle(void) { + rgb7seg_enabled ^= 1; } -uint8_t led_matrix_get_mode(void) { - return led_matrix_config.mode; +void rgb7seg_enable(void) { + rgb7seg_enabled = 1; } -void led_matrix_set_value_noeeprom(uint8_t val) { - led_matrix_config.val = val; +void rgb7seg_disable(void) { + rgb7seg_enabled = 0; } -void led_matrix_set_value(uint8_t val) { - led_matrix_set_value_noeeprom(val); - eeconfig_update_led_matrix(led_matrix_config.raw); +void rgb7seg_increase_val(void) { + // FIXME: Implement } -void backlight_set(uint8_t val) { - led_matrix_set_value(val); +void rgb7seg_decrease_val(void) { + // FIXME: Implement } diff --git a/drivers/qwiic/rgb7seg.h b/drivers/qwiic/rgb7seg.h index 618c5d67674..a87d7decf62 100644 --- a/drivers/qwiic/rgb7seg.h +++ b/drivers/qwiic/rgb7seg.h @@ -20,110 +20,41 @@ #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 -typedef struct Point { - uint8_t x; - uint8_t y; -} __attribute__((packed)) Point; - -typedef struct led_matrix { - union { - uint8_t raw; - struct { - uint8_t row:4; // 16 max - uint8_t col:4; // 16 max - }; - } matrix_co; - Point point; - uint8_t modifier:1; -} __attribute__((packed)) led_matrix; - -extern const led_matrix g_leds[LED_DRIVER_LED_COUNT]; - -typedef struct { - uint8_t index; - uint8_t value; -} led_indicator; - -typedef union { - uint32_t raw; - struct { - bool enable :1; - uint8_t mode :6; - uint8_t hue :8; // Unused by led_matrix - uint8_t sat :8; // Unused by led_matrix - uint8_t val :8; - uint8_t speed :8;//EECONFIG needs to be increased to support this - }; -} led_config_t; - -enum led_matrix_effects { - LED_MATRIX_UNIFORM_BRIGHTNESS = 1, - // All new effects go above this line - LED_MATRIX_EFFECT_MAX -}; - -void led_matrix_set_index_value(int index, uint8_t value); -void led_matrix_set_index_value_all(uint8_t value); - -// This runs after another backlight effect and replaces -// colors already set -void led_matrix_indicators(void); -void led_matrix_indicators_kb(void); -void led_matrix_indicators_user(void); - -void led_matrix_init(void); -void led_matrix_setup_drivers(void); - -void led_matrix_set_suspend_state(bool state); -void led_matrix_set_indicator_state(uint8_t state); - -void led_matrix_task(void); +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 led_matrix_update_pwm_buffers(void); - -bool process_led_matrix(uint16_t keycode, keyrecord_t *record); +void rgb7seg_flush(void); -uint32_t led_matrix_get_tick(void); +uint32_t rgb7seg_get_tick(void); -void led_matrix_toggle(void); -void led_matrix_enable(void); -void led_matrix_enable_noeeprom(void); -void led_matrix_disable(void); -void led_matrix_disable_noeeprom(void); -void led_matrix_step(void); -void led_matrix_step_reverse(void); -void led_matrix_increase_val(void); -void led_matrix_decrease_val(void); -void led_matrix_increase_speed(void); -void led_matrix_decrease_speed(void); -void led_matrix_mode(uint8_t mode, bool eeprom_write); -void led_matrix_mode_noeeprom(uint8_t mode); -uint8_t led_matrix_get_mode(void); -void led_matrix_set_value(uint8_t mode); -void led_matrix_set_value_noeeprom(uint8_t mode); +void rgb7seg_off(void); +void rgb7seg_set_index_value(int index, uint8_t value); +void rgb7seg_set_index_value_all(uint8_t value); -typedef struct { - /* Perform any initialisation required for the other driver functions to work. */ - void (*init)(void); +void rgb7seg_toggle(void); +void rgb7seg_enable(void); +void rgb7seg_disable(void); +void rgb7seg_increase_val(void); +void rgb7seg_decrease_val(void); - /* Set the brightness of a single LED in the buffer. */ - void (*set_value)(int index, uint8_t value); - /* Set the brightness of all LEDS on the keyboard in the buffer. */ - void (*set_value_all)(uint8_t value); - /* Flush any buffered changes to the hardware. */ - void (*flush)(void); -} led_matrix_driver_t; +typedef struct rgb7seg_led { + uint8_t driver; + uint8_t r; + uint8_t g; + uint8_t b; +} __attribute__((packed)) rgb7seg_led; -extern const led_matrix_driver_t led_matrix_driver; +extern const rgb7seg_led g_rgb7seg_leds[IS31FL3235A_COUNT * 8]; #endif diff --git a/keyboards/clueboard/66_hotswap/gen1/config.h b/keyboards/clueboard/66_hotswap/gen1/config.h index 6b0cfb60b53..59be685ed01 100644 --- a/keyboards/clueboard/66_hotswap/gen1/config.h +++ b/keyboards/clueboard/66_hotswap/gen1/config.h @@ -130,6 +130,13 @@ */ #define BACKLIGHT_LEVELS 10 +// For the rgb7seg +#define IS31FL3235A_COUNT 4 +#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,9 +145,12 @@ // 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 + */ #define LED_DRIVER_COUNT 1 #define LED_DRIVER_LED_COUNT 71 diff --git a/keyboards/clueboard/66_hotswap/gen1/gen1.c b/keyboards/clueboard/66_hotswap/gen1/gen1.c index 37e18900ce3..484015885a2 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 diff --git a/keyboards/clueboard/66_hotswap/gen1/mcuconf.h b/keyboards/clueboard/66_hotswap/gen1/mcuconf.h index 226da48d593..40fbeb76cf5 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 6b1ee92c180..5d4cafe2e39 100644 --- a/keyboards/clueboard/66_hotswap/gen1/rules.mk +++ b/keyboards/clueboard/66_hotswap/gen1/rules.mk @@ -39,7 +39,10 @@ OPT_DEFS = DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave # LED Configuration -LED_MATRIX_ENABLE = IS31FL3731 +#LED_MATRIX_ENABLE = IS31FL3731 + +# QWIIC Devices +QWIIC_ENABLE = RGB7SEG # Build Options # comment out to disable the options.