Added ISO/JIS keyboard support.

This commit is contained in:
tmk 2011-12-05 02:53:15 +09:00
parent 6284b147c2
commit 3f9de37310
5 changed files with 258 additions and 198 deletions

View File

@ -1,111 +1,75 @@
PS/2 to USB keyboard converter PS/2 to USB keyboard converter
============================== ==============================
This firmware converts PS/2 keyboard protocol to USB and for now supports only Scan Code Set 2.
This firmware converts PS/2 keyboard protocol to USB.
Demostration build
------------------
In this demo build, you can try several layouts,
mouse keys and USB NKRO.
Special keys:
Magic+0: Qwerty with mouse keys(default)
Magic+1: Qwerty
Magic+2: Colemak
Magic+3: Dvorak
Magic+4: Workman
Magic+N: toggles NKRO/6KRO(6KRO by default)
Magic+Esc: sends Power Event
where Magic=(LShift+RShift) or (LControl+RShift)
Keybinds:
Fn0+(hjkl): Mouse key move(vi cursor)
Fn0+(yuio): Mouse wheel(left,down,up,right)
Fn0+space: Mouse button1
Fn0+(mnb): Mouse buttons(1,2,3)
Fn0+(zxc): Media control(Volup, Voldown, Mute)
Fn1+(hjkl): Cursor move(vi cursor)
Fn1+(nm,.): Cursor move(Home,PageDown,PageUp,End)
Fn2+(esdf): Mouse key move(invert T cursor)
Fn2+(qwrt): Mouse wheel(left,down,up,right)
Fn2+space: Mouse button1
Fn2+(,./): Media control(Volup, Voldown, Mute)
where Fn0=;, Fn1=/, Fn2=a
Features Features
-------- --------
Mouse keys Mouse keys
You can emulates mouse move and button click using keyboard. You can emulates mouse move and button click using keyboard.
System/Media control System/Media control
You can sends Power event, Volume down/up and Mute. You can sends Power event, Volume down/up and Mute.
USB NKRO(actually 120KRO+8Modifiers) USB NKRO(actually 120KRO+8Modifiers)
You can tolggles NKRO/6KRO.(Not tested on Mac.) You can tolggles NKRO feature.
Keymap customization Keymap customization
You can customize keymaps easily by editing source code. You can customize keymaps easily by editing source code. See keymap.c.
Build for Teensy Build Converter
---------------- ---------------
0. Connect PS/2 keyboard to Teensy by 4 lines(Vcc, GND, Data, Clock). 0. Connect PS/2 keyboard into Teensy with 4 lines(Vcc, GND, Data, Clock).
1. Define following macros for PS/2 connection in config_pjrc.h: By default Clock is on PF0 and Data on PF1.
PS2_DATA_PORT You can change this pin configuration by editing config_pjrc.h.
PS2_DATA_PIN In this photo Vcc is yellow, GND is green, Data is red and Clock is black.
PS2_DATA_DDR http://img17.imageshack.us/img17/7243/201101181933.jpg
PS2_DATA_BIT
PS2_CLOCK_PORT
PS2_CLOCK_PIN Build Frimware
PS2_CLOCK_DDR --------------
PS2_CLOCK_BIT 1. Edit Makefile for build options and MCU setting.
2. Edit Makefile for build options and MCU setting. Use 'atmega32u4' for Teensy 2.0 or 'at90usb1286' for Teensy++ 2.0.
2. make 2. make
3. program Teensy. Just type 'make' in a terminal.
3. program with Teensy Loader.
http://www.pjrc.com/teensy/loader.html http://www.pjrc.com/teensy/loader.html
Build for V-USB Demonstration of Features
--------------- -------------------------
0. Build V-USB controller board and connect PS/2 keyboard. In default configuration, you can try several keymaps, mousekeys and USB NKRO.
1. Define macros in config_vusb.h if needed. Use following magic key combinations to enable some features.
2. Edit Makefile.vusb for build options and MCU setting.
3. make -f Makefile.vusb
4. program your V-USB controller.
keymaps and NKRO:
Magic+0: Qwerty with mousekeys(default)
Magic+1: Qwerty without mousekeys
Magic+2: Colemak
Magic+3: Dvorak
Magic+4: Workman
Magic+N: toggles NKRO/6KRO(6KRO by default)
Magic+Esc: sends Power Event(Power button)
V-USB Circuit where Magic=(LShift+RShift) or (LControl+RShift)
-------------
+---+ +---------------+ Fn layer function:
USB GND | | ATmega168 | Fn0+(hjkl): Mousekey move(vi cursor like)
=== C3 | | Fn0+(yuio): Mouse wheel(left,down,up,right)
5V <-------+--------+---|Vcc,AVCC | PS/2 Fn0+space: Mouse left button
R1 | | ==== Fn0+(mnb): Mouse buttons(m=left, n=right, b=middle)
D- <----+--+-----R2-----|INT1 RXD|------->DATA Fn0+(zxc): Media control(Volup, Voldown, Mute)
D+ <----|---+----R3-----|INT0 XCK|------->CLOCK Fn1+(hjkl): Cursor move(vi cursor like)
Z1 Z2 | | ->5V Fn1+(nm,.): Cursor move(Home,PageDown,PageUp,End)
GND<----+---+--+--+-----|GND | ->GND
| | | | where Fn0=;, Fn1=/
| C2-+--|XTAL1 |
| X1 | |
+--C3-+--|XTAL2 |
+---------------+
R1: 1.5K Ohm
R2,R3: 68 Ohm
Z1,Z2: Zenner 3.6V
C1,C2: 22pF
C3: 0.1uF
X1: Crystal 20MHz(16MHz/12MHz)
Keymap Keymap
------ ------
You can change a keymap by editing code of keymap.c like following. You can change a keymap by editing code of keymap.c like following.
How to define the keymap is probably obvious. You can find key How to define the keymap is probably obvious. You can find key symbols in usb_keycodes.h.
symbols in usb_keycodes.h. To define keymap layer switching may needs a bit of your effort at this time.
If you want to define more than one keymap, see hhkb/keymap.c and
macway/keymap.c as examples. To define keymap(layer) switching may
needs a bit of your effort at this time.
/* Default Layer: plain keymap /* Default Layer: plain keymap
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. * ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------.

37
ps2_usb/README.vusb Normal file
View File

@ -0,0 +1,37 @@
V-USB Support
=============
You can also use this converter on ATmega(168/328) with V-USB instead of Teensy.
The converter on V-USB lacks some features for now: USB NKRO and System/Media control.
To build a firmware use Makefile.vusb instead of Makefile.
Circuit
-------
+---+ +---------------+
USB GND | | ATmega168 |
=== C3 | |
5V <-------+--------+---|Vcc,AVCC | PS/2
R1 | | ====
D- <----+--+-----R2-----|INT1 RXD|------->DATA
D+ <----|---+----R3-----|INT0 XCK|------->CLOCK
Z1 Z2 | | ->5V
GND<----+---+--+--+-----|GND | ->GND
| | | |
| C2-+--|XTAL1 |
| X1 | |
+--C3-+--|XTAL2 |
+---------------+
R1: 1.5K Ohm
R2,R3: 68 Ohm
Z1,Z2: Zenner 3.6V
C1,C2: 22pF
C3: 0.1uF
X1: Crystal 20MHz(16MHz/12MHz)
This is my V-USB converter on breadboard.
[IMG]http://i.imgur.com/8jJCZl.jpg[/IMG]
EOF

View File

@ -28,11 +28,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keymap.h" #include "keymap.h"
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
// The keymap is a 32*8 matrix which convert a PS/2 scancode into a USB keycode. // Following macros help you to define a keymap with the form of actual keyboard layout.
// See matrix.c for the detail of matrix.
/* US layout plus all other various keys */
#define KEYMAP_ALL( \ #define KEYMAP_ALL( \
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
@ -41,6 +41,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \
\ \
K61, /* for European ISO */ \
K51, K13, K6A, K64, K67, /* for Japanese JIS */ \
K08, K10, K18, K20, K28, K30, K38, K40, K48, K50, K57, K5F, /* F13-24 */ \
KB7, KBF, KDE, /* System Power, Sleep, Wake */ \ KB7, KBF, KDE, /* System Power, Sleep, Wake */ \
KA3, KB2, KA1, /* Mute, Volume Up, Volume Down */ \ KA3, KB2, KA1, /* Mute, Volume Up, Volume Down */ \
KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */ \ KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */ \
@ -49,19 +52,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
KA8, KA0, K98 /* WWW Stop, Refresh, Favorites */ \ KA8, KA0, K98 /* WWW Stop, Refresh, Favorites */ \
) { \ ) { \
{ KB_NO, KB_##K01, KB_NO, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ { KB_NO, KB_##K01, KB_NO, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \
{ KB_NO, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_NO }, \ { KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_NO }, \
{ KB_NO, KB_##K11, KB_##K12, KB_NO, KB_##K14, KB_##K15, KB_##K16, KB_NO }, \ { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_NO }, \
{ KB_NO, KB_NO, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_NO }, \ { KB_##K18, KB_NO, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_NO }, \
{ KB_NO, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \ { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \
{ KB_NO, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_NO }, \ { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_NO }, \
{ KB_NO, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_NO }, \ { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_NO }, \
{ KB_NO, KB_NO, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \ { KB_##K38, KB_NO, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \
{ KB_NO, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \ { KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \
{ KB_NO, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_NO }, \ { KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, KB_NO }, \
{ KB_NO, KB_NO, KB_##K52, KB_NO, KB_##K54, KB_##K55, KB_NO, KB_NO }, \ { KB_##K50, KB_##K51, KB_##K52, KB_NO, KB_##K54, KB_##K55, KB_NO, KB_##K57 }, \
{ KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_NO, KB_##K5D, KB_NO, KB_NO }, \ { KB_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_NO, KB_##K5D, KB_NO, KB_##K5F }, \
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K66, KB_NO }, \ { KB_NO, KB_##K61, KB_NO, KB_NO, KB_##K64, KB_NO, KB_##K66, KB_##K67 }, \
{ KB_NO, KB_##K69, KB_NO, KB_##K6B, KB_##K6C, KB_NO, KB_NO, KB_NO }, \ { KB_NO, KB_##K69, KB_##K6A, KB_##K6B, KB_##K6C, KB_NO, KB_NO, KB_NO }, \
{ KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \ { KB_##K70, KB_##K71, KB_##K72, KB_##K73, KB_##K74, KB_##K75, KB_##K76, KB_##K77 }, \
{ KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \ { KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \
{ KB_NO, KB_NO, KB_NO, KB_##K83, KB_NO, KB_NO, KB_NO, KB_NO }, \ { KB_NO, KB_NO, KB_NO, KB_##K83, KB_NO, KB_NO, KB_NO, KB_NO }, \
@ -82,6 +85,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
{ KB_NO, KB_NO, KB_##KFA, KB_NO, KB_##KFC, KB_##KFD, KB_##KFE, KB_NO }, \ { KB_NO, KB_NO, KB_##KFA, KB_NO, KB_##KFC, KB_##KFD, KB_##KFE, KB_NO }, \
} }
/* US layout */
#define KEYMAP( \ #define KEYMAP( \
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \ K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \ K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
@ -98,6 +102,65 @@ KEYMAP_ALL( \
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \ K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \ K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \
\ \
NUBS, \
RO, KANA, JYEN, HENK, MHEN, \
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \
SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \
AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \
MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \
MAIL, CALCULATOR, MY_COMPUTER, \
WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \
WWW_STOP, WWW_REFRESH, WWW_FAVORITES \
)
/* ISO layout */
#define KEYMAP_ISO( \
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D,K5A, K6B,K73,K74,K79, \
K12,K61,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \
) \
KEYMAP_ALL( \
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \
\
K61, \
RO, KANA, JYEN, HENK, MHEN, \
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \
SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \
AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \
MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \
MAIL, CALCULATOR, MY_COMPUTER, \
WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \
WWW_STOP, WWW_REFRESH, WWW_FAVORITES \
)
/* JIS layout */
#define KEYMAP_JIS( \
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K6A,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B, KF1,KE9,KFA, K6C,K75,K7D, \
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52,K5D, K5A, K6B,K73,K74,K79, \
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A,K51, K59, KF5, K69,K72,K7A, \
K14,K9F,K11, K67,K29,K64,K13, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \
) \
KEYMAP_ALL( \
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \
\
NUBS, \
K51, K13, K6A, K64, K67, \
F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, \
SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \ SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \
AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \
MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \ MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \
@ -111,7 +174,7 @@ KEYMAP_ALL( \
static const uint8_t PROGMEM fn_layer[] = { static const uint8_t PROGMEM fn_layer[] = {
5, // Fn0 5, // Fn0
6, // Fn1 6, // Fn1
5, // Fn2 0, // Fn2
0, // Fn3 0, // Fn3
0, // Fn4 0, // Fn4
0, // Fn5 0, // Fn5
@ -132,6 +195,10 @@ static const uint8_t PROGMEM fn_keycode[] = {
KB_NO // Fn7 KB_NO // Fn7
}; };
// The keymap is a 32*8 byte array which convert a PS/2 scan code into a USB keycode.
// See usb_keycodes.h for USB keycodes. You should omit a 'KB_' prefix of USB keycodes in keymap macro.
// Use KEYMAP_ISO() or KEYMAP_JIS() instead of KEYMAP() if your keyboard is ISO or JIS.
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* keymap /* keymap
* ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. * ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------.
@ -223,7 +290,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
{ {
return KEYCODE(layer, row, col); return pgm_read_byte(&keymaps[(layer)][(row)][(col)]);
} }
uint8_t keymap_fn_layer(uint8_t fn_bits) uint8_t keymap_fn_layer(uint8_t fn_bits)

View File

@ -15,9 +15,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*
* scan matrix
*/
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <avr/io.h> #include <avr/io.h>
@ -29,54 +26,48 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "matrix.h" #include "matrix.h"
#if (MATRIX_COLS > 16) static void matrix_make(uint8_t code);
# error "MATRIX_COLS must not exceed 16" static void matrix_break(uint8_t code);
#endif #ifdef MATRIX_HAS_GHOST
#if (MATRIX_ROWS > 255) static bool matrix_has_ghost_in_row(uint8_t row);
# error "MATRIX_ROWS must not exceed 255"
#endif #endif
/* /*
* Matrix usage: * Matrix Array usage:
* "PS/2 Scan Codes Set 2" is assigned to 256(32x8)cells matrix. * 'Scan Code Set 2' is assigned into 256(32x8)cell matrix.
* Hmm, It is very sparse and not efficient :( * Hmm, it is very sparse and not efficient :(
* *
* 8bit * Notes:
* --------- * Both 'Hanguel/English'(F1) and 'Hanja'(F2) collide with 'Delete'(E0 71) and 'Down'(E0 72).
* These two Korean keys need exceptional handling and are not supported for now. Sorry.
*
* 8bit wide
* +---------+
* 0| | * 0| |
* :| XX | 00-7F for normal codes(without E0-prefix) * :| XX | 00-7F for normal codes(without E0-prefix)
* f|_________| * f|_________|
* 10| | * 10| |
* :| E0 XX | 80-FF for E0-prefix codes(use (XX|0x80) as code) * :| E0 YY | 80-FF for E0-prefixed codes
* 1f| | * 1f| | (<YY>|0x80) is used as matrix position.
* --------- * +---------+
* exceptions: *
* 83: F8[0x83](normal codes but > 0x7F) * Exceptions:
* FC: PrintScreen[E0 7C or 84] * 0x83: F7(0x83) This is a normal code but beyond 0x7F.
* FE: Puause * 0xFC: PrintScreen
* 0xFE: Pause
*/ */
#define F8 (0x83) static uint8_t matrix[MATRIX_ROWS];
#define PRINT_SCREEN (0xFC)
#define PAUSE (0xFE)
#define ROW(code) (code>>3) #define ROW(code) (code>>3)
#define COL(code) (code&0x07) #define COL(code) (code&0x07)
// matrix positions for exceptional keys
#define F7 (0x83)
#define PRINT_SCREEN (0xFC)
#define PAUSE (0xFE)
static bool is_modified = false; static bool is_modified = false;
// matrix state buffer(1:on, 0:off)
#if (MATRIX_COLS <= 8)
static uint8_t matrix[MATRIX_ROWS];
#else
static uint16_t matrix[MATRIX_ROWS];
#endif
#ifdef MATRIX_HAS_GHOST
static bool matrix_has_ghost_in_row(uint8_t row);
#endif
static void matrix_make(uint8_t code);
static void matrix_break(uint8_t code);
inline inline
uint8_t matrix_rows(void) uint8_t matrix_rows(void)
@ -107,13 +98,13 @@ void matrix_init(void)
* The scan code for these keys are varied or prefix/postfix'd * The scan code for these keys are varied or prefix/postfix'd
* depending on modifier key state. * depending on modifier key state.
* *
* References: * Keyboard Scan Code Specification:
* http://www.microsoft.com/whdc/archive/scancode.mspx * http://www.microsoft.com/whdc/archive/scancode.mspx
* http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc * http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc
* *
* *
* Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left: * 1) Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left
* Num Lock: off * a) when Num Lock is off
* modifiers | make | break * modifiers | make | break
* ----------+---------------------------+---------------------- * ----------+---------------------------+----------------------
* Ohter | <make> | <break> * Ohter | <make> | <break>
@ -121,16 +112,16 @@ void matrix_init(void)
* RShift | E0 F0 59 <make> | <break> E0 59 * RShift | E0 F0 59 <make> | <break> E0 59
* L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12 * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
* *
* Num Lock: on * b) when Num Lock is on
* modifiers | make | break * modifiers | make | break
* ----------+---------------------------+---------------------- * ----------+---------------------------+----------------------
* Other | E0 12 <make> | <break> E0 F0 12 * Other | E0 12 <make> | <break> E0 F0 12
* Shift'd | <make> | <break> * Shift'd | <make> | <break>
* *
* Handling: ignore these prefix/postfix codes * Handling: These prefix/postfix codes are ignored.
* *
* *
* Keypad-/: * 2) Keypad /
* modifiers | make | break * modifiers | make | break
* ----------+---------------------------+---------------------- * ----------+---------------------------+----------------------
* Ohter | <make> | <break> * Ohter | <make> | <break>
@ -138,12 +129,10 @@ void matrix_init(void)
* RShift | E0 F0 59 <make> | <break> E0 59 * RShift | E0 F0 59 <make> | <break> E0 59
* L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12 * L+RShift | E0 F0 12 E0 F0 59 <make> | <break> E0 59 E0 12
* *
* Handling: ignore these prefix/postfix codes * Handling: These prefix/postfix codes are ignored.
* *
* *
* PrintScreen: * 3) PrintScreen
* With hoding down modifiers, the scan code is sent as following:
*
* modifiers | make | break * modifiers | make | break
* ----------+--------------+----------------------------------- * ----------+--------------+-----------------------------------
* Other | E0 12 E0 7C | E0 F0 7C E0 F0 12 * Other | E0 12 E0 7C | E0 F0 7C E0 F0 12
@ -151,29 +140,30 @@ void matrix_init(void)
* Control'd | E0 7C | E0 F0 7C * Control'd | E0 7C | E0 F0 7C
* Alt'd | 84 | F0 84 * Alt'd | 84 | F0 84
* *
* Handling: ignore prefix/postfix codes and treat both scan code * Handling: These prefix/postfix codes are ignored, and both scan codes
* E0 7C and 84 as PrintScreen. * 'E0 7C' and 84 are seen as PrintScreen.
*
* Pause:
* With hoding down modifiers, the scan code is sent as following:
* *
* 4) Pause
* modifiers | make(no break code) * modifiers | make(no break code)
* ----------+-------------------------------------------------- * ----------+--------------------------------------------------
* no mods | E1 14 77 E1 F0 14 F0 77 * Other | E1 14 77 E1 F0 14 F0 77
* Control'd | E0 7E E0 F0 7E * Control'd | E0 7E E0 F0 7E
* *
* Handling: treat these two code sequence as Pause * Handling: Both code sequences are treated as a whole.
* And we need a ad hoc 'pseudo break code' hack to get the key off
* because it has no break code.
* *
*/ */
uint8_t matrix_scan(void) uint8_t matrix_scan(void)
{ {
// scan code reading states
static enum { static enum {
INIT, INIT,
F0, F0,
E0, E0,
E0_F0, E0_F0,
// states for Pause/Break // Pause
E1, E1,
E1_14, E1_14,
E1_14_77, E1_14_77,
@ -181,12 +171,16 @@ uint8_t matrix_scan(void)
E1_14_77_E1_F0, E1_14_77_E1_F0,
E1_14_77_E1_F0_14, E1_14_77_E1_F0_14,
E1_14_77_E1_F0_14_F0, E1_14_77_E1_F0_14_F0,
// Control'd Pause
E0_7E,
E0_7E_E0,
E0_7E_E0_F0,
} state = INIT; } state = INIT;
is_modified = false; is_modified = false;
// Pause/Break off(PS/2 has no break for this key) // 'pseudo break code' hack
if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) { if (matrix_is_on(ROW(PAUSE), COL(PAUSE))) {
matrix_break(PAUSE); matrix_break(PAUSE);
} }
@ -196,20 +190,20 @@ uint8_t matrix_scan(void)
switch (state) { switch (state) {
case INIT: case INIT:
switch (code) { switch (code) {
case 0xE0: // 2byte make case 0xE0:
state = E0; state = E0;
break; break;
case 0xF0: // break code case 0xF0:
state = F0; state = F0;
break; break;
case 0xE1: // Pause/Break case 0xE1:
state = E1; state = E1;
break; break;
case 0x83: // F8 case 0x83: // F7
matrix_make(F8); matrix_make(F7);
state = INIT; state = INIT;
break; break;
case 0x84: // PrintScreen case 0x84: // Alt'd PrintScreen
matrix_make(PRINT_SCREEN); matrix_make(PRINT_SCREEN);
state = INIT; state = INIT;
break; break;
@ -222,21 +216,19 @@ uint8_t matrix_scan(void)
state = INIT; state = INIT;
} }
break; break;
case E0: case E0: // E0-Prefixed
switch (code) { switch (code) {
case 0x12: // postfix/postfix code for exceptional keys case 0x12: // to be ignored
case 0x59: // postfix/postfix code for exceptional keys case 0x59: // to be ignored
// ignore
state = INIT; state = INIT;
break; break;
case 0x7E: // former part of Control-Pause[E0 7E E0 F0 7E] case 0x7E: // Control'd Pause
matrix_make(PAUSE); state = E0_7E;
state = INIT;
break; break;
case 0xF0: // E0 break case 0xF0:
state = E0_F0; state = E0_F0;
break; break;
default: // E0 make default:
if (code < 0x80) { if (code < 0x80) {
matrix_make(code|0x80); matrix_make(code|0x80);
} else { } else {
@ -245,13 +237,13 @@ uint8_t matrix_scan(void)
state = INIT; state = INIT;
} }
break; break;
case F0: case F0: // Break code
switch (code) { switch (code) {
case 0x83: case 0x83: // F7
matrix_break(F8); matrix_break(F7);
state = INIT; state = INIT;
break; break;
case 0x84: case 0x84: // Alt'd PrintScreen
matrix_break(PRINT_SCREEN); matrix_break(PRINT_SCREEN);
state = INIT; state = INIT;
break; break;
@ -264,12 +256,10 @@ uint8_t matrix_scan(void)
state = INIT; state = INIT;
} }
break; break;
case E0_F0: // E0 break case E0_F0: // Break code of E0-prefixed
switch (code) { switch (code) {
case 0x12: // postfix/postfix code for exceptional keys case 0x12: // to be ignored
case 0x59: // postfix/postfix code for exceptional keys case 0x59: // to be ignored
case 0x7E: // latter part of Control-Pause[E0 7E E0 F0 7E]
// ignore
state = INIT; state = INIT;
break; break;
default: default:
@ -281,7 +271,7 @@ uint8_t matrix_scan(void)
state = INIT; state = INIT;
} }
break; break;
/* Pause */ // following are states of Pause
case E1: case E1:
switch (code) { switch (code) {
case 0x14: case 0x14:
@ -346,6 +336,24 @@ uint8_t matrix_scan(void)
state = INIT; state = INIT;
} }
break; break;
// Following are states of Control'd Pause
case E0_7E:
if (code == 0xE0)
state = E0_7E_E0;
else
state = INIT;
break;
case E0_7E_E0:
if (code == 0xF0)
state = E0_7E_E0_F0;
else
state = INIT;
break;
case E0_7E_E0_F0:
if (code == 0x7E)
matrix_make(PAUSE);
state = INIT;
break;
default: default:
state = INIT; state = INIT;
} }
@ -378,29 +386,17 @@ bool matrix_is_on(uint8_t row, uint8_t col)
} }
inline inline
#if (MATRIX_COLS <= 8)
uint8_t matrix_get_row(uint8_t row) 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");
#else
print("\nr/c 0123456789ABCDEF\n");
#endif
for (uint8_t 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 #ifdef MATRIX_HAS_GHOST
if (matrix_has_ghost_in_row(row)) { if (matrix_has_ghost_in_row(row)) {
print(" <ghost"); print(" <ghost");
@ -414,11 +410,7 @@ uint8_t matrix_key_count(void)
{ {
uint8_t count = 0; uint8_t count = 0;
for (uint8_t 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;
} }

View File

@ -68,12 +68,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KB_NUHS KB_NONUS_HASH #define KB_NUHS KB_NONUS_HASH
#define KB_NUBS KB_NONUS_BSLASH #define KB_NUBS KB_NONUS_BSLASH
/* for Japanese */ /* for Japanese */
#define KB_ZKHK KB_GRAVE
#define KB_RO KB_INT1 #define KB_RO KB_INT1
#define KB_KANA KB_INT2 #define KB_KANA KB_INT2
#define KB_JYEN KB_INT3 #define KB_JYEN KB_INT3
#define KB_HENK KB_INT4 #define KB_HENK KB_INT4
#define KB_MHEN KB_INT5 #define KB_MHEN KB_INT5
#define KB_ZEHA KB_GRAVE
/* Keypad */ /* Keypad */
#define KB_P1 KB_KP_1 #define KB_P1 KB_KP_1
#define KB_P2 KB_KP_2 #define KB_P2 KB_KP_2