aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2013-02-11 12:48:49 +0900
committertmk <nobody@nowhere>2013-02-11 12:48:49 +0900
commit8c80deb775ac151001dc1592a2e94e8677b49964 (patch)
treeaa62c5cbef8419d9cdded26440cfdb42f7d806fd
parent4701b08b71b187cb3d015bec7e05d30e35c344ac (diff)
parent39d093339393e1758eede06f736b1f99a68ac74c (diff)
downloadqmk_firmware-8c80deb775ac151001dc1592a2e94e8677b49964.tar.gz
qmk_firmware-8c80deb775ac151001dc1592a2e94e8677b49964.zip
Merge branch 'keymap2'
Conflicts: common/keyboard.c
-rw-r--r--README.md612
-rw-r--r--common.mk3
-rw-r--r--common/action.c883
-rw-r--r--common/action.h331
-rw-r--r--common/action_macro.c67
-rw-r--r--common/action_macro.h107
-rw-r--r--common/command.c17
-rw-r--r--common/debug.h1
-rw-r--r--common/host.c13
-rw-r--r--common/host.h7
-rw-r--r--common/keyboard.c580
-rw-r--r--common/keyboard.h38
-rw-r--r--common/keycode.h55
-rw-r--r--common/keymap.c73
-rw-r--r--common/keymap.h20
-rw-r--r--common/print.c7
-rw-r--r--common/print.h2
-rw-r--r--common/report.h44
-rw-r--r--doc/keycode.txt261
-rw-r--r--keyboard/hhkb/Makefile.lufa3
-rw-r--r--keyboard/hhkb/Makefile.vusb3
-rw-r--r--keyboard/hhkb/config.h18
-rw-r--r--keyboard/hhkb/keymap.c304
-rw-r--r--keyboard/hhkb/matrix.c7
24 files changed, 2689 insertions, 767 deletions
diff --git a/README.md b/README.md
index 65fc72f53..cf09a9407 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,17 @@ Source code is available here: <http://github.com/tmk/tmk_keyboard>
7 7
8Features 8Features
9-------- 9--------
10* Mouse key - Mouse control by keyboard. 10* Multi-layer keymap - Multiple keyboard layouts with layer switching.
11* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up. 11* Mouse key - Mouse control with keyboard
12* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc. 12* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up
13* USB NKRO - Can send 120 keys(+ 8 modifiers) simultaneously. 13* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
14* PS/2 mouse support - integrate PS/2 mouse(TrackPoint) into keyboard as composite device. 14* USB NKRO - 120 keys(+ 8 modifiers) simultaneously
15* keyboard protocols - PS/2, ADB and old keyboard protocols. 15* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device
16* Keyboard protocols - PS/2, ADB, M0110, Sun and other old keyboard protocols
17* User Function - Customizable function of key with writing code
18* Macro - Very primitive at this time
19* Keyboard Tricks - Oneshot modifier and modifier with tapping feature
20* Debug Console - Messages for debug and interaction with firmware
16 21
17 22
18Projects 23Projects
@@ -24,11 +29,17 @@ Projects
24* terminal_usb - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal] 29* terminal_usb - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal]
25* news_usb - [Sony NEWS keyboard to USB][GH_news] 30* news_usb - [Sony NEWS keyboard to USB][GH_news]
26* x68k_usb - [Sharp X68000 keyboard to USB][GH_x68k] 31* x68k_usb - [Sharp X68000 keyboard to USB][GH_x68k]
32* sun_usb - Sun to USB(type4, 5 and 3?)
33* usb_usb - USB to USB(experimental)
27 34
28### keyboard 35### keyboard
29* hhkb - [Happy Hacking Keyboard professional][GH_hhkb] 36* hhkb - [Happy Hacking Keyboard professional][GH_hhkb]
30* macway - [Compact keyboard mod][GH_macway] 37* macway - [Compact keyboard mod][GH_macway]
31* hbkb - [Happy Buckling sprint keyboard(IBM Model M mod)][GH_hbkb] 38* hbkb - [Happy Buckling sprint keyboard(IBM Model M mod)][GH_hbkb]
39* IIgs_Standard - Apple IIGS keyboard mod(by JeffreySung)
40* hid_liber - [HID liberation controller][HID_liber](by alaricljs)
41* phantom - [Phantom keyboard][PHANTOM] (by Tranquilite)
42* gh60 - [GH60 keyboard][GH60]
32 43
33[GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930 44[GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930
34[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047 45[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047
@@ -40,52 +51,99 @@ Projects
40[GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272 51[GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272
41[GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060 52[GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060
42[GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483 53[GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483
54[HID_liber]: http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions
55[PHANTOM]: http://geekhack.org/index.php?topic=26742
56[GH60]: http://geekhack.org/index.php?topic=34959
43 57
44 58
45 59
46Files & Directories 60Build & Program
47------------------- 61---------------
48### Top 62### Install Tools
49* common/ - common codes 63First, you need tools to build firmware and program your controller. I assume you are on Windows here.
50* protocol/ - keyboard protocol support
51* keyboard/ - keyboard projects
52* converter/ - protocol converter projects
53* doc/ - documents
54* common.mk - Makefile for common
55* protoco.mk - Makefile for protocol
56* rules.mk - Makefile for build rules
57 64
58### Keyboard Protocols 651. Install [WinAVR][winavr]. This is old but works well for this purpose. `WinAVR` is a tool set to build firmware including C compiler(gcc) and make commands. You can use [CrossPack][crosspack] instead if you are on Mac.
59* pjrc/ - PJRC USB stack 66
60* vusb/ - Objective Development V-USB 672. Install [Atmel FLIP][flip]. `FLIP` is a tool to program(load) firmware into AVR controller(ATMega32u4) via DFU bootloader. ATMega32u4 has DFU bootloader by factory default. You can use [dfu-programmer][dfu-prog] instead if you are on Mac.
61* iwrap/ - Bluetooth HID for Bluegiga iWRAP 68
62* ps2.c - PS/2 protocol 693. Install driver for DFU bootloader. At first time you start DFU bootloader on Chip 'Found New Hardware Wizard' will come up on Windows. If you install device driver properly you can find chip name like 'ATmega32U4' under 'LibUSB-Win32 Devices' tree on 'Device Manager'. If not you shall need to update its driver on 'Device Manager'. You will find the driver in `FLIP` install directory like: C:\Program Files (x86)\Atmel\Flip 3.4.5\usb\. If you use `dfu-programmer` install its driver.
63* adb.c - Apple Desktop Bus protocol 70
64* m0110.c - Macintosh 128K/512K/Plus keyboard protocol 71If you use PJRC Teensy you don't need step 2 and 3, just get [Teensy loader][teensy-loader].
65* news.c - Sony NEWS keyboard protocol 72
66* x68k.c - Sharp X68000 keyboard protocol 73
74### Download source
75You can find firmware source at github: https://github.com/tmk/tmk_keyboard
76
77If you are familiar with `Git` tools you are recommended to use it.
78If not you can download zip archive from: https://github.com/tmk/tmk_keyboard/archive/master.zip
67 79
68 80
69Build & Program
70---------------
71### Build firmware 81### Build firmware
72To compile you need `AVR GCC`, `AVR Libc` and `GNU make`. 821. Open terminal window to get access to commands. You can use `cmd` in Windows or `Terminal.app` on Mac OSX. In Windows press `Windows` key and `R` then enter `cmd` in Run command dialog showing up.
73You can use [WinAVR][winavr] on Windows and [CrossPack][crosspack] on Mac. 83
842. Move to project directory in the firmware source.
85
86 cd tmk_keyboard/{keyboard or converter}/<project>
87
883. Build firmware using GNU `make` command. You'll see <project>_<variant>.hex file in that directory unless something unexpected occurs in build process.
89
90 mkae -f Makefile.<variant> clean
91 make -f Makefile.<variant>
74 92
75 $ cd <project>
76 $ make
77 93
78The firmware will be compiled as a file `tmk_<project>.hex`.
79 94
80[winavr]: http://winavr.sourceforge.net/
81[crosspack]: http://www.obdev.at/products/crosspack/index.html
82 95
83### Program Controller 96### Program Controller
97Sock AVR USB chip including ATmega32U4 has DFU bootloader by factory default, you can use DFU tools for this purpose. `FLIP` is a DFU tool on Windows offered by Atmel. Open source command line DFU tool `dfu-programmer` also supports AVR chips, which run on Linux, Mac OSX and even Windows. If you have a PJRC Teensy you should use `Teensy Loader`.
98
99#### DFU bootloader
100To program AVR chip with DFU bootloader use `FLIP` or `dfu-programmer`.
84If you have a proper program command in `Makefile` just type this. 101If you have a proper program command in `Makefile` just type this.
85 102
86 $ make program 103`FLIP` has two version of tool, GUI app and command line program. If you want GUI see tutorial section below.
104To use command line tool run this command. Note that you need to set PATH variable properly.
105
106 $ make -f Makefile.<variant> flip
107
108To program with `dfu-programmer` run:
109
110 $ make -f Makefile.<variant> dfu
111
112#### Teensy
113If you have PJRC Teensy see instruction of `Teensy Loader` at: <http://www.pjrc.com/teensy/loader.html>
114Or use this command if you have command line version of Teensy Loader installed.
115
116 $ make -f Makefile.<variant> teensy
87 117
88As for `Teensy` you can use `PJRC's loader` to program hex file. <http://www.pjrc.com/teensy/loader.html> 118
119#### Other programmer
120You may want to use other you favorite programmer like `avrdude` with AVRISPmkII, Aruduino or USBasp. In that case you can still use make target `program` for build with configuring PROGRAM_CMD in Makefile.
121
122 $ make -f Makefile.<variant> program
123
124
125
126#### FLIP GUI tutorial
1271. On menu bar click Device -> Select, then. `ATmega32u4`.
1282. On menu bar click Settings -> Communication -> USB, then click 'Open' button on 'USB Port Connection' dialog.
129At this point you'll see greyouted widgets on the app get colored and ready.
130
1313. On menu bar click File -> Load HEX File, then select your firmware hex file on File Selector dialog.
1324. On 'Operations Flow' panel click 'Run' button to load the firmware binary to the chip. Note that you should keep 'Erase', 'Blank Check', 'Program' and 'Verify' check boxes selected.
1335. Re-plug USB cord or click 'Start Application' button to restart your controller.
134Done.
135
136See also these instaructions if you need.
137
138- <http://code.google.com/p/micropendous/wiki/LoadingFirmwareWithFLIP>
139- <http://www.atmel.com/Images/doc7769.pdf>
140
141
142[winavr]: http://winavr.sourceforge.net/
143[crosspack]: http://www.obdev.at/products/crosspack/index.html
144[flip]: http://www.atmel.com/tools/FLIP.aspx
145[dfu-prog]: http://dfu-programmer.sourceforge.net/
146[teensy-loader]:http://www.pjrc.com/teensy/loader.html
89 147
90 148
91 149
@@ -106,20 +164,22 @@ Note that ***comment out*** to disable them.
106 NKRO_ENABLE = yes # USB Nkey Rollover 164 NKRO_ENABLE = yes # USB Nkey Rollover
107 165
108### 3. Programmer 166### 3. Programmer
109Set proper command for your controller, bootloader and programmer. 167Optional. Set proper command for your controller, bootloader and programmer.
110 168
111 # for PJRC Teensy 169 # for PJRC Teensy
112 PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex 170 PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
113 171
114 # for Atmel AT90USBKEY 172 # for Atmel chip with DFU bootloader
115 PROGRAM_CMD = dfu-programmer $(MCU) flash $(TARGET).hex 173 PROGRAM_CMD = dfu-programmer $(MCU) flash $(TARGET).hex
116 174
117 # avrdude 175 # avrdude with other methods
118 PROGRAM_CMD = avrdude -p $(MCU) -c avrispmkII -P USB -U flash:w:$(TARGET).hex 176 PROGRAM_CMD = avrdude -p $(MCU) -c avrispmkII -P USB -U flash:w:$(TARGET).hex
119 PROGRAM_CMD = avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex 177 PROGRAM_CMD = avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex
120 PROGRAM_CMD = avrdude -p $(MCU) -c arduino -P COM1 -b 57600 -U flash:w:$(TARGET).hex 178 PROGRAM_CMD = avrdude -p $(MCU) -c arduino -P COM1 -b 57600 -U flash:w:$(TARGET).hex
121 179
122config.h Options 180
181
182Config.h Options
123---------------- 183----------------
124### 1. USB vendor/product ID and device description 184### 1. USB vendor/product ID and device description
125 #define VENDOR_ID 0xFEED 185 #define VENDOR_ID 0xFEED
@@ -145,42 +205,458 @@ config.h Options
145 205
146Keymap 206Keymap
147------ 207------
208Many of existent projects offer keymap framework to define your own keymap easily. The following will explain how you can define keymap using this framework.
209 Instead, you can also implement your own `keymap_get_action()` to return action code for each key if you want.
210
211This is keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard. Keymap is defined in `keymaps[]` array.
212
213 static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
214 /* Layer 0: Default Layer
215 * ,-----------------------------------------------------------.
216 * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `|
217 * |-----------------------------------------------------------|
218 * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs|
219 * |-----------------------------------------------------------|
220 * |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter |
221 * |-----------------------------------------------------------|
222 * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn1|
223 * `-----------------------------------------------------------'
224 * |Gui|Alt |Space |Alt |Fn2|
225 * `-------------------------------------------'
226 */
227 KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
228 TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
229 LCTL,A, S, D, F, G, H, J, K, L, FN2, QUOT,ENT, \
230 LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN1, \
231 LGUI,LALT, SPC, RALT,FN3),
232
233 /* Layer 1: HHKB mode (HHKB Fn)
234 * ,-----------------------------------------------------------.
235 * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
236 * |-----------------------------------------------------------|
237 * |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
238 * |-----------------------------------------------------------|
239 * |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
240 * |-----------------------------------------------------------|
241 * |Shift | | | | | | +| -|End|PgD|Dow|Shift |Fn1|
242 * `-----------------------------------------------------------'
243 * |Gui |Alt |Space |Alt |Gui|
244 * `--------------------------------------------'
245 */
246 KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
247 CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, BSPC, \
248 LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
249 LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN0, \
250 LGUI,LALT, SPC, RALT,RGUI),
251 /* Layer 2: Mouse mode (Semicolon)
252 * ,-----------------------------------------------------------.
253 * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
254 * |-----------------------------------------------------------|
255 * |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
256 * |-----------------------------------------------------------|
257 * |Contro| | | | | |McL|McD|McU|McR|Fn0| |Return |
258 * |-----------------------------------------------------------|
259 * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
260 * `-----------------------------------------------------------'
261 * |Gui |Alt |Mb1 |Alt |Fn0|
262 * `--------------------------------------------'
263 * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
264 */
265 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
266 TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \
267 LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, QUOT,ENT, \
268 LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,NO, \
269 LGUI,LALT, BTN1, RALT,FN0),
270 };
271
272 static const uint16_t PROGMEM fn_actions[] = {
273 ACTION_LAYER_DEFAULT, // FN0
274 ACTION_LAYER_SET(1), // FN1
275 ACTION_LAYER_SET_TAP_KEY(2, KC_SCLN), // FN2
276 ACTION_LAYER_BIT_TOGGLE(2), // FN3
277 };
278
279
280
281### 1. Keycode
282See `common/keycode.h`. Keycode is 8bit internal code to inidicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like `KC_A` have simple action register key on press and unregister on release, on the other some of keycodes has some special actions like Fn keys, Media contorl keys, System control keys and Mouse keys.
283
284 ***In `KEYMAP` definition you need to omit prefix part `KC_` of keycode to keep keymap compact.*** For example, just use `A` instead you place `KC_A` in `KEYMAP`. Some keycodes has 4-letter short name in addition to descriptive name, you'll prefer short one in `KEYMAP`.
285
286#### 1.1 Normal key
287- `KC_NO` for no aciton
288- `KC_A` to `KC_Z`, `KC_1` to `KC_0` for alpha numeric key
289- `KC_MINS`, `KC_EQL`, `KC_GRV`, `KC_RBRC`, `KC_LBRC`, `KC_COMM`, `KC_DOT`, `KC_BSLS`, `KC_SLSH`, `KC_SCLN`, `KC_QUOT`
290- `KC_ESC`, `KC_TAB`, `KC_SPC`, `KC_BSPC`, `KC_ENT`, `KC_DEL`, `KC_INS`
291- `KC_UP`, `KC_DOWN`, `KC_RGHT`, `KC_LEFT`, `KC_PGUP`, `KC_PGDN`, `KC_HOME`, `KC_END`
292- `KC_CAPS`, `KC_NLCK`, `KC_SLCK`, `KC_PSCR`, `KC_PAUS`, `KC_APP`, `KC_F1` to `KC_F24`
293- `KC_P1` to `KC_P0`, `KC_PDOT`, `KC_PCMM`, `KC_PSLS`, `KC_PAST`, `KC_PMNS`, `KC_PPLS`, `KC_PEQL`, `KC_PENT` for keypad.
294
295#### 1.2 Modifier
296There are 8 modifiers which has discrimination between left and right.
297
298- `KC_LCTL` and `KC_RCTL` for Control
299- `KC_LSFT` and `KC_RSFT` for Shift
300- `KC_LALT` and `KC_RALT` for Alt
301- `KC_LGUI` and `KC_RGUI` for Windows key or Command key in Mac
302
303#### 1.3 Fn key
304 **`KC_FNnn`** are `Fn` keys which not given any action at the beginning unlike most of keycodes has its own action. To use these keys in `KEYMAP` you need to assign action you want at first. Action of `Fn` is defined in `fn_actions[]` and index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` designates action defined in first element of the array. ***32 `Fn` keys can be defined at most.***
305
306#### 1.4 Mousekey
307- `KC_MS_U`, `KC_MS_D`, `KC_MS_L`, `KC_MS_R` for mouse cursor
308- `KC_WH_U`, `KC_WH_D`, `KC_WH_L`, `KC_WH_R` for mouse wheel
309- `KC_BTN1`, `KC_BTN2`, `KC_BTN3`, `KC_BTN4`, `KC_BTN5` for mouse buttons
310
311#### 1.5 System & Media key
312- `KC_PWR`, `KC_SLEP`, `KC_WAKE` for Power, Sleep, Wake
313- `KC_MUTE`, `KC_VOLU`, `KC_VOLD` for audio volume control
314- `KC_MNXT`, `KC_MPRV`, `KC_MSTP`, `KC_MPLY`, `KC_MSEL` for media control
315- `KC_MAIL`, `KC_CALC`, `KC_MYCM` for application launch
316- `KC_WSCH`, `KC_WHOM`, `KC_WBAK`, `KC_WFWD`, `KC_WSTP`, `KC_WREF`, `KC_WFAV` for web browser operation
317
318#### Keycode Table
319 See [keycode table](doc/keycode.txt) in `doc/keycode.txt` or `common/keycode.h` for the detail or other keycodes.
320
321 In regard to implementation side most of keycodes are identical with [HID usage] sent to host for real and some virtual keycodes are defined to support special actions.
322[HID usage]: http://www.usb.org/developers/devclass_docs/Hut1_11.pdf
323
324
325
326### 2. Action
327See `common/action.h`. Action is a 16bit code and defines function to perform on events of a key like press, release, hold and tap. You can define various actions to use various action codes.
148 328
329Most of keys just register 8bit keycode as HID usage(or scan code) to host, but to support other complex features needs 16bit extended action codes internally. But using 16bit action codes in keymap results in double size in memory against keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP` to define instead of action codes. ***Keycodes can be considered as subset of action codes.*** Like `KC_A`(0x04) is equal to a `Key` action(0x0004) that transmit keycode of *'A'*.
330
331#### 2.1 Key action
332Key is simple action that registers keycode on press of key and unregister on release.
333You can define `Key` action on *'A'* key with:
334
335 ACTION_KEY(KC_A)
336
337But you don't need to use this expression directly because you can just put symbol `A` in `KEYMAP` definition.
338
339 Say you want to assign a key to `Shift + 1` to get charactor *'!'* or `Alt + Tab` to switch windows.
340
341 ACTION_MOD_KEY(KC_LSHIFT, KC_1)
342 ACTION_MOD_KEY(KC_LALT, KC_TAB)
343
344Or `Alt,Shift + Tab` can be defined.
345
346 ACTION_MODS_KEY((MOD_BIT(KC_LALT) | MOD_BIT(KC_LSHIFT)), KC_TAB)
347
348These actions are comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes.
349
350#### 2.2 Layer Actions
351This sets `default layer` into `current layer`. With this action you can return to `default layer`.
352
353 ACTION_LAYER_DEFAULT
354
355`Layer Set` action sets given layer argument to `current layer`. `Layer Set` action can take 0 to 15 as argument.
356
357 ACTION_LAYER_SET(layer)
358 ACTION_LAYER_SET_TOGGLE(layer)
359 ACTION_LAYER_SET_TAP_KEY(layer, key)
360 ACTION_LAYER_SET_TAP_TOGGLE(layer)
361
362`Layer Bit` action XOR bits with `current layer`. `Layer Bit` action can take 0 to 8 as argument.
363
364 ACTION_LAYER_BIT(bits)
365 ACTION_LAYER_BIT_TOGGLE(bits)
366 ACTION_LAYER_BIT_TAP_KEY(bits, key)
367 ACTION_LAYER_BIT_TAP_TOGGLE(bits)
368
369These acitons change `default layer`.
370 ACTION_LAYER_SET_DEFAULT(layer)
371 ACTION_LAYER_BIT_DEFAULT(bits)
372
373
374#### 2.3 Macro action
375***NOT FIXED***
376`Macro` action indicates complex key strokes.
377
378 MACRO( MD(LSHIFT), D(D), END )
379 MACRO( U(D), MU(LSHIFT), END )
380 MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )
381
382##### 2.3.1 Normal mode
383- **I()** change interavl of stroke.
384- **D()** press key
385- **U()** release key
386- **T()** type key(press and release)
387- **W()** wait
388- **MD()** modifier down
389- **MU()** modifier up
390- **END** end mark
391
392##### 2.3.2 Extended mode
393
394***TODO: sample impl***
395See `keyboard/hhkb/keymap.c` for sample.
396
397
398#### 2.4 Function action
399***NOT FIXED***
400There are two type of action, normal `Function` and tappable `Function`.
401These actions call user defined function with `id`, `opt`, and key event information as arguments.
402
403##### 2.4.1 Function
404To define normal `Function` action in keymap use this.
405
406 ACTION_FUNCTION(id, opt)
407
408##### 2.4.2 Function with tap
409To define tappable `Function` action in keymap use this.
410
411 ACTION_FUNCTION_TAP(id, opt)
412
413##### 2.4.3 Implement user function
414`Function` actions can be defined freely with C by user in callback function:
415
416 void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt)
417
418This C function is called every time key is operated, argument `id` selects action to be performed and `opt` can be used for option. Functon `id` can be 0-255 and `opt` can be 0-15.
419
420 `keyrecord_t` is comprised of key event and tap count. `keyevent_t` indicates which and when key is pressed or released. From `tap_count` you can know tap state, 0 means no tap. These information will be used in user function to decide how action of key is performed.
421
422 typedef struct {
423 keyevent_t event;
424 uint8_t tap_count;
425 } keyrecord_t;
426
427 typedef struct {
428 key_t key;
429 bool pressed;
430 uint16_t time;
431 } keyevent_t;
432
433 typedef struct {
434 uint8_t col;
435 uint8_t row;
436 } key_t;
437
438***TODO: sample impl***
439See `keyboard/hhkb/keymap.c` for sample.
440
441
442
443
444
445### 3. Layer
446 Layer is key-action map to assign action to every physical key. You can define multiple layers in keymap and select a layer out of keymap during operation at will.
447
448 First layer is indexed by `Layer 0` which usually become **`default layer`** and active in initial state. **`current layer`** is active layer at that time and can be changed with user interaction. You can define **16 layers** at most in default keymap framework.
449
450 you can define a layer with placing keycode symbols separated with `comma` in `KEYMAP`, which is formed with resemblance to physical keyboard layout so as you can easily put keycode on place you want to map. ***You can define most of keys with just using keycodes*** except for `Fn` key serving special actions.
451
452
453
454### 4. Layer switching
455You can have some ways to switch layer with these actions.
456There are two kind of layer switch action `Layer Set` and `Layer Bit` and two type of switching behaviour **Momentary** and **Toggle**.
457
458#### 4.1 Momentary switching
459Momentary switching changes layer only while holding Fn key.
460
461##### 4.1.1 Momentary Set
462This `Layer Set` action sets new layer `Layer 1` to `current layer` on key press event.
463
464 ACTION_LAYER_SET(1)
465
466It switches to destination layer immediately when key is pressed, after that actions on keymap of destination layer is perfomed. ***Thus you shall need to place action to come back on destination layer***, or you will be stuck in destination layer without way to get back. To get back to `default layer` you can use this action.
467
468 ACTION_LAYER_DEFAULT
469
470##### 4.1.2 Momentary Bit
471This `Layer Bit` action performs XOR `1` with `current layer` on both press and release event. If you are on `Layer 0` now next layer to switch will be `Layer 1`. To come back to previous layer you need to place same action on destination layer.
472
473 ACTION_LAYER_BIT(1)
474
475#### 4.2 Toggle switching
476Toggle switching changes layer after press then release. You keep being on the layer until you press key to return.
477
478##### 4.2.1 Toggle Set
479This `Layer Set Toggle` action is to set `Layer 1` to `current layer` on release and do none on press.
480
481 ACTION_LAYER_SET_TOGGLE(1)
482
483To get back to `default layer` you can use this action.
484
485 ACTION_LAYER_DEFAULT
486
487##### 4.2.2 Toggle Bit
488This `Layer Bit Toggle` action is to XOR `1` with `current layer` on release and do none on press. If you are on `Layer 2` you'll switch to `Layer 3` on press. To come back to previous layer you need to place same action on destination layer.
489
490 ACTION_LAYER_BIT_TOGGLE(1)
491
492
493#### 4.3 Momentary switching with Tap key
494These actions switch to layer only while holding `Fn` key and register key on tap. **Tap** means to press and release key quickly.
495
496 ACTION_LAYER_SET_TAP_KEY(2, KC_SCLN)
497 ACTION_LAYER_SET_BIT_KEY(2, KC_SCLN)
498
499With these you can place layer switching function on normal alphabet key like `;` without losing its original register function.
500
501#### 4.4 Momentary switching with Tap Toggle
502This changes layer only while holding `Fn` key and toggle layer after several taps. **Tap** means to press and release key quickly.
503
504 ACTION_LAYER_SET_TAP_TOGGLE(layer)
505 ACTION_LAYER_BIT_TAP_TOGGLE(layer)
506
507Number of taps can be defined with `TAPPING_TOGGLE` in `config.h`, `5` by default.
508
509
510
511
512Legacy Keymap
513-------------
514This was used in prior version and still works due to legacy support code in `common/keymap.c`. Legacy keymap doesn't support many of features that new keymap offers.
515
516In comparison with new keymap how to define Fn key is different. It uses two arrays `fn_layer[]` and `fn_keycode[]`. The index of arrays corresponds with postfix number of `Fn` key. Array `fn_layer[]` indicates destination layer to switch and `fn_keycode[]` has keycodes to send when tapping `Fn` key.
517
518In following setting example, `Fn0`, `Fn1` and `Fn2` switch layer to 1, 2 and 2 respectively. `Fn2` registers `Space` key when tap while `Fn0` and `Fn1` doesn't send any key.
519
520 static const uint8_t PROGMEM fn_layer[] = {
521 1, // Fn0
522 2, // Fn1
523 2, // Fn2
524 };
525
526 static const uint8_t PROGMEM fn_keycode[] = {
527 KC_NO, // Fn0
528 KC_NO, // Fn1
529 KC_SPC, // Fn2
530 };
149 531
150Build your own firmware
151-----------------------
152 532
153 533
154Debuging 534Debuging
155-------- 535--------
156Use PJRC's `hid_listen` to see debug messages and press `<COMMAND> + H` to debug menu. 536Use PJRC's `hid_listen` to see debug messages. You can use the tool for debug even if firmware use LUFA stack.
157See `config.h` for definition of `<COMMAND>` key combination. 537
538You will see output from firmware like this.
539
540 r/c 01234567
541 00: 00000000
542 01: 00000000
543 02: 00000000
544 03: 00000000
545 04: 00000000
546 05: 00000000
547 06: 00000000
548 07: 00000000
549
550 ---- action_exec: start -----
551 EVENT: 0307u(22511)
552 Tapping: Tap release(2)
553 ACTION: ACT_LAYER[5:2C]
554 LAYER_PRESSED: Tap: unregister_code
555 TAPPING_KEY=0307u(22511):2
556 processed: 0307u(22511):2
557
558 Tapping: End(Timeout after releasing last tap): FFFFu(22715)
559 TAPPING_KEY=0000u(0):0
560
561
562
158 563
564Magic Comannds
565--------------
566To see help press `Magic` + `H`.
159 567
160Other Keyboard Projects 568 `Magic` key bind may be `LShift` + `RShift` in many project, but `Power` key on ADB converter. `Magic` keybind can be vary on each project, check `config.h` in project directory.
569
570Following commands can be also executed with `Magic` + key. In console mode `Magic` keybind is not needed.
571
572 ----- Command Help -----
573 c: enter console mode
574 d: toggle debug enable
575 x: toggle matrix debug
576 k: toggle keyboard debug
577 m: toggle mouse debug
578 p: toggle print enable
579 v: print device version & info
580 t: print timer count
581 s: print status
582 0/F10: switch to Layer0
583 1/F1: switch to Layer1
584 2/F2: switch to Layer2
585 3/F3: switch to Layer3
586 4/F4: switch to Layer4
587 PScr: power down/remote wake-up
588 Caps: Lock Keyboard(Child Proof)
589 Paus: jump to bootloader
590
591### Boot Magic
592Magic commands are executed when boot time. Press `Magic` command key then pulgin.
593
594Define these macros in config.h.
595
596 IS_BOOTMAGIC_DEBUG
597 IS_BOOTMAGIC_BOOTLOADER
598
599***TODO: sample impl***
600See `keyboard/hhkb/config.h` for sample.
601
602
603
604Start Your Own Project
161----------------------- 605-----------------------
162### PJRC USB Keyboard/Mouse Example
163- <http://www.pjrc.com/teensy/usb_keyboard.html>
164- <http://www.pjrc.com/teensy/usb_mouse.html>
165 606
166### kbupgrade
167- <http://github.com/rhomann/kbupgrade>
168- <http://geekhack.org/showwiki.php?title=Island:8406>
169 607
170### c64key
171- <http://symlink.dk/projects/c64key/>
172 608
173### rump 609Files & Directories
174- <http://mg8.org/rump/> 610-------------------
175- <http://github.com/clee/rump> 611### Top
612* common/ - common codes
613* protocol/ - keyboard protocol support
614* keyboard/ - keyboard projects
615* converter/ - protocol converter projects
616* doc/ - documents
617* common.mk - Makefile for common
618* protoco.mk - Makefile for protocol
619* rules.mk - Makefile for build rules
620
621### Common
622* action.[ch]
623* action_macro.[ch]
624* bootloader.[ch]
625* command.[ch]
626* controller_teensy.h
627* debug.[ch]
628* host.[ch]
629* host_driver.h
630* keyboard.[ch]
631* keycode.h
632* keymap.[ch]
633* led.h
634* matrix.h
635* mousekey.[ch]
636* print.[ch]
637* report.h
638* sendchar.h
639* sendchar_null.c
640* sendchar_uart.c
641* timer.[ch]
642* uart.[ch]
643* util.[ch]
644
645### Keyboard Protocols
646* lufa/ - LUFA USB stack
647* pjrc/ - PJRC USB stack
648* vusb/ - Objective Development V-USB
649* iwrap/ - Bluetooth HID for Bluegiga iWRAP
650* ps2.c - PS/2 protocol
651* adb.c - Apple Desktop Bus protocol
652* m0110.c - Macintosh 128K/512K/Plus keyboard protocol
653* news.c - Sony NEWS keyboard protocol
654* x68k.c - Sharp X68000 keyboard protocol
655* serial_soft.c - Asynchronous Serial protocol implemented by software
176 656
177### dulcimer
178- <http://www.schatenseite.de/dulcimer.html>
179 657
180### humblehacker-keyboard
181- <http://github.com/humblehacker>
182- <http://www.humblehacker.com/keyboard/>
183- <http://geekhack.org/showwiki.php?title=Island:6292>
184 658
185### ps2avr 659License
186- <http://sourceforge.net/projects/ps2avr/> 660-------
661Under `GPL` 2 or later. Some protocol files are under `Modified BSD License`.
662PJRC stack has its own license.
diff --git a/common.mk b/common.mk
index 66f9fd099..86518f03f 100644
--- a/common.mk
+++ b/common.mk
@@ -1,6 +1,9 @@
1COMMON_DIR = common 1COMMON_DIR = common
2SRC += $(COMMON_DIR)/host.c \ 2SRC += $(COMMON_DIR)/host.c \
3 $(COMMON_DIR)/keyboard.c \ 3 $(COMMON_DIR)/keyboard.c \
4 $(COMMON_DIR)/action.c \
5 $(COMMON_DIR)/action_macro.c \
6 $(COMMON_DIR)/keymap.c \
4 $(COMMON_DIR)/command.c \ 7 $(COMMON_DIR)/command.c \
5 $(COMMON_DIR)/timer.c \ 8 $(COMMON_DIR)/timer.c \
6 $(COMMON_DIR)/print.c \ 9 $(COMMON_DIR)/print.c \
diff --git a/common/action.c b/common/action.c
new file mode 100644
index 000000000..6d5336752
--- /dev/null
+++ b/common/action.c
@@ -0,0 +1,883 @@
1/*
2Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17#include "host.h"
18#include "timer.h"
19#include "keymap.h"
20#include "keycode.h"
21#include "keyboard.h"
22#include "mousekey.h"
23#include "command.h"
24#include "util.h"
25#include "debug.h"
26#include "action.h"
27
28
29static void process_action(keyrecord_t *record);
30static bool process_tapping(keyrecord_t *record);
31static void waiting_buffer_scan_tap(void);
32
33static void debug_event(keyevent_t event);
34static void debug_record(keyrecord_t record);
35static void debug_action(action_t action);
36static void debug_tapping_key(void);
37static void debug_waiting_buffer(void);
38
39
40/*
41 * Tapping
42 */
43/* period of tapping(ms) */
44#ifndef TAPPING_TERM
45#define TAPPING_TERM 200
46#endif
47
48/* tap count needed for toggling a feature */
49#ifndef TAPPING_TOGGLE
50#define TAPPING_TOGGLE 5
51#endif
52
53/* stores a key event of current tap. */
54static keyrecord_t tapping_key = {};
55
56#define IS_TAPPING() !IS_NOEVENT(tapping_key.event)
57#define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
58#define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
59#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
60#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
61
62
63/*
64 * Waiting buffer
65 *
66 * stores key events waiting for settling current tap.
67 */
68#define WAITING_BUFFER_SIZE 8
69static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
70
71/* point to empty cell to enq */
72static uint8_t waiting_buffer_head = 0;
73
74/* point to the oldest data cell to deq */
75static uint8_t waiting_buffer_tail = 0;
76
77static bool waiting_buffer_enq(keyrecord_t record)
78{
79 if (IS_NOEVENT(record.event)) {
80 return true;
81 }
82
83 if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
84 debug("waiting_buffer_enq: Over flow.\n");
85 return false;
86 }
87
88 waiting_buffer[waiting_buffer_head] = record;
89 waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
90
91 debug("waiting_buffer_enq: "); debug_waiting_buffer();
92 return true;
93}
94
95static void waiting_buffer_clear(void)
96{
97 waiting_buffer_head = 0;
98 waiting_buffer_tail = 0;
99}
100
101#if TAPPING_TERM >= 500
102static bool waiting_buffer_typed(keyevent_t event)
103{
104 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
105 if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) {
106 return true;
107 }
108 }
109 return false;
110}
111#endif
112
113bool waiting_buffer_has_anykey_pressed(void)
114{
115 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
116 if (waiting_buffer[i].event.pressed) return true;
117 }
118 return false;
119}
120
121
122/* Oneshot modifier
123 *
124 * Problem: Want to capitalize like 'The' but the result tends to be 'THe'.
125 * Solution: Oneshot modifier have its effect on only one key coming next.
126 * Tap Shift, then type 't', 'h' and 'e'. Not need to hold Shift key.
127 *
128 * Hold: works as normal modifier.
129 * Tap: one shot modifier.
130 * 2 Tap: cancel one shot modifier.
131 * 5-Tap: toggles enable/disable oneshot feature.
132 */
133static struct {
134 uint8_t mods;
135 uint8_t time;
136 bool ready;
137 bool disabled;
138} oneshot_state;
139
140static void oneshot_start(uint8_t mods, uint16_t time)
141{
142 oneshot_state.mods = mods;
143 oneshot_state.time = time;
144 oneshot_state.ready = true;
145}
146
147static void oneshot_cancel(void)
148{
149 oneshot_state.mods = 0;
150 oneshot_state.time = 0;
151 oneshot_state.ready = false;
152}
153
154static void oneshot_toggle(void)
155{
156 oneshot_state.disabled = !oneshot_state.disabled;
157}
158
159
160
161void action_exec(keyevent_t event)
162{
163 if (!IS_NOEVENT(event)) {
164 debug("\n---- action_exec: start -----\n");
165 debug("EVENT: "); debug_event(event); debug("\n");
166 }
167
168 keyrecord_t record = { .event = event };
169
170 // pre-process on tapping
171 if (process_tapping(&record)) {
172 if (!IS_NOEVENT(record.event)) {
173 debug("processed: "); debug_record(record); debug("\n");
174 }
175 } else {
176 // enqueue
177 if (!waiting_buffer_enq(record)) {
178 // clear all in case of overflow.
179 debug("OVERFLOW: CLEAR ALL STATES\n");
180 clear_keyboard();
181 waiting_buffer_clear();
182 tapping_key = (keyrecord_t){};
183 }
184 }
185
186 // process waiting_buffer
187 if (!IS_NOEVENT(event) && waiting_buffer_head != waiting_buffer_tail) {
188 debug("---- action_exec: process waiting_buffer -----\n");
189 }
190
191 for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
192 if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
193 debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
194 debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n");
195 } else {
196 break;
197 }
198 }
199 if (!IS_NOEVENT(event)) {
200 debug("\n");
201 }
202}
203
204static void process_action(keyrecord_t *record)
205{
206 keyevent_t event = record->event;
207 uint8_t tap_count = record->tap_count;
208
209 if (IS_NOEVENT(event)) { return; }
210
211 action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col);
212 //debug("action: "); debug_hex16(action.code); if (event.pressed) debug("d\n"); else debug("u\n");
213 debug("ACTION: "); debug_action(action); debug("\n");
214
215 switch (action.kind.id) {
216 /* Key and Mods */
217 case ACT_LMODS:
218 case ACT_RMODS:
219 {
220 uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
221 action.key.mods<<4;
222 if (event.pressed) {
223 uint8_t tmp_mods = host_get_mods();
224 if (mods) {
225 host_add_mods(mods);
226 host_send_keyboard_report();
227 }
228 register_code(action.key.code);
229 if (mods && action.key.code) {
230 host_set_mods(tmp_mods);
231 host_send_keyboard_report();
232 }
233 } else {
234 if (mods && !action.key.code) {
235 host_del_mods(mods);
236 host_send_keyboard_report();
237 }
238 unregister_code(action.key.code);
239 }
240 }
241 break;
242 case ACT_LMODS_TAP:
243 case ACT_RMODS_TAP:
244 {
245 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
246 action.key.mods<<4;
247 switch (action.layer.code) {
248 case 0x00:
249 // Oneshot modifier
250 if (event.pressed) {
251 if (tap_count == 0) {
252 debug("MODS_TAP: Oneshot: add_mods\n");
253 add_mods(mods);
254 }
255 else if (tap_count == 1) {
256 debug("MODS_TAP: Oneshot: start\n");
257 oneshot_start(mods, event.time);
258 }
259 else if (tap_count == TAPPING_TOGGLE) {
260 debug("MODS_TAP: Oneshot: toggle\n");
261 oneshot_toggle();
262 }
263 else {
264 debug("MODS_TAP: Oneshot: cancel&add_mods\n");
265 // double tap cancels oneshot and works as normal modifier.
266 oneshot_cancel();
267 add_mods(mods);
268 }
269 } else {
270 if (tap_count == 0) {
271 debug("MODS_TAP: Oneshot: cancel/del_mods\n");
272 // cancel oneshot by holding.
273 oneshot_cancel();
274 del_mods(mods);
275 }
276 else if (tap_count == 1) {
277 debug("MODS_TAP: Oneshot: del_mods\n");
278 // retain Oneshot
279 del_mods(mods);
280 }
281 else {
282 debug("MODS_TAP: Oneshot: del_mods\n");
283 // cancel Mods
284 del_mods(mods);
285 }
286 }
287 break;
288 default:
289 if (event.pressed) {
290 if (tap_count > 0) {
291 if (waiting_buffer_has_anykey_pressed()) {
292 debug("MODS_TAP: Tap: Cancel: add_mods\n");
293 // ad hoc: set 0 to cancel tap
294 record->tap_count = 0;
295 add_mods(mods);
296 } else {
297 debug("MODS_TAP: Tap: register_code\n");
298 register_code(action.key.code);
299 }
300 } else {
301 debug("MODS_TAP: No tap: add_mods\n");
302 add_mods(mods);
303 }
304 } else {
305 if (tap_count > 0) {
306 debug("MODS_TAP: Tap: unregister_code\n");
307 unregister_code(action.key.code);
308 } else {
309 debug("MODS_TAP: No tap: add_mods\n");
310 del_mods(mods);
311 }
312 }
313 break;
314 }
315 }
316 break;
317
318 /* other HID usage */
319 case ACT_USAGE:
320#ifdef EXTRAKEY_ENABLE
321 switch (action.usage.page) {
322 case PAGE_SYSTEM:
323 if (event.pressed) {
324 host_system_send(action.usage.code);
325 } else {
326 host_system_send(0);
327 }
328 break;
329 case PAGE_CONSUMER:
330 if (event.pressed) {
331 host_consumer_send(action.usage.code);
332 } else {
333 host_consumer_send(0);
334 }
335 break;
336 }
337#endif
338 break;
339
340 /* Mouse key */
341 case ACT_MOUSEKEY:
342#ifdef MOUSEKEY_ENABLE
343 if (event.pressed) {
344 mousekey_on(action.key.code);
345 mousekey_send();
346 } else {
347 mousekey_off(action.key.code);
348 mousekey_send();
349 }
350#endif
351 break;
352
353 /* Layer key */
354 case ACT_LAYER:
355 switch (action.layer.code) {
356 case LAYER_MOMENTARY: /* momentary */
357 if (event.pressed) {
358 layer_switch(action.layer.val);
359 }
360 else {
361 layer_switch(default_layer);
362 }
363 break;
364 case LAYER_ON_PRESS:
365 if (event.pressed) {
366 layer_switch(action.layer.val);
367 }
368 break;
369 case LAYER_ON_RELEASE:
370 if (!event.pressed) {
371 layer_switch(action.layer.val);
372 }
373 break;
374 case LAYER_DEFAULT: /* default layer */
375 switch (action.layer.val) {
376 case DEFAULT_ON_BOTH:
377 layer_switch(default_layer);
378 break;
379 case DEFAULT_ON_PRESS:
380 if (event.pressed) {
381 layer_switch(default_layer);
382 }
383 break;
384 case DEFAULT_ON_RELEASE:
385 if (!event.pressed) {
386 layer_switch(default_layer);
387 }
388 break;
389 }
390 break;
391 case LAYER_TAP_TOGGLE: /* switch on hold and toggle on several taps */
392 if (event.pressed) {
393 if (tap_count < TAPPING_TOGGLE) {
394 layer_switch(action.layer.val);
395 }
396 } else {
397 if (tap_count >= TAPPING_TOGGLE) {
398 debug("LAYER_PRESSED: tap toggle.\n");
399 layer_switch(action.layer.val);
400 }
401 }
402 break;
403 case LAYER_CHANGE_DEFAULT: /* change default layer */
404 if (event.pressed) {
405 default_layer = action.layer.val;
406 layer_switch(default_layer);
407 }
408 break;
409 default: /* switch layer on hold and key on tap*/
410 if (event.pressed) {
411 if (tap_count > 0) {
412 debug("LAYER_PRESSED: Tap: register_code\n");
413 register_code(action.layer.code);
414 } else {
415 debug("LAYER_PRESSED: No tap: layer_switch\n");
416 layer_switch(action.layer.val);
417 }
418 } else {
419 if (tap_count > 0) {
420 debug("LAYER_PRESSED: Tap: unregister_code\n");
421 unregister_code(action.layer.code);
422 } else {
423 //debug("LAYER_PRESSED: No tap: NO ACTION\n");
424//TODO: this is ok?
425 debug("LAYER_PRESSED: No tap: return to default layer\n");
426 layer_switch(default_layer);
427 }
428 }
429 break;
430 }
431 break;
432 case ACT_LAYER_BIT:
433 switch (action.layer.code) {
434 case LAYER_MOMENTARY: /* momentary */
435 if (event.pressed) {
436 layer_switch(current_layer ^ action.layer.val);
437 } else {
438 layer_switch(current_layer ^ action.layer.val);
439 }
440 break;
441 case LAYER_ON_PRESS:
442 if (event.pressed) {
443 layer_switch(current_layer ^ action.layer.val);
444 }
445 break;
446 case LAYER_ON_RELEASE:
447 if (!event.pressed) {
448 layer_switch(current_layer ^ action.layer.val);
449 }
450 break;
451 case LAYER_TAP_TOGGLE: /* switch on hold and toggle on several taps */
452 if (event.pressed) {
453 if (tap_count < TAPPING_TOGGLE) {
454 debug("LAYER_BIT: tap toggle(press).\n");
455 layer_switch(current_layer ^ action.layer.val);
456 }
457 } else {
458 if (tap_count <= TAPPING_TOGGLE) {
459 debug("LAYER_BIT: tap toggle(release).\n");
460 layer_switch(current_layer ^ action.layer.val);
461 }
462 }
463 break;
464 case 0xFF:
465 // change default layer
466 if (event.pressed) {
467 default_layer = current_layer ^ action.layer.val;
468 layer_switch(default_layer);
469 } else {
470 default_layer = current_layer ^ action.layer.val;
471 layer_switch(default_layer);
472 }
473 break;
474 default:
475 // with tap key
476 if (event.pressed) {
477 if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
478 debug("LAYER_BIT: Tap: register_code\n");
479 register_code(action.layer.code);
480 } else {
481 debug("LAYER_BIT: No tap: layer_switch(bit on)\n");
482 layer_switch(current_layer ^ action.layer.val);
483 }
484 } else {
485 if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
486 debug("LAYER_BIT: Tap: unregister_code\n");
487 unregister_code(action.layer.code);
488 } else {
489 debug("LAYER_BIT: No tap: layer_switch(bit off)\n");
490 layer_switch(current_layer ^ action.layer.val);
491 }
492 }
493 break;
494 }
495 break;
496
497 /* Extentions */
498 case ACT_MACRO:
499 break;
500 case ACT_COMMAND:
501 break;
502 case ACT_FUNCTION:
503 // TODO
504 keymap_call_function(record, action.func.id, action.func.opt);
505 break;
506 default:
507 break;
508 }
509}
510
511/* Tapping
512 *
513 * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
514 * (without interfering by typing other key)
515 */
516/* return true when key event is processed or consumed. */
517static bool process_tapping(keyrecord_t *keyp)
518{
519 keyevent_t event = keyp->event;
520
521 // if tapping
522 if (IS_TAPPING_PRESSED()) {
523 if (WITHIN_TAPPING_TERM(event)) {
524 if (tapping_key.tap_count == 0) {
525 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
526 // first tap!
527 debug("Tapping: First tap(0->1).\n");
528 tapping_key.tap_count = 1;
529 debug_tapping_key();
530 process_action(&tapping_key);
531
532 // enqueue
533 keyp->tap_count = tapping_key.tap_count;
534 return false;
535 }
536#if TAPPING_TERM >= 500
537 /* This can prevent from typing some tap keys in a row at a time. */
538 else if (!event.pressed && waiting_buffer_typed(event)) {
539 // other key typed. not tap.
540 debug("Tapping: End. No tap. Interfered by typing key\n");
541 process_action(&tapping_key);
542 tapping_key = (keyrecord_t){};
543 debug_tapping_key();
544
545 // enqueue
546 return false;
547 }
548#endif
549 else {
550 // other key events shall be enq'd till tapping state settles.
551 return false;
552 }
553 }
554 // tap_count > 0
555 else {
556 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
557 debug("Tapping: Tap release("); debug_dec(tapping_key.tap_count); debug(")\n");
558 keyp->tap_count = tapping_key.tap_count;
559 process_action(keyp);
560 tapping_key = *keyp;
561 debug_tapping_key();
562 return true;
563 }
564 else if (is_tap_key(keyp->event.key) && event.pressed) {
565 if (tapping_key.tap_count > 1) {
566 debug("Tapping: Start new tap with releasing last tap(>1).\n");
567 // unregister key
568 process_action(&(keyrecord_t){
569 .tap_count = tapping_key.tap_count,
570 .event.key = tapping_key.event.key,
571 .event.time = event.time,
572 .event.pressed = false
573 });
574 } else {
575 debug("Tapping: Start while last tap(1).\n");
576 }
577 tapping_key = *keyp;
578 waiting_buffer_scan_tap();
579 debug_tapping_key();
580 return true;
581 }
582 else {
583 if (!IS_NOEVENT(keyp->event)) {
584 debug("Tapping: key event while last tap(>0).\n");
585 }
586 process_action(keyp);
587 return true;
588 }
589 }
590 }
591 // after TAPPING_TERM
592 else {
593 if (tapping_key.tap_count == 0) {
594 debug("Tapping: End. Timeout. Not tap(0): ");
595 debug_event(event); debug("\n");
596 process_action(&tapping_key);
597 tapping_key = (keyrecord_t){};
598 debug_tapping_key();
599 return false;
600 } else {
601 if (IS_TAPPING_KEY(event.key) && !event.pressed) {
602 debug("Tapping: End. last timeout tap release(>0).");
603 keyp->tap_count = tapping_key.tap_count;
604 process_action(keyp);
605 tapping_key = (keyrecord_t){};
606 return true;
607 }
608 else if (is_tap_key(keyp->event.key) && event.pressed) {
609 if (tapping_key.tap_count > 1) {
610 debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
611 // unregister key
612 process_action(&(keyrecord_t){
613 .tap_count = tapping_key.tap_count,
614 .event.key = tapping_key.event.key,
615 .event.time = event.time,
616 .event.pressed = false
617 });
618 } else {
619 debug("Tapping: Start while last timeout tap(1).\n");
620 }
621 tapping_key = *keyp;
622 waiting_buffer_scan_tap();
623 debug_tapping_key();
624 return true;
625 }
626 else {
627 if (!IS_NOEVENT(keyp->event)) {
628 debug("Tapping: key event while last timeout tap(>0).\n");
629 }
630 process_action(keyp);
631 return true;
632 }
633 }
634 }
635 } else if (IS_TAPPING_RELEASED()) {
636 if (WITHIN_TAPPING_TERM(event)) {
637 if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
638 // sequential tap.
639 keyp->tap_count = tapping_key.tap_count + 1;
640 debug("Tapping: Tap press("); debug_dec(keyp->tap_count); debug(")\n");
641 process_action(keyp);
642 tapping_key = *keyp;
643 debug_tapping_key();
644 return true;
645 } else if (event.pressed && is_tap_key(event.key)) {
646 // Sequential tap can be interfered with other tap key.
647 debug("Tapping: Start with interfering other tap.\n");
648 tapping_key = *keyp;
649 waiting_buffer_scan_tap();
650 debug_tapping_key();
651 return true;
652 } else {
653 if (!IS_NOEVENT(keyp->event)) debug("Tapping: other key just after tap.\n");
654 process_action(keyp);
655 return true;
656 }
657 } else {
658 // timeout. no sequential tap.
659 debug("Tapping: End(Timeout after releasing last tap): ");
660 debug_event(event); debug("\n");
661 tapping_key = (keyrecord_t){};
662 debug_tapping_key();
663 return false;
664 }
665 }
666 // not tapping satate
667 else {
668 if (event.pressed && is_tap_key(event.key)) {
669 debug("Tapping: Start(Press tap key).\n");
670 tapping_key = *keyp;
671 waiting_buffer_scan_tap();
672 debug_tapping_key();
673 return true;
674 } else {
675 process_action(keyp);
676 return true;
677 }
678 }
679}
680
681/* scan buffer for tapping */
682static void waiting_buffer_scan_tap(void)
683{
684 // tapping already is settled
685 if (tapping_key.tap_count > 0) return;
686 // invalid state: tapping_key released && tap_count == 0
687 if (!tapping_key.event.pressed) return;
688
689 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
690 if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
691 !waiting_buffer[i].event.pressed &&
692 WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
693 tapping_key.tap_count = 1;
694 waiting_buffer[i].tap_count = 1;
695 process_action(&tapping_key);
696
697 debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
698 debug_waiting_buffer();
699 return;
700 }
701 }
702}
703
704
705
706/*
707 * Utilities for actions.
708 */
709void register_code(uint8_t code)
710{
711 if (code == KC_NO) {
712 return;
713 }
714 else if IS_KEY(code) {
715 // TODO: should push command_proc out of this block?
716 if (command_proc(code)) return;
717
718 if (oneshot_state.mods && oneshot_state.ready && !oneshot_state.disabled) {
719 uint8_t tmp_mods = host_get_mods();
720 host_add_mods(oneshot_state.mods);
721 host_add_key(code);
722 host_send_keyboard_report();
723
724 host_set_mods(tmp_mods);
725 oneshot_state.ready = false;
726 } else {
727 host_add_key(code);
728 host_send_keyboard_report();
729 }
730 }
731 else if IS_MOD(code) {
732 host_add_mods(MOD_BIT(code));
733 host_send_keyboard_report();
734 }
735}
736
737void unregister_code(uint8_t code)
738{
739 if IS_KEY(code) {
740 host_del_key(code);
741 host_send_keyboard_report();
742 }
743 else if IS_MOD(code) {
744 host_del_mods(MOD_BIT(code));
745 host_send_keyboard_report();
746 }
747}
748
749void add_mods(uint8_t mods)
750{
751 if (mods) {
752 host_add_mods(mods);
753 host_send_keyboard_report();
754 }
755}
756
757void del_mods(uint8_t mods)
758{
759 if (mods) {
760 host_del_mods(mods);
761 host_send_keyboard_report();
762 }
763}
764
765void set_mods(uint8_t mods)
766{
767 host_set_mods(mods);
768 host_send_keyboard_report();
769}
770
771void clear_keyboard(void)
772{
773 host_clear_mods();
774 clear_keyboard_but_mods();
775}
776
777void clear_keyboard_but_mods(void)
778{
779 host_clear_keys();
780 host_send_keyboard_report();
781#ifdef MOUSEKEY_ENABLE
782 mousekey_clear();
783 mousekey_send();
784#endif
785#ifdef EXTRAKEY_ENABLE
786 host_system_send(0);
787 host_consumer_send(0);
788#endif
789}
790
791bool sending_anykey(void)
792{
793 return (host_has_anykey() || host_mouse_in_use() ||
794 host_last_sysytem_report() || host_last_consumer_report());
795}
796
797void layer_switch(uint8_t new_layer)
798{
799 if (current_layer != new_layer) {
800 debug("Layer Switch: "); debug_hex(current_layer);
801 debug(" -> "); debug_hex(new_layer); debug("\n");
802
803 current_layer = new_layer;
804 clear_keyboard_but_mods(); // To avoid stuck keys
805 // NOTE: update mods with full scan of matrix? if modifier changes between layers
806 }
807}
808
809bool is_tap_key(key_t key)
810{
811 action_t action = keymap_get_action(current_layer, key.pos.row, key.pos.col);
812 switch (action.kind.id) {
813 case ACT_LMODS_TAP:
814 case ACT_RMODS_TAP:
815 return true;
816 case ACT_LAYER:
817 case ACT_LAYER_BIT:
818 switch (action.layer.code) {
819 case LAYER_MOMENTARY:
820 case LAYER_ON_PRESS:
821 case LAYER_ON_RELEASE:
822 case LAYER_DEFAULT:
823 return false;
824 case LAYER_TAP_TOGGLE:
825 default: /* tap key */
826 return true;
827 }
828 return false;
829 case ACT_FUNCTION:
830 if (action.func.opt & FUNC_TAP) { return true; }
831 return false;
832 }
833 return false;
834}
835
836
837/*
838 * debug print
839 */
840static void debug_event(keyevent_t event)
841{
842 debug_hex16(event.key.raw);
843 if (event.pressed) debug("d("); else debug("u(");
844 debug_dec(event.time); debug(")");
845}
846static void debug_record(keyrecord_t record)
847{
848 debug_event(record.event); debug(":"); debug_dec(record.tap_count);
849}
850static void debug_action(action_t action)
851{
852 switch (action.kind.id) {
853 case ACT_LMODS: debug("ACT_LMODS"); break;
854 case ACT_RMODS: debug("ACT_RMODS"); break;
855 case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break;
856 case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break;
857 case ACT_USAGE: debug("ACT_USAGE"); break;
858 case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break;
859 case ACT_LAYER: debug("ACT_LAYER"); break;
860 case ACT_LAYER_BIT: debug("ACT_LAYER_BIT"); break;
861 case ACT_MACRO: debug("ACT_MACRO"); break;
862 case ACT_COMMAND: debug("ACT_COMMAND"); break;
863 case ACT_FUNCTION: debug("ACT_FUNCTION"); break;
864 default: debug("UNKNOWN"); break;
865 }
866 debug("[");
867 debug_hex4(action.kind.param>>8);
868 debug(":");
869 debug_hex8(action.kind.param & 0xff);
870 debug("]");
871}
872static void debug_tapping_key(void)
873{
874 debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n");
875}
876static void debug_waiting_buffer(void)
877{
878 debug("{ ");
879 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
880 debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" ");
881 }
882 debug("}\n");
883}
diff --git a/common/action.h b/common/action.h
new file mode 100644
index 000000000..9b559cb18
--- /dev/null
+++ b/common/action.h
@@ -0,0 +1,331 @@
1/*
2Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17#ifndef ACTION_H
18#define ACTION_H
19
20#include "keyboard.h"
21#include "keycode.h"
22
23
24/* Execute action per keyevent */
25void action_exec(keyevent_t event);
26
27
28/* Struct to record event and tap count */
29typedef struct {
30 keyevent_t event;
31 uint8_t tap_count;
32} keyrecord_t;
33
34/* Action struct.
35 *
36 * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
37 * AVR looks like a little endian in avr-gcc.
38 *
39 * NOTE: not portable across compiler/endianness?
40 * Byte order and bit order of 0x1234:
41 * Big endian: 15 ... 8 7 ... 210
42 * | 0x12 | 0x34 |
43 * 0001 0010 0011 0100
44 * Little endian: 012 ... 7 8 ... 15
45 * | 0x34 | 0x12 |
46 * 0010 1100 0100 1000
47 */
48typedef union {
49 uint16_t code;
50 struct action_kind {
51 uint16_t param :12;
52 uint8_t id :4;
53 } kind;
54 struct action_key {
55 uint8_t code :8;
56 uint8_t mods :4;
57 uint8_t kind :4;
58 } key;
59 struct action_layer {
60 uint8_t code :8;
61 uint8_t val :4;
62 uint8_t kind :4;
63 } layer;
64 struct action_usage {
65 uint16_t code :10;
66 uint8_t page :2;
67 uint8_t kind :4;
68 } usage;
69 struct action_command {
70 uint8_t id :8;
71 uint8_t opt :4;
72 uint8_t kind :4;
73 } command;
74 struct action_function {
75 uint8_t id :8;
76 uint8_t opt :4;
77 uint8_t kind :4;
78 } func;
79} action_t;
80
81
82/*
83 * Utilities for actions.
84 */
85void register_code(uint8_t code);
86void unregister_code(uint8_t code);
87void add_mods(uint8_t mods);
88void del_mods(uint8_t mods);
89void set_mods(uint8_t mods);
90void clear_keyboard(void);
91void clear_keyboard_but_mods(void);
92bool sending_anykey(void);
93void layer_switch(uint8_t new_layer);
94bool is_tap_key(key_t key);
95bool waiting_buffer_has_anykey_pressed(void);
96
97
98
99
100/*
101 * Action codes
102 * ============
103 * 16bit code: action_kind(4bit) + action_parameter(12bit)
104 *
105Keyboard Keys
106-------------
107ACT_LMODS(0000):
1080000|0000|000000|00 No action
1090000|0000| keycode Key
1100000|mods|000000|00 Left mods
1110000|mods| keycode Key & Left mods
112
113ACT_RMODS(0001):
1140001|0000|000000|00 No action
1150001|0000| keycode Key(no used)
1160001|mods|000000|00 Right mods
1170001|mods| keycode Key & Right mods
118
119ACT_LMODS_TAP(0010):
1200010|mods|000000|00 Left mods OneShot
1210010|mods|000000|01 (reserved)
1220010|mods|000000|10 (reserved)
1230010|mods|000000|11 (reserved)
1240010|mods| keycode Left mods + tap Key
125
126ACT_RMODS_TAP(0011):
1270011|mods|000000|00 Right mods OneShot
1280011|mods|000000|01 (reserved)
1290011|mods|000000|10 (reserved)
1300011|mods|000000|11 (reserved)
1310011|mods| keycode Right mods + tap Key
132
133
134Other HID Usage
135---------------
136This action handles other usages than keyboard.
137ACT_USAGE(0100):
1380100|00| usage(10) System control(0x80) - General Desktop page(0x01)
1390100|01| usage(10) Consumer control(0x01) - Consumer page(0x0C)
1400100|10| usage(10) (reserved)
1410100|11| usage(10) (reserved)
142
143
144Mouse Keys
145----------
146TODO: can be combined with 'Other HID Usage'? to save action kind id.
147ACT_MOUSEKEY(0110):
1480101|XXXX| keycode Mouse key
149
150
151Layer Actions
152-------------
153ACT_LAYER(1000): Set layer
154ACT_LAYER_BIT(1001): Bit-op layer
155
1561000|LLLL|0000 0000 set L to layer on press and set default on release(momentary)
1571000|LLLL|0000 0001 set L to layer on press
1581000|LLLL|0000 0010 set L to layer on release
1591000|----|0000 0011 set default to layer on both(return to default layer)
1601000|LLLL|xxxx xxxx set L to layer while hold and send key on tap
1611000|LLLL|1111 0000 set L to layer while hold and toggle on several taps
1621000|LLLL|1111 1111 set L to default and layer(on press)
163
1641001|BBBB|0000 0000 (not used)
1651001|BBBB|0000 0001 bit-xor layer with B on press
1661001|BBBB|0000 0010 bit-xor layer with B on release
1671001|BBBB|0000 0011 bit-xor layer with B on both(momentary)
1681001|BBBB|xxxx xxxx bit-xor layer with B while hold and send key on tap
1691001|BBBB|1111 0000 bit-xor layer with B while hold and toggle on several taps
1701001|BBBB|1111 1111 bit-xor default with B and set layer(on press)
171
172
173
174Extensions(11XX)
175----------------
176NOTE: NOT FIXED
177
178ACT_MACRO(1100):
1791100|opt | id(8) Macro play?
1801100|1111| id(8) Macro record?
181
182ACT_COMMAND(1110):
1831110|opt | id(8) Built-in Command exec
184
185ACT_FUNCTION(1111):
1861111| address(12) Function?
1871111|opt | id(8) Function?
188
189 */
190enum action_kind_id {
191 ACT_LMODS = 0b0000,
192 ACT_RMODS = 0b0001,
193 ACT_LMODS_TAP = 0b0010,
194 ACT_RMODS_TAP = 0b0011,
195
196 ACT_USAGE = 0b0100,
197 ACT_MOUSEKEY = 0b0101,
198
199 ACT_LAYER = 0b1000,
200 ACT_LAYER_BIT = 0b1001,
201
202 ACT_MACRO = 0b1100,
203 ACT_COMMAND = 0b1110,
204 ACT_FUNCTION = 0b1111
205};
206
207
208/* action utility */
209#define ACTION_NO 0
210#define ACTION(kind, param) ((kind)<<12 | (param))
211#define MODS4(mods) (((mods)>>4 | (mods)) & 0x0F)
212
213/* Key */
214#define ACTION_KEY(key) ACTION(ACT_LMODS, key)
215/* Mods & key */
216#define ACTION_LMODS(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x00)
217#define ACTION_LMODS_KEY(mods, key) ACTION(ACT_LMODS, (mods)<<8 | (key))
218#define ACTION_RMODS(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x00)
219#define ACTION_RMODS_KEY(mods, key) ACTION(ACT_RMODS, (mods)<<8 | (key))
220/* Mod & key */
221#define ACTION_LMOD(mod) ACTION(ACT_LMODS, MODS4(MOD_BIT(mod))<<8 | 0x00)
222#define ACTION_LMOD_KEY(mod, key) ACTION(ACT_LMODS, MODS4(MOD_BIT(mod))<<8 | (key))
223#define ACTION_RMOD(mod) ACTION(ACT_RMODS, MODS4(MOD_BIT(mod))<<8 | 0x00)
224#define ACTION_RMOD_KEY(mod, key) ACTION(ACT_RMODS, MODS4(MOD_BIT(mod))<<8 | (key))
225
226/* Mods + Tap key */
227enum mods_codes {
228 MODS_ONESHOT = 0x00,
229};
230#define ACTION_LMODS_TAP_KEY(mods, key) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | (key))
231#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | MODS_ONESHOT)
232#define ACTION_RMODS_TAP_KEY(mods, key) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | (key))
233#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | MODS_ONESHOT)
234/* Mod + Tap key */
235#define ACTION_LMOD_TAP_KEY(mod, key) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key))
236#define ACTION_LMOD_ONESHOT(mod) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | MODS_ONESHOT)
237#define ACTION_RMOD_TAP_KEY(mod, key) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key))
238#define ACTION_RMOD_ONESHOT(mod) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | MODS_ONESHOT)
239
240
241/*
242 * Switch layer
243 */
244enum layer_codes {
245 LAYER_MOMENTARY = 0,
246 LAYER_ON_PRESS = 1,
247 LAYER_ON_RELEASE = 2,
248 LAYER_DEFAULT =3,
249 LAYER_TAP_TOGGLE = 0xF0,
250 LAYER_CHANGE_DEFAULT = 0xFF
251};
252enum layer_vals_default {
253 DEFAULT_ON_PRESS = 1,
254 DEFAULT_ON_RELEASE = 2,
255 DEFAULT_ON_BOTH = 3,
256};
257
258/*
259 * return to default layer
260 */
261#define ACTION_LAYER_DEFAULT ACTION_LAYER_DEFAULT_R
262/* set default layer on press */
263#define ACTION_LAYER_DEFAULT_P ACTION(ACT_LAYER, DEFAULT_ON_PRESS<<8 | LAYER_DEFAULT)
264/* set default layer on release */
265#define ACTION_LAYER_DEFAULT_R ACTION(ACT_LAYER, DEFAULT_ON_RELEASE<<8 | LAYER_DEFAULT)
266/* change default layer and set layer */
267
268/*
269 * Set layer
270 */
271/* set layer on press and set default on release */
272#define ACTION_LAYER_SET(layer) ACTION_LAYER_SET_MOMENTARY(layer)
273#define ACTION_LAYER_SET_MOMENTARY(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_MOMENTARY)
274/* set layer on press and none on release */
275#define ACTION_LAYER_SET_TOGGLE(layer) ACTION_LAYER_SET_R(layer)
276/* set layer while hold and send key on tap */
277#define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER, (layer)<<8 | (key))
278/* set layer on press */
279#define ACTION_LAYER_SET_P(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_ON_PRESS)
280/* set layer on release */
281#define ACTION_LAYER_SET_R(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_ON_RELEASE)
282/* set layer on hold and toggle on several taps */
283#define ACTION_LAYER_SET_TAP_TOGGLE(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_TAP_TOGGLE)
284/* set default layer on both press and release */
285#define ACTION_LAYER_SET_DEFAULT(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_CHANGE_DEFAULT)
286
287/*
288 * Bit-op layer
289 */
290/* bit-xor on both press and release */
291#define ACTION_LAYER_BIT(bits) ACTION_LAYER_BIT_MOMENTARY(bits)
292#define ACTION_LAYER_BIT_MOMENTARY(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_MOMENTARY)
293/* bit-xor on press */
294#define ACTION_LAYER_BIT_TOGGLE(bits) ACTION_LAYER_BIT_R(bits)
295/* bit-xor while hold and send key on tap */
296#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (bits)<<8 | (key))
297/* bit-xor on press */
298#define ACTION_LAYER_BIT_P(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_ON_PRESS)
299/* bit-xor on release */
300#define ACTION_LAYER_BIT_R(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_ON_RELEASE)
301/* bit-xor while hold and toggle on several taps */
302#define ACTION_LAYER_BIT_TAP_TOGGLE(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_TAP_TOGGLE)
303/* bit-xor default layer and set layer */
304#define ACTION_LAYER_BIT_DEFAULT(bits) ACTION(ACT_LAYER, (bits)<<8 | LAYER_CHANGE_DEFAULT)
305
306
307/* HID Usage */
308enum usage_pages {
309 PAGE_SYSTEM,
310 PAGE_CONSUMER
311};
312#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM<<10 | (id))
313#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER<<10 | (id))
314
315/* Mousekey */
316#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key)
317
318/* Macro */
319#define ACTION_MACRO(opt, id) ACTION(ACT_FUNCTION, (opt)<<8 | (addr))
320
321/* Command */
322#define ACTION_COMMAND(opt, id) ACTION(ACT_COMMAND, (opt)<<8 | (addr))
323
324/* Function */
325enum function_opts {
326 FUNC_TAP = 0x8, /* indciates function is tappable */
327};
328#define ACTION_FUNCTION(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | id)
329#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | id)
330
331#endif /* ACTION_H */
diff --git a/common/action_macro.c b/common/action_macro.c
new file mode 100644
index 000000000..72859c0dd
--- /dev/null
+++ b/common/action_macro.c
@@ -0,0 +1,67 @@
1/*
2Copyright 2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17#include <util/delay.h>
18#include "debug.h"
19#include "action.h"
20#include "action_macro.h"
21
22
23#define MACRO_READ() (macro = pgm_read_byte(macro_p++))
24void action_macro_play(const prog_macro_t *macro_p)
25{
26 macro_t macro = END;
27 uint8_t interval = 0;
28
29 if (!macro_p) return;
30 while (true) {
31 switch (MACRO_READ()) {
32 case INTERVAL:
33 interval = MACRO_READ();
34 debug("INTERVAL("); debug_dec(interval); debug(")\n");
35 break;
36 case WAIT:
37 MACRO_READ();
38 debug("WAIT("); debug_dec(macro); debug(")\n");
39 { uint8_t ms = macro; while (ms--) _delay_ms(1); }
40 break;
41 case MODS_DOWN:
42 MACRO_READ();
43 debug("MODS_DOWN("); debug_hex(macro); debug(")\n");
44 debug("MODS_UP("); debug_hex(macro); debug(")\n");
45 add_mods(macro);
46 break;
47 case MODS_UP:
48 MACRO_READ();
49 debug("MODS_UP("); debug_hex(macro); debug(")\n");
50 del_mods(macro);
51 break;
52 case 0x04 ... 0x73:
53 debug("DOWN("); debug_hex(macro); debug(")\n");
54 register_code(macro);
55 break;
56 case 0x84 ... 0xF3:
57 debug("UP("); debug_hex(macro); debug(")\n");
58 unregister_code(macro&0x7F);
59 break;
60 case END:
61 default:
62 return;
63 }
64 // interval
65 { uint8_t ms = interval; while (ms--) _delay_ms(1); }
66 }
67}
diff --git a/common/action_macro.h b/common/action_macro.h
new file mode 100644
index 000000000..3833c7c8a
--- /dev/null
+++ b/common/action_macro.h
@@ -0,0 +1,107 @@
1/*
2Copyright 2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17#ifndef ACTION_MACRO_H
18#define ACTION_MACRO_H
19#include <stdint.h>
20#include <avr/pgmspace.h>
21
22
23typedef uint8_t macro_t;
24typedef macro_t prog_macro_t PROGMEM;
25
26
27void action_macro_play(const prog_macro_t *macro);
28
29
30
31/* TODO: NOT FINISHED
32normal mode command:
33 key(down): 0x04-7f/73(F24)
34 key(up): 0x84-ff
35command: 0x00-03, 0x80-83(0x74-7f, 0xf4-ff)
36 mods down 0x00
37 mods up 0x01
38 wait 0x02
39 interval 0x03
40 extkey down 0x80
41 extkey up 0x81
42 ext commad 0x82
43 ext mode 0x83
44 end 0xff
45
46extension mode command: NOT IMPLEMENTED
47 key down 0x00
48 key up 0x01
49 key down + wait
50 key up + wait
51 mods push
52 mods pop
53 wait
54 interval
55 if
56 loop
57 push
58 pop
59 all up
60 end
61*/
62enum macro_command_id{
63 /* 0x00 - 0x03 */
64 END = 0x00,
65 MODS_DOWN = 0x01,
66 MODS_UP = 0x02,
67 MODS_SET,
68 MODS_PUSH,
69 MODS_POP,
70
71 WAIT = 0x74,
72 INTERVAL,
73 /* 0x74 - 0x7f */
74 /* 0x80 - 0x84 */
75
76 EXT_DOWN,
77 EXT_UP,
78 EXT_WAIT,
79 EXT_INTERVAL,
80 COMPRESSION_MODE,
81
82 EXTENSION_MODE = 0xff,
83};
84
85
86/* normal mode */
87#define DOWN(key) (key)
88#define UP(key) ((key) | 0x80)
89#define TYPE(key) (key), (key | 0x80)
90#define MODS_DOWN(mods) MODS_DOWN, (mods)
91#define MODS_UP(mods) MODS_UP, (mods)
92#define WAIT(ms) WAIT, (ms)
93#define INTERVAL(ms) INTERVAL, (ms)
94
95#define D(key) DOWN(KC_##key)
96#define U(key) UP(KC_##key)
97#define T(key) TYPE(KC_##key)
98#define MD(key) MODS_DOWN(MOD_BIT(KC_##key))
99#define MU(key) MODS_UP(MOD_BIT(KC_##key))
100#define W(ms) WAIT(ms)
101#define I(ms) INTERVAL(ms)
102
103
104/* extension mode */
105
106
107#endif /* ACTION_MACRO_H */
diff --git a/common/command.c b/common/command.c
index 5cdd168d4..6d4e4c642 100644
--- a/common/command.c
+++ b/common/command.c
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
19#include <util/delay.h> 19#include <util/delay.h>
20#include "keycode.h" 20#include "keycode.h"
21#include "host.h" 21#include "host.h"
22#include "keymap.h"
22#include "print.h" 23#include "print.h"
23#include "debug.h" 24#include "debug.h"
24#include "util.h" 25#include "util.h"
@@ -53,7 +54,6 @@ static void mousekey_console_help(void);
53 54
54static uint8_t numkey2num(uint8_t code); 55static uint8_t numkey2num(uint8_t code);
55static void switch_layer(uint8_t layer); 56static void switch_layer(uint8_t layer);
56static void clear_keyboard(void);
57 57
58 58
59typedef enum { ONESHOT, CONSOLE, MOUSEKEY } cmdstate_t; 59typedef enum { ONESHOT, CONSOLE, MOUSEKEY } cmdstate_t;
@@ -556,18 +556,3 @@ static void switch_layer(uint8_t layer)
556 default_layer = layer; 556 default_layer = layer;
557 print("switch to "); print_val_hex8(layer); 557 print("switch to "); print_val_hex8(layer);
558} 558}
559
560static void clear_keyboard(void)
561{
562 host_clear_keys();
563 host_clear_mods();
564 host_send_keyboard_report();
565
566 host_system_send(0);
567 host_consumer_send(0);
568
569#ifdef MOUSEKEY_ENABLE
570 mousekey_clear();
571 mousekey_send();
572#endif
573}
diff --git a/common/debug.h b/common/debug.h
index 648f0e096..e63d46f0e 100644
--- a/common/debug.h
+++ b/common/debug.h
@@ -36,6 +36,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
36 36
37#define debug_dec(data) do { if (debug_enable) print_dec(data); } while (0) 37#define debug_dec(data) do { if (debug_enable) print_dec(data); } while (0)
38#define debug_decs(data) do { if (debug_enable) print_decs(data); } while (0) 38#define debug_decs(data) do { if (debug_enable) print_decs(data); } while (0)
39#define debug_hex4(data) do { if (debug_enable) print_hex4(data); } while (0)
39#define debug_hex8(data) do { if (debug_enable) print_hex8(data); } while (0) 40#define debug_hex8(data) do { if (debug_enable) print_hex8(data); } while (0)
40#define debug_hex16(data) do { if (debug_enable) print_hex16(data); } while (0) 41#define debug_hex16(data) do { if (debug_enable) print_hex16(data); } while (0)
41#define debug_hex32(data) do { if (debug_enable) print_hex32(data); } while (0) 42#define debug_hex32(data) do { if (debug_enable) print_hex32(data); } while (0)
diff --git a/common/host.c b/common/host.c
index 261ec6472..6ed3d780f 100644
--- a/common/host.c
+++ b/common/host.c
@@ -127,14 +127,19 @@ void host_clear_keys(void)
127 } 127 }
128} 128}
129 129
130void host_add_mod_bit(uint8_t mod) 130uint8_t host_get_mods(void)
131{ 131{
132 keyboard_report->mods |= mod; 132 return keyboard_report->mods;
133} 133}
134 134
135void host_del_mod_bit(uint8_t mod) 135void host_add_mods(uint8_t mods)
136{ 136{
137 keyboard_report->mods &= ~mod; 137 keyboard_report->mods |= mods;
138}
139
140void host_del_mods(uint8_t mods)
141{
142 keyboard_report->mods &= ~mods;
138} 143}
139 144
140void host_set_mods(uint8_t mods) 145void host_set_mods(uint8_t mods)
diff --git a/common/host.h b/common/host.h
index 841798796..7c4f06601 100644
--- a/common/host.h
+++ b/common/host.h
@@ -52,10 +52,13 @@ void host_consumer_send(uint16_t data);
52void host_add_key(uint8_t key); 52void host_add_key(uint8_t key);
53void host_del_key(uint8_t key); 53void host_del_key(uint8_t key);
54void host_clear_keys(void); 54void host_clear_keys(void);
55void host_add_mod_bit(uint8_t mod); 55
56void host_del_mod_bit(uint8_t mod); 56uint8_t host_get_mods(void);
57void host_add_mods(uint8_t mods);
58void host_del_mods(uint8_t mods);
57void host_set_mods(uint8_t mods); 59void host_set_mods(uint8_t mods);
58void host_clear_mods(void); 60void host_clear_mods(void);
61
59uint8_t host_has_anykey(void); 62uint8_t host_has_anykey(void);
60uint8_t host_has_anymod(void); 63uint8_t host_has_anymod(void);
61uint8_t host_get_first_key(void); 64uint8_t host_get_first_key(void);
diff --git a/common/keyboard.c b/common/keyboard.c
index 2dee51d4b..5e9945baf 100644
--- a/common/keyboard.c
+++ b/common/keyboard.c
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright 2011,2012 Jun Wako <wakojun@gmail.com> 2Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
3 3
4This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
@@ -26,536 +26,39 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
26#include "command.h" 26#include "command.h"
27#include "util.h" 27#include "util.h"
28#include "sendchar.h" 28#include "sendchar.h"
29#include "bootloader.h"
29#ifdef MOUSEKEY_ENABLE 30#ifdef MOUSEKEY_ENABLE
30#include "mousekey.h" 31#include "mousekey.h"
31#endif 32#endif
32 33
33 34
34#define Kdebug(s) do { if (debug_keyboard) debug(s); } while(0)
35#define Kdebug_P(s) do { if (debug_keyboard) debug_P(s); } while(0)
36#define Kdebug_hex(s) do { if (debug_keyboard) debug_hex(s); } while(0)
37
38#define LAYER_DELAY 250
39
40typedef enum keykind {
41 NONE,
42 FN_DOWN, FN_UP,
43 FNK_DOWN, FNK_UP,
44 KEY_DOWN, KEY_UP,
45 MOD_DOWN, MOD_UP,
46} keykind_t;
47
48typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
49
50
51#ifdef KEYMAP_DEFAULT_LAYER
52uint8_t default_layer = KEYMAP_DEFAULT_LAYER;
53uint8_t current_layer = KEYMAP_DEFAULT_LAYER;
54#else
55uint8_t default_layer = 0;
56uint8_t current_layer = 0;
57#endif
58
59/* keyboard internal states */
60static kbdstate_t kbdstate = IDLE;
61static uint8_t fn_state_bits = 0;
62static keyrecord_t delayed_fn;
63static keyrecord_t waiting_key;
64
65
66static const char *state_str(kbdstate_t state)
67{
68 if (state == IDLE) return PSTR("IDLE");
69 if (state == DELAYING) return PSTR("DELAYING");
70 if (state == WAITING) return PSTR("WAITING");
71 if (state == PRESSING) return PSTR("PRESSING");
72 return PSTR("UNKNOWN");
73}
74
75static inline keykind_t get_keykind(uint8_t code, bool pressed)
76{
77 if IS_KEY(code) return (pressed ? KEY_DOWN : KEY_UP);
78 if IS_MOD(code) return (pressed ? MOD_DOWN : MOD_UP);
79 if IS_FN(code) {
80 if (keymap_fn_keycode(FN_INDEX(code)))
81 return (pressed ? FNK_DOWN : FNK_UP);
82 else
83 return (pressed ? FN_DOWN : FN_UP);
84 }
85 if IS_MOUSEKEY(code) return (pressed ? KEY_DOWN : KEY_UP);
86 if IS_SYSTEM(code) return (pressed ? KEY_DOWN : KEY_UP);
87 if IS_CONSUMER(code) return (pressed ? KEY_DOWN : KEY_UP);
88 return NONE;
89}
90
91static void clear_keyboard(void)
92{
93 host_clear_keys();
94 host_clear_mods();
95 host_send_keyboard_report();
96
97 host_system_send(0);
98 host_consumer_send(0);
99
100#ifdef MOUSEKEY_ENABLE
101 mousekey_clear();
102 mousekey_send();
103#endif
104}
105
106static void clear_keyboard_but_mods(void)
107{
108 host_clear_keys();
109 host_send_keyboard_report();
110
111 host_system_send(0);
112 host_consumer_send(0);
113
114#ifdef MOUSEKEY_ENABLE
115 mousekey_clear();
116 mousekey_send();
117#endif
118}
119
120static bool anykey_sent_to_host(void)
121{
122 return (host_has_anykey() || host_mouse_in_use() ||
123 host_last_sysytem_report() || host_last_consumer_report());
124}
125
126static void layer_switch_on(uint8_t code)
127{
128 if (!IS_FN(code)) return;
129 fn_state_bits |= FN_BIT(code);
130 uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer);
131 if (current_layer != new_layer) {
132 Kdebug("Layer Switch(on): "); Kdebug_hex(current_layer);
133 Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");
134
135 clear_keyboard_but_mods();
136 current_layer = new_layer;
137 }
138}
139
140static bool layer_switch_off(uint8_t code)
141{
142 if (!IS_FN(code)) return false;
143 fn_state_bits &= ~FN_BIT(code);
144 uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer);
145 if (current_layer != new_layer) {
146 Kdebug("Layer Switch(off): "); Kdebug_hex(current_layer);
147 Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");
148
149 clear_keyboard_but_mods();
150 current_layer = new_layer;
151 return true;
152 }
153 return false;
154}
155
156static void register_code(uint8_t code)
157{
158 if IS_KEY(code) {
159 if (!command_proc(code)) {
160 host_add_key(code);
161 host_send_keyboard_report();
162 }
163 }
164 else if IS_MOD(code) {
165 host_add_mod_bit(MOD_BIT(code));
166 host_send_keyboard_report();
167 }
168 else if IS_FN(code) {
169 if (!command_proc(keymap_fn_keycode(FN_INDEX(code)))) {
170 host_add_key(keymap_fn_keycode(FN_INDEX(code)));
171 host_send_keyboard_report();
172 }
173 }
174 else if IS_MOUSEKEY(code) {
175#ifdef MOUSEKEY_ENABLE
176 mousekey_on(code);
177 mousekey_send();
178#endif
179 }
180 else if IS_CONSUMER(code) {
181 uint16_t usage = 0;
182 switch (code) {
183 case KC_AUDIO_MUTE:
184 usage = AUDIO_MUTE;
185 break;
186 case KC_AUDIO_VOL_UP:
187 usage = AUDIO_VOL_UP;
188 break;
189 case KC_AUDIO_VOL_DOWN:
190 usage = AUDIO_VOL_DOWN;
191 break;
192 case KC_MEDIA_NEXT_TRACK:
193 usage = TRANSPORT_NEXT_TRACK;
194 break;
195 case KC_MEDIA_PREV_TRACK:
196 usage = TRANSPORT_PREV_TRACK;
197 break;
198 case KC_MEDIA_STOP:
199 usage = TRANSPORT_STOP;
200 break;
201 case KC_MEDIA_PLAY_PAUSE:
202 usage = TRANSPORT_PLAY_PAUSE;
203 break;
204 case KC_MEDIA_SELECT:
205 usage = AL_CC_CONFIG;
206 break;
207 case KC_MAIL:
208 usage = AL_EMAIL;
209 break;
210 case KC_CALCULATOR:
211 usage = AL_CALCULATOR;
212 break;
213 case KC_MY_COMPUTER:
214 usage = AL_LOCAL_BROWSER;
215 break;
216 case KC_WWW_SEARCH:
217 usage = AC_SEARCH;
218 break;
219 case KC_WWW_HOME:
220 usage = AC_HOME;
221 break;
222 case KC_WWW_BACK:
223 usage = AC_BACK;
224 break;
225 case KC_WWW_FORWARD:
226 usage = AC_FORWARD;
227 break;
228 case KC_WWW_STOP:
229 usage = AC_STOP;
230 break;
231 case KC_WWW_REFRESH:
232 usage = AC_REFRESH;
233 break;
234 case KC_WWW_FAVORITES:
235 usage = AC_BOOKMARKS;
236 break;
237 }
238 host_consumer_send(usage);
239 }
240 else if IS_SYSTEM(code) {
241 uint16_t usage = 0;
242 switch (code) {
243 case KC_SYSTEM_POWER:
244 usage = SYSTEM_POWER_DOWN;
245 break;
246 case KC_SYSTEM_SLEEP:
247 usage = SYSTEM_SLEEP;
248 break;
249 case KC_SYSTEM_WAKE:
250 usage = SYSTEM_WAKE_UP;
251 break;
252 }
253 host_system_send(usage);
254 }
255
256}
257
258static void unregister_code(uint8_t code)
259{
260 if IS_KEY(code) {
261 host_del_key(code);
262 host_send_keyboard_report();
263 }
264 else if IS_MOD(code) {
265 host_del_mod_bit(MOD_BIT(code));
266 host_send_keyboard_report();
267 }
268 else if IS_FN(code) {
269 host_del_key(keymap_fn_keycode(FN_INDEX(code)));
270 host_send_keyboard_report();
271 }
272 else if IS_MOUSEKEY(code) {
273#ifdef MOUSEKEY_ENABLE
274 mousekey_off(code);
275 mousekey_send();
276#endif
277 }
278 else if IS_CONSUMER(code) {
279 host_consumer_send(0x0000);
280 }
281 else if IS_SYSTEM(code) {
282 host_system_send(0x0000);
283 }
284}
285
286/*
287 *
288 * Event/State|IDLE PRESSING DELAYING[f] WAITING[f,k]
289 * -----------+------------------------------------------------------------------
290 * Fn Down |(L+) -*1 WAITING(Sk) IDLE(Rf,Ps)*7
291 * Up |(L-) IDLE(L-)*8 IDLE(L-)*8 IDLE(L-)*8
292 * Fnk Down |DELAYING(Sf)* (Rf) WAITING(Sk) IDLE(Rf,Ps,Rf)
293 * Up |(L-) IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3
294 * Key Down |PRESSING(Rk) (Rk) WAITING(Sk) IDLE(Rf,Ps,Rk)
295 * Up |(Uk) IDLE(Uk)*4 (Uk) IDLE(L+,Ps,Pk)/(Uk)*a
296 * |
297 * Delay |- - IDLE(L+) IDLE(L+,Ps)
298 * Magic Key |COMMAND*5
299 *
300 * *1: ignore Fn if other key is down.
301 * *2: register Fnk if any key is pressing
302 * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8
303 * *4: if no keys registered to host
304 * *5: unregister all keys
305 * *6: only if no keys down
306 * *7: ignore Fn because Fnk key and stored key are down.
307 * *8: move to IDLE if layer switch(off) occurs, else stay at current state
308 * *9: repeat key if pressing Fnk twice quickly(move to PRESSING)
309 * *a: layer switch and process waiting key and code if code == wainting key, else unregister key
310 *
311 * States:
312 * IDLE: No key is down except modifiers
313 * DELAYING: delay layer switch after pressing Fn with alt keycode
314 * WAITING: key is pressed during DELAYING
315 *
316 * Events:
317 * Fn: Fn key without alternative keycode
318 * Fnk: Fn key with alternative keycode
319 * -: ignore
320 * Delay: layer switch delay term is elapsed
321 *
322 * Actions:
323 * Rk: register key
324 * Uk: unregister key
325 * Rf: register Fn(alt keycode)
326 * Uf: unregister Fn(alt keycode)
327 * Rs: register stored key
328 * Us: unregister stored key
329 * Sk: Store key(waiting Key)
330 * Sf: Store Fn(delayed Fn)
331 * Ps: Process stored key
332 * Ps: Process key
333 * Is: Interpret stored keys in current layer
334 * L+: Switch to new layer(*unregister* all keys but modifiers)
335 * L-: Switch back to last layer(*unregister* all keys but modifiers)
336 * Ld: Switch back to default layer(*unregister* all keys but modifiers)
337 */
338#define NEXT(state) do { \
339 Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \
340 kbdstate = state; \
341 Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \
342} while (0)
343
344static inline void process_key(keyevent_t event)
345{
346 uint8_t code = keymap_get_keycode(current_layer, event.key.row, event.key.col);
347 keykind_t kind = get_keykind(code, event.pressed);
348
349 uint8_t tmp_mods;
350
351 Kdebug("state: "); Kdebug_P(state_str(kbdstate));
352 Kdebug(" kind: "); Kdebug_hex(kind);
353 Kdebug(" code: "); Kdebug_hex(code);
354 if (event.pressed) { Kdebug("d"); } else { Kdebug("u"); }
355 Kdebug("\n");
356
357 switch (kbdstate) {
358 case IDLE:
359 switch (kind) {
360 case FN_DOWN:
361 layer_switch_on(code);
362 break;
363 case FN_UP:
364 layer_switch_off(code);
365 break;
366 case FNK_DOWN:
367 // repeat Fn alt key when press Fn key down, up then down again quickly
368 if (KEYEQ(delayed_fn.event.key, event.key) &&
369 timer_elapsed(delayed_fn.time) < LAYER_DELAY) {
370 register_code(code);
371 NEXT(PRESSING);
372 } else {
373 delayed_fn = (keyrecord_t) {
374 .event = event,
375 .code = code,
376 .mods = keyboard_report->mods,
377 .time = timer_read()
378 };
379 NEXT(DELAYING);
380 }
381 break;
382 case FNK_UP:
383 layer_switch_off(code);
384 break;
385 case KEY_DOWN:
386 register_code(code);
387 NEXT(PRESSING);
388 break;
389 case MOD_DOWN:
390 register_code(code);
391 break;
392 case KEY_UP:
393 case MOD_UP:
394 unregister_code(code);
395 break;
396 default:
397 break;
398 }
399 break;
400 case PRESSING:
401 switch (kind) {
402 case FN_DOWN:
403 // ignored when any key is pressed
404 break;
405 case FN_UP:
406 if (layer_switch_off(code))
407 NEXT(IDLE);
408 break;
409 case FNK_DOWN:
410 register_code(code);
411 break;
412 case FNK_UP:
413 if (layer_switch_off(code)) {
414 NEXT(IDLE);
415 } else {
416 unregister_code(code);
417 if (!anykey_sent_to_host())
418 NEXT(IDLE);
419 }
420 break;
421 case KEY_DOWN:
422 case MOD_DOWN:
423 register_code(code);
424 break;
425 case KEY_UP:
426 case MOD_UP:
427 unregister_code(code);
428 if (!anykey_sent_to_host())
429 NEXT(IDLE);
430 break;
431 default:
432 break;
433 }
434 break;
435 case DELAYING:
436 switch (kind) {
437 case FN_DOWN:
438 case FNK_DOWN:
439 case KEY_DOWN:
440 waiting_key = (keyrecord_t) {
441 .event = event,
442 .code = code,
443 .mods = keyboard_report->mods,
444 .time = timer_read()
445 };
446 NEXT(WAITING);
447 break;
448 case MOD_DOWN:
449 register_code(code);
450 break;
451 case FN_UP:
452 if (layer_switch_off(code))
453 NEXT(IDLE);
454 break;
455 case FNK_UP:
456 if (code == delayed_fn.code) {
457 // type Fn with alt keycode
458 // restore the mod status at the time of pressing Fn key
459 tmp_mods = keyboard_report->mods;
460 host_set_mods(delayed_fn.mods);
461 register_code(delayed_fn.code);
462 unregister_code(delayed_fn.code);
463 host_set_mods(tmp_mods);
464 NEXT(IDLE);
465 } else {
466 if (layer_switch_off(code))
467 NEXT(IDLE);
468 }
469 break;
470 case KEY_UP:
471 case MOD_UP:
472 unregister_code(code);
473 break;
474 default:
475 break;
476 }
477 break;
478 case WAITING:
479 switch (kind) {
480 case FN_DOWN:
481 case FNK_DOWN:
482 case KEY_DOWN:
483 tmp_mods = keyboard_report->mods;
484 host_set_mods(delayed_fn.mods);
485 register_code(delayed_fn.code);
486 host_set_mods(waiting_key.mods);
487 register_code(waiting_key.code);
488 host_set_mods(tmp_mods);
489 if (kind == FN_DOWN) {
490 // ignore Fn
491 } else if (kind == FNK_DOWN) {
492 register_code(code);
493 } else if (kind == KEY_DOWN) {
494 register_code(code);
495 }
496 NEXT(IDLE);
497 break;
498 case MOD_DOWN:
499 register_code(code);
500 break;
501 case FN_UP:
502 if (layer_switch_off(code))
503 NEXT(IDLE);
504 break;
505 case FNK_UP:
506 if (code == delayed_fn.code) {
507 // alt down, key down, alt up
508 tmp_mods = keyboard_report->mods;
509 host_set_mods(delayed_fn.mods);
510 register_code(delayed_fn.code);
511 host_set_mods(waiting_key.mods);
512 register_code(waiting_key.code);
513 unregister_code(delayed_fn.code);
514 host_set_mods(tmp_mods);
515 NEXT(IDLE);
516 } else {
517 if (layer_switch_off(code))
518 NEXT(IDLE);
519 }
520 break;
521 case KEY_UP:
522 if (code == waiting_key.code) {
523 layer_switch_on(delayed_fn.code);
524 NEXT(IDLE);
525 // process waiting_key
526 tmp_mods = keyboard_report->mods;
527 host_set_mods(waiting_key.mods);
528 process_key(waiting_key.event);
529 host_set_mods(tmp_mods);
530 process_key(event);
531 } else {
532 unregister_code(code);
533 }
534 break;
535 case MOD_UP:
536 unregister_code(code);
537 break;
538 default:
539 break;
540 }
541 break;
542 }
543}
544
545void keyboard_init(void) 35void keyboard_init(void)
546{ 36{
547 // TODO: to enable debug print magic key bind on boot time
548
549 // TODO: configuration of sendchar impl 37 // TODO: configuration of sendchar impl
550 print_sendchar_func = sendchar; 38 print_sendchar_func = sendchar;
551 39
552 timer_init(); 40 timer_init();
553 matrix_init(); 41 matrix_init();
42
43 /* boot magic keys goes here */
44 matrix_scan();
45#ifdef IS_BOOTMAGIC_BOOTLOADER
46 /* kick up bootloader */
47 if (IS_BOOTMAGIC_BOOTLOADER()) bootloader_jump();
48#endif
49#ifdef IS_BOOTMAGIC_DEBUG
50 if (IS_BOOTMAGIC_DEBUG()) debug_enable = true;
51#endif
52
554#ifdef PS2_MOUSE_ENABLE 53#ifdef PS2_MOUSE_ENABLE
555 ps2_mouse_init(); 54 ps2_mouse_init();
556#endif 55#endif
557} 56}
558 57
58/*
59 * Do keyboard routine jobs: scan mantrix, light LEDs, ...
60 * This is repeatedly called as fast as possible.
61 */
559void keyboard_task(void) 62void keyboard_task(void)
560{ 63{
561 static matrix_row_t matrix_prev[MATRIX_ROWS]; 64 static matrix_row_t matrix_prev[MATRIX_ROWS];
@@ -572,9 +75,10 @@ void keyboard_task(void)
572 75
573 for (uint8_t c = 0; c < MATRIX_COLS; c++) { 76 for (uint8_t c = 0; c < MATRIX_COLS; c++) {
574 if (matrix_change & ((matrix_row_t)1<<c)) { 77 if (matrix_change & ((matrix_row_t)1<<c)) {
575 process_key((keyevent_t){ 78 action_exec((keyevent_t){
576 .key = (key_t){ .row = r, .col = c }, 79 .key.pos = (keypos_t){ .row = r, .col = c },
577 .pressed = (matrix_row & ((matrix_row_t)1<<c)) 80 .pressed = (matrix_row & (1<<c)),
81 .time = (timer_read() | 1) /* time should not be 0 */
578 }); 82 });
579 // record a processed key 83 // record a processed key
580 matrix_prev[r] ^= ((matrix_row_t)1<<c); 84 matrix_prev[r] ^= ((matrix_row_t)1<<c);
@@ -584,55 +88,19 @@ void keyboard_task(void)
584 } 88 }
585 } 89 }
586 } 90 }
587 MATRIX_LOOP_END: 91 // call with pseudo tick event when no real key event.
588 92 action_exec(TICK);
589 // layer switch when delay term elapses
590 if (kbdstate == DELAYING || kbdstate == WAITING) {
591 if (timer_elapsed(delayed_fn.time) > LAYER_DELAY) {
592 if (kbdstate == DELAYING) {
593 layer_switch_on(delayed_fn.code);
594 NEXT(IDLE);
595 }
596 if (kbdstate == WAITING) {
597 layer_switch_on(delayed_fn.code);
598 NEXT(IDLE);
599 uint8_t tmp_mods = keyboard_report->mods;
600 host_set_mods(waiting_key.mods);
601 process_key(waiting_key.event);
602 host_set_mods(tmp_mods);
603 }
604 }
605 }
606 93
94MATRIX_LOOP_END:
607#ifdef MOUSEKEY_ENABLE 95#ifdef MOUSEKEY_ENABLE
608 // mousekey repeat & acceleration 96 // mousekey repeat & acceleration
609 mousekey_task(); 97 mousekey_task();
610#endif 98#endif
611
612 // FAIL SAFE: clear all key if no key down
613 if (matrix_change) {
614 matrix_row_t is_matrix_on = 0;
615 for (int r = 0; r < MATRIX_ROWS; r++) {
616 is_matrix_on |= matrix_get_row(r);
617 }
618 if (!is_matrix_on) {
619 Kdebug("FAIL SAFE: clear all keys(default layer).\n");
620 clear_keyboard();
621 current_layer = default_layer;
622 fn_state_bits = 0;
623 delayed_fn = (keyrecord_t){};
624 waiting_key = (keyrecord_t){};
625 NEXT(IDLE);
626 }
627 }
628
629 // update LED 99 // update LED
630 if (led_status != host_keyboard_leds()) { 100 if (led_status != host_keyboard_leds()) {
631 led_status = host_keyboard_leds(); 101 led_status = host_keyboard_leds();
632 keyboard_set_leds(led_status); 102 keyboard_set_leds(led_status);
633 } 103 }
634
635 return;
636} 104}
637 105
638void keyboard_set_leds(uint8_t leds) 106void keyboard_set_leds(uint8_t leds)
diff --git a/common/keyboard.h b/common/keyboard.h
index 2353805e1..e1cab3119 100644
--- a/common/keyboard.h
+++ b/common/keyboard.h
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com> 2Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
3 3
4This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
@@ -26,28 +26,44 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
26extern "C" { 26extern "C" {
27#endif 27#endif
28 28
29/* key matrix position */
29typedef struct { 30typedef struct {
30 uint8_t row;
31 uint8_t col; 31 uint8_t col;
32 uint8_t row;
33} keypos_t;
34
35// TODO: need raw? keypos_t -> key_t?
36typedef union {
37 uint16_t raw;
38 keypos_t pos;
32} key_t; 39} key_t;
33 40
41/* key event */
34typedef struct { 42typedef struct {
35 key_t key; 43 key_t key;
36 bool pressed; 44 bool pressed;
45 uint16_t time;
37} keyevent_t; 46} keyevent_t;
38 47
39typedef struct { 48/* equivalent test of key_t */
40 keyevent_t event; 49#define KEYEQ(keya, keyb) ((keya).raw == (keyb).raw)
41 uint8_t code;
42 uint8_t mods;
43 uint16_t time;
44} keyrecord_t;
45 50
46#define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col) 51/* (time == 0) means no event and assumes matrix has no 255 line. */
52#define IS_NOEVENT(event) ((event).time == 0 || ((event).key.pos.row == 255 && (event).key.pos.col == 255))
47 53
54#define NOEVENT (keyevent_t){ \
55 .key.pos = (keypos_t){ .row = 255, .col = 255 }, \
56 .pressed = false, \
57 .time = 0 \
58}
59
60/* tick event */
61#define TICK (keyevent_t){ \
62 .key.pos = (keypos_t){ .row = 255, .col = 255 }, \
63 .pressed = false, \
64 .time = (timer_read() | 1) \
65}
48 66
49extern uint8_t current_layer;
50extern uint8_t default_layer;
51 67
52void keyboard_init(void); 68void keyboard_init(void);
53void keyboard_task(void); 69void keyboard_task(void);
diff --git a/common/keycode.h b/common/keycode.h
index f9331cdbf..4f57a5887 100644
--- a/common/keycode.h
+++ b/common/keycode.h
@@ -28,14 +28,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
28#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL) 28#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL)
29#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI) 29#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI)
30 30
31#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN7) 31#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31)
32#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2) 32#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2)
33#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT) 33#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT)
34#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN5) 34#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN5)
35#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT) 35#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT)
36#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2) 36#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2)
37 37
38#define IS_SPECIAL(code) ((0xB0 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF)) 38#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
39#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_WFAV) 39#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_WFAV)
40#define IS_SYSTEM(code) (KC_POWER <= (code) && (code) <= KC_WAKE) 40#define IS_SYSTEM(code) (KC_POWER <= (code) && (code) <= KC_WAKE)
41 41
@@ -43,6 +43,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
43#define MOD_INDEX(code) ((code) & 0x07) 43#define MOD_INDEX(code) ((code) & 0x07)
44#define FN_BIT(code) (1<<FN_INDEX(code)) 44#define FN_BIT(code) (1<<FN_INDEX(code))
45#define FN_INDEX(code) ((code) - KC_FN0) 45#define FN_INDEX(code) ((code) - KC_FN0)
46#define FN_MIN KC_FN0
47#define FN_MAX KC_FN31
46 48
47 49
48/* 50/*
@@ -388,11 +390,10 @@ enum internal_special_keycodes {
388 /* System Control */ 390 /* System Control */
389 KC_SYSTEM_POWER = 0xA5, 391 KC_SYSTEM_POWER = 0xA5,
390 KC_SYSTEM_SLEEP, 392 KC_SYSTEM_SLEEP,
391 KC_SYSTEM_WAKE, /* 0xA7 */ 393 KC_SYSTEM_WAKE,
392 /* 0xA8-AF */
393 394
394 /* Consumer Page */ 395 /* Media Control */
395 KC_AUDIO_MUTE = 0xB0, 396 KC_AUDIO_MUTE,
396 KC_AUDIO_VOL_UP, 397 KC_AUDIO_VOL_UP,
397 KC_AUDIO_VOL_DOWN, 398 KC_AUDIO_VOL_DOWN,
398 KC_MEDIA_NEXT_TRACK, 399 KC_MEDIA_NEXT_TRACK,
@@ -408,21 +409,47 @@ enum internal_special_keycodes {
408 KC_WWW_BACK, 409 KC_WWW_BACK,
409 KC_WWW_FORWARD, 410 KC_WWW_FORWARD,
410 KC_WWW_STOP, 411 KC_WWW_STOP,
411 KC_WWW_REFRESH, /* 0xC0 */ 412 KC_WWW_REFRESH,
412 KC_WWW_FAVORITES, /* 0xC1 */ 413 KC_WWW_FAVORITES, /* 0xB9 */
413 /* 0xC2-DF vacant for future use */
414 414
415 /* 0xE0-E7 for Modifiers. DO NOT USE. */ 415 /* Fn key */
416 416 KC_FN0 = 0xC0,
417 /* Layer Switching */
418 KC_FN0 = 0xE8,
419 KC_FN1, 417 KC_FN1,
420 KC_FN2, 418 KC_FN2,
421 KC_FN3, 419 KC_FN3,
422 KC_FN4, 420 KC_FN4,
423 KC_FN5, 421 KC_FN5,
424 KC_FN6, 422 KC_FN6,
425 KC_FN7, /* 0xEF */ 423 KC_FN7,
424 KC_FN8,
425 KC_FN9,
426 KC_FN10,
427 KC_FN11,
428 KC_FN12,
429 KC_FN13,
430 KC_FN14,
431 KC_FN15,
432
433 KC_FN16 = 0xD0,
434 KC_FN17,
435 KC_FN18,
436 KC_FN19,
437 KC_FN20,
438 KC_FN21,
439 KC_FN22,
440 KC_FN23,
441 KC_FN24,
442 KC_FN25,
443 KC_FN26,
444 KC_FN27,
445 KC_FN28,
446 KC_FN29,
447 KC_FN30,
448 KC_FN31, /* 0xDF */
449
450 /**************************************/
451 /* 0xE0-E7 for Modifiers. DO NOT USE. */
452 /**************************************/
426 453
427 /* Mousekey */ 454 /* Mousekey */
428 KC_MS_UP = 0xF0, 455 KC_MS_UP = 0xF0,
diff --git a/common/keymap.c b/common/keymap.c
new file mode 100644
index 000000000..8302c2704
--- /dev/null
+++ b/common/keymap.c
@@ -0,0 +1,73 @@
1/*
2Copyright 2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17#include "keymap.h"
18#include "report.h"
19#include "keycode.h"
20
21
22/* layer */
23uint8_t default_layer = 0;
24uint8_t current_layer = 0;
25
26
27#ifndef NO_LEGACY_KEYMAP_SUPPORT
28/* legacy support with weak reference */
29__attribute__ ((weak))
30action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col)
31{
32 /* convert from legacy keycode to action */
33 uint8_t key = keymap_get_keycode(layer, row, col);
34 action_t action;
35 switch (key) {
36 case KC_A ... KC_EXSEL:
37 action.code = ACTION_KEY(key);
38 break;
39 case KC_LCTRL ... KC_LGUI:
40 action.code = ACTION_LMOD(key);
41 break;
42 case KC_RCTRL ... KC_RGUI:
43 action.code = ACTION_RMOD(key);
44 break;
45 case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
46 action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(key));
47 break;
48 case KC_AUDIO_MUTE ... KC_WWW_FAVORITES:
49 action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(key));
50 break;
51 case KC_MS_UP ... KC_MS_ACCEL2:
52 action.code = ACTION_MOUSEKEY(key);
53 break;
54 case KC_FN0 ... KC_FN31:
55 {
56 uint8_t layer = keymap_fn_layer(FN_INDEX(key));
57 uint8_t code = keymap_fn_keycode(FN_INDEX(key));
58 action.code = ACTION_LAYER_SET_TAP_KEY(layer, code);
59 }
60 break;
61 case KC_NO ... KC_UNDEFINED:
62 default:
63 action.code = ACTION_NO;
64 break;
65 }
66 return action;
67}
68#endif
69
70__attribute__ ((weak))
71void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt)
72{
73}
diff --git a/common/keymap.h b/common/keymap.h
index 7dfd6c2a1..30d73f797 100644
--- a/common/keymap.h
+++ b/common/keymap.h
@@ -20,9 +20,26 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
20 20
21#include <stdint.h> 21#include <stdint.h>
22#include <stdbool.h> 22#include <stdbool.h>
23#include "action.h"
23 24
24 25
25/* keycode in specific layer */ 26// TODO: move to action.h?
27/* layer used currently */
28extern uint8_t current_layer;
29/* layer to return or start with */
30extern uint8_t default_layer;
31
32
33/* action for key */
34// TODO: should use struct key_t?
35action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col);
36
37/* user defined special function */
38void keymap_call_function(keyrecord_t *record, uint8_t id, uint8_t opt);
39
40
41#ifndef NO_LEGACY_KEYMAP_SUPPORT
42/* keycode of key */
26uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col); 43uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col);
27 44
28/* layer to move during press Fn key */ 45/* layer to move during press Fn key */
@@ -30,5 +47,6 @@ uint8_t keymap_fn_layer(uint8_t fn_bits);
30 47
31/* keycode to send when release Fn key without using */ 48/* keycode to send when release Fn key without using */
32uint8_t keymap_fn_keycode(uint8_t fn_bits); 49uint8_t keymap_fn_keycode(uint8_t fn_bits);
50#endif
33 51
34#endif 52#endif
diff --git a/common/print.c b/common/print.c
index 84400a1df..08d211f20 100644
--- a/common/print.c
+++ b/common/print.c
@@ -113,7 +113,6 @@ void print_decs(int16_t data)
113} 113}
114 114
115 115
116static inline
117void print_hex4(uint8_t data) 116void print_hex4(uint8_t data)
118{ 117{
119 sendchar(data + ((data < 10) ? '0' : 'A' - 10)); 118 sendchar(data + ((data < 10) ? '0' : 'A' - 10));
@@ -137,6 +136,12 @@ void print_hex32(uint32_t data)
137 print_hex16(data); 136 print_hex16(data);
138} 137}
139 138
139void print_bin4(uint8_t data)
140{
141 for (int i = 4; i >= 0; i--) {
142 sendchar((data & (1<<i)) ? '1' : '0');
143 }
144}
140 145
141void print_bin8(uint8_t data) 146void print_bin8(uint8_t data)
142{ 147{
diff --git a/common/print.h b/common/print.h
index 9c31b24a2..b22509477 100644
--- a/common/print.h
+++ b/common/print.h
@@ -87,11 +87,13 @@ void print_dec(uint16_t data);
87void print_decs(int16_t data); 87void print_decs(int16_t data);
88 88
89/* hex */ 89/* hex */
90void print_hex4(uint8_t data);
90void print_hex8(uint8_t data); 91void print_hex8(uint8_t data);
91void print_hex16(uint16_t data); 92void print_hex16(uint16_t data);
92void print_hex32(uint32_t data); 93void print_hex32(uint32_t data);
93 94
94/* binary */ 95/* binary */
96void print_bin4(uint8_t data);
95void print_bin8(uint8_t data); 97void print_bin8(uint8_t data);
96void print_bin16(uint16_t data); 98void print_bin16(uint16_t data);
97void print_bin32(uint32_t data); 99void print_bin32(uint32_t data);
diff --git a/common/report.h b/common/report.h
index a73e0aba1..0995189b3 100644
--- a/common/report.h
+++ b/common/report.h
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com> 2Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
3 3
4This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
19#define REPORT_H 19#define REPORT_H
20 20
21#include <stdint.h> 21#include <stdint.h>
22#include "keycode.h"
22 23
23 24
24/* report id */ 25/* report id */
@@ -33,8 +34,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
33#define MOUSE_BTN4 (1<<3) 34#define MOUSE_BTN4 (1<<3)
34#define MOUSE_BTN5 (1<<4) 35#define MOUSE_BTN5 (1<<4)
35 36
36// Consumer Page(0x0C) 37/* Consumer Page(0x0C)
37// following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx 38 * following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
39 */
38#define AUDIO_MUTE 0x00E2 40#define AUDIO_MUTE 0x00E2
39#define AUDIO_VOL_UP 0x00E9 41#define AUDIO_VOL_UP 0x00E9
40#define AUDIO_VOL_DOWN 0x00EA 42#define AUDIO_VOL_DOWN 0x00EA
@@ -42,10 +44,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
42#define TRANSPORT_PREV_TRACK 0x00B6 44#define TRANSPORT_PREV_TRACK 0x00B6
43#define TRANSPORT_STOP 0x00B7 45#define TRANSPORT_STOP 0x00B7
44#define TRANSPORT_PLAY_PAUSE 0x00CD 46#define TRANSPORT_PLAY_PAUSE 0x00CD
47/* application launch */
45#define AL_CC_CONFIG 0x0183 48#define AL_CC_CONFIG 0x0183
46#define AL_EMAIL 0x018A 49#define AL_EMAIL 0x018A
47#define AL_CALCULATOR 0x0192 50#define AL_CALCULATOR 0x0192
48#define AL_LOCAL_BROWSER 0x0194 51#define AL_LOCAL_BROWSER 0x0194
52/* application control */
49#define AC_SEARCH 0x0221 53#define AC_SEARCH 0x0221
50#define AC_HOME 0x0223 54#define AC_HOME 0x0223
51#define AC_BACK 0x0224 55#define AC_BACK 0x0224
@@ -53,20 +57,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
53#define AC_STOP 0x0226 57#define AC_STOP 0x0226
54#define AC_REFRESH 0x0227 58#define AC_REFRESH 0x0227
55#define AC_BOOKMARKS 0x022A 59#define AC_BOOKMARKS 0x022A
56// supplement for Bluegiga iWRAP HID(not supported by Windows?) 60/* supplement for Bluegiga iWRAP HID(not supported by Windows?) */
57#define AL_LOCK 0x019E 61#define AL_LOCK 0x019E
58#define TRANSPORT_RECORD 0x00B2 62#define TRANSPORT_RECORD 0x00B2
59#define TRANSPORT_REWIND 0x00B4 63#define TRANSPORT_REWIND 0x00B4
60#define TRANSPORT_EJECT 0x00B8 64#define TRANSPORT_EJECT 0x00B8
61#define AC_MINIMIZE 0x0206 65#define AC_MINIMIZE 0x0206
62 66
63// Generic Desktop Page(0x01) 67/* Generic Desktop Page(0x01) - system power control */
64#define SYSTEM_POWER_DOWN 0x0081 68#define SYSTEM_POWER_DOWN 0x0081
65#define SYSTEM_SLEEP 0x0082 69#define SYSTEM_SLEEP 0x0082
66#define SYSTEM_WAKE_UP 0x0083 70#define SYSTEM_WAKE_UP 0x0083
67 71
68 72
69// key report size(NKRO or boot mode) 73/* key report size(NKRO or boot mode) */
70#if defined(HOST_PJRC) 74#if defined(HOST_PJRC)
71# include "usb.h" 75# include "usb.h"
72# if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS 76# if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS
@@ -97,6 +101,34 @@ typedef struct {
97 int8_t h; 101 int8_t h;
98} __attribute__ ((packed)) report_mouse_t; 102} __attribute__ ((packed)) report_mouse_t;
99 103
104
105/* keycode to system usage */
106#define KEYCODE2SYSTEM(key) \
107 (key == KC_SYSTEM_POWER ? SYSTEM_POWER_DOWN : \
108 (key == KC_SYSTEM_SLEEP ? SYSTEM_SLEEP : \
109 (key == KC_SYSTEM_WAKE ? SYSTEM_WAKE_UP : 0)))
110
111/* keycode to consumer usage */
112#define KEYCODE2CONSUMER(key) \
113 (key == KC_AUDIO_MUTE ? AUDIO_MUTE : \
114 (key == KC_AUDIO_VOL_UP ? AUDIO_VOL_UP : \
115 (key == KC_AUDIO_VOL_DOWN ? AUDIO_VOL_DOWN : \
116 (key == KC_MEDIA_NEXT_TRACK ? TRANSPORT_NEXT_TRACK : \
117 (key == KC_MEDIA_PREV_TRACK ? TRANSPORT_PREV_TRACK : \
118 (key == KC_MEDIA_STOP ? TRANSPORT_STOP : \
119 (key == KC_MEDIA_PLAY_PAUSE ? TRANSPORT_PLAY_PAUSE : \
120 (key == KC_MEDIA_SELECT ? AL_CC_CONFIG : \
121 (key == KC_MAIL ? AL_EMAIL : \
122 (key == KC_CALCULATOR ? AL_CALCULATOR : \
123 (key == KC_MY_COMPUTER ? AL_LOCAL_BROWSER : \
124 (key == KC_WWW_SEARCH ? AC_SEARCH : \
125 (key == KC_WWW_HOME ? AC_HOME : \
126 (key == KC_WWW_BACK ? AC_BACK : \
127 (key == KC_WWW_FORWARD ? AC_FORWARD : \
128 (key == KC_WWW_STOP ? AC_STOP : \
129 (key == KC_WWW_REFRESH ? AC_REFRESH : \
130 (key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0))))))))))))))))))
131
100#ifdef __cplusplus 132#ifdef __cplusplus
101} 133}
102#endif 134#endif
diff --git a/doc/keycode.txt b/doc/keycode.txt
new file mode 100644
index 000000000..413756692
--- /dev/null
+++ b/doc/keycode.txt
@@ -0,0 +1,261 @@
1Keycode Symbol Table
2====================
3Keycodes are defined in `common/keycode.h`.
4Range of 00-A4 and E0-E7 are identical with HID Usage:
5<http://www.usb.org/developers/devclass_docs/Hut1_11.pdf>
6Virtual keycodes are defined out of above range to support special actions.
7
8
9Keycode Symbol Short name Description
10--------------------------------------------------------------------------------
11KC_NO 00 Reserved (no event indicated)
12KC_ROLL_OVER 01 Keyboard ErrorRollOver
13KC_POST_FAIL 02 Keyboard POSTFail
14KC_UNDEFINED 03 Keyboard ErrorUndefined
15KC_A 04 Keyboard a and A
16KC_B 05 Keyboard b and B
17KC_C 06 Keyboard c and C
18KC_D 07 Keyboard d and D
19KC_E 08 Keyboard e and E
20KC_F 09 Keyboard f and F
21KC_G 0A Keyboard g and G
22KC_H 0B Keyboard h and H
23KC_I 0C Keyboard i and I
24KC_J 0D Keyboard j and J
25KC_K 0E Keyboard k and K
26KC_L 0F Keyboard l and L
27KC_M 10 Keyboard m and M
28KC_N 11 Keyboard n and N
29KC_O 12 Keyboard o and O
30KC_P 13 Keyboard p and P
31KC_Q 14 Keyboard q and Q
32KC_R 15 Keyboard r and R
33KC_S 16 Keyboard s and S
34KC_T 17 Keyboard t and T
35KC_U 18 Keyboard u and U
36KC_V 19 Keyboard v and V
37KC_W 1A Keyboard w and W
38KC_X 1B Keyboard x and X
39KC_Y 1C Keyboard y and Y
40KC_Z 1D Keyboard z and Z
41KC_1 1E Keyboard 1 and !
42KC_2 1F Keyboard 2 and @
43KC_3 20 Keyboard 3 and #
44KC_4 21 Keyboard 4 and $
45KC_5 22 Keyboard 5 and %
46KC_6 23 Keyboard 6 and ^
47KC_7 24 Keyboard 7 and &
48KC_8 25 Keyboard 8 and *
49KC_9 26 Keyboard 9 and (
50KC_0 27 Keyboard 0 and )
51KC_ENTER KC_ENT 28 Keyboard Return (ENTER)
52KC_ESCAPE KC_ESC 29 Keyboard ESCAPE
53KC_BSPACE KC_BSPC 2A Keyboard DELETE (Backspace)
54KC_TAB 2B Keyboard Tab
55KC_SPACE KC_SPC 2C Keyboard Spacebar
56KC_MINUS KC_MINS 2D Keyboard - and (underscore)
57KC_EQUAL KC_EQL 2E Keyboard = and +
58KC_LBRACKET KC_LBRC 2F Keyboard [ and {
59KC_RBRACKET KC_RBRC 30 Keyboard ] and }
60KC_BSLASH KC_BSLS 31 Keyboard \ and |
61KC_NONUS_HASH KC_NUHS 32 Keyboard Non-US # and ~
62KC_SCOLON KC_SCLN 33 Keyboard ; and :
63KC_QUOTE KC_QUOT 34 Keyboard ‘ and “
64KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde
65KC_COMMA KC_COMM 36 Keyboard, and <
66KC_DOT 37 Keyboard . and >
67KC_SLASH KC_SLSH 38 Keyboard / and ?
68KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock
69KC_F1 3A Keyboard F1
70KC_F2 3B Keyboard F2
71KC_F3 3C Keyboard F3
72KC_F4 3D Keyboard F4
73KC_F5 3E Keyboard F5
74KC_F6 3F Keyboard F6
75KC_F7 40 Keyboard F7
76KC_F8 41 Keyboard F8
77KC_F9 42 Keyboard F9
78KC_F10 43 Keyboard F10
79KC_F11 44 Keyboard F11
80KC_F12 45 Keyboard F12
81KC_PSCREEN KC_PSCR 46 Keyboard PrintScreen1
82KC_SCKLOCK KC_SLCK 47 Keyboard Scroll Lock11
83KC_PAUSE KC_PAUS 48 Keyboard Pause1
84KC_INSERT KC_INT 49 Keyboard Insert1
85KC_HOME 4A Keyboard Home1
86KC_PGUP 4B Keyboard PageUp1
87KC_DELETE KC_DELETE 4C Keyboard Delete Forward
88KC_END 4D Keyboard End1
89KC_PGDOWN KC_PGDN 4E Keyboard PageDown1
90KC_RIGHT KC_RGHT 4F Keyboard RightArrow1
91KC_LEFT 50 Keyboard LeftArrow1
92KC_DOWN 51 Keyboard DownArrow1
93KC_UP 52 Keyboard UpArrow1
94KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11
95KC_KP_SLASH KC_PSLS 54 Keypad /1
96KC_KP_ASTERISK KC_PAST 55 Keypad *
97KC_KP_MINUS KC_PMNS 56 Keypad -
98KC_KP_PLUS KC_PPLS 57 Keypad +
99KC_KP_ENTER KC_PENT 58 Keypad ENTER5
100KC_KP_1 KC_P1 59 Keypad 1 and End
101KC_KP_2 KC_P2 5A Keypad 2 and Down Arrow
102KC_KP_3 KC_P3 5B Keypad 3 and PageDn
103KC_KP_4 KC_P4 5C Keypad 4 and Left Arrow
104KC_KP_5 KC_P5 5D Keypad 5
105KC_KP_6 KC_P6 5E Keypad 6 and Right Arrow
106KC_KP_7 KC_P7 5F Keypad 7 and Home
107KC_KP_8 KC_P8 60 Keypad 8 and Up Arrow
108KC_KP_9 KC_P9 61 Keypad 9 and PageUp
109KC_KP_0 KC_P0 62 Keypad 0 and Insert
110KC_KP_DOT KC_PDOT 63 Keypad . and Delete
111KC_NONUS_BSLASH KC_NUBS 64 Keyboard Non-US \ and |
112KC_APPLICATION KC_APP 65 Keyboard Application10
113KC_POWER 66 Keyboard Power9
114KC_KP_EQUAL KC_PEQL 67 Keypad =
115KC_F13 68 Keyboard F13
116KC_F14 69 Keyboard F14
117KC_F15 6A Keyboard F15
118KC_F16 6B Keyboard F16
119KC_F17 6C Keyboard F17
120KC_F18 6D Keyboard F18
121KC_F19 6E Keyboard F19
122KC_F20 6F Keyboard F20
123KC_F21 70 Keyboard F21
124KC_F22 71 Keyboard F22
125KC_F23 72 Keyboard F23
126KC_F24 73 Keyboard F24
127KC_EXECUTE 74 Keyboard Execute
128KC_HELP 75 Keyboard Help
129KC_MENU 76 Keyboard Menu
130KC_SELECT 77 Keyboard Select
131KC_STOP 78 Keyboard Stop
132KC_AGAIN 79 Keyboard Again
133KC_UNDO 7A Keyboard Undo
134KC_CUT 7B Keyboard Cut
135KC_COPY 7C Keyboard Copy
136KC_PASTE 7D Keyboard Paste
137KC_FIND 7E Keyboard Find
138KC__MUTE 7F Keyboard Mute
139KC__VOLUP 80 Keyboard Volume Up
140KC__VOLDOWN 81 Keyboard Volume Down
141KC_LOCKING_CAPS 82 Keyboard Locking Caps Lock12
142KC_LOCKING_NUM 83 Keyboard Locking Num Lock12
143KC_LOCKING_SCROLL 84 Keyboard Locking Scroll Lock12
144KC_KP_COMMA KC_PCMM 85 Keypad Comma27
145KC_KP_EQUAL_AS400 86 Keypad Equal Sign29
146KC_INT1 KC_RO 87 Keyboard International115,28
147KC_INT2 KC_KANA 88 Keyboard International216
148KC_INT3 KC_JYEN 89 Keyboard International317
149KC_INT4 KC_HENK 8A Keyboard International418
150KC_INT5 KC_MHEN 8B Keyboard International519
151KC_INT6 8C Keyboard International620
152KC_INT7 8D Keyboard International721
153KC_INT8 8E Keyboard International822
154KC_INT9 8F Keyboard International922
155KC_LANG1 90 Keyboard LANG125
156KC_LANG2 91 Keyboard LANG226
157KC_LANG3 92 Keyboard LANG330
158KC_LANG4 93 Keyboard LANG431
159KC_LANG5 94 Keyboard LANG532
160KC_LANG6 95 Keyboard LANG68
161KC_LANG7 96 Keyboard LANG78
162KC_LANG8 97 Keyboard LANG88
163KC_LANG9 98 Keyboard LANG98
164KC_ALT_ERASE 99 Keyboard Alternate Erase7
165KC_SYSREQ 9A Keyboard SysReq/Attention1
166KC_CANCEL 9B Keyboard Cancel
167KC_CLEAR 9C Keyboard Clear
168KC_PRIOR 9D Keyboard Prior
169KC_RETURN 9E Keyboard Return
170KC_SEPARATOR 9F Keyboard Separator
171KC_OUT A0 Keyboard Out
172KC_OPER A1 Keyboard Oper
173KC_CLEAR_AGAIN A2 Keyboard Clear/Again
174KC_CRSEL A3 Keyboard CrSel/Props
175KC_EXSEL A4 Keyboard ExSel
176/* Modifiers */
177KC_LCTRL KC_LCTRL E0 Keyboard LeftControl
178KC_LSHIFT KC_LSFT E1 Keyboard LeftShift
179KC_LALT E2 Keyboard LeftAlt
180KC_LGUI E3 Keyboard Left GUI(Windows/Apple/Meta key)
181KC_RCTRL KC_RCTL E4 Keyboard RightControl
182KC_RSHIFT KC_RSFT E5 Keyboard RightShift
183KC_RALT E6 Keyboard RightAlt
184KC_RGUI E7 Keyboard Right GUI(Windows/Apple/Meta key)
185
186/*
187 * Virtual keycodes
188 */
189/* System Control */
190KC_SYSTEM_POWER KC_PWR System Power Down
191KC_SYSTEM_SLEEP KC_SLEP System Sleep
192KC_SYSTEM_WAKE KC_WAKE System Wake
193/* Consumer Page */
194KC_AUDIO_MUTE KC_MUTE
195KC_AUDIO_VOL_UP KC_VOLU
196KC_AUDIO_VOL_DOWN KC_VOLD
197KC_MEDIA_NEXT_TRACK KC_MNXT
198KC_MEDIA_PREV_TRACK KC_MPRV
199KC_MEDIA_STOP KC_MSTP
200KC_MEDIA_PLAY_PAUSE KC_MPLY
201KC_MEDIA_SELECT KC_MSEL
202KC_MAIL KC_MAIL
203KC_CALCULATOR KC_CALC
204KC_MY_COMPUTER KC_MYCM
205KC_WWW_SEARCH KC_WSCH
206KC_WWW_HOME KC_WHOM
207KC_WWW_BACK KC_WBAK
208KC_WWW_FORWARD KC_WFWD
209KC_WWW_STOP KC_WSTP
210KC_WWW_REFRESH KC_WREF
211KC_WWW_FAVORITES KC_WFAV
212/* Mousekey */
213KC_MS_UP KC_MS_U Mouse Cursor Up
214KC_MS_DOWN KC_MS_D Mouse Cursor Down
215KC_MS_LEFT KC_MS_L Mouse Cursor Left
216KC_MS_RIGHT KC_MS_R Mouse Cursor Right
217KC_MS_BTN1 KC_BTN1 Mouse Button 1
218KC_MS_BTN2 KC_BTN2 Mouse Button 2
219KC_MS_BTN3 KC_BTN3 Mouse Button 3
220KC_MS_BTN4 KC_BTN4 Mouse Button 4
221KC_MS_BTN5 KC_BTN5 Mouse Button 5
222KC_MS_WH_UP KC_WH_U Mouse Wheel Up
223KC_MS_WH_DOWN KC_WH_D Mouse Wheel Down
224KC_MS_WH_LEFT KC_WH_L Mouse Wheel Left
225KC_MS_WH_RIGHT KC_WH_R Mouse Wheel Right
226KC_MS_ACCEL0 KC_ACL0 Mouse Acceleration 0
227KC_MS_ACCEL1 KC_ACL1 Mouse Acceleration 1
228KC_MS_ACCEL2 KC_ACL2 Mouse Acceleration 2
229/* Fn key */
230KC_FN0
231KC_FN1
232KC_FN2
233KC_FN3
234KC_FN4
235KC_FN5
236KC_FN6
237KC_FN7
238KC_FN8
239KC_FN9
240KC_FN10
241KC_FN11
242KC_FN12
243KC_FN13
244KC_FN14
245KC_FN15
246KC_FN16
247KC_FN17
248KC_FN18
249KC_FN19
250KC_FN20
251KC_FN21
252KC_FN22
253KC_FN23
254KC_FN24
255KC_FN25
256KC_FN26
257KC_FN27
258KC_FN28
259KC_FN29
260KC_FN30
261KC_FN31
diff --git a/keyboard/hhkb/Makefile.lufa b/keyboard/hhkb/Makefile.lufa
index 5acc93a23..afd413d01 100644
--- a/keyboard/hhkb/Makefile.lufa
+++ b/keyboard/hhkb/Makefile.lufa
@@ -121,3 +121,6 @@ VPATH += $(TOP_DIR)
121include $(TOP_DIR)/protocol/lufa.mk 121include $(TOP_DIR)/protocol/lufa.mk
122include $(TOP_DIR)/common.mk 122include $(TOP_DIR)/common.mk
123include $(TOP_DIR)/rules.mk 123include $(TOP_DIR)/rules.mk
124
125debug-on: EXTRAFLAGS += -DDEBUG
126debug-on: all
diff --git a/keyboard/hhkb/Makefile.vusb b/keyboard/hhkb/Makefile.vusb
index 8caf23497..0e0e4a8cd 100644
--- a/keyboard/hhkb/Makefile.vusb
+++ b/keyboard/hhkb/Makefile.vusb
@@ -89,3 +89,6 @@ VPATH += $(TOP_DIR)
89include $(TOP_DIR)/protocol/vusb.mk 89include $(TOP_DIR)/protocol/vusb.mk
90include $(TOP_DIR)/common.mk 90include $(TOP_DIR)/common.mk
91include $(TOP_DIR)/rules.mk 91include $(TOP_DIR)/rules.mk
92
93debug-on: EXTRAFLAGS += -DDEBUG
94debug-on: all
diff --git a/keyboard/hhkb/config.h b/keyboard/hhkb/config.h
index cca75f243..5fcec95eb 100644
--- a/keyboard/hhkb/config.h
+++ b/keyboard/hhkb/config.h
@@ -37,6 +37,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
37#define MATRIX_COLS 8 37#define MATRIX_COLS 8
38 38
39 39
40/*
41 * Boot magic keys
42 * call some function by pressing key when pluging cable or powering on.
43 */
44/* key position on matrix(ROW:COL) */
45#define KEY_FN 0x54
46#define KEY_D 0x14
47#define KEY_IS_ON(key) matrix_is_on((key)>>4, (key)&0xF)
48/* kick up bootloader */
49#define IS_BOOTMAGIC_BOOTLOADER() KEY_IS_ON(KEY_FN)
50/* debug on */
51#define IS_BOOTMAGIC_DEBUG() KEY_IS_ON(KEY_D)
52
53
40/* key combination for command */ 54/* key combination for command */
41#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) 55#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
42 56
@@ -45,6 +59,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
45# define MOUSEKEY_DELAY_TIME 100 59# define MOUSEKEY_DELAY_TIME 100
46#endif 60#endif
47 61
62/* period of tapping(ms) */
63#define TAPPING_TERM 200
64/* tap count needed for toggling a feature */
65#define TAPPING_TOGGLE 5
48 66
49/* PS/2 mouse */ 67/* PS/2 mouse */
50#ifdef PS2_MOUSE_ENABLE 68#ifdef PS2_MOUSE_ENABLE
diff --git a/keyboard/hhkb/keymap.c b/keyboard/hhkb/keymap.c
index 5dc5582ec..65ef89ad7 100644
--- a/keyboard/hhkb/keymap.c
+++ b/keyboard/hhkb/keymap.c
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com> 2Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
3 3
4This program is free software: you can redistribute it and/or modify 4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by 5it under the terms of the GNU General Public License as published by
@@ -21,16 +21,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
21#include <stdint.h> 21#include <stdint.h>
22#include <stdbool.h> 22#include <stdbool.h>
23#include <avr/pgmspace.h> 23#include <avr/pgmspace.h>
24#include "host.h"
25#include "keycode.h" 24#include "keycode.h"
26#include "print.h" 25#include "action.h"
26#include "action_macro.h"
27#include "host.h"
27#include "debug.h" 28#include "debug.h"
28#include "util.h"
29#include "keymap.h" 29#include "keymap.h"
30 30
31 31
32// Convert physical keyboard layout to matrix array.
33// This is a macro to define keymap easily in keyboard layout form.
34#define KEYMAP( \ 32#define KEYMAP( \
35 K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \ 33 K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \
36 K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \ 34 K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \
@@ -49,34 +47,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
49 { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO } \ 47 { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_NO } \
50} 48}
51 49
52#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
53
54
55// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
56static const uint8_t PROGMEM fn_layer[] = {
57 0, // Fn0
58 1, // Fn1
59 2, // Fn2
60 3, // Fn3
61 3, // Fn4
62 5, // Fn5
63 0, // Fn6
64 0 // Fn7
65};
66
67// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer.
68// See layer.c for details.
69static const uint8_t PROGMEM fn_keycode[] = {
70 KC_NO, // Fn0
71 KC_NO, // Fn1
72 KC_SLSH, // Fn2
73 KC_SCLN, // Fn3
74 KC_NO, // Fn4
75 KC_SPC, // Fn5
76 KC_NO, // Fn6
77 KC_NO // Fn7
78};
79 50
51// TODO: use [1] = KEYMAP(...) to prevent from changing index of element?
80static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 52static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
81 /* Layer 0: Default Layer 53 /* Layer 0: Default Layer
82 * ,-----------------------------------------------------------. 54 * ,-----------------------------------------------------------.
@@ -84,18 +56,18 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
84 * |-----------------------------------------------------------| 56 * |-----------------------------------------------------------|
85 * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs| 57 * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs|
86 * |-----------------------------------------------------------| 58 * |-----------------------------------------------------------|
87 * |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Return | 59 * |Fn6 | A| S| D| F| G| H| J| K| L|Fn3| '|Return |
88 * |-----------------------------------------------------------| 60 * |-----------------------------------------------------------|
89 * |Shift | Z| X| C| V| B| N| M| ,| .|Fn2|Shift |Fn1| 61 * |Fn8 | Z| X| C| V| B| N| M| ,| .|Fn2|Fn12 |Fn1|
90 * `-----------------------------------------------------------' 62 * `-----------------------------------------------------------'
91 * |Gui|Alt |Fn5 |Alt |Fn4| 63 * |Gui|Alt | Fn5 |Alt |Fn4|
92 * `-------------------------------------------' 64 * `-------------------------------------------'
93 */ 65 */
94 KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \ 66 KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
95 TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \ 67 TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
96 LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,ENT, \ 68 FN6, A, S, D, F, G, H, J, K, L, FN3, QUOT,FN7, \
97 LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \ 69 FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, FN12,FN9, \
98 LGUI,LALT, FN5, RALT,FN4), 70 LGUI,LALT, FN5, FN13,FN4),
99 71
100 /* Layer 1: HHKB mode (HHKB Fn) 72 /* Layer 1: HHKB mode (HHKB Fn)
101 * ,-----------------------------------------------------------. 73 * ,-----------------------------------------------------------.
@@ -105,16 +77,16 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
105 * |-----------------------------------------------------------| 77 * |-----------------------------------------------------------|
106 * |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter | 78 * |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
107 * |-----------------------------------------------------------| 79 * |-----------------------------------------------------------|
108 * |Shift | | | | | | +| -|End|PgD|Dow|Shift |xxx| 80 * |Shift | | | | | | +| -|End|PgD|Dow|Shift |Fn0|
109 * `-----------------------------------------------------------' 81 * `-----------------------------------------------------------'
110 * |Gui |Alt |Space |Alt |xxx| 82 * |Gui|Alt | Space |Alt |Gui|
111 * `--------------------------------------------' 83 * `-------------------------------------------'
112 */ 84 */
113 KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ 85 KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
114 CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,BRK, UP, NO, BSPC, \ 86 CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS, UP, NO, BSPC, \
115 LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \ 87 LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
116 LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN1, \ 88 LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN0, \
117 LGUI,LALT, SPC, RALT,FN7), 89 LGUI,LALT, SPC, RALT,RGUI),
118 90
119 /* Layer 2: Vi mode (Slash) 91 /* Layer 2: Vi mode (Slash)
120 * ,-----------------------------------------------------------. 92 * ,-----------------------------------------------------------.
@@ -124,49 +96,36 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
124 * |-----------------------------------------------------------| 96 * |-----------------------------------------------------------|
125 * |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | |Return | 97 * |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | |Return |
126 * |-----------------------------------------------------------| 98 * |-----------------------------------------------------------|
127 * |Shift | | | | | |Hom|PgD|PgUlEnd|xxx|Shift | | 99 * |Shift | | | | | |Hom|PgD|PgUlEnd|Fn0|Shift | |
128 * `-----------------------------------------------------------' 100 * `-----------------------------------------------------------'
129 * |Gui|Alt |Space |Alt |Gui| 101 * |Gui|Alt | Space |Alt |Gui|
130 * `-------------------------------------------' 102 * `-------------------------------------------'
131 */ 103 */
132 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ 104 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
133 TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \ 105 TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \
134 LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \ 106 LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \
135 LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, RSFT,NO, \ 107 LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN0, RSFT,NO, \
136 LGUI,LALT, SPC, RALT,RGUI), 108 LGUI,LALT, SPC, RALT,RGUI),
137 109
138 /* Layer 3: Mouse mode (Semicolon) 110 /* Layer 3: Mouse mode (Semicolon)
139 * ,-----------------------------------------------------------. 111 * ,-----------------------------------------------------------.
140 * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del| 112 * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
141 * |-----------------------------------------------------------| 113 * |-----------------------------------------------------------|
142 * |Tab |MwL|MwU|McU|MwD|MwR|MwL|MwD|MwU|MwR| | | |Backs| 114 * |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
143 * |-----------------------------------------------------------| 115 * |-----------------------------------------------------------|
144 * |Contro| |McL|McD|McR| |McL|McD|McU|McR|xxx| |Return | 116 * |Contro| | | | | |McL|McD|McU|McR|Fn0| |Return |
145 * |-----------------------------------------------------------| 117 * |-----------------------------------------------------------|
146 * |Shift |Mb4|Mb5|Mb1|Mb2|Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | | 118 * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
147 * `-----------------------------------------------------------' 119 * `-----------------------------------------------------------'
148 * |Gui |Alt |Mb1 |Alt |Gui| 120 * |Gui |Alt | Mb1 |Alt |Fn0|
149 * `--------------------------------------------' 121 * `--------------------------------------------'
150 * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel 122 * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
151 */ 123 */
152#ifdef HOST_IWRAP
153// iWRAP does not support mouse wheel, use these keycodes to remap as wheel
154#define KC_KPPL KC_KP_PLUS
155#define KC_KPMI KC_KP_MINUS
156#define KC_KPAS KC_KP_ASTERISK
157#define KC_KPSL KC_KP_SLASH
158 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
159 TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \
160 LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \
161 LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,NO, NO, NO, RSFT,NO, \
162 LGUI,LALT, BTN1, RALT,FN4),
163#else
164 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ 124 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
165 TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ 125 TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \
166 LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ 126 LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, QUOT,ENT, \
167 LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ 127 LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,NO, \
168 LGUI,LALT, BTN1, RALT,FN4), 128 LGUI,LALT, BTN1, RALT,FN0),
169#endif
170 129
171 /* Layer 4: Matias half keyboard style (Space) 130 /* Layer 4: Matias half keyboard style (Space)
172 * ,-----------------------------------------------------------. 131 * ,-----------------------------------------------------------.
@@ -178,43 +137,212 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
178 * |-----------------------------------------------------------| 137 * |-----------------------------------------------------------|
179 * |Shift | /| .| ,| M| N| B| V| C| X| Z|Shift | | 138 * |Shift | /| .| ,| M| N| B| V| C| X| Z|Shift | |
180 * `-----------------------------------------------------------' 139 * `-----------------------------------------------------------'
181 * |Gui |Alt |xxxxxxxxxxxxxxxxxxxxxxx|Alt |Gui| 140 * |Gui |Alt | Fn0 |Alt |Gui|
182 * `--------------------------------------------' 141 * `--------------------------------------------'
183 */ 142 */
184 KEYMAP(MINS,0, 9, 8, 7, 6, 5, 4, 3, 2, 1, NO, NO, NO, ESC, \ 143 KEYMAP(MINS,0, 9, 8, 7, 6, 5, 4, 3, 2, 1, NO, NO, NO, ESC, \
185 BSPC,P, O, I, U, Y, T, R, E, W, Q, NO, NO, TAB, \ 144 BSPC,P, O, I, U, Y, T, R, E, W, Q, NO, NO, TAB, \
186 LCTL,SCLN,L, K, J, H, G, F, D, S, A, RCTL,RCTL, \ 145 LCTL,SCLN,L, K, J, H, G, F, D, S, A, RCTL,RCTL, \
187 LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT,NO, \ 146 LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT,NO, \
188 LGUI,LALT, FN5, RALT,RGUI), 147 LGUI,LALT, FN0, RALT,RGUI),
189 148
190 /* Layer5: another Mouse mode (Space) */ 149 /* Layer5: another Mouse mode (Space)
191#ifdef HOST_IWRAP 150 * ,-----------------------------------------------------------.
192 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ 151 * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
193 TAB, KPAS,KPPL,MS_U,KPMI,KPSL,KPAS,KPPL,KPMI,KPSL,NO, NO, NO, BSPC, \ 152 * |-----------------------------------------------------------|
194 LCTL,NO, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ 153 * |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
195 LSFT,BTN4,BTN5,BTN1,BTN2,BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ 154 * |-----------------------------------------------------------|
196 LGUI,LALT, FN5, RALT,RGUI), 155 * |Contro| | | | | |McL|McD|McU|McR|Fn0| |Return |
197#else 156 * |-----------------------------------------------------------|
157 * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
158 * `-----------------------------------------------------------'
159 * |Gui |Alt | Fn0 |Alt |Fn0|
160 * `--------------------------------------------'
161 * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
162 */
198 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \ 163 KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
199 TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \ 164 TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \
200 LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN3, NO, ENT, \ 165 LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,NO, NO, ENT, \
201 LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \ 166 LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \
202 LGUI,LALT, FN5, RALT,RGUI), 167 LGUI,LALT, FN0, RALT,RGUI),
203#endif 168};
169
170
171
172/* id for user defined functions */
173enum function_id {
174 LSHIFT_LPAREN,
175 RSHIFT_RPAREN,
176 MACRO = 0xff
177};
178
179
180/*
181 * Fn action definition
182 */
183// TODO: use [1] = KEYMAP(...) to prevent from changing index of element?
184static const uint16_t PROGMEM fn_actions[] = {
185 ACTION_LAYER_DEFAULT, // FN0
186 ACTION_LAYER_SET(1), // FN1
187 ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH), // FN2 Layer with Slash
188 ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // FN3 Layer with Semicolon
189
190 ACTION_LAYER_SET(3), // FN4
191// ACTION_LAYER_SET_TOGGLE(3), // FN4
192// ACTION_FUNCTION(MACRO, 0), // FN4
193 ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // FN5
194// ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // FN6 Control with tap Backspace
195 ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC), // FN6 Control with tap Backspace
196 ACTION_RMOD_TAP_KEY(KC_RCTL, KC_ENT), // FN7 Control with tap Enter
197 ACTION_LMOD_ONESHOT(KC_LSFT), // FN8 Oneshot Shift
198 ACTION_LAYER_SET_TAP_TOGGLE(1), // FN9
199 ACTION_LAYER_BIT_TAP_KEY(1, KC_GRV), // FN10 Layer with Grave
200 //ACTION_LAYER_BIT(1), // FN10
201 //ACTION_LAYER_BIT_TAP_TOGGLE(1), // FN10
202 ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // FN11 Function: LShift with tap '('
203 ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // FN12 Function: RShift with tap ')'
204 ACTION_FUNCTION(MACRO, 1), // FN13 Macro:
204}; 205};
205 206
206 207
207uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) 208/*
209 * Macro definition
210 */
211#define MACRO(...) ({ static prog_macro_t _m[] PROGMEM = { __VA_ARGS__ }; _m; })
212#define MACRO_NONE 0
213static const prog_macro_t *get_macro(uint8_t id, bool pressed)
208{ 214{
209 return KEYCODE(layer, row, col); 215 switch (id) {
216 case 0:
217 return (pressed ?
218 MACRO( MD(LSHIFT), D(D), END ) :
219 MACRO( U(D), MU(LSHIFT), END ) );
220 case 1:
221 return (pressed ?
222 MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END ) :
223 MACRO_NONE );
224 }
225 return 0;
210} 226}
211 227
212uint8_t keymap_fn_layer(uint8_t index) 228
229
230/*
231 * user defined action function
232 */
233void keymap_call_function(keyrecord_t *record, uint8_t id, uint8_t opt)
213{ 234{
214 return pgm_read_byte(&fn_layer[index]); 235 keyevent_t event = record->event;
236 uint8_t tap_count = record->tap_count;
237
238 debug("action_call_function: ");
239 if (event.pressed) debug("pressed"); else debug("released");
240 debug(" id: "); debug_hex(id);
241 debug(" tap_count: "); debug_dec(tap_count);
242 debug("\n");
243
244 switch (id) {
245 case LSHIFT_LPAREN:
246 // LShft + tap '('
247 if (event.pressed) {
248 if (tap_count == 0) {
249 add_mods(MOD_BIT(KC_LSHIFT));
250 } else {
251 if (waiting_buffer_has_anykey_pressed()) {
252 // ad hoc: set 0 to cancel tap
253 record->tap_count = 0;
254 add_mods(MOD_BIT(KC_LSHIFT));
255 } else {
256 // NOTE to avoid conflicting command key bind(LShift+RShift)
257 //register_code(KC_LSHIFT);
258 //register_code(KC_9);
259 host_add_mods(MOD_BIT(KC_LSHIFT));
260 host_add_key(KC_9);
261 host_send_keyboard_report();
262 }
263 }
264 } else {
265 if (tap_count == 0) {
266 del_mods(MOD_BIT(KC_LSHIFT));
267 } else {
268 //unregister_code(KC_9);
269 //unregister_code(KC_LSHIFT);
270 host_del_mods(MOD_BIT(KC_LSHIFT));
271 host_del_key(KC_9);
272 host_send_keyboard_report();
273 }
274 }
275 break;
276 case RSHIFT_RPAREN:
277 // RShift + tap ')'
278 if (event.pressed) {
279 if (tap_count == 0) {
280 add_mods(MOD_BIT(KC_RSHIFT));
281 } else {
282 if (waiting_buffer_has_anykey_pressed()) {
283 // ad hoc: set 0 to cancel tap
284 record->tap_count = 0;
285 add_mods(MOD_BIT(KC_RSHIFT));
286 } else {
287 //register_code(KC_RSHIFT);
288 //register_code(KC_0);
289 host_add_mods(MOD_BIT(KC_RSHIFT));
290 host_add_key(KC_0);
291 host_send_keyboard_report();
292 }
293 }
294 } else {
295 if (tap_count == 0) {
296 del_mods(MOD_BIT(KC_RSHIFT));
297 } else {
298 //unregister_code(KC_0);
299 //unregister_code(KC_RSHIFT);
300 host_del_mods(MOD_BIT(KC_RSHIFT));
301 host_del_key(KC_0);
302 host_send_keyboard_report();
303 }
304 }
305 break;
306 case MACRO:
307 action_macro_play(get_macro(opt, event.pressed));
308 break;
309 }
215} 310}
216 311
217uint8_t keymap_fn_keycode(uint8_t index) 312/* convert keycode to action */
218{ 313action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) {
219 return pgm_read_byte(&fn_keycode[index]); 314 uint8_t key = (pgm_read_byte(&keymaps[(layer)][(row)][(col)]));
315 action_t action;
316 switch (key) {
317 case KC_A ... KC_EXSEL:
318 action.code = ACTION_KEY(key);
319 break;
320 case KC_LCTRL ... KC_LGUI:
321 action.code = ACTION_LMOD(key);
322 break;
323 case KC_RCTRL ... KC_RGUI:
324 action.code = ACTION_RMOD(key);
325 break;
326 case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
327 action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(key));
328 break;
329 case KC_AUDIO_MUTE ... KC_WWW_FAVORITES:
330 action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(key));
331 break;
332 case KC_MS_UP ... KC_MS_ACCEL2:
333 action.code = ACTION_MOUSEKEY(key);
334 break;
335 case KC_FN0 ... KC_FN31:
336 if (FN_INDEX(key) < sizeof(fn_actions) / sizeof(fn_actions[0])) {
337 action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]);
338 } else {
339 action.code = ACTION_NO;
340 }
341 break;
342 case KC_NO ... KC_UNDEFINED:
343 default:
344 action.code = ACTION_NO;
345 break;
346 }
347 return action;
220} 348}
diff --git a/keyboard/hhkb/matrix.c b/keyboard/hhkb/matrix.c
index fd0d6f97f..f53e36dbe 100644
--- a/keyboard/hhkb/matrix.c
+++ b/keyboard/hhkb/matrix.c
@@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
24#include <avr/interrupt.h> 24#include <avr/interrupt.h>
25#include <util/delay.h> 25#include <util/delay.h>
26#include "print.h" 26#include "print.h"
27#include "debug.h"
27#include "util.h" 28#include "util.h"
28#include "timer.h" 29#include "timer.h"
29#include "matrix.h" 30#include "matrix.h"
@@ -135,6 +136,12 @@ uint8_t matrix_cols(void)
135 136
136void matrix_init(void) 137void matrix_init(void)
137{ 138{
139#ifdef DEBUG
140 print_enable = true;
141 debug_enable = true;
142 debug_keyboard = true;
143#endif
144
138 KEY_INIT(); 145 KEY_INIT();
139 146
140 // initialize matrix state: all keys off 147 // initialize matrix state: all keys off