#include QMK_KEYBOARD_H
#include "i2c_master.h"
#include <print.h>
extern i2c_status_t mcp23017_status;
#define MCP23017_I2C_TIMEOUT 1000
#define I2C_WRITE 0x00
#define I2C_READ 0x01
#define I2C_ADDR 0b0100000
#define I2C_ADDR_WRITE ((I2C_ADDR << 1) | I2C_WRITE)
#define I2C_ADDR_READ ((I2C_ADDR << 1) | I2C_READ)
#define IODIRA 0x00
#define IODIRB 0x01
#define GPPUA 0x0C
#define GPPUB 0x0D
#define MCP23017_GPIOA 0x12
#define MCP23017_GPIOB 0x13
#define OLATA 0x14
#define OLATB 0x15
bool i2c_initialized = 0;
i2c_status_t mcp23017_status = I2C_ADDR;
#define I2C2_SCL_BANK GPIOB
#define I2C2_SCL 10
#define I2C2_SDA_BANK GPIOB
#define I2C2_SDA 11
uint8_t init_mcp23017(void) {
print("init mcp23017\n");
mcp23017_status = I2C_ADDR;
if (i2c_initialized == 0) {
i2c_init(); i2c_initialized = true;
wait_ms(MCP23017_I2C_TIMEOUT);
}
uint8_t buf[] = {IODIRA, 0b11111111, 0b11110000};
print("before transmit\n");
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), MCP23017_I2C_TIMEOUT);
uprintf("after transmit %i\n", mcp23017_status);
if (!mcp23017_status) {
uint8_t pullup_buf[] = {GPPUA, 0b11111111, 0b11110000};
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, pullup_buf, sizeof(pullup_buf), MCP23017_I2C_TIMEOUT);
uprintf("after transmit2 %i\n", mcp23017_status);
}
return mcp23017_status;
}
static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t read_cols(uint8_t row);
static void unselect_row(uint8_t row);
static void unselect_rows(void);
static void unselect_cols(void);
static void select_row(uint8_t row);
static uint8_t mcp23017_reset_loop;
static void init_mcu_pins(void) {
unselect_rows();
unselect_cols();
}
void matrix_init_custom(void) {
debug_enable = true;
debug_matrix = true;
dprint("matrix_init_custom\n");
init_mcu_pins();
mcp23017_status = init_mcp23017();
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
}
}
static inline bool store_matrix_row(matrix_row_t current_matrix[], uint8_t index) {
matrix_row_t temp = read_cols(index);
if (current_matrix[index] != temp) {
current_matrix[index] = temp;
return true;
}
return false;
}
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
if (mcp23017_status) { if (++mcp23017_reset_loop == 0) {
print("trying to reset mcp23017\n");
mcp23017_status = init_mcp23017();
if (mcp23017_status) {
print("right side not responding\n");
} else {
print("right side attached\n");
}
}
}
bool changed = false;
for (uint8_t i = 0; i < MATRIX_ROWS_PER_SIDE; i++) {
uint8_t left_index = i;
uint8_t right_index = i + MATRIX_ROWS_PER_SIDE;
changed |= store_matrix_row(current_matrix, left_index);
changed |= store_matrix_row(current_matrix, right_index);
unselect_rows();
}
return changed;
}
static matrix_row_t read_cols(uint8_t row) {
select_row(row);
if (row < MATRIX_ROWS_PER_SIDE) {
pin_t matrix_col_pins_mcu[MATRIX_COLS_PER_SIDE] = MATRIX_COL_PINS_MCU;
matrix_row_t current_row_value = 0;
matrix_io_delay();
for (uint8_t col_index = 0; col_index < MATRIX_COLS_PER_SIDE; col_index++) {
uint8_t pin_state = readPin(matrix_col_pins_mcu[col_index]);
current_row_value |= pin_state ? 0 : (MATRIX_ROW_SHIFTER << col_index);
}
unselect_row(row);
return current_row_value;
} else {
if (mcp23017_status) { return 0;
} else {
uint8_t buf[] = {MCP23017_GPIOA};
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), MCP23017_I2C_TIMEOUT);
uint8_t data[] = {0};
if (!mcp23017_status) {
mcp23017_status = i2c_receive(I2C_ADDR_READ, data, sizeof(data), MCP23017_I2C_TIMEOUT);
data[0] = ~(data[0]);
}
return data[0];
}
}
}
static void unselect_row(uint8_t row) {
pin_t matrix_row_pins_mcu[MATRIX_ROWS_PER_SIDE] = MATRIX_ROW_PINS_MCU;
setPinInputHigh(matrix_row_pins_mcu[row]);
}
static void unselect_rows(void) {
pin_t matrix_row_pins_mcu[MATRIX_ROWS_PER_SIDE] = MATRIX_ROW_PINS_MCU;
for (int pin_index = 0; pin_index < MATRIX_ROWS_PER_SIDE; pin_index++) {
pin_t pin = matrix_row_pins_mcu[pin_index];
setPinInputHigh(pin);
}
}
static void unselect_cols(void) {
pin_t matrix_col_pins_mcu[MATRIX_COLS_PER_SIDE] = MATRIX_COL_PINS_MCU;
for (int pin_index = 0; pin_index < MATRIX_COLS_PER_SIDE; pin_index++) {
pin_t pin = matrix_col_pins_mcu[pin_index];
setPinInputHigh(pin);
}
}
static void select_row(uint8_t row) {
if (row < MATRIX_ROWS_PER_SIDE) {
pin_t matrix_row_pins_mcu[MATRIX_ROWS_PER_SIDE] = MATRIX_ROW_PINS_MCU;
pin_t pin = matrix_row_pins_mcu[row];
setPinOutput(pin);
writePinLow(pin);
} else {
if (mcp23017_status) { } else {
uint8_t buf[] = {MCP23017_GPIOB, 0xFF & ~(1 << (row - MATRIX_ROWS_PER_SIDE))};
mcp23017_status = i2c_transmit(I2C_ADDR_WRITE, buf, sizeof(buf), I2C_TIMEOUT);
}
}
}