diff options
author | QMK Bot <hello@qmk.fm> | 2021-02-28 05:38:43 +0000 |
---|---|---|
committer | QMK Bot <hello@qmk.fm> | 2021-02-28 05:38:43 +0000 |
commit | c2f446f40e20007170396aba2ca559d602a1e72e (patch) | |
tree | c319f9a816dcf43b8c7d8eb356a259ec23520c34 | |
parent | d9d03d5af882d1cf7632726f8a1fc7909e53b725 (diff) | |
parent | e6f7da403676b491ac278d5b793d18a0d114477e (diff) |
Merge remote-tracking branch 'origin/master' into develop
-rw-r--r-- | keyboards/k_type/i2c_master.c | 145 | ||||
-rw-r--r-- | keyboards/k_type/i2c_master.h | 127 | ||||
-rw-r--r-- | keyboards/k_type/is31fl3733.c | 231 | ||||
-rw-r--r-- | keyboards/k_type/is31fl3733.h | 251 | ||||
-rw-r--r-- | keyboards/k_type/k_type.c | 201 | ||||
-rw-r--r-- | keyboards/k_type/keymaps/andrew-fahmy/config.h | 52 | ||||
-rw-r--r-- | keyboards/k_type/keymaps/andrew-fahmy/keymap.c | 60 | ||||
-rw-r--r-- | keyboards/k_type/keymaps/andrew-fahmy/rules.mk | 1 | ||||
-rw-r--r-- | keyboards/k_type/keymaps/rgb/config.h | 25 | ||||
-rw-r--r-- | keyboards/k_type/keymaps/rgb/keymap.c | 4 | ||||
-rw-r--r-- | keyboards/k_type/keymaps/rgb/readme.md | 4 | ||||
-rw-r--r-- | keyboards/k_type/led.c | 53 | ||||
-rw-r--r-- | keyboards/k_type/mcuconf.h | 3 | ||||
-rw-r--r-- | keyboards/k_type/rules.mk | 4 |
14 files changed, 1058 insertions, 103 deletions
diff --git a/keyboards/k_type/i2c_master.c b/keyboards/k_type/i2c_master.c new file mode 100644 index 0000000000..72d835a604 --- /dev/null +++ b/keyboards/k_type/i2c_master.c @@ -0,0 +1,145 @@ +/* Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* This library is only valid for STM32 processors. + * This library follows the convention of the AVR i2c_master library. + * As a result addresses are expected to be already shifted (addr << 1). + * I2CD1 is the default driver which corresponds to pins B6 and B7. This + * can be changed. + * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that + * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. Pins B6 and B7 are used + * but using any other I2C pins should be trivial. + */ +#include "quantum.h" +#include "i2c_master.h" +#include "print.h" +#include <string.h> +#include <hal.h> + +static uint8_t i2c_address; + +I2CDriver *drivers[I2C_COUNT]; + +static const I2CConfig i2cconfig = { +#if defined(USE_I2CV1_CONTRIB) + I2C1_CLOCK_SPEED, +#elif defined(USE_I2CV1) + I2C1_OPMODE, + I2C1_CLOCK_SPEED, + I2C1_DUTY_CYCLE, +#else + // This configures the I2C clock to 400khz assuming a 72Mhz clock + // For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html + STM32_TIMINGR_PRESC(I2C1_TIMINGR_PRESC) | STM32_TIMINGR_SCLDEL(I2C1_TIMINGR_SCLDEL) | STM32_TIMINGR_SDADEL(I2C1_TIMINGR_SDADEL) | STM32_TIMINGR_SCLH(I2C1_TIMINGR_SCLH) | STM32_TIMINGR_SCLL(I2C1_TIMINGR_SCLL), 0, 0 +#endif +}; + +static i2c_status_t chibios_to_qmk(const msg_t* status) { + switch (*status) { + case I2C_NO_ERROR: + return I2C_STATUS_SUCCESS; + case I2C_TIMEOUT: + return I2C_STATUS_TIMEOUT; + // I2C_BUS_ERROR, I2C_ARBITRATION_LOST, I2C_ACK_FAILURE, I2C_OVERRUN, I2C_PEC_ERROR, I2C_SMB_ALERT + default: + return I2C_STATUS_ERROR; + } +} + +__attribute__((weak)) void i2c_init(I2CDriver *driver, ioportid_t scl_port, ioportid_t sda_port, iopadid_t scl_pad, iopadid_t sda_pad) { + static uint8_t index = 0; + if (index < I2C_COUNT) { + + // Try releasing special pins for a short time + palSetPadMode(scl_port, scl_pad, PAL_MODE_INPUT); + palSetPadMode(sda_port, sda_pad, PAL_MODE_INPUT); + + chThdSleepMilliseconds(10); + +#if defined(USE_GPIOV1) + palSetPadMode(scl_port, scl_pad, I2C1_SCL_PAL_MODE); + palSetPadMode(sda_port, sda_pad, I2C1_SDA_PAL_MODE); +#else + palSetPadMode(scl_port, scl_pad, PAL_MODE_ALTERNATE(I2C1_SCL_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); + palSetPadMode(sda_port, sda_pad, PAL_MODE_ALTERNATE(I2C1_SDA_PAL_MODE) | PAL_STM32_OTYPE_OPENDRAIN); +#endif + + drivers[index++] = driver; + } +} + +i2c_status_t i2c_start(uint8_t index, uint8_t address) { + if(index >= I2C_COUNT) { + return I2C_STATUS_ERROR; + } + i2c_address = address; + i2cStart(drivers[index], &i2cconfig); + return I2C_STATUS_SUCCESS; +} + +i2c_status_t i2c_transmit(uint8_t index, uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout) { + if(index >= I2C_COUNT) { + return I2C_STATUS_ERROR; + } + i2c_address = address; + i2cStart(drivers[index], &i2cconfig); + msg_t status = i2cMasterTransmitTimeout(drivers[index], (i2c_address >> 1), data, length, 0, 0, TIME_MS2I(timeout)); + return chibios_to_qmk(&status); +} + +i2c_status_t i2c_receive(uint8_t index, uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout) { + if(index >= I2C_COUNT) { + return I2C_STATUS_ERROR; + } + i2c_address = address; + i2cStart(drivers[index], &i2cconfig); + msg_t status = i2cMasterReceiveTimeout(drivers[index], (i2c_address >> 1), data, length, TIME_MS2I(timeout)); + return chibios_to_qmk(&status); +} + +i2c_status_t i2c_writeReg(uint8_t index, uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout) { + if(index >= I2C_COUNT) { + return I2C_STATUS_ERROR; + } + i2c_address = devaddr; + i2cStart(drivers[index], &i2cconfig); + + uint8_t complete_packet[length + 1]; + for (uint8_t i = 0; i < length; i++) { + complete_packet[i + 1] = data[i]; + } + complete_packet[0] = regaddr; + + msg_t status = i2cMasterTransmitTimeout(drivers[index], (i2c_address >> 1), complete_packet, length + 1, 0, 0, TIME_MS2I(timeout)); + return chibios_to_qmk(&status); +} + +i2c_status_t i2c_readReg(uint8_t index, uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout) { + if(index >= I2C_COUNT) { + return I2C_STATUS_ERROR; + } + i2c_address = devaddr; + i2cStart(drivers[index], &i2cconfig); + msg_t status = i2cMasterTransmitTimeout(drivers[index], (i2c_address >> 1), ®addr, 1, data, length, TIME_MS2I(timeout)); + return chibios_to_qmk(&status); +} + +void i2c_stop(uint8_t index) { + if(index < I2C_COUNT) { + i2cStop(drivers[index]); + } +} diff --git a/keyboards/k_type/i2c_master.h b/keyboards/k_type/i2c_master.h new file mode 100644 index 0000000000..5a7893fae8 --- /dev/null +++ b/keyboards/k_type/i2c_master.h @@ -0,0 +1,127 @@ +/* Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* This library follows the convention of the AVR i2c_master library. + * As a result addresses are expected to be already shifted (addr << 1). + * I2CD1 is the default driver which corresponds to pins B6 and B7. This + * can be changed. + * Please ensure that HAL_USE_I2C is TRUE in the halconf.h file and that + * STM32_I2C_USE_I2C1 is TRUE in the mcuconf.h file. + */ +#pragma once + +#include <ch.h> +#include <hal.h> + +#ifndef I2C_COUNT +# define I2C_COUNT 1 +#endif + +#ifdef I2C1_BANK +# define I2C1_SCL_BANK I2C1_BANK +# define I2C1_SDA_BANK I2C1_BANK +#endif + +#ifndef I2C1_SCL_BANK +# define I2C1_SCL_BANK GPIOB +#endif + +#ifndef I2C1_SDA_BANK +# define I2C1_SDA_BANK GPIOB +#endif + + +#ifdef USE_I2C2 +# ifdef I2C2_BANK +# define I2C2_SCL_BANK I2C2_BANK +# define I2C2_SDA_BANK I2C2_BANK +# endif +# ifndef I2C2_SCL_BANK +# define I2C2_SCL_BANK GPIOC +# endif +# ifndef I2C2_SDA_BANK +# define I2C2_SDA_BANK GPIOC +# endif +#endif + +#ifndef I2C1_SCL +# define I2C1_SCL 6 +#endif +#ifndef I2C1_SDA +# define I2C1_SDA 7 +#endif + +#ifdef USE_I2CV1 +# ifndef I2C1_OPMODE +# define I2C1_OPMODE OPMODE_I2C +# endif +# ifndef I2C1_CLOCK_SPEED +# define I2C1_CLOCK_SPEED 100000 /* 400000 */ +# endif +# ifndef I2C1_DUTY_CYCLE +# define I2C1_DUTY_CYCLE STD_DUTY_CYCLE /* FAST_DUTY_CYCLE_2 */ +# endif +#else +// The default timing values below configures the I2C clock to 400khz assuming a 72Mhz clock +// For more info : https://www.st.com/en/embedded-software/stsw-stm32126.html +# ifndef I2C1_TIMINGR_PRESC +# define I2C1_TIMINGR_PRESC 0U +# endif +# ifndef I2C1_TIMINGR_SCLDEL +# define I2C1_TIMINGR_SCLDEL 7U +# endif +# ifndef I2C1_TIMINGR_SDADEL +# define I2C1_TIMINGR_SDADEL 0U +# endif +# ifndef I2C1_TIMINGR_SCLH +# define I2C1_TIMINGR_SCLH 38U +# endif +# ifndef I2C1_TIMINGR_SCLL +# define I2C1_TIMINGR_SCLL 129U +# endif +#endif + +#ifdef USE_GPIOV1 +# ifndef I2C1_SCL_PAL_MODE +# define I2C1_SCL_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN +# endif +# ifndef I2C1_SDA_PAL_MODE +# define I2C1_SDA_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN +# endif +#else +// The default PAL alternate modes are used to signal that the pins are used for I2C +# ifndef I2C1_SCL_PAL_MODE +# define I2C1_SCL_PAL_MODE 4 +# endif +# ifndef I2C1_SDA_PAL_MODE +# define I2C1_SDA_PAL_MODE 4 +# endif +#endif + +typedef int16_t i2c_status_t; + +#define I2C_STATUS_SUCCESS (0) +#define I2C_STATUS_ERROR (-1) +#define I2C_STATUS_TIMEOUT (-2) + +void i2c_init(I2CDriver *driver, ioportid_t scl_port, ioportid_t sda_port, iopadid_t scl_pad, iopadid_t sda_pad); +i2c_status_t i2c_start(uint8_t index, uint8_t address); +i2c_status_t i2c_transmit(uint8_t index, uint8_t address, const uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_receive(uint8_t index, uint8_t address, uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_writeReg(uint8_t index, uint8_t devaddr, uint8_t regaddr, const uint8_t* data, uint16_t length, uint16_t timeout); +i2c_status_t i2c_readReg(uint8_t index, uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length, uint16_t timeout); +void i2c_stop(uint8_t index); diff --git a/keyboards/k_type/is31fl3733.c b/keyboards/k_type/is31fl3733.c new file mode 100644 index 0000000000..8818a622bc --- /dev/null +++ b/keyboards/k_type/is31fl3733.c @@ -0,0 +1,231 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "is31fl3733.h" +#include "i2c_master.h" +#include "wait.h" + +// This is a 7-bit address, that gets left-shifted and bit 0 +// set to 0 for write, 1 for read (as per I2C protocol) +// The address will vary depending on your wiring: +// 00 <-> GND +// 01 <-> SCL +// 10 <-> SDA +// 11 <-> VCC +// ADDR1 represents A1:A0 of the 7-bit address. +// ADDR2 represents A3:A2 of the 7-bit address. +// The result is: 0b101(ADDR2)(ADDR1) +#define ISSI_ADDR_DEFAULT 0x50 + +#define ISSI_COMMANDREGISTER 0xFD +#define ISSI_COMMANDREGISTER_WRITELOCK 0xFE +#define ISSI_INTERRUPTMASKREGISTER 0xF0 +#define ISSI_INTERRUPTSTATUSREGISTER 0xF1 + +#define ISSI_PAGE_LEDCONTROL 0x00 // PG0 +#define ISSI_PAGE_PWM 0x01 // PG1 +#define ISSI_PAGE_AUTOBREATH 0x02 // PG2 +#define ISSI_PAGE_FUNCTION 0x03 // PG3 + +#define ISSI_REG_CONFIGURATION 0x00 // PG3 +#define ISSI_REG_GLOBALCURRENT 0x01 // PG3 +#define ISSI_REG_RESET 0x11 // PG3 +#define ISSI_REG_SWPULLUP 0x0F // PG3 +#define ISSI_REG_CSPULLUP 0x10 // PG3 + +#ifndef ISSI_TIMEOUT +# define ISSI_TIMEOUT 100 +#endif + +#ifndef ISSI_PERSISTENCE +# define ISSI_PERSISTENCE 0 +#endif + +// Transfer buffer for TWITransmitData() +uint8_t g_twi_transfer_buffer[20]; + +// These buffers match the IS31FL3733 PWM registers. +// The control buffers match the PG0 LED On/Off registers. +// Storing them like this is optimal for I2C transfers to the registers. +// We could optimize this and take out the unused registers from these +// buffers and the transfers in IS31FL3733_write_pwm_buffer() but it's +// probably not worth the extra complexity. +uint8_t g_pwm_buffer[DRIVER_COUNT][192]; +bool g_pwm_buffer_update_required[DRIVER_COUNT] = {false}; + +uint8_t g_led_control_registers[DRIVER_COUNT][24] = {{0}, {0}}; +bool g_led_control_registers_update_required[DRIVER_COUNT] = {false}; + +bool IS31FL3733_write_register(uint8_t index, uint8_t addr, uint8_t reg, uint8_t data) { + // If the transaction fails function returns false. + g_twi_transfer_buffer[0] = reg; + g_twi_transfer_buffer[1] = data; + +#if ISSI_PERSISTENCE > 0 + for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { + if (i2c_transmit(index, addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(index, addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT) != 0) { + return false; + } +#endif + return true; +} + +bool IS31FL3733_write_pwm_buffer(uint8_t index, uint8_t addr, uint8_t *pwm_buffer) { + // Assumes PG1 is already selected. + // If any of the transactions fails function returns false. + // Transmit PWM registers in 12 transfers of 16 bytes. + // g_twi_transfer_buffer[] is 20 bytes + + // Iterate over the pwm_buffer contents at 16 byte intervals. + for (int i = 0; i < 192; i += 16) { + g_twi_transfer_buffer[0] = i; + // Copy the data from i to i+15. + // Device will auto-increment register for data after the first byte + // Thus this sets registers 0x00-0x0F, 0x10-0x1F, etc. in one transfer. + for (int j = 0; j < 16; j++) { + g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; + } + +#if ISSI_PERSISTENCE > 0 + for (uint8_t i = 0; i < ISSI_PERSISTENCE; i++) { + if (i2c_transmit(index, addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) != 0) { + return false; + } + } +#else + if (i2c_transmit(index, addr << 1, g_twi_transfer_buffer, 17, ISSI_TIMEOUT) != 0) { + return false; + } +#endif + } + return true; +} + +void IS31FL3733_init(uint8_t bus, uint8_t addr, uint8_t sync) { + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, shutdown is enabled last. + // Set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + // Sync is passed so set it according to the datasheet. + + // Unlock the command register. + IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); + // Select PG0 + IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL); + // Turn off all LEDs. + for (int i = 0x00; i <= 0x17; i++) { + IS31FL3733_write_register(bus, addr, i, 0x00); + } + // Unlock the command register. + IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); + // Select PG1 + IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM); + // Set PWM on all LEDs to 0 + // No need to setup Breath registers to PWM as that is the default. + for (int i = 0x00; i <= 0xBF; i++) { + IS31FL3733_write_register(bus, addr, i, 0x00); + } + // Unlock the command register. + IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); + // Select PG3 + IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION); + // Set global current to maximum. + IS31FL3733_write_register(bus, addr, ISSI_REG_GLOBALCURRENT, 0xFF); + // Disable software shutdown. + IS31FL3733_write_register(bus, addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01); + // Wait 10ms to ensure the device has woken up. + wait_ms(10); +} + +void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + if (index >= 0 && index < DRIVER_LED_TOTAL) { + is31_led led = g_is31_leds[index]; + + g_pwm_buffer[led.driver][led.r] = red; + g_pwm_buffer[led.driver][led.g] = green; + g_pwm_buffer[led.driver][led.b] = blue; + g_pwm_buffer_update_required[led.driver] = true; + } +} + +void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { + for (int i = 0; i < DRIVER_LED_TOTAL; i++) { + IS31FL3733_set_color(i, red, green, blue); + } +} + +void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bool blue) { + is31_led led = g_is31_leds[index]; + + uint8_t control_register_r = led.r / 8; + uint8_t control_register_g = led.g / 8; + uint8_t control_register_b = led.b / 8; + uint8_t bit_r = led.r % 8; + uint8_t bit_g = led.g % 8; + uint8_t bit_b = led.b % 8; + + if (red) { + g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r); + } else { + g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r); + } + if (green) { + g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g); + } else { + g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g); + } + if (blue) { + g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b); + } else { + g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); + } + + g_led_control_registers_update_required[led.driver] = true; +} + +void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index) { + if (g_pwm_buffer_update_required[index]) { + // Firstly we need to unlock the command register and select PG1. + IS31FL3733_write_register(index, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); + IS31FL3733_write_register(index, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM); + + // If any of the transactions fail we risk writing dirty PG0, + // refresh page 0 just in case. + if (!IS31FL3733_write_pwm_buffer(index, addr, g_pwm_buffer[index])) { + g_led_control_registers_update_required[index] = true; + } + } + g_pwm_buffer_update_required[index] = false; +} + +void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index) { + if (g_led_control_registers_update_required[index]) { + // Firstly we need to unlock the command register and select PG0 + IS31FL3733_write_register(index, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5); + IS31FL3733_write_register(index, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL); + for (int i = 0; i < 24; i++) { + IS31FL3733_write_register(index, addr, i, g_led_control_registers[index][i]); + } + } + g_led_control_registers_update_required[index] = false; +} diff --git a/keyboards/k_type/is31fl3733.h b/keyboards/k_type/is31fl3733.h new file mode 100644 index 0000000000..272bcdc417 --- /dev/null +++ b/keyboards/k_type/is31fl3733.h @@ -0,0 +1,251 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * Copyright 2018 Yiancar + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +typedef struct is31_led { + uint8_t driver : 2; + uint8_t r; + uint8_t g; + uint8_t b; +} __attribute__((packed)) is31_led; + +extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; + +void IS31FL3733_init(uint8_t bus, uint8_t addr, uint8_t sync); +bool IS31FL3733_write_register(uint8_t index, uint8_t addr, uint8_t reg, uint8_t data); +bool IS31FL3733_write_pwm_buffer(uint8_t index, uint8_t addr, uint8_t *pwm_buffer); + +void IS31FL3733_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); +void IS31FL3733_set_color_all(uint8_t red, uint8_t green, uint8_t blue); + +void IS31FL3733_set_led_control_register(uint8_t index, bool red, bool green, bool blue); + +// This should not be called from an interrupt +// (eg. from a timer interrupt). +// Call this while idle (in between matrix scans). +// If the buffer is dirty, it will update the driver with the buffer. +void IS31FL3733_update_pwm_buffers(uint8_t addr, uint8_t index); // index is the driver index +void IS31FL3733_update_led_control_registers(uint8_t addr, uint8_t index); + +#define A_1 0x00 +#define A_2 0x01 +#define A_3 0x02 +#define A_4 0x03 +#define A_5 0x04 +#define A_6 0x05 +#define A_7 0x06 +#define A_8 0x07 +#define A_9 0x08 +#define A_10 0x09 +#define A_11 0x0A +#define A_12 0x0B +#define A_13 0x0C +#define A_14 0x0D +#define A_15 0x0E +#define A_16 0x0F + +#define B_1 0x10 +#define B_2 0x11 +#define B_3 0x12 +#define B_4 0x13 +#define B_5 0x14 +#define B_6 0x15 +#define B_7 0x16 +#define B_8 0x17 +#define B_9 0x18 +#define B_10 0x19 +#define B_11 0x1A +#define B_12 0x1B +#define B_13 0x1C +#define B_14 0x1D +#define B_15 0x1E +#define B_16 0x1F + +#define C_1 0x20 +#define C_2 0x21 +#define C_3 0x22 +#define C_4 0x23 +#define C_5 0x24 +#define C_6 0x25 +#define C_7 0x26 +#define C_8 0x27 +#define C_9 0x28 +#define C_10 0x29 +#define C_11 0x2A +#define C_12 0x2B +#define C_13 0x2C +#define C_14 0x2D +#define C_15 0x2E +#define C_16 0x2F + +#define D_1 0x30 +#define D_2 0x31 +#define D_3 0x32 +#define D_4 0x33 +#define D_5 0x34 +#define D_6 0x35 +#define D_7 0x36 +#define D_8 0x37 +#define D_9 0x38 +#define D_10 0x39 +#define D_11 0x3A +#define D_12 0x3B +#define D_13 0x3C +#define D_14 0x3D +#define D_15 0x3E +#define D_16 0x3F + +#define E_1 0x40 +#define E_2 0x41 +#define E_3 0x42 +#define E_4 0x43 +#define E_5 0x44 +#define E_6 0x45 +#define E_7 0x46 +#define E_8 0x47 +#define E_9 0x48 +#define E_10 0x49 +#define E_11 0x4A +#define E_12 0x4B +#define E_13 0x4C +#define E_14 0x4D +#define E_15 0x4E +#define E_16 0x4F + +#define F_1 0x50 +#define F_2 0x51 +#define F_3 0x52 +#define F_4 0x53 +#define F_5 0x54 +#define F_6 0x55 +#define F_7 0x56 +#define F_8 0x57 +#define F_9 0x58 +#define F_10 0x59 +#define F_11 0x5A +#define F_12 0x5B +#define F_13 0x5C +#define F_14 0x5D +#define F_15 0x5E +#define F_16 0x5F + +#define G_1 0x60 +#define G_2 0x61 +#define G_3 0x62 +#define G_4 0x63 +#define G_5 0x64 +#define G_6 0x65 +#define G_7 0x66 +#define G_8 0x67 +#define G_9 0x68 +#define G_10 0x69 +#define G_11 0x6A +#define G_12 0x6B +#define G_13 0x6C +#define G_14 0x6D +#define G_15 0x6E +#define G_16 0x6F + +#define H_1 0x70 +#define H_2 0x71 +#define H_3 0x72 +#define H_4 0x73 +#define H_5 0x74 +#define H_6 0x75 +#define H_7 0x76 +#define H_8 0x77 +#define H_9 0x78 +#define H_10 0x79 +#define H_11 0x7A +#define H_12 0x7B +#define H_13 0x7C +#define H_14 0x7D +#define H_15 0x7E +#define H_16 0x7F + +#define I_1 0x80 +#define I_2 0x81 +#define I_3 0x82 +#define I_4 0x83 +#define I_5 0x84 +#define I_6 0x85 +#define I_7 0x86 +#define I_8 0x87 +#define I_9 0x88 +#define I_10 0x89 +#define I_11 0x8A +#define I_12 0x8B +#define I_13 0x8C +#define I_14 0x8D +#define I_15 0x8E +#define I_16 0x8F + +#define J_1 0x90 +#define J_2 0x91 +#define J_3 0x92 +#define J_4 0x93 +#define J_5 0x94 +#define J_6 0x95 +#define J_7 0x96 +#define J_8 0x97 +#define J_9 0x98 +#define J_10 0x99 +#define J_11 0x9A +#define J_12 0x9B +#define J_13 0x9C +#define J_14 0x9D +#define J_15 0x9E +#define J_16 0x9F + +#define K_1 0xA0 +#define K_2 0xA1 +#define K_3 0xA2 +#define K_4 0xA3 +#define K_5 0xA4 +#define K_6 0xA5 +#define K_7 0xA6 +#define K_8 0xA7 +#define K_9 0xA8 +#define K_10 0xA9 +#define K_11 0xAA +#define K_12 0xAB +#define K_13 0xAC +#define K_14 0xAD +#define K_15 0xAE +#define K_16 0xAF + +#define L_1 0xB0 +#define L_2 0xB1 +#define L_3 0xB2 +#define L_4 0xB3 +#define L_5 0xB4 +#define L_6 0xB5 +#define L_7 0xB6 +#define L_8 0xB7 +#define L_9 0xB8 +#define L_10 0xB9 +#define L_11 0xBA +#define L_12 0xBB +#define L_13 0xBC +#define L_14 0xBD +#define L_15 0xBE +#define L_16 0xBF diff --git a/keyboards/k_type/k_type.c b/keyboards/k_type/k_type.c index ae62f0e723..567ad28430 100644 --- a/keyboards/k_type/k_type.c +++ b/keyboards/k_type/k_type.c @@ -17,6 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "k_type.h" +#include "is31fl3733.h" + #ifdef RGB_MATRIX_ENABLE const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { { 0, B_1, A_1, C_1 }, @@ -45,11 +47,11 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { { 0, E_7, D_7, F_7 }, { 0, E_8, D_8, F_8 }, { 0, E_9, D_9, F_9 }, - { 0, E_10, D_1, F_10 }, - { 0, E_11, D_1, F_11 }, - { 0, E_12, D_1, F_12 }, - { 0, E_13, D_1, F_13 }, - { 0, E_14, D_1, F_14 }, + { 0, E_10, D_10, F_10 }, + { 0, E_11, D_11, F_11 }, + { 0, E_12, D_12, F_12 }, + { 0, E_13, D_13, F_13 }, + { 0, E_14, D_14, F_14 }, { 0, E_15, D_15, F_15 }, { 0, E_16, D_16, F_16 }, @@ -62,11 +64,11 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { { 0, H_7, G_7, I_7 }, { 0, H_8, G_8, I_8 }, { 0, H_9, G_9, I_9 }, - { 0, H_10, G_1, I_10 }, - { 0, H_11, G_1, I_11 }, - { 0, H_12, G_1, I_12 }, - { 0, H_13, G_1, I_13 }, - { 0, H_14, G_1, I_14 }, + { 0, H_10, G_10, I_10 }, + { 0, H_11, G_11, I_11 }, + { 0, H_12, G_12, I_12 }, + { 0, H_13, G_13, I_13 }, + { 0, H_14, G_14, I_14 }, { 0, H_15, G_15, I_15 }, { 0, H_16, G_16, I_16 }, @@ -79,106 +81,123 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { { 0, K_7, J_7, L_7 }, { 0, K_8, J_8, L_8 }, { 0, K_9, J_9, L_9 }, - { 0, K_10, J_1, L_10 }, - { 0, K_11, J_1, L_11 }, - { 0, K_12, J_1, L_12 }, - { 0, K_13, J_1, L_13 }, - { 0, K_14, J_1, L_14 }, + { 0, K_10, J_10, L_10 }, + { 0, K_11, J_11, L_11 }, + { 0, K_12, J_12, L_12 }, + { 0, K_13, J_13, L_13 }, + { 0, K_14, J_14, L_14 }, { 0, K_15, J_15, L_15 }, { 0, K_16, J_16, L_16 }, // Driver 2 is on I2C2 - currently not usable with i2c_master - //{ 1, B_1, A_1, C_1 }, - //{ 1, B_2, A_2, C_2 }, - //{ 1, B_3, A_3, C_3 }, - //{ 1, B_4, A_4, C_4 }, - //{ 1, B_5, A_5, C_5 }, - //{ 1, B_6, A_6, C_6 }, - //{ 1, B_7, A_7, C_7 }, - //{ 1, B_8, A_8, C_8 }, - //{ 1, B_9, A_9, C_9 }, - //{ 1, B_10, A_10, C_10 }, - //{ 1, B_11, A_11, C_11 }, - //{ 1, B_12, A_12, C_12 }, - //{ 1, B_13, A_13, C_13 }, - //{ 1, B_14, A_14, C_14 }, - //{ 1, B_15, A_15, C_15 }, - //{ 1, B_16, A_16, C_16 }, - - //{ 1, E_1, D_1, F_1 }, - //{ 1, E_2, D_2, F_2 }, - //{ 1, E_3, D_3, F_3 }, - //{ 1, E_4, D_4, F_4 }, - //{ 1, E_5, D_5, F_5 }, - //{ 1, E_6, D_6, F_6 }, - //{ 1, E_7, D_7, F_7 }, - //{ 1, E_8, D_8, F_8 }, - //{ 1, E_9, D_9, F_9 }, - //{ 1, E_10, D_1, F_10 }, - //{ 1, E_11, D_1, F_11 }, - //{ 1, E_12, D_1, F_12 }, - //{ 1, E_13, D_1, F_13 }, - //{ 1, E_14, D_1, F_14 }, - //{ 1, E_15, D_15, F_15 }, - //{ 1, E_16, D_16, F_16 }, - - //{ 1, H_1, G_1, I_1 }, - //{ 1, H_2, G_2, I_2 }, - //{ 1, H_3, G_3, I_3 }, - //{ 1, H_4, G_4, I_4 }, - //{ 1, H_5, G_5, I_5 }, - //{ 1, H_6, G_6, I_6 }, - //{ 1, H_7, G_7, I_7 }, - //{ 1, H_8, G_8, I_8 }, - //{ 1, H_9, G_9, I_9 }, - //{ 1, H_10, G_1, I_10 }, - //{ 1, H_11, G_1, I_11 }, - //{ 1, H_12, G_1, I_12 }, - //{ 1, H_13, G_1, I_13 }, - //{ 1, H_14, G_1, I_14 }, - //{ 1, H_15, G_15, I_15 }, - //{ 1, H_16, G_16, I_16 }, - - //{ 1, K_1, J_1, L_1 }, - //{ 1, K_2, J_2, L_2 }, - //{ 1, K_3, J_3, L_3 }, - //{ 1, K_4, J_4, L_4 }, - //{ 1, K_5, J_5, L_5 }, - //{ 1, K_6, J_6, L_6 }, - //{ 1, K_7, J_7, L_7 } + { 1, B_1, A_1, C_1 }, + { 1, B_2, A_2, C_2 }, + { 1, B_3, A_3, C_3 }, + { 1, B_4, A_4, C_4 }, + { 1, B_5, A_5, C_5 }, + { 1, B_6, A_6, C_6 }, + { 1, B_7, A_7, C_7 }, + { 1, B_8, A_8, C_8 }, + { 1, B_9, A_9, C_9 }, + { 1, B_10, A_10, C_10 }, + { 1, B_11, A_11, C_11 }, + { 1, B_12, A_12, C_12 }, + { 1, B_13, A_13, C_13 }, + { 1, B_14, A_14, C_14 }, + { 1, B_15, A_15, C_15 }, + { 1, B_16, A_16, C_16 }, + + { 1, E_1, D_1, F_1 }, + { 1, E_2, D_2, F_2 }, + { 1, E_3, D_3, F_3 }, + { 1, E_4, D_4, F_4 }, + { 1, E_5, D_5, F_5 }, + { 1, E_6, D_6, F_6 }, + { 1, E_7, D_7, F_7 }, + { 1, E_8, D_8, F_8 }, + { 1, E_9, D_9, F_9 }, + { 1, E_10, D_10, F_10 }, + { 1, E_11, D_11, F_11 }, + { 1, E_12, D_12, F_12 }, + { 1, E_13, D_13, F_13 }, + { 1, E_14, D_14, F_14 }, + { 1, E_15, D_15, F_15 }, + { 1, E_16, D_16, F_16 }, + + { 1, H_1, G_1, I_1 }, + { 1, H_2, G_2, I_2 }, + { 1, H_3, G_3, I_3 }, + { 1, H_4, G_4, I_4 }, + { 1, H_5, G_5, I_5 }, + { 1, H_6, G_6, I_6 }, + { 1, H_7, G_7, I_7 }, + { 1, H_8, G_8, I_8 }, + { 1, H_9, G_9, I_9 }, + { 1, H_10, G_10, I_10 }, + { 1, H_11, G_11, I_11 }, + { 1, H_12, G_12, I_12 }, + { 1, H_13, G_13, I_13 }, + { 1, H_14, G_14, I_14 }, + { 1, H_15, G_15, I_15 }, + { 1, H_16, G_16, I_16 }, + + { 1, K_1, J_1, L_1 }, + { 1, K_2, J_2, L_2 }, + { 1, K_3, J_3, L_3 }, + { 1, K_4, J_4, L_4 }, + { 1, K_5, J_5, L_5 }, + { 1, K_6, J_6, L_6 }, + { 1, K_7, J_7, L_7 } }; led_config_t g_led_config = { { // Key Matrix to LED Index - { 0, 10, 20, 29, 38, 47, 57, NO_LED, NO_LED, NO_LED }, - { 1, 11, 21, NO_LED, 39, 48, 58, NO_LED, NO_LED, NO_LED }, - { 2, 12, 22, 30, 40, 49, 59, NO_LED, NO_LED, NO_LED }, - { 3, 13, 23, 31, 41, 50, 60, NO_LED, NO_LED, NO_LED }, - { 4, 14, 24, 32, 42, 51, 61, NO_LED, NO_LED, NO_LED }, - { 5, 15, 25, 33, 43, 52, NO_LED, NO_LED, NO_LED, NO_LED }, - { 6, 16, 26, 34, 44, 53, 62, NO_LED, NO_LED, NO_LED }, - { 7, 17, 27, 35, 45, 54, NO_LED, NO_LED, NO_LED, NO_LED }, - { 8, 18, 28, 36, 46, 55, 63, NO_LED, NO_LED, NO_LED }, - { 9, 19, NO_LED, 37, NO_LED, 56, NO_LED, NO_LED, NO_LED, NO_LED } + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }, + { 20, 21, 22, 23, 24, 25, 26, 27, 28, NO_LED }, + { 29, NO_LED, 30, 31, 32, 33, 34, 35, 36, 37 }, + { 38, 39, 40, 41, 42, 43, 44, 45, 46, NO_LED }, + { 47, 48, 49, 50, 51, 52, 53, 54, 55, 56 }, + { 57, 58, 59, 60, 61, NO_LED |