Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Re)Fixing K-type RGB lighting #12084

Merged
merged 13 commits into from
Mar 25, 2021
Merged
Prev Previous commit
Next Next commit
refactored my code to make it more maintainable and updated keymaps.
  • Loading branch information
Andrew-Fahmy committed Jan 26, 2021
commit f0506e51387c61f13112efb9070b059ec6a136c4
76 changes: 48 additions & 28 deletions keyboards/k_type/i2c_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@

static uint8_t i2c_address;

I2CDriver *drivers[2] = {
&I2CD1,
&I2CD2
};
I2CDriver *drivers[I2C_COUNT];

static const I2CConfig i2cconfig = {
#if defined(USE_I2CV1_CONTRIB)
Expand All @@ -44,6 +41,10 @@ static const I2CConfig i2cconfig = {
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
};

Expand All @@ -59,67 +60,86 @@ static i2c_status_t chibios_to_qmk(const msg_t* status) {
}
}

__attribute__((weak)) void i2c_init(void) {
static bool is_initialised = false;
if (!is_initialised) {
is_initialised = true;

__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(I2C1_SCL_BANK, I2C1_SCL, PAL_MODE_INPUT);
palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, PAL_MODE_INPUT);

palSetPadMode(I2C2_SCL_BANK, I2C2_SCL, PAL_MODE_INPUT);
palSetPadMode(I2C2_SDA_BANK, I2C2_SDA, PAL_MODE_INPUT);
palSetPadMode(scl_port, scl_pad, PAL_MODE_INPUT);
palSetPadMode(sda_port, sda_pad, PAL_MODE_INPUT);

chThdSleepMilliseconds(10);

palSetPadMode(I2C1_SCL_BANK, I2C1_SCL, I2C1_SCL_PAL_MODE);
palSetPadMode(I2C1_SDA_BANK, I2C1_SDA, I2C1_SDA_PAL_MODE);
#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

palSetPadMode(I2C2_SCL_BANK, I2C2_SCL, I2C2_SCL_PAL_MODE);
palSetPadMode(I2C2_SDA_BANK, I2C2_SDA, I2C2_SDA_PAL_MODE);
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);
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));
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));
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);
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));
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), &regaddr, 1, data, length, TIME_MS2I(timeout));
i2cStart(drivers[index], &i2cconfig);
msg_t status = i2cMasterTransmitTimeout(drivers[index], (i2c_address >> 1), &regaddr, 1, data, length, TIME_MS2I(timeout));
return chibios_to_qmk(&status);
}

void i2c_stop(void) { i2cStop(&I2CD1); i2cStop(&I2CD2); }
void i2c_stop(uint8_t index) {
if(index < I2C_COUNT) {
i2cStop(drivers[index]);
}
}
70 changes: 40 additions & 30 deletions keyboards/k_type/i2c_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#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
Expand All @@ -40,25 +44,26 @@
# define I2C1_SDA_BANK GPIOB
#endif

#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
#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 I2C2_SDA_BANK
# define I2C2_SDA_BANK GPIOC
#ifndef I2C1_SCL
# define I2C1_SCL 6
#endif
#ifndef I2C1_SDA
# define I2C1_SDA 7
#endif

// #ifndef I2C1_SCL
// # define I2C1_SCL 6
// #endif
// #ifndef I2C1_SDA
// # define I2C1_SDA 7
// #endif

#ifdef USE_I2CV1
# ifndef I2C1_OPMODE
Expand All @@ -70,6 +75,24 @@
# 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
Expand All @@ -79,12 +102,6 @@
# ifndef I2C1_SDA_PAL_MODE
# define I2C1_SDA_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
# endif
# ifndef I2C2_SCL_PAL_MODE
# define I2C2_SCL_PAL_MODE PAL_MODE_STM32_ALTERNATE_OPENDRAIN
# endif
# ifndef I2C2_SDA_PAL_MODE
# define I2C2_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
Expand All @@ -93,13 +110,6 @@
# ifndef I2C1_SDA_PAL_MODE
# define I2C1_SDA_PAL_MODE 4
# endif

# ifndef I2C2_SCL_PAL_MODE
# define I2C2_SCL_PAL_MODE 4
# endif
# ifndef I2C2_SDA_PAL_MODE
# define I2C2_SDA_PAL_MODE 4
# endif
#endif

typedef int16_t i2c_status_t;
Expand All @@ -108,10 +118,10 @@ typedef int16_t i2c_status_t;
#define I2C_STATUS_ERROR (-1)
#define I2C_STATUS_TIMEOUT (-2)

void i2c_init(void);
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(void);
void i2c_stop(uint8_t index);
38 changes: 11 additions & 27 deletions keyboards/k_type/is31fl3733.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,54 +121,38 @@ bool IS31FL3733_write_pwm_buffer(uint8_t index, uint8_t addr, uint8_t *pwm_buffe
return true;
}

void IS31FL3733_init(uint8_t addr, uint8_t sync) {
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(0, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3733_write_register(1, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);

IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
// Select PG0
IS31FL3733_write_register(0, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
IS31FL3733_write_register(1, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL);
// Turn off all LEDs.
for (int i = 0x00; i <= 0x17; i++) {
IS31FL3733_write_register(0, addr, i, 0x00);
IS31FL3733_write_register(1, addr, i, 0x00);
IS31FL3733_write_register(bus, addr, i, 0x00);
}

// Unlock the command register.
IS31FL3733_write_register(0, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3733_write_register(1, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);

IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
// Select PG1
IS31FL3733_write_register(0, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
IS31FL3733_write_register(1, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM);
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(0, addr, i, 0x00);
IS31FL3733_write_register(1, addr, i, 0x00);
IS31FL3733_write_register(bus, addr, i, 0x00);
}

// Unlock the command register.
IS31FL3733_write_register(0, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
IS31FL3733_write_register(1, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);

IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5);
// Select PG3
IS31FL3733_write_register(0, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION);
IS31FL3733_write_register(1, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION);
IS31FL3733_write_register(bus, addr, ISSI_COMMANDREGISTER, ISSI_PAGE_FUNCTION);
// Set global current to maximum.
IS31FL3733_write_register(0, addr, ISSI_REG_GLOBALCURRENT, 0xFF);
IS31FL3733_write_register(1, addr, ISSI_REG_GLOBALCURRENT, 0xFF);
IS31FL3733_write_register(bus, addr, ISSI_REG_GLOBALCURRENT, 0xFF);
// Disable software shutdown.
IS31FL3733_write_register(0, addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01);
IS31FL3733_write_register(1, addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01);

IS31FL3733_write_register(bus, addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01);
// Wait 10ms to ensure the device has woken up.
wait_ms(10);
}
Expand Down
2 changes: 1 addition & 1 deletion keyboards/k_type/is31fl3733.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ typedef struct is31_led {

extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];

void IS31FL3733_init(uint8_t addr, uint8_t sync);
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);

Expand Down
2 changes: 2 additions & 0 deletions keyboards/k_type/k_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
26 changes: 22 additions & 4 deletions keyboards/k_type/keymaps/andrew-fahmy/config.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,42 @@
#pragma once
/* Copyright 2021 Andrew Fahmy
*
* 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


#ifdef RGB_MATRIX_ENABLE
// # define RGB_MATRIX_FRAMEBUFFER_EFFECTS
# define RGB_MATRIX_KEYPRESSES
# define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_SOLID_COLOR
// # define RGB_MATRIX_KEYPRESSES
# define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_RAINDROPS

// # define DEBUG_MATRIX_SCAN_RATE
# define DEBUG_MATRIX_SCAN_RATE

# define RGB_MATRIX_LED_FLUSH_LIMIT 100
// # define RGB_MATRIX_LED_PROCESS_LIMIT 2

// i2c_master defines
# define I2C_COUNT 2

# define I2C1_BANK GPIOB
# define I2C1_SCL 0 // A2 on pinout = B0
# define I2C1_SDA 1 // A2 on pinout = B1
# define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATIVE_2
# define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATIVE_2

# define USE_I2C2
# define I2C2_BANK GPIOC
# define I2C2_SCL 10 // A2 on pinout = C10
# define I2C2_SDA 11 // A2 on pinout = C11
Expand Down
Loading