Made directories for keyboard and converter projects.

This commit is contained in:
tmk 2012-06-08 00:37:46 +09:00
parent 63d82fcaeb
commit afb0846208
99 changed files with 191 additions and 165 deletions

View file

@ -0,0 +1,54 @@
# Target file name (without extension).
TARGET = adb_usb
# Directory common source filess exist
TOP_DIR = ../..
# Directory keyboard dependent files exist
TARGET_DIR = .
# keyboard dependent files
SRC = main.c \
keymap.c \
matrix.c \
led.c \
adb.c
CONFIG_H = config.h
# MCU name, you MUST set this to match the board you are using
# type "make clean" after changing this, so all files will be rebuilt
#MCU = at90usb162 # Teensy 1.0
MCU = atmega32u4 # Teensy 2.0
#MCU = at90usb646 # Teensy++ 1.0
#MCU = at90usb1286 # Teensy++ 2.0
# Processor frequency.
# Normally the first thing your program should do is set the clock prescaler,
# so your program will run at the correct speed. You should also set this
# variable to same clock speed. The _delay_ms() macro uses this, and many
# examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 16000000
# Build Options
# comment out to disable the options.
#
#MOUSEKEY_ENABLE = yes # Mouse keys
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
EXTRAKEY_ENABLE = yes # Audio control and System control
#NKRO_ENABLE = yes # USB Nkey Rollover
#---------------- Programming Options --------------------------
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
include $(TOP_DIR)/protocol/pjrc.mk
include $(TOP_DIR)/protocol.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk

70
converter/adb_usb/README Normal file
View file

@ -0,0 +1,70 @@
ADB to USB keyboard converter
=============================
http://geekhack.org/showwiki.php?title=Island:14290
This firmware converts ADB keyboard protocol to USB.
Build
-----
0. Connect ADB keyboard to Teensy by 3 lines(Vcc, GND, Data).
You need a external pull-up resistor on DATA line in most case,
in particular when you want to use a long or coiled cable.
This converter uses AVR's internal pull-up, but it seems to be too weak.
The external pull-up resistor is strongly recommended.
PSW line is optional. See ADB.txt for details.
1. Define following macros for ADB connection in config.h:
ADB_PORT
ADB_PIN
ADB_DDR
ADB_DATA_BIT
ADB_PSW_BIT
2. make
3. program Teensy.
Keymap
------
You can change a keymap by editing code of keymap.c like following.
This is a keymap for AEK, however, also used for other keyboards.
How to define the keymap is probably obvious. You can find key
symbols in usb_keycodes.h.
If you want to define some keymaps than just one, see hhkb/keymap.c and
macway/keymap.c as examples. Keymap(layer) switching may needs a bit of
effort at this time.
/* Default Layer: plain keymap
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,---.
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|
* `---' `---------------' `---------------' `---------------' `-----------' `---'
* ,-----------------------------------------------------------. ,-----------. ,---------------.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *|
* |-----------------------------------------------------------| |-----------| |---------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -|
* |-----------------------------------------------------------| `-----------' |---------------|
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| +|
* |-----------------------------------------------------------| ,---. |---------------|
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| |
* |-----------------------------------------------------------| ,-----------. |-----------|Ent|
* |Ctrl |Gui |Alt | Space | | | | |Lef|Dow|Rig| | 0| .| |
* `-----------------------------------------------------------' `-----------' `---------------'
*/
KEYMAP(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR,
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,EQL, PSLS,PAST,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, PMNS,
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS,
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3,
LCTL,LGUI,LALT, SPC, LEFT,DOWN,RGHT, P0, PDOT,PENT
),
Notes
-----
Many ADB keyboards has no discrimination between right modifier and left one,
you will always see left control even if you press right control key.
Apple Extended Keyboard and Apple Extended Keyboard II are the examples.
Though ADB protocol itsef has the ability of distinction between right and left.
And most ADB keyboard has no NKRO functionality, though ADB protocol itsef has that.
EOF

View file

@ -0,0 +1,72 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIG_H
#define CONFIG_H
/* controller configuration */
#include "controller_teensy.h"
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x0ADB
#define DEVICE_VER 0x0101
#define MANUFACTURER t.m.k.
#define PRODUCT ADB keyboard converter
#define DESCRIPTION convert ADB keyboard to USB
/* matrix size */
#define MATRIX_ROWS 16 // keycode bit: 3-0
#define MATRIX_COLS 8 // keycode bit: 6-4
/* Locking Caps Lock support */
#define MATRIX_HAS_LOCKING_CAPS
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \
keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \
)
/* mouse keys */
#ifdef MOUSEKEY_ENABLE
# define MOUSEKEY_DELAY_TIME 192
#endif
/* PS/2 mouse */
#ifdef PS2_MOUSE_ENABLE
# define PS2_CLOCK_PORT PORTF
# define PS2_CLOCK_PIN PINF
# define PS2_CLOCK_DDR DDRF
# define PS2_CLOCK_BIT 0
# define PS2_DATA_PORT PORTF
# define PS2_DATA_PIN PINF
# define PS2_DATA_DDR DDRF
# define PS2_DATA_BIT 1
#endif
/* ADB port setting */
#define ADB_PORT PORTF
#define ADB_PIN PINF
#define ADB_DDR DDRF
#define ADB_DATA_BIT 0
//#define ADB_PSW_BIT 1 // optional
#endif

150
converter/adb_usb/keymap.c Normal file
View file

@ -0,0 +1,150 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Keymap for ADB keyboard
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "usb_keyboard.h"
#include "usb_keycodes.h"
#include "print.h"
#include "debug.h"
#include "util.h"
#include "keymap.h"
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
// Convert physical keyboard layout to matrix array.
// This is a macro to define keymap easily in keyboard layout form.
/* Apple Extended Keyboard */
#define KEYMAP( \
K35, K7A,K78,K63,K76, K60,K61,K62,K64, K65,K6D,K67,K6F, K69,K6B,K71, K7F, \
K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, K72,K73,K74, K47,K51,K4B,K43, \
K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E,K2A, K75,K77,K79, K59,K5B,K5C,K4E, \
K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27, K24, K56,K57,K58,K45, \
K38,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C, K7B, K3E, K53,K54,K55, \
K36,K3A,K37, K31, K3B,K3D,K3C, K52, K41,K4C \
) { \
{ KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \
{ KB_##K08, KB_##K09, KB_NO, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \
{ KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \
{ KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \
{ KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \
{ KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \
{ KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_NO, KB_##K35, KB_##K36, KB_##K37 }, \
{ KB_##K38, KB_##K39, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \
{ KB_NO, KB_##K41, KB_NO, KB_##K43, KB_NO, KB_##K45, KB_NO, KB_##K47 }, \
{ KB_NO, KB_NO, KB_NO, KB_##K4B, KB_##K4C, KB_NO, KB_##K4E, KB_NO }, \
{ KB_NO, KB_##K51, KB_##K52, KB_##K53, KB_##K54, KB_##K55, KB_##K56, KB_##K57 }, \
{ KB_##K58, KB_##K59, KB_NO, KB_##K5B, KB_##K5C, KB_NO, KB_NO, KB_NO }, \
{ KB_##K60, KB_##K61, KB_##K62, KB_##K63, KB_##K64, KB_##K65, KB_NO, KB_##K67 }, \
{ KB_NO, KB_##K69, KB_NO, KB_##K6B, KB_NO, KB_##K6D, KB_NO, KB_##K6F }, \
{ KB_NO, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \
{ KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_NO, KB_NO, KB_NO, KB_##K7F } \
}
/* plain keymap
{
{ KB_A, KB_S, KB_D, KB_F, KB_H, KB_G, KB_Z, KB_X }, // 00-07
{ KB_C, KB_V, KB_NO, KB_B, KB_Q, KB_W, KB_E, KB_R }, // 08-0F
{ KB_Y, KB_T, KB_1, KB_2, KB_3, KB_4, KB_6, KB_5 }, // 10-17
{ KB_EQL, KB_9, KB_7, KB_MINS,KB_8, KB_0, KB_RBRC,KB_O }, // 18-1F
{ KB_U, KB_LBRC,KB_I, KB_P, KB_ENT, KB_L, KB_J, KB_QUOT}, // 20-27
{ KB_K, KB_SCLN,KB_BSLS,KB_COMM,KB_SLSH,KB_N, KB_M, KB_DOT }, // 28-2F
{ KB_TAB, KB_SPC, KB_GRV, KB_BSPC,KB_NO, KB_ESC, KB_LCTL,KB_LGUI}, // 30-37
{ KB_LSFT,KB_CAPS,KB_LALT,KB_LEFT,KB_RGHT,KB_DOWN,KB_UP, KB_NO }, // 38-3F
{ KB_NO, KB_PDOT,KB_NO, KB_PAST,KB_NO, KB_PPLS,KB_NO, KB_NLCK}, // 40-47
{ KB_NO, KB_NO, KB_NO, KB_PSLS,KB_PENT,KB_NO, KB_PMNS,KB_NO }, // 48-4F
{ KB_NO, KB_PEQL,KB_P0, KB_P1, KB_P2, KB_P3, KB_P4, KB_P5 }, // 50-57
{ KB_P6, KB_P7, KB_NO, KB_P8, KB_P9, KB_NO, KB_NO, KB_NO }, // 58-5F
{ KB_F5, KB_F6, KB_F7, KB_F3, KB_F8, KB_F9, KB_NO, KB_F11 }, // 60-67
{ KB_NO, KB_PSCR,KB_NO, KB_SLCK,KB_NO, KB_F10, KB_NO, KB_F12 }, // 68-6F
{ KB_NO, KB_BRK, KB_INS, KB_HOME,KB_PGUP,KB_DEL, KB_F4, KB_END }, // 70-77
{ KB_F2, KB_PGDN,KB_F1, KB_RSFT,KB_NO, KB_NO, KB_NO, KB_PWR }, // 78-7F
},
*/
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
static const uint8_t PROGMEM fn_layer[] = {
0, // Fn0
0, // Fn1
0, // Fn2
0, // Fn3
0, // Fn4
0, // Fn5
0, // Fn6
0 // Fn7
};
// 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, // Fn0
KB_NO, // Fn1
KB_NO, // Fn2
KB_NO, // Fn3
KB_NO, // Fn4
KB_NO, // Fn5
KB_NO, // Fn6
KB_NO // Fn7
};
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Default Layer: plain keymap
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,---.
* |Esc| |F1 |F2 |F3 |F4 | |F5 |F6 |F7 |F8 | |F9 |F10|F11|F12| |PrS|ScL|Pau| |Pwr|
* `---' `---------------' `---------------' `---------------' `-----------' `---'
* ,-----------------------------------------------------------. ,-----------. ,---------------.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backspa| |Ins|Hom|PgU| |NmL| =| /| *|
* |-----------------------------------------------------------| |-----------| |---------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|End|PgD| | 7| 8| 9| -|
* |-----------------------------------------------------------| `-----------' |---------------|
* |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return | | 4| 5| 6| +|
* |-----------------------------------------------------------| ,---. |---------------|
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | |Up | | 1| 2| 3| |
* |-----------------------------------------------------------| ,-----------. |-----------|Ent|
* |Ctrl |Gui |Alt | Space | | | | |Lef|Dow|Rig| | 0| .| |
* `-----------------------------------------------------------' `-----------' `---------------'
*/
KEYMAP(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR,
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,EQL, PSLS,PAST,
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9, PMNS,
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS,
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3,
LCTL,LGUI,LALT, SPC, LEFT,DOWN,RGHT, P0, PDOT,PENT
),
};
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
{
return KEYCODE(layer, row, col);
}
uint8_t keymap_fn_layer(uint8_t fn_bits)
{
return pgm_read_byte(&fn_layer[biton(fn_bits)]);
}
uint8_t keymap_fn_keycode(uint8_t fn_bits)
{
return pgm_read_byte(&fn_keycode[(biton(fn_bits))]);
}

26
converter/adb_usb/led.c Normal file
View file

@ -0,0 +1,26 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdint.h"
#include "adb.h"
#include "led.h"
void led_set(uint8_t usb_led)
{
adb_host_kbd_led(~usb_led);
}

241
converter/adb_usb/matrix.c Normal file
View file

@ -0,0 +1,241 @@
/*
Copyright 2011 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* scan matrix
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "print.h"
#include "util.h"
#include "debug.h"
#include "host.h"
#include "led.h"
#include "adb.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
#define CAPS 0x39
#define CAPS_UP (CAPS | 0x80)
#define ROW(key) ((key)>>3&0x0F)
#define COL(key) ((key)&0x07)
static bool _matrix_is_modified = false;
// matrix state buffer(1:on, 0:off)
#if (MATRIX_COLS <= 8)
static uint8_t *matrix;
static uint8_t _matrix0[MATRIX_ROWS];
#else
static uint16_t *matrix;
static uint16_t _matrix0[MATRIX_ROWS];
#endif
#ifdef MATRIX_HAS_GHOST
static bool matrix_has_ghost_in_row(uint8_t row);
#endif
static void _register_key(uint8_t key);
inline
uint8_t matrix_rows(void)
{
return MATRIX_ROWS;
}
inline
uint8_t matrix_cols(void)
{
return MATRIX_COLS;
}
void matrix_init(void)
{
adb_host_init();
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
matrix = _matrix0;
print_enable = true;
debug_enable = true;
debug_matrix = true;
debug_keyboard = true;
debug_mouse = true;
print("debug enabled.\n");
return;
}
uint8_t matrix_scan(void)
{
uint16_t codes;
uint8_t key0, key1;
_matrix_is_modified = false;
codes = adb_host_kbd_recv();
key0 = codes>>8;
key1 = codes&0xFF;
#ifdef MATRIX_HAS_LOCKING_CAPS
// Send Caps key up event
if (matrix_is_on(ROW(CAPS), COL(CAPS))) {
_matrix_is_modified = true;
_register_key(CAPS_UP);
}
#endif
if (codes == 0) { // no keys
return 0;
} else if (key0 == 0xFF && key1 != 0xFF) { // error
return codes&0xFF;
} else {
#ifdef MATRIX_HAS_LOCKING_CAPS
if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) {
// Ignore LockingCaps key down event when CAPS LOCK is on
if (key0 == CAPS && (key1 == CAPS || key1 == 0xFF)) return 0;
if (key0 == CAPS) key0 = key1;
if (key1 == CAPS) key1 = 0xFF;
// Convert LockingCaps key up event into down event
if (key0 == CAPS_UP) key0 = CAPS;
if (key1 == CAPS_UP) key1 = CAPS;
} else {
// CAPS LOCK off:
// Ignore LockingCaps key up event when CAPS LOCK is off
if (key0 == CAPS_UP && (key1 == CAPS_UP || key1 == 0xFF)) return 0;
if (key0 == CAPS_UP) key0 = key1;
if (key1 == CAPS_UP) key1 = 0xFF;
}
#endif
_matrix_is_modified = true;
_register_key(key0);
if (key1 != 0xFF) // key1 is 0xFF when no second key.
_register_key(key1);
}
if (debug_enable) {
print("adb_host_kbd_recv: "); phex16(codes); print("\n");
}
return 1;
}
bool matrix_is_modified(void)
{
return _matrix_is_modified;
}
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(uint8_t row, uint8_t col)
{
return (matrix[row] & (1<<col));
}
inline
#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");
#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");
}
}
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
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
inline
static void _register_key(uint8_t key)
{
uint8_t col, row;
col = key&0x07;
row = (key>>3)&0x0F;
if (key&0x80) {
matrix[row] &= ~(1<<col);
} else {
matrix[row] |= (1<<col);
}
}