瀏覽代碼

kimera: Improve matrix scanning frequency

- Implement improved debounce algorithm
- Change combining of keymap for two-headed kimera
master
Kai Ryu 8 年之前
父節點
當前提交
93029977a8
共有 3 個文件被更改,包括 210 次插入19 次删除
  1. 64
    4
      keyboard/kimera/kimera.c
  2. 3
    12
      keyboard/kimera/kimera.h
  3. 143
    3
      keyboard/kimera/matrix.c

+ 64
- 4
keyboard/kimera/kimera.c 查看文件

static uint8_t data[EXP_COUNT][EXP_PORT_COUNT]; static uint8_t data[EXP_COUNT][EXP_PORT_COUNT];
static uint8_t exp_status = 0; static uint8_t exp_status = 0;


static uint8_t read_matrix_mapping(void);
static void write_matrix_mapping(void);
static void expander_init(uint8_t exp);
static uint8_t expander_write(uint8_t exp, uint8_t command, uint8_t *data);
static uint8_t expander_read(uint8_t exp, uint8_t command, uint8_t *data);
static uint8_t expander_write_output(uint8_t exp, uint8_t *data);
static uint8_t expander_write_inversion(uint8_t exp, uint8_t *data);
static uint8_t expander_write_config(uint8_t exp, uint8_t *data);
static uint8_t expander_read_input(uint8_t exp, uint8_t *data);
static void init_data(uint8_t value);

void kimera_init(void) void kimera_init(void)
{ {
/* read config */ /* read config */
#ifdef TWO_HEADED_KIMERA #ifdef TWO_HEADED_KIMERA
row_left_count = (rows + 1) / 2; row_left_count = (rows + 1) / 2;
col_left_count = (cols + 1) / 2; col_left_count = (cols + 1) / 2;
col_left_mask = (1 << row_left_count) - 1;
col_left_mask = (1 << col_left_count) - 1;
#endif #endif


/* read row mapping */ /* read row mapping */
} }
} }


#define CHANGE_COMBINING 1

inline inline
uint8_t kimera_matrix_rows(void) uint8_t kimera_matrix_rows(void)
{ {
#if CHANGE_COMBINING
#ifndef TWO_HEADED_KIMERA
return row_count;
#else
return row_left_count;
#endif
#else
return row_count; return row_count;
#endif
} }


inline inline
uint8_t kimera_matrix_cols(void) uint8_t kimera_matrix_cols(void)
{ {
#if CHANGE_COMBINING
return col_count;
#else
#ifndef TWO_HEADED_KIMERA #ifndef TWO_HEADED_KIMERA
return col_count; return col_count;
#else #else
return col_left_count; return col_left_count;
#endif #endif
#endif
} }


matrix_row_t kimera_read_cols(uint8_t row)
void kimera_read_cols(void)
{ {
init_data(0xFF);

/* read all input registers */ /* read all input registers */
init_data(0xFF);
for (uint8_t exp = 0; exp < EXP_COUNT; exp++) { for (uint8_t exp = 0; exp < EXP_COUNT; exp++) {
expander_read_input(exp, data[exp]); expander_read_input(exp, data[exp]);
} }
}

uint8_t kimera_get_col(uint8_t row, uint8_t col)
{
#if CHANGE_COMBINING
#else
#ifdef TWO_HEADED_KIMERA
if (row >= row_left_count) {
col += col_left_count;
}
#endif
#endif

uint8_t px = col_mapping[col];
if (px != UNCONFIGURED) {
if (!(data[PX_TO_EXP(px)][PX_TO_PORT(px)] & (1 << PX_TO_PIN(px)))) {
return 1;
}
}
return 0;
}

matrix_row_t kimera_read_row(uint8_t row)
{
kimera_read_cols();


/* make cols */ /* make cols */
matrix_row_t cols = 0; matrix_row_t cols = 0;
} }
} }


#if CHANGE_COMBINING
#else
#ifdef TWO_HEADED_KIMERA #ifdef TWO_HEADED_KIMERA
if (row < row_left_count) { if (row < row_left_count) {
cols &= col_left_mask; cols &= col_left_mask;
else { else {
cols >>= col_left_count; cols >>= col_left_count;
} }
#endif
#endif #endif


return cols; return cols;
data[exp][PX_TO_PORT(px)] &= ~(1 << PX_TO_PIN(px)); data[exp][PX_TO_PORT(px)] &= ~(1 << PX_TO_PIN(px));
expander_write_config(exp, data[exp]); expander_write_config(exp, data[exp]);
} }
#if CHANGE_COMBINING
#ifdef TWO_HEADED_KIMERA
if (row < row_left_count) {
kimera_select_row(row + row_left_count);
}
#endif
#endif
} }


void expander_init(uint8_t exp) void expander_init(uint8_t exp)
{ {
return expander_write(exp, EXP_COMM_CONFIG_0, data); return expander_write(exp, EXP_COMM_CONFIG_0, data);
} }

inline inline
uint8_t expander_read_input(uint8_t exp, uint8_t *data) uint8_t expander_read_input(uint8_t exp, uint8_t *data)
{ {

+ 3
- 12
keyboard/kimera/kimera.h 查看文件

/* Functions */ /* Functions */


void kimera_init(void); void kimera_init(void);
void wdt_init(void);
uint8_t read_matrix_mapping(void);
void write_matrix_mapping(void);
void kimera_scan(void); void kimera_scan(void);
uint8_t kimera_matrix_rows(void); uint8_t kimera_matrix_rows(void);
uint8_t kimera_matrix_cols(void); uint8_t kimera_matrix_cols(void);
matrix_row_t kimera_read_cols(uint8_t row);
void kimera_read_cols(void);
uint8_t kimera_get_col(uint8_t row, uint8_t col);
matrix_row_t kimera_read_row(uint8_t row);
void kimera_unselect_rows(void); void kimera_unselect_rows(void);
void kimera_select_row(uint8_t row); void kimera_select_row(uint8_t row);
void expander_init(uint8_t exp);
uint8_t expander_write(uint8_t exp, uint8_t command, uint8_t *data);
uint8_t expander_read(uint8_t exp, uint8_t command, uint8_t *data);
uint8_t expander_write_output(uint8_t exp, uint8_t *data);
uint8_t expander_write_inversion(uint8_t exp, uint8_t *data);
uint8_t expander_write_config(uint8_t exp, uint8_t *data);
uint8_t expander_read_input(uint8_t exp, uint8_t *data);
void init_data(uint8_t value);


#endif #endif

+ 143
- 3
keyboard/kimera/matrix.c 查看文件

#include "matrix.h" #include "matrix.h"
#include "kimera.h" #include "kimera.h"
#include "keymap_in_eeprom.h" #include "keymap_in_eeprom.h"
#include "timer.h"




#ifndef DEBOUNCE #ifndef DEBOUNCE
# define DEBOUNCE 5 # define DEBOUNCE 5
#endif #endif
static uint8_t debouncing = DEBOUNCE;


/* matrix state(1:on, 0:off) */ /* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS]; static matrix_row_t matrix[MATRIX_ROWS];

#define IMPROVED_DEBOUNCE 1

#if IMPROVED_DEBOUNCE
#define DEBOUNCE_MASK ((1 << DEBOUNCE) - 1)
static uint8_t matrix_current_row;
static uint16_t matrix_row_timestamp[MATRIX_ROWS];
static uint8_t matrix_debouncing[MATRIX_ROWS][MATRIX_COLS];
#else
static uint8_t debouncing = DEBOUNCE;
static matrix_row_t matrix_debouncing[MATRIX_ROWS]; static matrix_row_t matrix_debouncing[MATRIX_ROWS];
#endif

static uint16_t kimera_scan_timestamp;


inline inline
uint8_t matrix_rows(void) uint8_t matrix_rows(void)
MCUCR = (1<<JTD); MCUCR = (1<<JTD);


kimera_init(); kimera_init();
kimera_scan_timestamp = timer_read();


// initialize row and col // initialize row and col
kimera_unselect_rows(); kimera_unselect_rows();


// initialize matrix state: all keys off // initialize matrix state: all keys off
#if IMPROVED_DEBOUNCE
for (uint8_t i = 0; i < matrix_rows(); i++) {
matrix[i] = 0;
matrix_current_row = 0;
matrix_row_timestamp[i] = timer_read();
for (uint8_t j = 0; j < matrix_cols(); j++) {
matrix_debouncing[i][j] = 0;
}
}
#else
for (uint8_t i=0; i < matrix_rows(); i++) { for (uint8_t i=0; i < matrix_rows(); i++) {
matrix[i] = 0; matrix[i] = 0;
matrix_debouncing[i] = 0; matrix_debouncing[i] = 0;
} }
#endif


PORTD &= ~(1<<PD4); PORTD &= ~(1<<PD4);




uint8_t matrix_scan(void) uint8_t matrix_scan(void)
{ {
kimera_scan();


/* xprintf("Row: %d, %u\n", matrix_current_row, timer_read()); */

if (timer_elapsed(kimera_scan_timestamp) >= 1000) {
xprintf("Scan, %u\n", kimera_scan_timestamp);
kimera_scan_timestamp = timer_read();
kimera_scan();
}

#if IMPROVED_DEBOUNCE
uint16_t elapsed = timer_elapsed(matrix_row_timestamp[matrix_current_row]);
if (elapsed >= 1) {
matrix_row_timestamp[matrix_current_row] = timer_read();
kimera_select_row(matrix_current_row);
_delay_us(30);
kimera_read_cols();
for (uint8_t i = 0; i < matrix_cols(); i++) {
uint8_t *debounce = &matrix_debouncing[matrix_current_row][i];
uint8_t col = kimera_get_col(matrix_current_row, i);
uint8_t count = elapsed;
do {
*debounce <<= 1;
*debounce |= col;
} while (--count);
matrix_row_t *row = &matrix[matrix_current_row];
matrix_row_t mask = ((matrix_row_t)1 << i);
switch (*debounce & DEBOUNCE_MASK) {
case DEBOUNCE_MASK:
#if DEBOUNCE > 1
case (DEBOUNCE_MASK >> 1):
#if DEBOUNCE > 2
case (DEBOUNCE_MASK >> 2):
#if DEBOUNCE > 3
case (DEBOUNCE_MASK >> 3):
#if DEBOUNCE > 4
case (DEBOUNCE_MASK >> 4):
#if DEBOUNCE > 5
case (DEBOUNCE_MASK >> 5):
#if DEBOUNCE > 6
case (DEBOUNCE_MASK >> 6):
#if DEBOUNCE > 7
case (DEBOUNCE_MASK >> 7):
#if DEBOUNCE > 8
case (DEBOUNCE_MASK >> 8):
#if DEBOUNCE > 9
case (DEBOUNCE_MASK >> 9):
#if DEBOUNCE > 10
case (DEBOUNCE_MASK >> 10):
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
if ((*row & mask) == 0) {
*row |= mask;
}
break;
#if DEBOUNCE > 1
case ((DEBOUNCE_MASK << 1) & DEBOUNCE_MASK):
#if DEBOUNCE > 2
case ((DEBOUNCE_MASK << 2) & DEBOUNCE_MASK):
#if DEBOUNCE > 3
case ((DEBOUNCE_MASK << 3) & DEBOUNCE_MASK):
#if DEBOUNCE > 4
case ((DEBOUNCE_MASK << 4) & DEBOUNCE_MASK):
#if DEBOUNCE > 5
case ((DEBOUNCE_MASK << 5) & DEBOUNCE_MASK):
#if DEBOUNCE > 6
case ((DEBOUNCE_MASK << 6) & DEBOUNCE_MASK):
#if DEBOUNCE > 7
case ((DEBOUNCE_MASK << 7) & DEBOUNCE_MASK):
#if DEBOUNCE > 8
case ((DEBOUNCE_MASK << 8) & DEBOUNCE_MASK):
#if DEBOUNCE > 9
case ((DEBOUNCE_MASK << 9) & DEBOUNCE_MASK):
#if DEBOUNCE > 10
case ((DEBOUNCE_MASK << 10) & DEBOUNCE_MASK):
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
#endif
break;
case 0:
if ((*row & mask) != 0) {
*row &= ~mask;
}
break;
default:
debug("bounce!: ");
debug_bin8(*debounce & DEBOUNCE_MASK);
debug("\n");
break;
}
}
kimera_unselect_rows();
}

matrix_current_row++;
if (matrix_current_row >= matrix_rows()) {
matrix_current_row = 0;
}
#else
for (uint8_t i = 0; i < matrix_rows(); i++) { for (uint8_t i = 0; i < matrix_rows(); i++) {
kimera_select_row(i); kimera_select_row(i);
_delay_us(30); // without this wait read unstable value. _delay_us(30); // without this wait read unstable value.
matrix_row_t cols = kimera_read_cols(i);
matrix_row_t cols = kimera_read_row(i);
if (matrix_debouncing[i] != cols) { if (matrix_debouncing[i] != cols) {
matrix_debouncing[i] = cols; matrix_debouncing[i] = cols;
if (debouncing) { if (debouncing) {
} }
} }
} }
#endif


return 1; return 1;
} }


#if IMPROVED_DEBOUNCE
#else
bool matrix_is_modified(void) bool matrix_is_modified(void)
{ {
if (debouncing) return false; if (debouncing) return false;
return true; return true;
} }
#endif


inline inline
bool matrix_is_on(uint8_t row, uint8_t col) bool matrix_is_on(uint8_t row, uint8_t col)