1
0
Fork 0

Add HHKB JP support

- scan matrix about twice faster
This commit is contained in:
tmk 2014-07-09 15:31:52 +09:00
parent 34373185b7
commit 6013483050
7 changed files with 375 additions and 164 deletions

View file

@ -53,12 +53,6 @@ SRC += keymap_common.c \
matrix.c \ matrix.c \
led.c led.c
ifdef KEYMAP
SRC := keymap_$(KEYMAP).c $(SRC)
else
SRC := keymap_hhkb.c $(SRC)
endif
CONFIG_H = config.h CONFIG_H = config.h
@ -123,7 +117,27 @@ 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 COMMAND_ENABLE = yes # Commands for debug and configuration
NKRO_ENABLE = yes # USB Nkey Rollover NKRO_ENABLE = yes # USB Nkey Rollover
KEYMAP_SECTION_ENABLE = yes # fixed address keymap for keymap editor #KEYMAP_SECTION_ENABLE = yes # fixed address keymap for keymap editor
#HHKB_JP = yes # HHKB JP support
ifdef HHKB_JP
OPT_DEFS += -DHHKB_JP
endif
#
# Keymap file
#
ifdef KEYMAP
SRC := keymap_$(KEYMAP).c $(SRC)
else
ifdef HHKB_JP
SRC := keymap_jp.c $(SRC)
else
SRC := keymap_hhkb.c $(SRC)
endif
endif
# Search Path # Search Path

View file

@ -28,7 +28,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* matrix size */ /* matrix size */
#ifdef HHKB_JP
# define MATRIX_ROWS 16
#else
# define MATRIX_ROWS 8 # define MATRIX_ROWS 8
#endif
#define MATRIX_COLS 8 #define MATRIX_COLS 8

View file

@ -12,11 +12,11 @@ Controller PCB
Keyswitch PCB Keyswitch PCB
------------- -------------
HC4051 Analog Multiplexer: select a row line. HC4051 Analog Multiplexer: select a row line.
http://www.alldatasheet.com/datasheet-pdf/pdf/203989/KODENSHI/KK74HC4051A.html http://www.ti.com/lit/ds/schs122j/schs122j.pdf
LS145 BCD Decoder: select a column line. LS145 BCD Decoder: select a column line.
http://www.alldatasheet.com/datasheet-pdf/pdf/27373/TI/SN74LS145D.html http://www.ti.com/lit/ds/symlink/sn74ls145.pdf
BU9831 Non-volatile electronic potentiometer: for calibration? BU9831 Non-volatile electronic potentiometer: for calibration?
http://www.alldatasheet.com/datasheet-pdf/pdf/36387/ROHM/BU9831.html https://www.spezial.com/doc/rohm-a/bu9831.pdf
TP1683/4 Capacitive Sensing controller: no datasheet available. TP1683/4 Capacitive Sensing controller: no datasheet available.
(HHKB_keyswitch.jpg) (HHKB_keyswitch.jpg)
@ -28,37 +28,41 @@ Keyswitch PCB
Connector Cable Connector Cable
--------------- ---------------
Two PCBs are connected by 15 lines(13 in case of Pro2). Two PCBs are connected by 15 lines(13 in case of Pro2).
Vcc and GND use 3(2) lines each, other 9 lines are for keyboard signaling. Vcc and GND use 3(2) lines each, other lines are for keyboard signaling.
Keyswitch connector HHKB connector lines:
pro pro2 Description Teensy++ pins JP Pro2 Pro Function Description Teensy++ pins
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
1 Vcc(5V) Not exist on Pro2 5V 1 Vcc(5V) 5V
2 1 Vcc(5V) 5V 1 1 2 Vcc(5V) 5V
3 2 Vcc(5V) 5V 2 2 3 Vcc(5V) 5V
4 3 TP1684 KEY: Low(0) when key pressed PE6 input(with pullup) 3 3 4 TP1684 KEY: Low(0) when key pressed PE6 input(with pullup)
5 4 TP1684 KEY_PREV: make threshold PE7 output 4 4 5 TP1684 KEY_PREV: make threshold PE7 output
6 5 HC4051 A(bit0)\ PB0 output 5 5 6 HC4051 A(bit0)\ PB0 output
7 6 HC4051 B(bit1) > select row(0 to 7) PB1 output 6 6 7 HC4051 B(bit1) > select row 0-7 PB1 output
8 7 HC4051 C(bit2)/ PB2 output 7 7 8 HC4051 C(bit2)/ PB2 output
9 8 LS145 A(bit0)\ PB3 output 8 8 9 LS145 A(bit0)\ PB3 output
10 9 LS145 B(bit1) > select column(0 to 7) PB4 output 9 9 10 LS145 B(bit1) > select column 0-7 PB4 output
11 10 LS145 C(bit2)/ PB5 output 10 10 11 LS145 C(bit2)/ PB5 output
12 11 LS145 D(enable) Low(0) enables selected column PB6 output 11 11 12 LS145 D(enable) Low(0) enables selected column PB6 output
13 12 GND GND 12 12 13 GND GND
14 13 GND GND 13 13 14 GND GND
15 GND Not exist on Pro2 GND 15 GND
14 HC4051(Z2) ~Enable of Z2 row0-7
15 HC4051(Z3) ~Enable of Z3 row8-15
NOTE: guessing pin5(KEY_PREV) may work for hysteresis of capacitive sensing. NOTE: guessing pin5(KEY_PREV) may work for hysteresis of capacitive sensing.
NOTE: 1KOhm didn't work as pullup resistor on KEY. AVR internal pullup or 10KOhm resistor was OK. NOTE: 1KOhm didn't work as pullup resistor on KEY. AVR internal pullup or 10KOhm resistor was OK.
NOTE: JP has two HC4051(Z2,Z3) and line 5, 6 and 7 are connected to both of them.
(HHKB_connector.jpg) (HHKB_connector.jpg)
Keyswitch matrix Keyswitch matrix
---------------- ----------------
60 keyswitches in 8*8 matrix. It is ghost-free and bounce-free. HHKB switch matrix is ghost-free and bounce-free.
Pro/Pro2(8x8):
COL 0 1 2 3 4 5 6 7 COL 0 1 2 3 4 5 6 7
ROW --------------------------------------------------------------- ROW ---------------------------------------------------------------
0| 2 q w s a z x c 0| 2 q w s a z x c
@ -71,8 +75,30 @@ Keyswitch matrix
7| - + ] [ ' / . _NONE_ 7| - + ] [ ' / . _NONE_
JP(16x8):
COL 0 1 2 3 4 5 6 7
ROW ---------------------------------------------------------------
0| ESC TAB LFn LShift LCtrl
1| 4 E MuHKN C D
2| 3 W LAlt X S
3| 1 HHK
4|
5| 5 R V F
6| 2 Q LGui Z A
7| 6 T Space B G
8| 9 I Kana , K
9| 8 U Henkan M J
A| 7 Y N H
B| 0 O RAlt . L
C| BS Right RShift Enter
D| \ [ Down Up ]
E| - P RFn / ;
F| ~ @ Left Ro :
Matrix diagram: Matrix diagram:
Pro/Pro2:
+-------------------------+-+-+-+-+-+-+-+ Vcc +-------------------------+-+-+-+-+-+-+-+ Vcc
|bias control? - - - - - - - - --- |bias control? - - - - - - - - ---
| 3.9K*8 R R R R R R R R | | 3.9K*8 R R R R R R R R |
@ -89,13 +115,49 @@ Matrix diagram:
KEY PREV | A B C +-----------------+ KEY PREV | A B C +-----------------+
| | +-^----+ | | | | LS145 | | | +-^----+ | | | | LS145 |
Vcc | | |BU9831| | | | +-^--^--^--^------+ Vcc | | |BU9831| | | | +-^--^--^--^------+
--- | | +------+ | | | A B C D +------+ --- | | +------+ | | | A B C D +-------+
| | | | | | | | | | | | | | | | | | | | | | | |
1-3 4 5 6 7 8 9 10 11 12 13-15 | 1-3 4 5 6 7 8 9 10 11 12 13-15 Pro |
1-2 3 4 5 6 7 8 9 10 11 12-13 Pro2|
+--------------------------------------------------+ |
| connector | ---
+--------------------------------------------------+ GND
JP:
+-----------------------------+-+-+-+-+ Vcc
|bias control? - - - - - ---
| 3.9K*5 R R R R R |
+--------^+ +--------+ - - - - - |
| | | HC4051 <0-----------|-|-|-|-|----|R|-+
| |capa. | Z2 <1-----------|-|-|-|-|----|R|-+
| TP1684 |sense | <2-----------|-|-|-|-|----|R|-+
| <---+--| <3-----------|-|-|-|-|----|R|-+
| | | | <4-----------|-|-|-|-|----|R|-+
| | ~En| <5-----------|-|-|-|-|----|R|-+
| | +----> <6-----------|-|-|-|-|----|R|-+
| | | | | A B C <7-----------|-|-|-|-|----|R|-+
+---V---^-+ | | +-^-^-^--+ | | | | | |
KEY PREV | | | | | | | | | | |
| | | | +--------+ | | | | | |
| | | | | HC4051 <8-----------|-|-|-|-|----|R|-+
| | | | | Z3 <9-----------|-|-|-|-|----|R|-+
| | | +--| <A-----------|-|-|-|-|----|R|-+
| | | | <B-----------|-|-|-|-|----|R|-+
| | | | <C-----------|-|-|-|-|----|R|-+
| | | ~En| <D-----------|-|-|-|-|----|R|-+
| | | +-> <E-----------|-|-|-|-|----|R|-+
| | | | | A B C <F-----------|-|-|-|-|----|R|-+
| | | | +-^-^-^--+ 0 1 2 3 4 5 6 7 33K*8
| | | | | | | +-----------------+
| | | | | | | | LS145 |
Vcc | | | | | | | +-^--^--^--^------+
--- | | | | | | | A B C D +-------+
| | | | | | | | | | | | | |
1-2 3 4 14 15 5 6 7 8 9 10 11 12-13 |
+--------------------------------------------------+ | +--------------------------------------------------+ |
| connector | --- | connector | ---
+--------------------------------------------------+ GND +--------------------------------------------------+ GND
to controller
Signals charts Signals charts
@ -114,6 +176,33 @@ Signals charts
(HHKB_chart2.jpg) (HHKB_chart2.jpg)
5us after setting colA-C
colA _~~~~~~~~~~~~~~~~~~
prev _~~~~_____ 20us if previous key state is low
colD ~~~__~~~~~ 10us column enabled
key ~~~____~~~ 22us hold state of the key
prev ____~~~~__________ 20us(JP)/17us(Pro2)
key ~~~~~~_____~~~~~~~ 22us
colD ~~~~~~__~~~~~~~~~~ 10us(LS175)
colC ____~~~~____~~~~ 550/410us(JP)
colB __~~__~~__~~__~~ 200/210us(JP)
colA _~_~_~_~_~_~_~_~ 100/110us(JP) 200/210us(Pro2)
0123456701234567 selected column
rowC ____~~~~____~~~~ 3.8/3.8ms(JP) S2 of HC4051
rowB __~~__~~__~~__~~ 1.9/1.9ms(JP) S1 of HC4051
rowA _~_~_~_~_~_~_~_~ 1.0/1.0ms(JP) S0 of HC4051
0123456701234567 selected row(Pro/Pro2)
0123456789ABCDEF selected row(JP)
rowEn0 ________~~~~~~~~ 7.7/7.7ms ~Enable of Z2 HC4051(JP only)
rowEn1 ~~~~~~~~________ 7.7/7.7ms ~Enable of Z3 HC4051(JP only)
NOTE: JP scans twice fast as Pro2 does. So Pro2 scan 8x8 matrix in 15.4ms while JP can 16x8 in that time.
Matrix scan pseudo code Matrix scan pseudo code
----------------------- -----------------------

148
keyboard/hhkb/hhkb_avr.h Normal file
View file

@ -0,0 +1,148 @@
#ifndef HHKB_AVR_H
#define HHKB_AVR_H
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// Timer resolution check
#if (1000000/TIMER_RAW_FREQ > 20)
# error "Timer resolution(>20us) is not enough for HHKB matrix scan tweak on V-USB."
#endif
/*
* HHKB Matrix I/O
*
* row: HC4051[A,B,C] selects scan row0-7
* row-ext: [En0,En1] row extention for JP
* col: LS145[A,B,C,D] selects scan col0-7 and enable(D)
* key: on: 0/off: 1
* prev: hysteresis control: assert(1) when previous key state is on
*/
#if defined(__AVR_ATmega32U4__)
/*
* For TMK HHKB alt controller(ATMega32U4)
*
* row: PB0-2
* col: PB3-5,6
* key: PD7(pull-uped)
* prev: PB7
* power: PD4(L:off/H:on)
* row-ext: PC6,7 for HHKB JP(active low)
*/
static inline void KEY_ENABLE(void) { (PORTB &= ~(1<<6)); }
static inline void KEY_UNABLE(void) { (PORTB |= (1<<6)); }
static inline bool KEY_STATE(void) { return (PIND & (1<<7)); }
static inline void KEY_PREV_ON(void) { (PORTB |= (1<<7)); }
static inline void KEY_PREV_OFF(void) { (PORTB &= ~(1<<7)); }
static inline void KEY_POWER_ON(void) {}
static inline void KEY_POWER_OFF(void) {}
static inline void KEY_INIT(void)
{
DDRB = 0xFF;
PORTB = 0x00;
DDRD &= ~0x80;
PORTD |= 0x80;
/* keyswitch board power on */
DDRD |= (1<<4);
PORTD |= (1<<4);
#ifdef HHKB_JP
/* row extention for HHKB JP */
DDRC |= (1<<6|1<<7);
PORTC |= (1<<6|1<<7);
#endif
KEY_UNABLE();
KEY_PREV_OFF();
}
static inline void KEY_SELECT(uint8_t ROW, uint8_t COL)
{
PORTB = (PORTB & 0xC0) | (((COL) & 0x07)<<3) | ((ROW) & 0x07);
#ifdef HHKB_JP
if ((ROW) & 0x08) PORTC = (PORTC & ~(1<<6|1<<7)) | (1<<6);
else PORTC = (PORTC & ~(1<<6|1<<7)) | (1<<7);
#endif
}
#elif defined(__AVR_AT90USB1286__)
/*
* For Teensy++(AT90USB1286)
*
* row: PB0-2
* col: PB3-5,6
* key: PE6(pull-uped)
* prev: PE7
*
* TODO: convert into 'staitc inline' function
*/
#define KEY_INIT() do { \
DDRB |= 0x7F; \
DDRE |= (1<<7); \
DDRE &= ~(1<<6); \
PORTE |= (1<<6); \
} while (0)
#define KEY_SELECT(ROW, COL) (PORTB = (PORTB & 0xC0) | \
(((COL) & 0x07)<<3) | \
((ROW) & 0x07))
#define KEY_ENABLE() (PORTB &= ~(1<<6))
#define KEY_UNABLE() (PORTB |= (1<<6))
#define KEY_STATE() (PINE & (1<<6))
#define KEY_PREV_ON() (PORTE |= (1<<7))
#define KEY_PREV_OFF() (PORTE &= ~(1<<7))
#define KEY_POWER_ON()
#define KEY_POWER_OFF()
#else
# error "define code for matrix scan"
#endif
#if 0
// For ATMega328P with V-USB
//
// #elif defined(__AVR_ATmega328P__)
// Ports for V-USB
// key: PB0(pull-uped)
// prev: PB1
// row: PB2-4
// col: PC0-2,3
// power: PB5(Low:on/Hi-z:off)
#define KEY_INIT() do { \
DDRB |= 0x3E; \
DDRB &= ~(1<<0); \
PORTB |= 1<<0; \
DDRC |= 0x0F; \
KEY_UNABLE(); \
KEY_PREV_OFF(); \
} while (0)
#define KEY_SELECT(ROW, COL) do { \
PORTB = (PORTB & 0xE3) | ((ROW) & 0x07)<<2; \
PORTC = (PORTC & 0xF8) | ((COL) & 0x07); \
} while (0)
#define KEY_ENABLE() (PORTC &= ~(1<<3))
#define KEY_UNABLE() (PORTC |= (1<<3))
#define KEY_STATE() (PINB & (1<<0))
#define KEY_PREV_ON() (PORTB |= (1<<1))
#define KEY_PREV_OFF() (PORTB &= ~(1<<1))
// Power supply switching
#define KEY_POWER_ON() do { \
KEY_INIT(); \
PORTB &= ~(1<<5); \
_delay_ms(1); \
} while (0)
#define KEY_POWER_OFF() do { \
DDRB &= ~0x3F; \
PORTB &= ~0x3F; \
DDRC &= ~0x0F; \
PORTC &= ~0x0F; \
} while (0)
#endif
#endif

View file

@ -54,4 +54,31 @@ extern const uint16_t fn_actions[];
{ KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO } \ { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO } \
} }
#define KEYMAP_JP( \
K02, K32, K62, K22, K12, K52, K72, KA2, K92, K82, KB2, KE2, KF2, KD2, KC2, \
K03, K63, K23, K13, K53, K73, KA3, K93, K83, KB3, KE3, KF3, KD3, \
K06, K66, K26, K16, K56, K76, KA6, K96, K86, KB6, KE6, KF6, KD6, KC6, \
K05, K65, K25, K15, K55, K75, KA5, K95, K85, KB5, KE5, KF5, KD5, KC5, \
K04, K34, K64, K24, K14, K74, K94, K84, KB4, KE4, KF4, KD4, KC4 \
) \
{ \
{ KC_NO, KC_NO, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_NO }, \
{ KC_NO, KC_NO, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_NO }, \
{ KC_NO, KC_NO, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_NO }, \
{ KC_NO, KC_NO, KC_##K32, KC_NO, KC_##K34, KC_NO, KC_NO, KC_NO }, \
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_NO, KC_NO, KC_##K52, KC_##K53, KC_NO, KC_##K55, KC_##K56, KC_NO }, \
{ KC_NO, KC_NO, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_NO }, \
{ KC_NO, KC_NO, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO }, \
{ KC_NO, KC_NO, KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86, KC_NO }, \
{ KC_NO, KC_NO, KC_##K92, KC_##K93, KC_##K94, KC_##K95, KC_##K96, KC_NO }, \
{ KC_NO, KC_NO, KC_##KA2, KC_##KA3, KC_NO, KC_##KA5, KC_##KA6, KC_NO }, \
{ KC_NO, KC_NO, KC_##KB2, KC_##KB3, KC_##KB4, KC_##KB5, KC_##KB6, KC_NO }, \
{ KC_NO, KC_NO, KC_##KC2, KC_NO, KC_##KC4, KC_##KC5, KC_##KC6, KC_NO }, \
{ KC_NO, KC_NO, KC_##KD2, KC_##KD3, KC_##KD4, KC_##KD5, KC_##KD6, KC_NO }, \
{ KC_NO, KC_NO, KC_##KE2, KC_##KE3, KC_##KE4, KC_##KE5, KC_##KE6, KC_NO }, \
{ KC_NO, KC_NO, KC_##KF2, KC_##KF3, KC_##KF4, KC_##KF5, KC_##KF6, KC_NO } \
}
#endif #endif

50
keyboard/hhkb/keymap_jp.c Normal file
View file

@ -0,0 +1,50 @@
/*
* HHKB JP Layout
*/
#include "keymap_common.h"
#ifdef KEYMAP_SECTION_ENABLE
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] __attribute__ ((section (".keymap.keymaps"))) = {
#else
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
#endif
/* Layer 0: Default Layer */
KEYMAP_JP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, JYEN,BSPC, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, \
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,BSLS,ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RO, UP, RSFT, \
FN0, ZKHK,LGUI,LALT,MHEN, SPC, HENK,KANA,RALT,FN0, LEFT,DOWN,RGHT),
/* Layer 1: HHKB mode (HHKB Fn)
* ,-----------------------------------------------------------.
* |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Caps | | | | | | | |Psc|Slk|Pus|Up | | |
* |------------------------------------------------------` |
* | |VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig| | |
* |-----------------------------------------------------------|
* | | | | | | | +| -|End|PgD|Dow| | | |
* |-----------------------------------------------------------|
* | || | | | | | | | | || | | |
* `-----------------------------------------------------------'
*/
KEYMAP_JP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS, \
TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,TRNS,PENT, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS),
};
/*
* Fn action definition
*/
#ifdef KEYMAP_SECTION_ENABLE
const uint16_t fn_actions[] __attribute__ ((section (".keymap.fn_actions"))) = {
#else
const uint16_t fn_actions[] PROGMEM = {
#endif
[0] = ACTION_LAYER_MOMENTARY(1),
};

View file

@ -20,20 +20,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h> #include <util/delay.h>
#include "print.h" #include "print.h"
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
#include "timer.h" #include "timer.h"
#include "matrix.h" #include "matrix.h"
#include "hhkb_avr.h"
// Timer resolution check
#if (1000000/TIMER_RAW_FREQ > 20)
# error "Timer resolution(>20us) is not enough for HHKB matrix scan tweak on V-USB."
#endif
// matrix state buffer(1:on, 0:off) // matrix state buffer(1:on, 0:off)
@ -43,122 +36,6 @@ static matrix_row_t _matrix0[MATRIX_ROWS];
static matrix_row_t _matrix1[MATRIX_ROWS]; static matrix_row_t _matrix1[MATRIX_ROWS];
// Matrix I/O ports
//
// row: HC4051[A,B,C] selects scan row0-7
// col: LS145[A,B,C,D] selects scan col0-7 and enable(D)
// key: on: 0/off: 1
// prev: unknown: output previous key state(negated)?
#if defined(__AVR_AT90USB1286__)
// Ports for Teensy++
// row: PB0-2
// col: PB3-5,6
// key: PE6(pull-uped)
// prev: PE7
#define KEY_INIT() do { \
DDRB |= 0x7F; \
DDRE |= (1<<7); \
DDRE &= ~(1<<6); \
PORTE |= (1<<6); \
} while (0)
#define KEY_SELECT(ROW, COL) (PORTB = (PORTB & 0xC0) | \
(((COL) & 0x07)<<3) | \
((ROW) & 0x07))
#define KEY_ENABLE() (PORTB &= ~(1<<6))
#define KEY_UNABLE() (PORTB |= (1<<6))
#define KEY_STATE() (PINE & (1<<6))
#define KEY_PREV_ON() (PORTE |= (1<<7))
#define KEY_PREV_OFF() (PORTE &= ~(1<<7))
#define KEY_POWER_ON()
#define KEY_POWER_OFF()
#elif defined(__AVR_ATmega32U4__)
// Ports for my designed Alt Controller PCB
// row: PB0-2
// col: PB3-5,6
// key: PD7(pull-uped)
// prev: PB7
// power: PD4(L:off/H:on)
#define KEY_INIT() do { \
DDRB = 0xFF; \
PORTB = 0x00; \
DDRD &= ~0x80; \
PORTD |= 0x80; \
/* keyswitch board power on */ \
DDRD |= (1<<4); \
PORTD |= (1<<4); \
KEY_UNABLE(); \
KEY_PREV_OFF(); \
} while (0)
#define KEY_SELECT(ROW, COL) (PORTB = (PORTB & 0xC0) | \
(((COL) & 0x07)<<3) | \
((ROW) & 0x07))
#define KEY_ENABLE() (PORTB &= ~(1<<6))
#define KEY_UNABLE() (PORTB |= (1<<6))
#define KEY_STATE() (PIND & (1<<7))
#define KEY_PREV_ON() (PORTB |= (1<<7))
#define KEY_PREV_OFF() (PORTB &= ~(1<<7))
#define KEY_POWER_ON()
#define KEY_POWER_OFF()
/*
#define KEY_POWER_ON() do { \
KEY_INIT(); \
PORTD |= (1<<4); \
_delay_ms(1); \
} while (0)
#define KEY_POWER_OFF() do { \
PORTD &= ~(1<<4); \
DDRB &= ~0xFF; \
PORTB &= ~0xFF; \
DDRB &= ~0x80; \
PORTB &= ~0x80; \
} while (0)
*/
#elif defined(__AVR_ATmega328P__)
// Ports for V-USB
// key: PB0(pull-uped)
// prev: PB1
// row: PB2-4
// col: PC0-2,3
// power: PB5(Low:on/Hi-z:off)
#define KEY_INIT() do { \
DDRB |= 0x3E; \
DDRB &= ~(1<<0); \
PORTB |= 1<<0; \
DDRC |= 0x0F; \
KEY_UNABLE(); \
KEY_PREV_OFF(); \
} while (0)
#define KEY_SELECT(ROW, COL) do { \
PORTB = (PORTB & 0xE3) | ((ROW) & 0x07)<<2; \
PORTC = (PORTC & 0xF8) | ((COL) & 0x07); \
} while (0)
#define KEY_ENABLE() (PORTC &= ~(1<<3))
#define KEY_UNABLE() (PORTC |= (1<<3))
#define KEY_STATE() (PINB & (1<<0))
#define KEY_PREV_ON() (PORTB |= (1<<1))
#define KEY_PREV_OFF() (PORTB &= ~(1<<1))
// Power supply switching
#define KEY_POWER_ON() do { \
KEY_INIT(); \
PORTB &= ~(1<<5); \
_delay_ms(1); \
} while (0)
#define KEY_POWER_OFF() do { \
DDRB &= ~0x3F; \
PORTB &= ~0x3F; \
DDRC &= ~0x0F; \
PORTC &= ~0x0F; \
} while (0)
#else
# error "define code for matrix scan"
#endif
inline inline
uint8_t matrix_rows(void) uint8_t matrix_rows(void)
{ {
@ -199,13 +76,13 @@ uint8_t matrix_scan(void)
for (uint8_t row = 0; row < MATRIX_ROWS; row++) { for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
for (uint8_t col = 0; col < MATRIX_COLS; col++) { for (uint8_t col = 0; col < MATRIX_COLS; col++) {
KEY_SELECT(row, col); KEY_SELECT(row, col);
_delay_us(40); _delay_us(5);
// Not sure this is needed. This just emulates HHKB controller's behaviour. // Not sure this is needed. This just emulates HHKB controller's behaviour.
if (matrix_prev[row] & (1<<col)) { if (matrix_prev[row] & (1<<col)) {
KEY_PREV_ON(); KEY_PREV_ON();
} }
_delay_us(7); _delay_us(10);
// NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE. // NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE.
// If V-USB interrupts in this section we could lose 40us or so // If V-USB interrupts in this section we could lose 40us or so
@ -241,11 +118,13 @@ uint8_t matrix_scan(void)
matrix[row] = matrix_prev[row]; matrix[row] = matrix_prev[row];
} }
_delay_us(5);
KEY_PREV_OFF(); KEY_PREV_OFF();
KEY_UNABLE(); KEY_UNABLE();
// NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE. // NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE.
// This takes 25us or more to make sure KEY_STATE returns to idle state. // This takes 25us or more to make sure KEY_STATE returns to idle state.
_delay_us(150); _delay_us(75);
} }
} }
KEY_POWER_OFF(); KEY_POWER_OFF();