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, \