From 3f9de37310f670e6289738c628747e6787d42b22 Mon Sep 17 00:00:00 2001 From: tmk Date: Mon, 5 Dec 2011 02:53:15 +0900 Subject: [PATCH] Added ISO/JIS keyboard support. --- ps2_usb/README | 130 +++++++++++-------------------- ps2_usb/README.vusb | 37 +++++++++ ps2_usb/keymap.c | 103 ++++++++++++++++++++----- ps2_usb/matrix.c | 184 +++++++++++++++++++++----------------------- usb_keycodes.h | 2 +- 5 files changed, 258 insertions(+), 198 deletions(-) create mode 100644 ps2_usb/README.vusb diff --git a/ps2_usb/README b/ps2_usb/README index 0fdeaf1df5..b3bcfbe4dc 100644 --- a/ps2_usb/README +++ b/ps2_usb/README @@ -1,111 +1,75 @@ PS/2 to USB keyboard converter ============================== - -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 +This firmware converts PS/2 keyboard protocol to USB and for now supports only Scan Code Set 2. Features -------- Mouse keys You can emulates mouse move and button click using keyboard. + System/Media control You can sends Power event, Volume down/up and Mute. + USB NKRO(actually 120KRO+8Modifiers) - You can tolggles NKRO/6KRO.(Not tested on Mac.) + You can tolggles NKRO feature. + 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 ----------------- -0. Connect PS/2 keyboard to Teensy by 4 lines(Vcc, GND, Data, Clock). -1. Define following macros for PS/2 connection in config_pjrc.h: - PS2_DATA_PORT - PS2_DATA_PIN - PS2_DATA_DDR - PS2_DATA_BIT - PS2_CLOCK_PORT - PS2_CLOCK_PIN - PS2_CLOCK_DDR - PS2_CLOCK_BIT -2. Edit Makefile for build options and MCU setting. +Build Converter +--------------- +0. Connect PS/2 keyboard into Teensy with 4 lines(Vcc, GND, Data, Clock). + By default Clock is on PF0 and Data on PF1. + You can change this pin configuration by editing config_pjrc.h. + In this photo Vcc is yellow, GND is green, Data is red and Clock is black. + http://img17.imageshack.us/img17/7243/201101181933.jpg + + +Build Frimware +-------------- +1. Edit Makefile for build options and MCU setting. + Use 'atmega32u4' for Teensy 2.0 or 'at90usb1286' for Teensy++ 2.0. 2. make -3. program Teensy. + Just type 'make' in a terminal. +3. program with Teensy Loader. http://www.pjrc.com/teensy/loader.html -Build for V-USB ---------------- -0. Build V-USB controller board and connect PS/2 keyboard. -1. Define macros in config_vusb.h if needed. -2. Edit Makefile.vusb for build options and MCU setting. -3. make -f Makefile.vusb -4. program your V-USB controller. +Demonstration of Features +------------------------- +In default configuration, you can try several keymaps, mousekeys and USB NKRO. +Use following magic key combinations to enable some features. +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 -------------- - +---+ +---------------+ -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) + where Magic=(LShift+RShift) or (LControl+RShift) + +Fn layer function: + Fn0+(hjkl): Mousekey move(vi cursor like) + Fn0+(yuio): Mouse wheel(left,down,up,right) + Fn0+space: Mouse left button + Fn0+(mnb): Mouse buttons(m=left, n=right, b=middle) + Fn0+(zxc): Media control(Volup, Voldown, Mute) + Fn1+(hjkl): Cursor move(vi cursor like) + Fn1+(nm,.): Cursor move(Home,PageDown,PageUp,End) + + where Fn0=;, Fn1=/ Keymap ------ 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 -symbols in usb_keycodes.h. -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. +How to define the keymap is probably obvious. You can find key symbols in usb_keycodes.h. +To define keymap layer switching may needs a bit of your effort at this time. /* Default Layer: plain keymap * ,---. ,---------------. ,---------------. ,---------------. ,-----------. ,-----------. diff --git a/ps2_usb/README.vusb b/ps2_usb/README.vusb new file mode 100644 index 0000000000..c92871bcdd --- /dev/null +++ b/ps2_usb/README.vusb @@ -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 diff --git a/ps2_usb/keymap.c b/ps2_usb/keymap.c index e84e8c29b8..fc429212de 100644 --- a/ps2_usb/keymap.c +++ b/ps2_usb/keymap.c @@ -28,11 +28,11 @@ along with this program. If not, see . #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. -// See matrix.c for the detail of matrix. +// Following macros help you to define a keymap with the form of actual keyboard layout. + +/* US layout plus all other various keys */ #define 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, \ @@ -41,6 +41,9 @@ along with this program. If not, see . 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, /* 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 */ \ KA3, KB2, KA1, /* Mute, Volume Up, Volume Down */ \ KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */ \ @@ -49,19 +52,19 @@ along with this program. If not, see . 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_##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_NO, 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_NO, 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_NO, 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_NO, 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_##K58, KB_##K59, KB_##K5A, KB_##K5B, KB_NO, KB_##K5D, KB_NO, KB_NO }, \ - { KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K66, KB_NO }, \ - { KB_NO, KB_##K69, KB_NO, KB_##K6B, KB_##K6C, KB_NO, KB_NO, KB_NO }, \ + { KB_##K08, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_NO }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_NO }, \ + { KB_##K18, KB_NO, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_NO }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_NO }, \ + { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_NO }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_##K35, KB_##K36, KB_NO }, \ + { KB_##K38, KB_NO, KB_##K3A, KB_##K3B, KB_##K3C, KB_##K3D, KB_##K3E, KB_NO }, \ + { KB_##K40, KB_##K41, KB_##K42, KB_##K43, KB_##K44, KB_##K45, KB_##K46, KB_NO }, \ + { KB_##K48, KB_##K49, KB_##K4A, KB_##K4B, KB_##K4C, KB_##K4D, KB_##K4E, 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_##K5F }, \ + { KB_NO, KB_##K61, KB_NO, KB_NO, KB_##K64, KB_NO, KB_##K66, KB_##K67 }, \ + { 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_##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 }, \ @@ -82,6 +85,7 @@ along with this program. If not, see . { KB_NO, KB_NO, KB_##KFA, KB_NO, KB_##KFC, KB_##KFD, KB_##KFE, KB_NO }, \ } +/* US layout */ #define KEYMAP( \ 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, \ @@ -98,6 +102,65 @@ KEYMAP_ALL( \ 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, \ + 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, \ AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \ 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[] = { 5, // Fn0 6, // Fn1 - 5, // Fn2 + 0, // Fn2 0, // Fn3 0, // Fn4 0, // Fn5 @@ -132,6 +195,10 @@ static const uint8_t PROGMEM fn_keycode[] = { 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] = { /* 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) { - return KEYCODE(layer, row, col); + return pgm_read_byte(&keymaps[(layer)][(row)][(col)]); } uint8_t keymap_fn_layer(uint8_t fn_bits) diff --git a/ps2_usb/matrix.c b/ps2_usb/matrix.c index 1aac3f8661..4187ea0601 100644 --- a/ps2_usb/matrix.c +++ b/ps2_usb/matrix.c @@ -15,9 +15,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/* - * scan matrix - */ #include #include #include @@ -29,54 +26,48 @@ along with this program. If not, see . #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" +static void matrix_make(uint8_t code); +static void matrix_break(uint8_t code); +#ifdef MATRIX_HAS_GHOST +static bool matrix_has_ghost_in_row(uint8_t row); #endif /* - * Matrix usage: - * "PS/2 Scan Codes Set 2" is assigned to 256(32x8)cells matrix. - * Hmm, It is very sparse and not efficient :( + * Matrix Array usage: + * 'Scan Code Set 2' is assigned into 256(32x8)cell matrix. + * 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| | * :| XX | 00-7F for normal codes(without E0-prefix) * f|_________| * 10| | - * :| E0 XX | 80-FF for E0-prefix codes(use (XX|0x80) as code) - * 1f| | - * --------- - * exceptions: - * 83: F8[0x83](normal codes but > 0x7F) - * FC: PrintScreen[E0 7C or 84] - * FE: Puause + * :| E0 YY | 80-FF for E0-prefixed codes + * 1f| | (|0x80) is used as matrix position. + * +---------+ + * + * Exceptions: + * 0x83: F7(0x83) This is a normal code but beyond 0x7F. + * 0xFC: PrintScreen + * 0xFE: Pause */ -#define F8 (0x83) -#define PRINT_SCREEN (0xFC) -#define PAUSE (0xFE) +static uint8_t matrix[MATRIX_ROWS]; #define ROW(code) (code>>3) #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; -// 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 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 * depending on modifier key state. * - * References: + * Keyboard Scan Code Specification: * http://www.microsoft.com/whdc/archive/scancode.mspx * 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: - * Num Lock: off + * 1) Insert, Delete, Home, End, PageUp, PageDown, Up, Down, Right, Left + * a) when Num Lock is off * modifiers | make | break * ----------+---------------------------+---------------------- * Ohter | | @@ -121,16 +112,16 @@ void matrix_init(void) * RShift | E0 F0 59 | E0 59 * L+RShift | E0 F0 12 E0 F0 59 | E0 59 E0 12 * - * Num Lock: on + * b) when Num Lock is on * modifiers | make | break * ----------+---------------------------+---------------------- * Other | E0 12 | E0 F0 12 * Shift'd | | * - * Handling: ignore these prefix/postfix codes + * Handling: These prefix/postfix codes are ignored. * * - * Keypad-/: + * 2) Keypad / * modifiers | make | break * ----------+---------------------------+---------------------- * Ohter | | @@ -138,12 +129,10 @@ void matrix_init(void) * RShift | E0 F0 59 | E0 59 * L+RShift | E0 F0 12 E0 F0 59 | E0 59 E0 12 * - * Handling: ignore these prefix/postfix codes + * Handling: These prefix/postfix codes are ignored. * * - * PrintScreen: - * With hoding down modifiers, the scan code is sent as following: - * + * 3) PrintScreen * modifiers | make | break * ----------+--------------+----------------------------------- * 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 * Alt'd | 84 | F0 84 * - * Handling: ignore prefix/postfix codes and treat both scan code - * E0 7C and 84 as PrintScreen. - * - * Pause: - * With hoding down modifiers, the scan code is sent as following: + * Handling: These prefix/postfix codes are ignored, and both scan codes + * 'E0 7C' and 84 are seen as PrintScreen. * + * 4) Pause * 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 * - * 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) { + // scan code reading states static enum { INIT, F0, E0, E0_F0, - // states for Pause/Break + // Pause E1, E1_14, E1_14_77, @@ -181,12 +171,16 @@ uint8_t matrix_scan(void) E1_14_77_E1_F0, E1_14_77_E1_F0_14, E1_14_77_E1_F0_14_F0, + // Control'd Pause + E0_7E, + E0_7E_E0, + E0_7E_E0_F0, } state = INIT; 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))) { matrix_break(PAUSE); } @@ -196,20 +190,20 @@ uint8_t matrix_scan(void) switch (state) { case INIT: switch (code) { - case 0xE0: // 2byte make + case 0xE0: state = E0; break; - case 0xF0: // break code + case 0xF0: state = F0; break; - case 0xE1: // Pause/Break + case 0xE1: state = E1; break; - case 0x83: // F8 - matrix_make(F8); + case 0x83: // F7 + matrix_make(F7); state = INIT; break; - case 0x84: // PrintScreen + case 0x84: // Alt'd PrintScreen matrix_make(PRINT_SCREEN); state = INIT; break; @@ -222,21 +216,19 @@ uint8_t matrix_scan(void) state = INIT; } break; - case E0: + case E0: // E0-Prefixed switch (code) { - case 0x12: // postfix/postfix code for exceptional keys - case 0x59: // postfix/postfix code for exceptional keys - // ignore + case 0x12: // to be ignored + case 0x59: // to be ignored state = INIT; break; - case 0x7E: // former part of Control-Pause[E0 7E E0 F0 7E] - matrix_make(PAUSE); - state = INIT; + case 0x7E: // Control'd Pause + state = E0_7E; break; - case 0xF0: // E0 break + case 0xF0: state = E0_F0; break; - default: // E0 make + default: if (code < 0x80) { matrix_make(code|0x80); } else { @@ -245,13 +237,13 @@ uint8_t matrix_scan(void) state = INIT; } break; - case F0: + case F0: // Break code switch (code) { - case 0x83: - matrix_break(F8); + case 0x83: // F7 + matrix_break(F7); state = INIT; break; - case 0x84: + case 0x84: // Alt'd PrintScreen matrix_break(PRINT_SCREEN); state = INIT; break; @@ -264,12 +256,10 @@ uint8_t matrix_scan(void) state = INIT; } break; - case E0_F0: // E0 break + case E0_F0: // Break code of E0-prefixed switch (code) { - case 0x12: // postfix/postfix code for exceptional keys - case 0x59: // postfix/postfix code for exceptional keys - case 0x7E: // latter part of Control-Pause[E0 7E E0 F0 7E] - // ignore + case 0x12: // to be ignored + case 0x59: // to be ignored state = INIT; break; default: @@ -281,7 +271,7 @@ uint8_t matrix_scan(void) state = INIT; } break; - /* Pause */ + // following are states of Pause case E1: switch (code) { case 0x14: @@ -346,6 +336,24 @@ uint8_t matrix_scan(void) state = INIT; } 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: state = INIT; } @@ -378,29 +386,17 @@ bool matrix_is_on(uint8_t row, uint8_t 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(" . #define KB_NUHS KB_NONUS_HASH #define KB_NUBS KB_NONUS_BSLASH /* for Japanese */ +#define KB_ZKHK KB_GRAVE #define KB_RO KB_INT1 #define KB_KANA KB_INT2 #define KB_JYEN KB_INT3 #define KB_HENK KB_INT4 #define KB_MHEN KB_INT5 -#define KB_ZEHA KB_GRAVE /* Keypad */ #define KB_P1 KB_KP_1 #define KB_P2 KB_KP_2