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.
This commit is contained in:
parent
590235d4bc
commit
fd49c69d1a
7 changed files with 211 additions and 73 deletions
|
@ -1,18 +1,20 @@
|
||||||
#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
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#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, \
|
||||||
|
@ -33,19 +35,29 @@
|
||||||
#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 */
|
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
|
||||||
static const int PROGMEM fn_layer[] = { 0, 1, 2, 3, 4, 0, 0, 1 };
|
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_0
|
||||||
KB_NO, // FN_1 layer 1
|
KB_NO, // FN_1
|
||||||
KB_SLSH, // FN_2 layer 2
|
KB_SLSH, // FN_2
|
||||||
KB_SCLN, // FN_3 layer 3
|
KB_SCLN, // FN_3
|
||||||
KB_SPC, // FN_4 layer 4
|
KB_SPC, // FN_4
|
||||||
KB_NO, // FN_5 [NOT USED]
|
KB_NO, // FN_5
|
||||||
KB_NO, // FN_6 [NOT USED]
|
KB_NO, // FN_6
|
||||||
KB_NO // FN_7 layer 1
|
KB_NO // FN_7
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
@ -152,7 +164,7 @@ uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
|
||||||
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)]);
|
||||||
}
|
}
|
||||||
|
@ -162,6 +174,7 @@ uint8_t keymap_fn_keycode(uint8_t 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));
|
||||||
|
|
106
hhkb/matrix.c
106
hhkb/matrix.c
|
@ -9,6 +9,33 @@
|
||||||
#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.
|
||||||
|
@ -28,26 +55,19 @@
|
||||||
#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)
|
||||||
|
@ -59,13 +79,13 @@ void matrix_init(void)
|
||||||
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 (uint8_t 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++) _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;
|
||||||
|
|
||||||
|
@ -73,8 +93,8 @@ int matrix_scan(void)
|
||||||
matrix_prev = matrix;
|
matrix_prev = matrix;
|
||||||
matrix = tmp;
|
matrix = tmp;
|
||||||
|
|
||||||
for (int row = 0; row < MATRIX_ROWS; row++) {
|
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
||||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
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)) {
|
||||||
|
@ -98,7 +118,7 @@ int matrix_scan(void)
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -108,36 +128,80 @@ bool matrix_is_modified(void)
|
||||||
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;
|
uint8_t count = 0;
|
||||||
for (int i = 0; i < MATRIX_ROWS; i++) {
|
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
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
#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
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#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"
|
||||||
|
@ -13,6 +12,8 @@
|
||||||
#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, \
|
||||||
|
@ -34,17 +35,29 @@
|
||||||
#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_0
|
||||||
KB_NO, // FN_1 layer 1
|
KB_NO, // FN_1
|
||||||
KB_SLSH, // FN_2 layer 2
|
KB_SLSH, // FN_2
|
||||||
KB_SCLN, // FN_3 layer 3
|
KB_SCLN, // FN_3
|
||||||
KB_SPC, // FN_4 layer 4
|
KB_SPC, // FN_4
|
||||||
KB_NO, // FN_5 [NOT USED]
|
KB_NO, // FN_5
|
||||||
KB_NO, // FN_6 layer 2
|
KB_NO, // FN_6
|
||||||
KB_NO // FN_7 layer 3
|
KB_NO // FN_7
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
@ -155,7 +168,7 @@ uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
|
||||||
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)]);
|
||||||
}
|
}
|
||||||
|
@ -165,6 +178,7 @@ uint8_t keymap_fn_keycode(uint8_t 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));
|
||||||
|
|
|
@ -10,31 +10,47 @@
|
||||||
#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
|
||||||
|
@ -44,13 +60,13 @@ void matrix_init(void)
|
||||||
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 (uint8_t 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++) _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;
|
||||||
|
|
||||||
|
@ -58,7 +74,7 @@ int matrix_scan(void)
|
||||||
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.
|
||||||
|
@ -70,30 +86,37 @@ int matrix_scan(void)
|
||||||
|
|
||||||
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];
|
||||||
}
|
}
|
||||||
|
@ -101,25 +124,37 @@ uint16_t matrix_get_row(int 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;
|
uint8_t count = 0;
|
||||||
for (int i = 0; i < MATRIX_ROWS; i++) {
|
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
|
||||||
|
@ -127,18 +162,21 @@ static bool matrix_has_ghost_in_row(uint8_t row)
|
||||||
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
|
||||||
|
@ -150,6 +188,7 @@ static void unselect_rows(void)
|
||||||
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
|
||||||
|
|
|
@ -4,23 +4,27 @@
|
||||||
#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…
Reference in a new issue