static uint8_t debouncing = DEBOUNCE; | static uint8_t debouncing = DEBOUNCE; | ||||
/* matrix state(1:on, 0:off) */ | /* matrix state(1:on, 0:off) */ | ||||
static matrix_row_t *matrix; | |||||
static matrix_row_t *matrix_debouncing; | |||||
static matrix_row_t matrix0[MATRIX_ROWS]; | |||||
static matrix_row_t matrix1[MATRIX_ROWS]; | |||||
static matrix_row_t matrix[MATRIX_ROWS]; | |||||
static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | |||||
static matrix_row_t read_cols(void); | static matrix_row_t read_cols(void); | ||||
static void init_cols(void); | static void init_cols(void); | ||||
init_cols(); | init_cols(); | ||||
// initialize matrix state: all keys off | // initialize matrix state: all keys off | ||||
matrix = matrix0; | |||||
matrix_debouncing = matrix1; | |||||
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; | ||||
if (--debouncing) { | if (--debouncing) { | ||||
_delay_ms(1); | _delay_ms(1); | ||||
} else { | } else { | ||||
matrix_row_t *tmp = matrix; | |||||
matrix = matrix_debouncing; | |||||
matrix_debouncing = tmp; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
matrix[i] = matrix_debouncing[i]; | |||||
} | |||||
} | } | ||||
} | } | ||||
# Build Options | # Build Options | ||||
# comment out to disable the options. | # comment out to disable the options. | ||||
# | # | ||||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | MOUSEKEY_ENABLE = yes # Mouse keys | ||||
EXTRAKEY_ENABLE = yes # Audio control and System control | EXTRAKEY_ENABLE = yes # Audio control and System control | ||||
CONSOLE_ENABLE = yes # Console for debug | CONSOLE_ENABLE = yes # Console for debug | ||||
#NKRO_ENABLE = yes # USB Nkey Rollover | |||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||||
# Boot Section Size in bytes | # Boot Section Size in bytes |
#define MATRIX_HAS_GHOST | #define MATRIX_HAS_GHOST | ||||
/* Set 0 if need no debouncing */ | /* Set 0 if need no debouncing */ | ||||
#define DEBOUNCE 10 | |||||
#define DEBOUNCE 5 | |||||
/* legacy keymap support */ | /* legacy keymap support */ | ||||
#define USE_LEGACY_KEYMAP | #define USE_LEGACY_KEYMAP |
#endif | #endif | ||||
static uint8_t debouncing = DEBOUNCE; | static uint8_t debouncing = DEBOUNCE; | ||||
// matrix state buffer(1:on, 0:off) | |||||
static uint8_t *matrix; | |||||
static uint8_t *matrix_debouncing; | |||||
static uint8_t matrix0[MATRIX_ROWS]; | |||||
static uint8_t matrix1[MATRIX_ROWS]; | |||||
/* matrix state(1:on, 0:off) */ | |||||
static matrix_row_t matrix[MATRIX_ROWS]; | |||||
static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | |||||
#ifdef MATRIX_HAS_GHOST | #ifdef MATRIX_HAS_GHOST | ||||
static bool matrix_has_ghost_in_row(uint8_t row); | static bool matrix_has_ghost_in_row(uint8_t row); | ||||
#endif | #endif | ||||
static uint8_t read_col(void); | |||||
static matrix_row_t read_cols(void); | |||||
static void unselect_rows(void); | static void unselect_rows(void); | ||||
static void select_row(uint8_t row); | static void select_row(uint8_t row); | ||||
void matrix_init(void) | void matrix_init(void) | ||||
{ | { | ||||
print_enable = true; | |||||
debug_enable = true; | |||||
debug_matrix = true; | |||||
debug_keyboard = false; | |||||
debug_mouse = false; | |||||
print("debug enabled.\n"); | |||||
// JTAG disable for PORT F. write JTD bit twice within four cycles. | // JTAG disable for PORT F. write JTD bit twice within four cycles. | ||||
MCUCR |= (1<<JTD); | MCUCR |= (1<<JTD); | ||||
MCUCR |= (1<<JTD); | MCUCR |= (1<<JTD); | ||||
PORTD = 0xFF; | PORTD = 0xFF; | ||||
// initialize matrix state: all keys off | // initialize matrix state: all keys off | ||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix0[i] = 0x00; | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix1[i] = 0x00; | |||||
matrix = matrix0; | |||||
matrix_debouncing = matrix1; | |||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | |||||
matrix[i] = 0; | |||||
matrix_debouncing[i] = 0; | |||||
} | |||||
} | } | ||||
uint8_t matrix_scan(void) | uint8_t matrix_scan(void) | ||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||||
select_row(i); | select_row(i); | ||||
_delay_us(30); // without this wait read unstable value. | _delay_us(30); // without this wait read unstable value. | ||||
if (matrix_debouncing[i] != read_col()) { | |||||
matrix_debouncing[i] = read_col(); | |||||
matrix_row_t cols = read_cols(); | |||||
if (matrix_debouncing[i] != cols) { | |||||
matrix_debouncing[i] = cols; | |||||
if (debouncing) { | if (debouncing) { | ||||
debug("bounce!: "); debug_hex(debouncing); debug("\n"); | debug("bounce!: "); debug_hex(debouncing); debug("\n"); | ||||
} | } | ||||
if (--debouncing) { | if (--debouncing) { | ||||
_delay_ms(1); | _delay_ms(1); | ||||
} else { | } else { | ||||
uint8_t *tmp = matrix; | |||||
matrix = matrix_debouncing; | |||||
matrix_debouncing = tmp; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
matrix[i] = matrix_debouncing[i]; | |||||
} | |||||
} | } | ||||
} | } | ||||
inline | inline | ||||
bool matrix_is_on(uint8_t row, uint8_t col) | bool matrix_is_on(uint8_t row, uint8_t col) | ||||
{ | { | ||||
return (matrix[row] & (1<<col)); | |||||
return (matrix[row] & ((matrix_row_t)1<<col)); | |||||
} | } | ||||
inline | inline | ||||
#if (MATRIX_COLS <= 8) | |||||
uint8_t matrix_get_row(uint8_t row) | |||||
#else | |||||
uint16_t matrix_get_row(uint8_t row) | |||||
#endif | |||||
matrix_row_t matrix_get_row(uint8_t row) | |||||
{ | { | ||||
return matrix[row]; | return matrix[row]; | ||||
} | } | ||||
print("\nr/c 01234567\n"); | print("\nr/c 01234567\n"); | ||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | for (uint8_t row = 0; row < matrix_rows(); row++) { | ||||
phex(row); print(": "); | phex(row); print(": "); | ||||
#if (MATRIX_COLS <= 8) | |||||
pbin_reverse(matrix_get_row(row)); | pbin_reverse(matrix_get_row(row)); | ||||
#else | |||||
pbin_reverse16(matrix_get_row(row)); | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | #ifdef MATRIX_HAS_GHOST | ||||
if (matrix_has_ghost_in_row(row)) { | if (matrix_has_ghost_in_row(row)) { | ||||
print(" <ghost"); | print(" <ghost"); | ||||
#endif | #endif | ||||
inline | inline | ||||
static uint8_t read_col(void) | |||||
static matrix_row_t read_cols(void) | |||||
{ | { | ||||
return ~PIND; | return ~PIND; | ||||
} | } |
# Build Options | # Build Options | ||||
# comment out to disable the options. | # comment out to disable the options. | ||||
# | # | ||||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | MOUSEKEY_ENABLE = yes # Mouse keys | ||||
EXTRAKEY_ENABLE = yes # Audio control and System control | EXTRAKEY_ENABLE = yes # Audio control and System control | ||||
CONSOLE_ENABLE = yes # Console for debug | CONSOLE_ENABLE = yes # Console for debug | ||||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | #NKRO_ENABLE = yes # USB Nkey Rollover | ||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | |||||
# Boot Section Size in bytes | # Boot Section Size in bytes |
# Build Options | # Build Options | ||||
# comment out to disable the options. | # comment out to disable the options. | ||||
# | # | ||||
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | MOUSEKEY_ENABLE = yes # Mouse keys | ||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | #PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | ||||
EXTRAKEY_ENABLE = yes # Audio control and System control | EXTRAKEY_ENABLE = yes # Audio control and System control | ||||
COMMAND_ENABLE = yes # Commands for debug and configuration | |||||
#NKRO_ENABLE = yes # USB Nkey Rollover | #NKRO_ENABLE = yes # USB Nkey Rollover | ||||
#include "matrix.h" | #include "matrix.h" | ||||
#if (MATRIX_COLS > 16) | |||||
# error "MATRIX_COLS must not exceed 16" | |||||
#endif | |||||
#if (MATRIX_ROWS > 255) | |||||
# error "MATRIX_ROWS must not exceed 255" | |||||
#endif | |||||
#ifndef DEBOUNCE | #ifndef DEBOUNCE | ||||
# define DEBOUNCE 5 | # define DEBOUNCE 5 | ||||
#endif | #endif | ||||
static uint8_t debouncing = DEBOUNCE; | static uint8_t debouncing = DEBOUNCE; | ||||
// matrix state buffer(1:on, 0:off) | |||||
static matrix_row_t *matrix; | |||||
static matrix_row_t *matrix_debouncing; | |||||
static matrix_row_t matrix0[MATRIX_ROWS]; | |||||
static matrix_row_t matrix1[MATRIX_ROWS]; | |||||
/* matrix state(1:on, 0:off) */ | |||||
static matrix_row_t matrix[MATRIX_ROWS]; | |||||
static matrix_row_t matrix_debouncing[MATRIX_ROWS]; | |||||
#ifdef MATRIX_HAS_GHOST | #ifdef MATRIX_HAS_GHOST | ||||
static bool matrix_has_ghost_in_row(uint8_t row); | static bool matrix_has_ghost_in_row(uint8_t row); | ||||
#endif | #endif | ||||
static matrix_row_t read_col(void); | |||||
static matrix_row_t read_cols(void); | |||||
static void unselect_rows(void); | static void unselect_rows(void); | ||||
static void select_row(uint8_t row); | static void select_row(uint8_t row); | ||||
// initialize matrix state: all keys off | // initialize matrix state: all keys off | ||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | ||||
matrix0[i] = 0; | |||||
matrix1[i] = 0; | |||||
matrix[i] = 0; | |||||
matrix_debouncing[i] = 0; | |||||
} | } | ||||
matrix = matrix0; | |||||
matrix_debouncing = matrix1; | |||||
} | } | ||||
uint8_t matrix_scan(void) | uint8_t matrix_scan(void) | ||||
{ | { | ||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | ||||
unselect_rows(); | |||||
select_row(i); | select_row(i); | ||||
_delay_us(30); // without this wait read unstable value. | _delay_us(30); // without this wait read unstable value. | ||||
if (matrix[i] != read_col()) { | |||||
matrix[i] = read_col(); | |||||
matrix_row_t cols = read_cols(); | |||||
if (matrix_debouncing[i] != cols) { | |||||
matrix_debouncing[i] = cols; | |||||
if (debouncing) { | if (debouncing) { | ||||
debug("bounce!: "); debug_hex(debouncing); print("\n"); | |||||
debug("bounce!: "); debug_hex(debouncing); debug("\n"); | |||||
} | } | ||||
debouncing = DEBOUNCE; | debouncing = DEBOUNCE; | ||||
} | } | ||||
unselect_rows(); | |||||
} | } | ||||
unselect_rows(); | |||||
if (debouncing) { | if (debouncing) { | ||||
if (--debouncing) { | if (--debouncing) { | ||||
_delay_ms(1); | _delay_ms(1); | ||||
} else { | } else { | ||||
matrix_row_t *tmp = matrix; | |||||
matrix = matrix_debouncing; | |||||
matrix_debouncing = tmp; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
matrix[i] = matrix_debouncing[i]; | |||||
} | |||||
} | } | ||||
} | } | ||||
inline | inline | ||||
bool matrix_is_on(uint8_t row, uint8_t col) | bool matrix_is_on(uint8_t row, uint8_t col) | ||||
{ | { | ||||
return (matrix[row] & (1<<col)); | |||||
return (matrix[row] & ((matrix_row_t)1<<col)); | |||||
} | } | ||||
inline | inline | ||||
print("\nr/c 01234567\n"); | print("\nr/c 01234567\n"); | ||||
for (uint8_t row = 0; row < matrix_rows(); row++) { | for (uint8_t row = 0; row < matrix_rows(); row++) { | ||||
phex(row); print(": "); | phex(row); print(": "); | ||||
#if (MATRIX_COLS <= 8) | |||||
pbin_reverse(matrix_get_row(row)); | pbin_reverse(matrix_get_row(row)); | ||||
#else | |||||
pbin_reverse16(matrix_get_row(row)); | |||||
#endif | |||||
#ifdef MATRIX_HAS_GHOST | #ifdef MATRIX_HAS_GHOST | ||||
if (matrix_has_ghost_in_row(row)) { | if (matrix_has_ghost_in_row(row)) { | ||||
print(" <ghost"); | print(" <ghost"); | ||||
} | } | ||||
} | } | ||||
uint8_t matrix_key_count(void) | |||||
{ | |||||
uint8_t count = 0; | |||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { | |||||
#if (MATRIX_COLS <= 8) | |||||
count += bitpop(matrix[i]); | |||||
#else | |||||
count += bitpop16(matrix[i]); | |||||
#endif | |||||
} | |||||
return count; | |||||
} | |||||
#ifdef MATRIX_HAS_GHOST | #ifdef MATRIX_HAS_GHOST | ||||
inline | inline | ||||
static bool matrix_has_ghost_in_row(uint8_t row) | static bool matrix_has_ghost_in_row(uint8_t row) | ||||
// ghost exists in case same state as other row | // ghost exists in case same state as other row | ||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) { | for (uint8_t i=0; i < MATRIX_ROWS; i++) { | ||||
if (i != row && (matrix[i] & matrix[row]) == matrix[row]) | |||||
if (i != row && (matrix[i] & matrix[row])) | |||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
#endif | #endif | ||||
inline | inline | ||||
static matrix_row_t read_col(void) | |||||
static matrix_row_t read_cols(void) | |||||
{ | { | ||||
return ~PINB; | return ~PINB; | ||||
} | } |