1
0
Fork 0

add directories for each keyboard: hhkb, macway

This commit is contained in:
tmk 2010-10-14 17:36:00 +09:00
parent 82637ded27
commit 54b5bafaac
26 changed files with 383 additions and 794 deletions

72
hhkb/Makefile Normal file
View file

@ -0,0 +1,72 @@
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
# Carlos Lamas
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
# Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# Target file name (without extension).
TARGET = tmk_hhkb
# Directory common source filess exist
COMMON_DIR = ..
# Directory keyboard dependent files exist
TARGET_DIR = .
# keyboard dependent files
TARGET_SRC = keymap.c \
matrix.c
# 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
include $(COMMON_DIR)/Makefile.common

186
hhkb/doc/HHKB.txt Normal file
View file

@ -0,0 +1,186 @@
Alternative Controller for HHKB pro
===================================
I want to add vi cursor and mouse keys to HHKB. Original HHKB controller is not programmable and
firmware source code is not open. So, customizing HHKB needs to replace original controller with programmable one.
I used Teensy++ as alternative controller. Though a Teensy has enough ports to drive HHKB,
Teensy++ has clean pinout and it makes programing and wiring easier.
This is just a proof of concept for replacing controller of HHKB, not a complete firmware.
My prototype firmware source tree is here:
branch: hhkb(http://github.com/tmk/tmk_keyboard/tree/hhkb)
This firmware is a port of my previous project:
HHKB style Mod(http://geekhack.org/showwiki.php?title=Island:11930)
PJRC:
Teensy++/Teensy(http://www.pjrc.com/teensy/)
Pros:
* without pattern cutting, case mod and soldering
* can keep original controller intact
* can change HHKB behaviour as you like(by C programming)
Cons:
* void your warranty
* unavailability of Teensy++/Teensy(because of PS3 cracking boom?)
Features:
* customized keymap
* more keymap layers
* mouse keys for minimum mouse operation(never comfortable for normal use)
* and more...(in the future)
Any suggestions or ideas are welcome.
NOTE:
My HHKB is just "Professional". This means followings may not be applied to "Professional2".
DISCLAIMER:
I'm not a professional for electronics and MCU programming. This may damage your HHKB.
And my English writing is poor, I'm not sure I can convey my notions accurately.
Teensy++ installation
---------------------
Angled USB mini B adapter is used to install Teensy++ laterally.
(teensy_install.jpg)
Bread baord cables used for connect Teensy++.
(teensy_wiring.jpg)
(connector_contact.jpg)
HHKB internal
-------------
HHKB pro has two PCBs and some chips.
Controller PCB:
M38K07M4 Renesas MCU with USB function
http://documentation.renesas.com/eng/products/mpumcu/rej03b0192_38k0ds.pdf
(HHKB_controller.jpg)
Keyswitch PCB:
HC4051 Analog Multiplexer: select a row line.
http://www.alldatasheet.com/datasheet-pdf/pdf/203989/KODENSHI/KK74HC4051A.html
LS145 BCD Decoder: select a column line.
http://www.alldatasheet.com/datasheet-pdf/pdf/27373/TI/SN74LS145D.html
BU9831 Non-volatile electronic potentiometer: for calibration?
http://www.alldatasheet.com/datasheet-pdf/pdf/36387/ROHM/BU9831.html
TP1684 Capacitive Sensing controller: no datasheet available.
(HHKB_keyswitch.jpg)
Topre original chip?
(HHKB_TP1684.jpg)
Two PCBs are connected by 15 lines. Vcc/GND uses 3 lines each, 9lines for keyboard signaling.
Keyswitch PCB connector Teensy++ pins
-------------------------------------------------------------------------------
1 Vcc(5V) 5V
2 Vcc(5V)
3 Vcc(5V)
4 TP1684 KEY: Low(0) when key pressed PE6 input(with pullup)
5 TP1684 unknown:how to use PE7 input(with pullup)
6 HC4051 A(bit0) select 8 rows(0 to 7) PB0 output
7 HC4051 B(bit1) PB1 output
8 HC4051 C(bit2) PB2 output
9 LS145 A(bit0) select 8 columns(0 to 7) PB3 output
10 LS145 B(bit1) PB4 output
11 LS145 C(bit2) PB5 output
12 LS145 D(enable) Low(0) enable selected column PB6 output
13 GND
14 GND
15 GND GND
(HHKB_connector.jpg)
Keyswitch matrix
----------------
60 keyswitches in 8*8 matrix. ghost free. bounce free.
COL 0 1 2 3 4 5 6 7
ROW ---------------------------------------------------------------
0| 2 q w s a z x c
1| 3 4 r e d f v b
2| 5 6 y t g h n _NONE_
3| 1 Esc Tab Control LShift LAlt LMeta Space
4| 7 8 u i k j m _NONE_
5| \ ` Delete Return Fn RShift RAlt RMeta
6| 9 0 o p ; l , _NONE_
7| - + ] [ ' / . _NONE_
Matrix diagram:
+-------------------------+-+-+-+-+-+-+-+ Vcc
|bias control? - - - - - - - - ---
| 3.9K*8 R R R R R R R R |
+--------^+ +--------+ - - - - - - - - |
| TP 1684 | | HC4051 <0-------|-|-|-|-|-|-|-|--|R|-+
| |capa. | <1-------|-|-|-|-|-|-|-|--|R|-+
| |sense | <2-------|-|-|-|-|-|-|-|--|R|-+
| <------| <3-------|-|-|-|-|-|-|-|--|R|-+
| | | <4-------|-|-|-|-|-|-|-|--|R|-+
| | | <5-------|-|-|-|-|-|-|-|--|R|-+
| |calib.| <6-------|-|-|-|-|-|-|-|--|R|-+
| <-+? | <7-------|-|-|-|-|-|-|-|--|R|-+
+---V-----+ | +-^-^-^--+ 0 1 2 3 4 5 6 7 33K*8
KEY ??? | A B C +-----------------+
| | +-^----+ | | | | LS145 |
Vcc | | |BU9831| | | | +-^--^--^--^------+
--- | | +------+ | | | A B C D +------+
| | | | | | | | | | | |
1-3 4 5 6 7 8 9 10 11 12 13-15 |
+--------------------------------------------------+ |
| connector | ---
+--------------------------------------------------+ GND
to controller
Signals charts:
While pressing space bar, watched HHKB original controller signals by logic analyzer.
Row and column is looping between 0-7 each for selecting a key.
A key is scaned every about 15ms, so scan rate is 66Hz.
(HHKB_chart1.jpg)
Space bar locate at ROW:3 COL:7. Key are selected by HC4051(C,B,A) and LS145(C,B,A).
Key state can be read on TP1684(4/KEY) while asserting low on LS145(D).
Usage of TP1684(5) is unknown. Key state can be read without using this signal.
(HHKB_chart2.jpg)
Matrix scan pseudo code:
for (row: 0-7) {
SELECT_ROW(row); // set HC4051(A,B,C)
for (col: 0-7) {
SELECT_COL(col); // set LS145(A,B,C)
_delay_us(50);
ENALBLE_COL(); // set LS145(D) to low
_delay_us(10);
if (KEY == 0) { // read TP1684(KEY)
// key pressed
} else {
// not pressed
}
}
}
Keymap layers
-------------
Followings are added layers with additional Fn keys. They are not final decision.
see keymap_hhkb.c
EOF

BIN
hhkb/doc/HHKB_TP1684.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

BIN
hhkb/doc/HHKB_chart1.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

BIN
hhkb/doc/HHKB_chart2.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

BIN
hhkb/doc/HHKB_connector.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

BIN
hhkb/doc/HHKB_controller.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
hhkb/doc/HHKB_keyswitch.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

BIN
hhkb/doc/connector_contact.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
hhkb/doc/logic_analyzer.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

BIN
hhkb/doc/probe_contact.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

BIN
hhkb/doc/teensy_install.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
hhkb/doc/teensy_wiring.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

189
hhkb/keymap.c Normal file
View file

@ -0,0 +1,189 @@
/*
* keymap for HHKB pro
*/
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "matrix.h"
#include "keymap.h"
#include "usb_keyboard.h"
int current_layer = 0;
bool key_sent = false;
/*
* Layer0(Default Layer)
* ,-----------------------------------------------------------.
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `|
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs|
* |-----------------------------------------------------------|
* |Contro| A| S| D| F| G| H| J| K| L| ;| '|Return |
* |-----------------------------------------------------------|
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Fn2 |Fn1|
* `-----------------------------------------------------------'
* |Gui|Alt |Space |Fn3 |Gui|
* `-------------------------------------------'
*
* Layer1(Fn) HHKB mode
* ,-----------------------------------------------------------.
* |Pow| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
* |-----------------------------------------------------------|
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
* |-----------------------------------------------------------|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift |xxx|
* `-----------------------------------------------------------'
* |Gui |Alt |Space |Alt |Gui|
* `--------------------------------------------'
*
* Layer3(RALT) vi mode
* ,-----------------------------------------------------------.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Tab | | | | | |Hom|PgD|PgUlEnd| | | |Backs|
* |-----------------------------------------------------------|
* |Contro| | | | | |Lef|Dow|Up |Rig| | |Return |
* |-----------------------------------------------------------|
* |Shift | | | | | |McL|McD|McU|McR|Mb1|Mb2 | |
* `-----------------------------------------------------------'
* |Gui|Alt |Sapce |xxxxx|Mb3|
* `-------------------------------------------'
*
* Layer4(semicolon) mouse mode
* ,-----------------------------------------------------------.
* |Esc| | | | | | | | | | | | | | |
* |-----------------------------------------------------------|
* |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
* |-----------------------------------------------------------|
* |Contro| | | | | |McL|McD|McU|McR|xxx| |Return |
* |-----------------------------------------------------------|
* |Shift | | | | | | |Mb1|Mb2|Mb3| |Shift | |
* `-----------------------------------------------------------'
* |Gui |Alt |Mb1 |Alt |Gui|
* `--------------------------------------------'
*
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
*/
/* keycode sent when Fn key released without using layer keys. */
static const uint8_t PROGMEM FnKey[] = {
KB_NO, // this must be KB_NO. (not used)
KB_NO, // FN_1
KB_RALT, // FN_2
KB_SCOLON, // FN_3
};
static const uint8_t PROGMEM Keymap[][MATRIX_ROWS][MATRIX_COLS] = {
/* plain keymap
{
{ KB_2, KB_Q, KB_W, KB_S, KB_A, KB_Z, KB_X, KB_C },
{ KB_3, KB_4, KB_R, KB_E, KB_D, KB_F, KB_V, KB_B },
{ KB_5, KB_6, KB_Y, KB_T, KB_G, KB_H, KB_N, KB_NO },
{ KB_1, KB_ESCAPE, KB_TAB, KB_LCTRL, KB_LSHIFT, KB_LGUI, KB_LALT, KB_SPACE },
{ KB_7, KB_8, KB_U, KB_I, KB_K, KB_J, KB_M, KB_NO },
{ KB_BSLASH, KB_GRAVE, KB_BSPACE, KB_ENTER, FN_1, KB_RSHIFT, KB_RGUI, KB_RALT },
{ KB_9, KB_0, KB_O, KB_P, KB_SCOLON, KB_L, KB_COMMA, KB_NO },
{ KB_MINUS, KB_EQUAL, KB_RBRACKET,KB_LBRACKET,KB_QUOTE, KB_SLASH, KB_DOT, KB_NO },
},
*/
// 0: default
{
{ KB_2, KB_Q, KB_W, KB_S, KB_A, KB_Z, KB_X, KB_C },
{ KB_3, KB_4, KB_R, KB_E, KB_D, KB_F, KB_V, KB_B },
{ KB_5, KB_6, KB_Y, KB_T, KB_G, KB_H, KB_N, KB_NO },
{ KB_1, KB_ESCAPE, KB_TAB, KB_LCTRL, KB_LSHIFT, KB_LGUI, KB_LALT, KB_SPACE },
{ KB_7, KB_8, KB_U, KB_I, KB_K, KB_J, KB_M, KB_NO },
{ KB_BSLASH, KB_GRAVE, KB_BSPACE, KB_ENTER, FN_1, KB_RSHIFT, KB_RGUI, FN_2 },
{ KB_9, KB_0, KB_O, KB_P, FN_3, KB_L, KB_COMMA, KB_NO },
{ KB_MINUS, KB_EQUAL, KB_RBRACKET,KB_LBRACKET,KB_QUOTE, KB_SLASH, KB_DOT, KB_NO },
},
// 1: FN_1 HHKB mode(Fn)
{
{ KB_F2, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO },
{ KB_F3, KB_F4, KB_NO, KB_NO, KB_MUTE, KB_F20, KB_NO, KB_NO },
{ KB_F5, KB_F6, KB_NO, KB_NO, KB_NO, KP_ASTERISK,KP_PLUS, KB_NO },
{ KB_F1, KB_POWER, KB_CAPSLOCK,KB_LCTRL, KB_LSHIFT, KB_LGUI, KB_LALT, KB_SPACE },
{ KB_F7, KB_F8, KB_NO, KB_PSCREEN, KB_HOME, KP_SLASH, KB_MINUS, KB_NO },
{ KB_INSERT, KB_DELETE, KB_BSPACE, KP_ENTER, KB_NO, KB_RSHIFT, KB_RGUI, KB_RALT },
{ KB_F9, KB_F10, KB_SCKLOCK, KB_BREAK, KB_LEFT, KB_PGUP, KB_END, KB_NO },
{ KB_F11, KB_F12, KB_NO, KB_UP, KB_RIGHT, KB_DOWN, KB_PGDOWN, KB_NO },
},
// 2: FN_2 vi mode(RALT)
{
{ KB_F2, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO },
{ KB_F3, KB_F4, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO },
{ KB_F5, KB_F6, KB_HOME, KB_NO, KB_NO, KB_LEFT, MS_LEFT, KB_NO },
{ KB_F1, KB_ESCAPE, KB_TAB, KB_LCTRL, KB_LSHIFT, KB_LGUI, KB_LALT, KB_SPACE },
{ KB_F7, KB_F8, KB_PGDOWN, KB_PGUP, KB_UP, KB_DOWN, MS_DOWN, KB_NO },
{ KB_INSERT, KB_DELETE, KB_BSPACE, KB_ENTER, KB_NO, MS_BTN2, MS_BTN3, KB_NO },
{ KB_F9, KB_F10, KB_END, KB_NO, KB_NO, KB_RIGHT, MS_UP, KB_NO },
{ KB_F11, KB_F12, MS_WH_UP, MS_WH_DOWN, KB_NO, MS_BTN1, MS_RIGHT, KB_NO },
},
// 3: FN_3 vi mouse mode(SCOLON)
{
{ KB_F2, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO },
{ KB_F3, KB_F4, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO },
{ KB_F5, KB_F6, MS_WH_LEFT, KB_NO, KB_NO, MS_LEFT, KB_NO, KB_NO },
{ KB_F1, KB_ESCAPE, KB_TAB, KB_LCTRL, KB_LSHIFT, KB_LGUI, KB_LALT, MS_BTN1 },
{ KB_F7, KB_F8, MS_WH_DOWN, MS_WH_UP, MS_UP, MS_DOWN, MS_BTN1, KB_NO },
{ KB_NO, KB_NO, KB_BSPACE, KB_ENTER, KB_NO, KB_RSHIFT, KB_RGUI, KB_RALT },
{ KB_F9, KB_F10, MS_WH_RIGHT,KB_NO, KB_NO, MS_RIGHT, MS_BTN2, KB_NO },
{ KB_F11, KB_F12, KB_NO, KB_NO, KB_NO, KB_NO, MS_BTN3, KB_NO },
},
};
uint8_t get_keycode(int layer, int row, int col)
{
if (row >= MATRIX_ROWS)
return KB_NO;
if (col >= MATRIX_COLS)
return KB_NO;
return pgm_read_byte(&Keymap[layer][row][col]);
}
int get_layer(void) {
// keep modifier state when Fn key pressed
static uint8_t preserved_modifiers = 0;
int layer = 0;
uint8_t modifiers = 0;
for (int row = 0; row < MATRIX_ROWS; row++) {
for (int col = 0; col < MATRIX_ROWS; col++) {
if (matrix[row] & 1<<col) continue; // NOT pressed
uint8_t code = get_keycode(0, row, col);
if (code == FN_1) layer = 1;
else if (code == FN_2) layer = 2;
else if (code == FN_3) layer = 3;
else if (code == FN_4) layer = 4;
else if (KB_LCTRL <= code && code <= KB_RGUI)
modifiers |= 1<<(code & 0x07);
}
}
// TODO: this logic should go anywhere
// TODO: need timeout for key_sent
// send key when Fn key reloeased without used
if (layer != current_layer) {
if (layer == 0 && !key_sent) {
uint8_t code = pgm_read_byte(&FnKey[current_layer]);
if (code) {
// send modifiers when Fn key pressed.
keyboard_modifier_keys = preserved_modifiers;
for (int i = 0; i < 6; i++) keyboard_keys[i] = KB_NO;
if (KB_LCTRL <= code && code <= KB_RGUI) {
keyboard_modifier_keys |= 1<<(code & 0x07);
} else {
keyboard_keys[0] = code;
}
usb_keyboard_send();
}
}
current_layer = layer;
key_sent = false;
preserved_modifiers = modifiers;
}
return current_layer;
}

20
hhkb/keymap.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef KEYMAP_H
#define KEYMAP_H 1
#include <stdint.h>
#include <stdbool.h>
#include "usb_keycodes.h"
#define MATRIX_ROWS 8
#define MATRIX_COLS 8
extern int current_layer;
extern bool key_sent;
int get_layer(void);
uint8_t get_keycode(int layer, int row, int col);
#endif

91
hhkb/matrix.c Normal file
View file

@ -0,0 +1,91 @@
/*
* scan matrix
*/
#include <avr/io.h>
#include <util/delay.h>
#include "keymap.h"
#include "matrix.h"
#include "print.h"
// matrix is active low. (key on: 0/key off: 1)
//
// HHKB has no ghost and no bounce.
// row: HC4051 select input channel(0-8)
// PB0, PB1, PB2(A, B, C)
// col: LS145 select low output line(0-8)
// PB3, PB4, PB5, PB6(A, B, C, D)
// use D as ENABLE: (enable: 0/unenable: 1)
// key: KEY: (on: 0/ off:1)
// UNKNOWN: unknown whether input or output
// PE6,PE7(KEY, UNKNOWN)
#define COL_ENABLE (1<<6)
#define KEY_SELELCT(ROW, COL) (PORTB = COL_ENABLE|(((COL)&0x07)<<3)|((ROW)&0x07))
#define KEY_ENABLE (PORTB &= ~COL_ENABLE)
#define KEY_UNABLE (PORTB |= COL_ENABLE)
#define KEY_ON ((PINE&(1<<6)) ? false : true)
// matrix state buffer
uint8_t *matrix;
uint8_t *matrix_prev;
static uint8_t _matrix0[MATRIX_ROWS];
static uint8_t _matrix1[MATRIX_ROWS];
// this must be called once before matrix_scan.
void matrix_init(void)
{
// row & col output(PB0-6)
DDRB = 0xFF;
PORTB = KEY_SELELCT(0, 0);
// KEY & VALID input with pullup(PE6,7)
DDRE = 0x3F;
PORTE = 0xC0;
// initialize matrix state: all keys off
for (int i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0xFF;
for (int i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0xFF;
matrix = _matrix0;
matrix_prev = _matrix1;
}
uint8_t matrix_scan(void)
{
uint8_t *tmp;
tmp = matrix_prev;
matrix_prev = matrix;
matrix = tmp;
for (int row = 0; row < MATRIX_ROWS; row++) {
for (int col = 0; col < MATRIX_COLS; col++) {
KEY_SELELCT(row, col);
_delay_us(50); // from logic analyzer chart
KEY_ENABLE;
_delay_us(10); // from logic analyzer chart
if (KEY_ON) {
matrix[row] &= ~(1<<col);
} else {
matrix[row] |= (1<<col);
}
KEY_UNABLE;
_delay_us(150); // from logic analyzer chart
}
}
return 1;
}
bool matrix_is_modified(void) {
for (int i=0; i <MATRIX_ROWS; i++) {
if (matrix[i] != matrix_prev[i])
return true;
}
return false;
}
bool matrix_has_ghost(void) {
return false;
}
bool matrix_has_ghost_in_row(uint8_t row) {
return false;
}