Browse Source

added config option: MATRIX_HAS_GHOST and fixed some on matrix.c

ADD: Build option: MATRIX_HAS_GHOST to enable ghost blocking logic.
FIX: choose matrix buffer type(uint8_t/uint16_t) automatically
     depending on column size in matrix.c.
FIX: use uint8_t insted of int in matrix.c.
tags/v1.9
tmk 13 years ago
parent
commit
fd49c69d1a
7 changed files with 212 additions and 74 deletions
  1. 5
    3
      hhkb/config.h
  2. 25
    12
      hhkb/keymap.c
  3. 85
    21
      hhkb/matrix.c
  4. 5
    3
      macway/config.h
  5. 25
    11
      macway/keymap.c
  6. 57
    18
      macway/matrix.c
  7. 10
    6
      matrix_skel.h

+ 5
- 3
hhkb/config.h View File

#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H


/* controller configuration */
#include "controller_teensy.h"

#define VENDOR_ID 0xFEED #define VENDOR_ID 0xFEED
#define PRODUCT_ID 0xCAFE #define PRODUCT_ID 0xCAFE
#define MANUFACTURER t.m.k. #define MANUFACTURER t.m.k.
#define PRODUCT HHKB mod #define PRODUCT HHKB mod
#define DESCRIPTION t.m.k. keyboard firmware for HHKB mod #define DESCRIPTION t.m.k. keyboard firmware for HHKB mod


/* controller */
#include "controller_teensy.h"

/* matrix size */ /* matrix size */
#define MATRIX_ROWS 8 #define MATRIX_ROWS 8
#define MATRIX_COLS 8 #define MATRIX_COLS 8
/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST


/* USB NKey Rollover */ /* USB NKey Rollover */
#ifdef USB_NKRO_ENABLE #ifdef USB_NKRO_ENABLE

+ 25
- 12
hhkb/keymap.c View File

#include "keymap_skel.h" #include "keymap_skel.h"




// Convert physical keyboard layout to matrix array.
// This is a macro to define keymap easily in keyboard layout form.
#define KEYMAP( \ #define KEYMAP( \
R3C1, R3C0, R0C0, R1C0, R1C1, R2C0, R2C1, R4C0, R4C1, R6C0, R6C1, R7C0, R7C1, R5C0, R5C1, \ R3C1, R3C0, R0C0, R1C0, R1C1, R2C0, R2C1, R4C0, R4C1, R6C0, R6C1, R7C0, R7C1, R5C0, R5C1, \
R3C2, R0C1, R0C2, R1C3, R1C2, R2C3, R2C2, R4C2, R4C3, R6C2, R6C3, R7C3, R7C2, R5C2, \ R3C2, R0C1, R0C2, R1C3, R1C2, R2C3, R2C2, R4C2, R4C3, R6C2, R6C3, R7C3, R7C2, R5C2, \
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) #define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))




/* layer to change into while Fn key pressed */
static const int PROGMEM fn_layer[] = { 0, 1, 2, 3, 4, 0, 0, 1 };
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
static const uint8_t PROGMEM fn_layer[] = {
0, // FN_0
1, // FN_1
2, // FN_2
3, // FN_3
4, // FN_4
0, // FN_5
0, // FN_6
1 // FN_7
};


/* keycode to sent when Fn key released without using layer keys. */
// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer.
// See layer.c for details.
static const uint8_t PROGMEM fn_keycode[] = { static const uint8_t PROGMEM fn_keycode[] = {
KB_NO, // FN_0 [NOT USED]
KB_NO, // FN_1 layer 1
KB_SLSH, // FN_2 layer 2
KB_SCLN, // FN_3 layer 3
KB_SPC, // FN_4 layer 4
KB_NO, // FN_5 [NOT USED]
KB_NO, // FN_6 [NOT USED]
KB_NO // FN_7 layer 1
KB_NO, // FN_0
KB_NO, // FN_1
KB_SLSH, // FN_2
KB_SCLN, // FN_3
KB_SPC, // FN_4
KB_NO, // FN_5
KB_NO, // FN_6
KB_NO // FN_7
}; };


static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
return KEYCODE(layer, row, col); return KEYCODE(layer, row, col);
} }


int keymap_fn_layer(uint8_t fn_bits)
uint8_t keymap_fn_layer(uint8_t fn_bits)
{ {
return pgm_read_byte(&fn_layer[biton(fn_bits)]); return pgm_read_byte(&fn_layer[biton(fn_bits)]);
} }
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); return pgm_read_byte(&fn_keycode[(biton(fn_bits))]);
} }


// define a condition to enter special function mode
bool keymap_is_special_mode(uint8_t fn_bits) bool keymap_is_special_mode(uint8_t fn_bits)
{ {
return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI)); return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));

+ 85
- 21
hhkb/matrix.c View File

#include "util.h" #include "util.h"
#include "matrix_skel.h" #include "matrix_skel.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


// matrix state buffer(1:on, 0:off)
#if (MATRIX_COLS <= 8)
static uint8_t *matrix;
static uint8_t *matrix_prev;
static uint8_t _matrix0[MATRIX_ROWS];
static uint8_t _matrix1[MATRIX_ROWS];
#else
static uint16_t *matrix;
static uint16_t *matrix_prev;
static uint16_t _matrix0[MATRIX_ROWS];
static uint16_t _matrix1[MATRIX_ROWS];
#endif

#ifdef MATRIX_HAS_GHOST
static bool matrix_has_ghost_in_row(uint8_t row);
#endif


// matrix is active low. (key on: 0/key off: 1) // matrix is active low. (key on: 0/key off: 1)
// //
// HHKB has no ghost and no bounce. // HHKB has no ghost and no bounce.
#define KEY_PREV_ON (PORTE |= (1<<7)) #define KEY_PREV_ON (PORTE |= (1<<7))
#define KEY_PREV_OFF (PORTE &= ~(1<<7)) #define KEY_PREV_OFF (PORTE &= ~(1<<7))


// matrix state buffer
static uint8_t *matrix;
static uint8_t *matrix_prev;
static uint8_t _matrix0[MATRIX_ROWS];
static uint8_t _matrix1[MATRIX_ROWS];



inline inline
int matrix_rows(void)
uint8_t matrix_rows(void)
{ {
return MATRIX_ROWS; return MATRIX_ROWS;
} }


inline inline
int matrix_cols(void)
uint8_t matrix_cols(void)
{ {
return MATRIX_COLS; return MATRIX_COLS;
} }


// this must be called once before matrix_scan.
void matrix_init(void) void matrix_init(void)
{ {
// row & col output(PB0-6) // row & col output(PB0-6)
PORTE = 0x40; PORTE = 0x40;


// initialize matrix state: all keys off // initialize matrix state: all keys off
for (int i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
for (int i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
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 = _matrix0;
matrix_prev = _matrix1; matrix_prev = _matrix1;
} }


int matrix_scan(void)
uint8_t matrix_scan(void)
{ {
uint8_t *tmp; uint8_t *tmp;


matrix_prev = matrix; matrix_prev = matrix;
matrix = tmp; matrix = tmp;


for (int row = 0; row < MATRIX_ROWS; row++) {
for (int col = 0; col < MATRIX_COLS; col++) {
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
KEY_SELELCT(row, col); KEY_SELELCT(row, col);
_delay_us(40); // from logic analyzer chart _delay_us(40); // from logic analyzer chart
if (matrix_prev[row] & (1<<col)) { if (matrix_prev[row] & (1<<col)) {


bool matrix_is_modified(void) bool matrix_is_modified(void)
{ {
for (int i = 0; i < MATRIX_ROWS; i++) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
if (matrix[i] != matrix_prev[i]) if (matrix[i] != matrix_prev[i])
return true; return true;
} }
inline inline
bool matrix_has_ghost(void) bool matrix_has_ghost(void)
{ {
#ifdef MATRIX_HAS_GHOST
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
if (matrix_has_ghost_in_row(i))
return true;
}
#endif
return false; return false;
} }


inline inline
bool matrix_is_on(int row, int col)
bool matrix_is_on(uint8_t row, uint8_t col)
{ {
return (matrix[row] & (1<<col)); return (matrix[row] & (1<<col));
} }


inline inline
uint16_t matrix_get_row(int row)
#if (MATRIX_COLS <= 8)
uint8_t matrix_get_row(uint8_t row)
#else
uint16_t matrix_get_row(uint8_t row)
#endif
{ {
return matrix[row]; return matrix[row];
} }


void matrix_print(void) void matrix_print(void)
{ {
#if (MATRIX_COLS <= 8)
print("\nr/c 01234567\n"); print("\nr/c 01234567\n");
for (int row = 0; row < matrix_rows(); row++) {
#else
print("\nr/c 0123456789ABCDEF\n");
#endif
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
if (matrix_has_ghost_in_row(row)) {
print(" <ghost");
}
#endif
print("\n"); print("\n");
} }
} }


int matrix_key_count(void)
uint8_t matrix_key_count(void)
{ {
int count = 0;
for (int i = 0; i < MATRIX_ROWS; i++) {
uint8_t count = 0;
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
#if (MATRIX_COLS <= 8)
count += bitpop(matrix[i]); count += bitpop(matrix[i]);
#else
count += bitpop16(matrix[i]);
#endif
} }
return count; return count;
} }

#ifdef MATRIX_HAS_GHOST
inline
static bool matrix_has_ghost_in_row(uint8_t row)
{
// no ghost exists in case less than 2 keys on
if (((matrix[row] - 1) & matrix[row]) == 0)
return false;

// ghost exists in case same state as other row
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
if (i != row && (matrix[i] & matrix[row]) == matrix[row])
return true;
}
return false;
}
#endif

+ 5
- 3
macway/config.h View File

#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H


/* controller configuration */
#include "controller_teensy.h"

#define VENDOR_ID 0xFEED #define VENDOR_ID 0xFEED
#define PRODUCT_ID 0xBEE0 #define PRODUCT_ID 0xBEE0
#define MANUFACTURER t.m.k. #define MANUFACTURER t.m.k.
#define PRODUCT Macway mod #define PRODUCT Macway mod
#define DESCRIPTION t.m.k. keyboard firmware for Macway mod #define DESCRIPTION t.m.k. keyboard firmware for Macway mod


/* controller */
#include "controller_teensy.h"

/* matrix size */ /* matrix size */
#define MATRIX_ROWS 9 #define MATRIX_ROWS 9
#define MATRIX_COLS 8 #define MATRIX_COLS 8
/* define if matrix has ghost */
#define MATRIX_HAS_GHOST


/* USB NKey Rollover */ /* USB NKey Rollover */
#ifdef USB_NKRO_ENABLE #ifdef USB_NKRO_ENABLE

+ 25
- 11
macway/keymap.c View File

#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "usb_keyboard.h" #include "usb_keyboard.h"
#include "usb_keycodes.h" #include "usb_keycodes.h"
#include "print.h" #include "print.h"
#include "keymap_skel.h" #include "keymap_skel.h"




// Convert physical keyboard layout to matrix array.
// This is a macro to define keymap easily in keyboard layout form.
#define KEYMAP( \ #define KEYMAP( \
R1C1, R1C0, R2C0, R3C0, R4C0, R4C1, R5C1, R5C0, R6C0, R7C0, R8C0, R8C1, R6C1, R0C2, \ R1C1, R1C0, R2C0, R3C0, R4C0, R4C1, R5C1, R5C0, R6C0, R7C0, R8C0, R8C1, R6C1, R0C2, \
R1C2, R1C3, R2C3, R3C3, R4C3, R4C2, R5C2, R5C3, R6C3, R7C3, R8C3, R8C2, R6C2, \ R1C2, R1C3, R2C3, R3C3, R4C3, R4C2, R5C2, R5C3, R6C3, R7C3, R8C3, R8C2, R6C2, \
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) #define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))




static const uint8_t PROGMEM fn_layer[] = { 0, 1, 2, 3, 4, 0, 2, 3 };
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
static const uint8_t PROGMEM fn_layer[] = {
0, // FN_0
1, // FN_1
2, // FN_2
3, // FN_3
4, // FN_4
0, // FN_5
2, // FN_6
3 // FN_7
};


// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer.
// See layer.c for details.
static const uint8_t PROGMEM fn_keycode[] = { static const uint8_t PROGMEM fn_keycode[] = {
KB_NO, // FN_0 [NOT USED]
KB_NO, // FN_1 layer 1
KB_SLSH, // FN_2 layer 2
KB_SCLN, // FN_3 layer 3
KB_SPC, // FN_4 layer 4
KB_NO, // FN_5 [NOT USED]
KB_NO, // FN_6 layer 2
KB_NO // FN_7 layer 3
KB_NO, // FN_0
KB_NO, // FN_1
KB_SLSH, // FN_2
KB_SCLN, // FN_3
KB_SPC, // FN_4
KB_NO, // FN_5
KB_NO, // FN_6
KB_NO // FN_7
}; };


static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
return KEYCODE(layer, row, col); return KEYCODE(layer, row, col);
} }


int keymap_fn_layer(uint8_t fn_bits)
uint8_t keymap_fn_layer(uint8_t fn_bits)
{ {
return pgm_read_byte(&fn_layer[biton(fn_bits)]); return pgm_read_byte(&fn_layer[biton(fn_bits)]);
} }
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); return pgm_read_byte(&fn_keycode[(biton(fn_bits))]);
} }


// define a condition to enter special function mode
bool keymap_is_special_mode(uint8_t fn_bits) bool keymap_is_special_mode(uint8_t fn_bits)
{ {
//return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI)); //return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));

+ 57
- 18
macway/matrix.c View File

#include "matrix_skel.h" #include "matrix_skel.h"




// matrix state buffer (key on: 1/key off: 0)
#if (MATRIX_COLS > 16)
# error "MATRIX_COLS must not exceed 16"
#endif
#if (MATRIX_ROWS > 255)
# error "MATRIX_ROWS must not exceed 255"
#endif


// matrix state buffer(1:on, 0:off)
#if (MATRIX_COLS <= 8)
static uint8_t *matrix; static uint8_t *matrix;
static uint8_t *matrix_prev; static uint8_t *matrix_prev;
static uint8_t _matrix0[MATRIX_ROWS]; static uint8_t _matrix0[MATRIX_ROWS];
static uint8_t _matrix1[MATRIX_ROWS]; static uint8_t _matrix1[MATRIX_ROWS];

#else
static uint16_t *matrix;
static uint16_t *matrix_prev;
static uint16_t _matrix0[MATRIX_ROWS];
static uint16_t _matrix1[MATRIX_ROWS];
#endif

#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
static uint8_t read_col(void); static uint8_t read_col(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);




inline inline
int matrix_rows(void)
uint8_t matrix_rows(void)
{ {
return MATRIX_ROWS; return MATRIX_ROWS;
} }


inline inline
int matrix_cols(void)
uint8_t matrix_cols(void)
{ {
return MATRIX_COLS; return MATRIX_COLS;
} }


// this must be called once before matrix_scan.
void matrix_init(void) void matrix_init(void)
{ {
// initialize row and col // initialize row and col
PORTB = 0xFF; PORTB = 0xFF;


// initialize matrix state: all keys off // initialize matrix state: all keys off
for (int i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
for (int i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
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 = _matrix0;
matrix_prev = _matrix1; matrix_prev = _matrix1;
} }


int matrix_scan(void)
uint8_t matrix_scan(void)
{ {
uint8_t *tmp; uint8_t *tmp;


matrix_prev = matrix; matrix_prev = matrix;
matrix = tmp; matrix = tmp;


for (int i = 0; i < MATRIX_ROWS; i++) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
unselect_rows(); 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.


bool matrix_is_modified(void) bool matrix_is_modified(void)
{ {
for (int i = 0; i < MATRIX_ROWS; i++) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
if (matrix[i] != matrix_prev[i]) if (matrix[i] != matrix_prev[i])
return true; return true;
} }
return false; return false;
} }


inline
bool matrix_has_ghost(void) bool matrix_has_ghost(void)
{ {
for (int i = 0; i < MATRIX_ROWS; i++) {
#ifdef MATRIX_HAS_GHOST
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
if (matrix_has_ghost_in_row(i)) if (matrix_has_ghost_in_row(i))
return true; return true;
} }
#endif
return false; return false;
} }


inline inline
bool matrix_is_on(int row, int col)
bool matrix_is_on(uint8_t row, uint8_t col)
{ {
return (matrix[row] & (1<<col)); return (matrix[row] & (1<<col));
} }


inline inline
uint16_t matrix_get_row(int row)
#if (MATRIX_COLS <= 8)
uint8_t matrix_get_row(uint8_t row)
#else
uint16_t matrix_get_row(uint8_t row)
#endif
{ {
return matrix[row]; return matrix[row];
} }
void matrix_print(void) void matrix_print(void)
{ {
print("\nr/c 01234567\n"); print("\nr/c 01234567\n");
for (int 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
if (matrix_has_ghost_in_row(row)) { if (matrix_has_ghost_in_row(row)) {
print(" <ghost"); print(" <ghost");
} }
#endif
print("\n"); print("\n");
} }
} }


int matrix_key_count(void)
uint8_t matrix_key_count(void)
{ {
int count = 0;
for (int i = 0; i < MATRIX_ROWS; i++) {
uint8_t count = 0;
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
#if (MATRIX_COLS <= 8)
count += bitpop(matrix[i]); count += bitpop(matrix[i]);
#else
count += bitpop16(matrix[i]);
#endif
} }
return count; return count;
} }


#ifdef MATRIX_HAS_GHOST
inline
static bool matrix_has_ghost_in_row(uint8_t row) static bool matrix_has_ghost_in_row(uint8_t row)
{ {
// no ghost exists in case less than 2 keys on // no ghost exists in case less than 2 keys on
return false; return false;


// ghost exists in case same state as other row // ghost exists in case same state as other row
for (int 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]) == matrix[row])
return true; return true;
} }
return false; return false;
} }
#endif


inline
static uint8_t read_col(void) static uint8_t read_col(void)
{ {
return PINB; return PINB;
} }


inline
static void unselect_rows(void) static void unselect_rows(void)
{ {
// Hi-Z(DDR:0, PORT:0) to unselect // Hi-Z(DDR:0, PORT:0) to unselect
PORTF &= ~0b11000000; PORTF &= ~0b11000000;
} }


inline
static void select_row(uint8_t row) static void select_row(uint8_t row)
{ {
// Output low(DDR:1, PORT:0) to select // Output low(DDR:1, PORT:0) to select

+ 10
- 6
matrix_skel.h View File

#include <stdbool.h> #include <stdbool.h>


/* number of matrix rows */ /* number of matrix rows */
int matrix_rows(void);
uint8_t matrix_rows(void);
/* number of matrix columns */ /* number of matrix columns */
int matrix_cols(void);
uint8_t matrix_cols(void);
/* intialize matrix for scaning. should be called once. */ /* intialize matrix for scaning. should be called once. */
void matrix_init(void); void matrix_init(void);
/* scan all key states on matrix */ /* scan all key states on matrix */
int matrix_scan(void);
uint8_t matrix_scan(void);
/* whether modified from previous scan. used after matrix_scan. */ /* whether modified from previous scan. used after matrix_scan. */
bool matrix_is_modified(void); bool matrix_is_modified(void);
/* whether ghosting occur on matrix. */ /* whether ghosting occur on matrix. */
bool matrix_has_ghost(void); bool matrix_has_ghost(void);
/* whether a swtich is on */ /* whether a swtich is on */
bool matrix_is_on(int row, int col);
bool matrix_is_on(uint8_t row, uint8_t col);
/* matrix state on row */ /* matrix state on row */
uint16_t matrix_get_row(int row);
#if (MATRIX_COLS <= 8)
uint8_t matrix_get_row(uint8_t row);
#else
uint16_t matrix_get_row(uint8_t row);
#endif
/* count keys pressed */ /* count keys pressed */
int matrix_key_count(void);
uint8_t matrix_key_count(void);
/* print matrix for debug */ /* print matrix for debug */
void matrix_print(void); void matrix_print(void);



Loading…
Cancel
Save