1
0

kimera: Improve matrix scanning frequency

- Implement improved debounce algorithm
- Change combining of keymap for two-headed kimera
This commit is contained in:
Kai Ryu 2016-03-31 18:52:43 +09:00
parent e2773c801a
commit 93029977a8
3 changed files with 210 additions and 19 deletions

View File

@ -86,6 +86,17 @@ static matrix_row_t col_left_mask;
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 */
@ -130,7 +141,7 @@ uint8_t read_matrix_mapping(void)
#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 */
@ -200,30 +211,68 @@ void kimera_scan(void)
} }
} }
#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; return row_count;
#else
return row_left_count;
#endif
#else
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;
@ -236,6 +285,8 @@ matrix_row_t kimera_read_cols(uint8_t row)
} }
} }
#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;
@ -243,6 +294,7 @@ matrix_row_t kimera_read_cols(uint8_t row)
else { else {
cols >>= col_left_count; cols >>= col_left_count;
} }
#endif
#endif #endif
return cols; return cols;
@ -267,6 +319,13 @@ void kimera_select_row(uint8_t row)
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)
@ -349,6 +408,7 @@ uint8_t expander_write_config(uint8_t exp, uint8_t *data)
{ {
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)
{ {

View File

@ -156,22 +156,13 @@ const uint16_t PROGMEM dummy[] = {
/* 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

View File

@ -28,16 +28,29 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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)
@ -58,15 +71,27 @@ void matrix_init(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);
@ -74,12 +99,123 @@ void matrix_init(void)
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) {
@ -99,15 +235,19 @@ uint8_t matrix_scan(void)
} }
} }
} }
#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)