~ruther/qmk_firmware

fd49c69d1a173b9d273b2b53eb6a22eda920223a — tmk 14 years ago 590235d
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.
7 files changed, 212 insertions(+), 74 deletions(-)

M hhkb/config.h
M hhkb/keymap.c
M hhkb/matrix.c
M macway/config.h
M macway/keymap.c
M macway/matrix.c
M matrix_skel.h
M hhkb/config.h => hhkb/config.h +5 -3
@@ 1,18 1,20 @@
#ifndef CONFIG_H
#define CONFIG_H

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

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

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

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

/* USB NKey Rollover */
#ifdef USB_NKRO_ENABLE

M hhkb/keymap.c => hhkb/keymap.c +25 -12
@@ 12,6 12,8 @@
#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( \
    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, \


@@ 33,19 35,29 @@
#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[] = {
    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] = {


@@ 152,7 164,7 @@ uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t 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)]);
}


@@ 162,6 174,7 @@ uint8_t keymap_fn_keycode(uint8_t 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)
{
    return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));

M hhkb/matrix.c => hhkb/matrix.c +85 -21
@@ 9,6 9,33 @@
#include "util.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)
//
// HHKB has no ghost and no bounce.


@@ 28,26 55,19 @@
#define KEY_PREV_ON             (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
int matrix_rows(void)
uint8_t matrix_rows(void)
{
    return MATRIX_ROWS;
}

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

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


@@ 59,13 79,13 @@ void matrix_init(void)
    PORTE = 0x40;

    // 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_prev = _matrix1;
}

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



@@ 73,8 93,8 @@ int matrix_scan(void)
    matrix_prev = matrix;
    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);
            _delay_us(40);  // from logic analyzer chart
            if (matrix_prev[row] & (1<<col)) {


@@ 98,7 118,7 @@ int matrix_scan(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])
            return true;
    }


@@ 108,36 128,80 @@ bool matrix_is_modified(void)
inline
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;
}

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

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];
}

void matrix_print(void)
{
#if (MATRIX_COLS <= 8)
    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(": ");
#if (MATRIX_COLS <= 8)
        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");
    }
}

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]);
#else
        count += bitpop16(matrix[i]);
#endif
    }
    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

M macway/config.h => macway/config.h +5 -3
@@ 1,18 1,20 @@
#ifndef CONFIG_H
#define CONFIG_H

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

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

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

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

/* USB NKey Rollover */
#ifdef USB_NKRO_ENABLE

M macway/keymap.c => macway/keymap.c +25 -11
@@ 4,7 4,6 @@
#include <stdint.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "usb_keyboard.h"
#include "usb_keycodes.h"
#include "print.h"


@@ 13,6 12,8 @@
#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( \
    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, \


@@ 34,17 35,29 @@
#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[] = {
    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] = {


@@ 155,7 168,7 @@ uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t 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)]);
}


@@ 165,6 178,7 @@ uint8_t keymap_fn_keycode(uint8_t 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)
{
    //return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI));

M macway/matrix.c => macway/matrix.c +57 -18
@@ 10,31 10,47 @@
#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_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
static uint8_t read_col(void);
static void unselect_rows(void);
static void select_row(uint8_t row);


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

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

// this must be called once before matrix_scan.
void matrix_init(void)
{
    // initialize row and col


@@ 44,13 60,13 @@ void matrix_init(void)
    PORTB = 0xFF;

    // 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_prev = _matrix1;
}

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



@@ 58,7 74,7 @@ int matrix_scan(void)
    matrix_prev = matrix;
    matrix = tmp;

    for (int i = 0; i < MATRIX_ROWS; i++) {
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        unselect_rows();
        select_row(i);
        _delay_us(30);  // without this wait read unstable value.


@@ 70,30 86,37 @@ int matrix_scan(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])
            return true;
    }
    return false;
}

inline
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))
            return true;
    }
#endif
    return false;
}

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

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];
}


@@ 101,25 124,37 @@ uint16_t matrix_get_row(int row)
void matrix_print(void)
{
    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(": ");
#if (MATRIX_COLS <= 8)
        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");
    }
}

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]);
#else
        count += bitpop16(matrix[i]);
#endif
    }
    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


@@ 127,18 162,21 @@ static bool matrix_has_ghost_in_row(uint8_t row)
        return false;

    // 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])
            return true;
    }
    return false;
}
#endif

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

inline
static void unselect_rows(void)
{
    // Hi-Z(DDR:0, PORT:0) to unselect


@@ 150,6 188,7 @@ static void unselect_rows(void)
    PORTF &= ~0b11000000;
}

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

M matrix_skel.h => matrix_skel.h +10 -6
@@ 4,23 4,27 @@
#include <stdbool.h>

/* number of matrix rows */
int  matrix_rows(void);
uint8_t matrix_rows(void);
/* number of matrix columns */
int  matrix_cols(void);
uint8_t matrix_cols(void);
/* intialize matrix for scaning. should be called once. */
void matrix_init(void);
/* scan all key states on matrix */
int  matrix_scan(void);
uint8_t matrix_scan(void);
/* whether modified from previous scan. used after matrix_scan. */
bool matrix_is_modified(void);
/* whether ghosting occur on matrix. */
bool matrix_has_ghost(void);
/* 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 */
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 */
int matrix_key_count(void);
uint8_t matrix_key_count(void);
/* print matrix for debug */
void matrix_print(void);