1
0
Fork 0

Merge branch 'overlays'

This commit is contained in:
tmk 2013-03-05 15:45:15 +09:00
commit 38bbe976e0
51 changed files with 2871 additions and 958 deletions

368
README.md
View file

@ -7,7 +7,7 @@ Source code is available here: <http://github.com/tmk/tmk_keyboard>
Features
--------
* Multi-layer Keymap - Multiple keyboard layouts with layer switching.
* Multi-layer Keymap - Multiple keyboard layouts with layer switching
* Mouse key - Mouse control with keyboard
* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up
* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
@ -22,24 +22,27 @@ Features
Projects
--------
You can find some keyboard specific projects under `converter` and `keyboard` directory.
### converter
* ps2_usb - [PS/2 keyboard to USB][GH_ps2]
* adb_usb - [ADB keyboard to USB][GH_adb]
* m0110_usb - [Machintosh 128K/512K/Plus keyboard to USB][GH_m0110]
* terminal_usb - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal]
* news_usb - [Sony NEWS keyboard to USB][GH_news]
* x68k_usb - [Sharp X68000 keyboard to USB][GH_x68k]
* sun_usb - Sun to USB(type4, 5 and 3?)
* usb_usb - USB to USB(experimental)
* [ps2_usb](converter/ps2_usb/) - [PS/2 keyboard to USB][GH_ps2]
* [adb_usb](converter/adb_usb/) - [ADB keyboard to USB][GH_adb]
* [m0110_usb](converter/m0110_usb) - [Machintosh 128K/512K/Plus keyboard to USB][GH_m0110]
* [terminal_usb](converter/terminal_usb/) - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal]
* [news_usb](converter/news_usb/) - [Sony NEWS keyboard to USB][GH_news]
* [x68k_usb](converter/x68k_usb/) - [Sharp X68000 keyboard to USB][GH_x68k]
* [sun_usb](converter/sun_usb/) - [Sun] to USB(type4, 5 and 3?)
* [pc98_usb](converter/pc98_usb/) - [PC98] to USB
* [usb_usb](converter/usb_usb/) - USB to USB(experimental)
### keyboard
* hhkb - [Happy Hacking Keyboard professional][GH_hhkb]
* macway - [Compact keyboard mod][GH_macway]
* hbkb - [Happy Buckling sprint keyboard(IBM Model M mod)][GH_hbkb]
* IIgs_Standard - Apple IIGS keyboard mod(by JeffreySung)
* hid_liber - [HID liberation controller][HID_liber](by alaricljs)
* phantom - [Phantom keyboard][PHANTOM] (by Tranquilite)
* gh60 - [GH60 keyboard][GH60]
* [hhkb](keyboard/hhkb/) - [Happy Hacking Keyboard professional][GH_hhkb]
* [macway](keyboard/macway/) - [Compact keyboard mod][GH_macway]
* [hbkb](keyboard/hbkb/) - [Happy Buckling sprint keyboard(IBM Model M mod)][GH_hbkb]
* [IIgs_Standard](keyboard/IIgs/) - Apple [IIGS] keyboard mod(by JeffreySung)
* [hid_liber](keyboard/hid_liber/) - [HID liberation controller][HID_liber](by alaricljs)
* [phantom](keyboard/phantom/) - [Phantom keyboard][PHANTOM] (by Tranquilite)
* [gh60](keyboard/gh60/) - [GH60 keyboard][GH60]
[GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930
[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047
@ -54,6 +57,9 @@ Projects
[HID_liber]: http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions
[PHANTOM]: http://geekhack.org/index.php?topic=26742
[GH60]: http://geekhack.org/index.php?topic=34959
[PC98]: http://en.wikipedia.org/wiki/NEC_PC-9801
[Sun]: http://en.wikipedia.org/wiki/Sun-3
[IIGS]: http://en.wikipedia.org/wiki/Apple_IIGS
@ -203,334 +209,10 @@ Config.h Options
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)))
Keymap
------
Many of existent projects offer keymap framework to define your own keymap easily. The following will explain how you can define keymap using this framework.
Instead, you can also implement your own `keymap_get_action()` to return action code for each key if you want.
Change your keymap
------------------
[keymap.md](doc/keymap.md)
This is keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard. Keymap is defined in `keymaps[]` array.
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Layer 0: Default Layer
* ,-----------------------------------------------------------.
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `|
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs|
* |-----------------------------------------------------------|
* |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter |
* |-----------------------------------------------------------|
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn1|
* `-----------------------------------------------------------'
* |Gui|Alt |Space |Alt |Fn2|
* `-------------------------------------------'
*/
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
LCTL,A, S, D, F, G, H, J, K, L, FN2, QUOT,ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN1, \
LGUI,LALT, SPC, RALT,FN3),
/* Layer 1: HHKB mode (HHKB Fn)
* ,-----------------------------------------------------------.
* |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
* |-----------------------------------------------------------|
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
* |-----------------------------------------------------------|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift |Fn1|
* `-----------------------------------------------------------'
* |Gui |Alt |Space |Alt |Gui|
* `--------------------------------------------'
*/
KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, BSPC, \
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN0, \
LGUI,LALT, SPC, RALT,RGUI),
/* Layer 2: Mouse mode (Semicolon)
* ,-----------------------------------------------------------.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
* |-----------------------------------------------------------|
* |Contro| | | | | |McL|McD|McU|McR|Fn0| |Return |
* |-----------------------------------------------------------|
* |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
* `-----------------------------------------------------------'
* |Gui |Alt |Mb1 |Alt |Fn0|
* `--------------------------------------------'
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
*/
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \
LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, QUOT,ENT, \
LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,NO, \
LGUI,LALT, BTN1, RALT,FN0),
};
static const uint16_t PROGMEM fn_actions[] = {
ACTION_LAYER_DEFAULT, // FN0
ACTION_LAYER_SET(1), // FN1
ACTION_LAYER_SET_TAP_KEY(2, KC_SCLN), // FN2
ACTION_LAYER_BIT_TOGGLE(2), // FN3
};
### 1. Keycode
See `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.
***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`.
#### 1.0 Other key
- `KC_NO` for no aciton
- `KC_TRNS` for transparent layer
#### 1.1 Normal key
- `KC_A` to `KC_Z`, `KC_1` to `KC_0` for alpha numeric key
- `KC_MINS`, `KC_EQL`, `KC_GRV`, `KC_RBRC`, `KC_LBRC`, `KC_COMM`, `KC_DOT`, `KC_BSLS`, `KC_SLSH`, `KC_SCLN`, `KC_QUOT`
- `KC_ESC`, `KC_TAB`, `KC_SPC`, `KC_BSPC`, `KC_ENT`, `KC_DEL`, `KC_INS`
- `KC_UP`, `KC_DOWN`, `KC_RGHT`, `KC_LEFT`, `KC_PGUP`, `KC_PGDN`, `KC_HOME`, `KC_END`
- `KC_CAPS`, `KC_NLCK`, `KC_SLCK`, `KC_PSCR`, `KC_PAUS`, `KC_APP`, `KC_F1` to `KC_F24`
- `KC_P1` to `KC_P0`, `KC_PDOT`, `KC_PCMM`, `KC_PSLS`, `KC_PAST`, `KC_PMNS`, `KC_PPLS`, `KC_PEQL`, `KC_PENT` for keypad.
#### 1.2 Modifier
There are 8 modifiers which has discrimination between left and right.
- `KC_LCTL` and `KC_RCTL` for Control
- `KC_LSFT` and `KC_RSFT` for Shift
- `KC_LALT` and `KC_RALT` for Alt
- `KC_LGUI` and `KC_RGUI` for Windows key or Command key in Mac
#### 1.3 Fn key
`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.***
#### 1.4 Mousekey
- `KC_MS_U`, `KC_MS_D`, `KC_MS_L`, `KC_MS_R` for mouse cursor
- `KC_WH_U`, `KC_WH_D`, `KC_WH_L`, `KC_WH_R` for mouse wheel
- `KC_BTN1`, `KC_BTN2`, `KC_BTN3`, `KC_BTN4`, `KC_BTN5` for mouse buttons
#### 1.5 System & Media key
- `KC_PWR`, `KC_SLEP`, `KC_WAKE` for Power, Sleep, Wake
- `KC_MUTE`, `KC_VOLU`, `KC_VOLD` for audio volume control
- `KC_MNXT`, `KC_MPRV`, `KC_MSTP`, `KC_MPLY`, `KC_MSEL` for media control
- `KC_MAIL`, `KC_CALC`, `KC_MYCM` for application launch
- `KC_WSCH`, `KC_WHOM`, `KC_WBAK`, `KC_WFWD`, `KC_WSTP`, `KC_WREF`, `KC_WFAV` for web browser operation
#### Keycode Table
See [keycode table](doc/keycode.txt) in `doc/keycode.txt` or `common/keycode.h` for the detail or other keycodes.
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.
[HID usage]: http://www.usb.org/developers/devclass_docs/Hut1_11.pdf
### 2. Action
See `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.
Most 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'*.
#### 2.1 Key action
Key is simple action that registers keycode on press of key and unregister on release.
You can define `Key` action on *'A'* key with:
ACTION_KEY(KC_A)
But you don't need to use this expression directly because you can just put symbol `A` in `KEYMAP` definition.
Say you want to assign a key to `Shift + 1` to get charactor *'!'* or `Alt + Tab` to switch windows.
ACTION_MOD_KEY(KC_LSHIFT, KC_1)
ACTION_MOD_KEY(KC_LALT, KC_TAB)
Or `Alt,Shift + Tab` can be defined.
ACTION_MODS_KEY((MOD_BIT(KC_LALT) | MOD_BIT(KC_LSHIFT)), KC_TAB)
These actions are comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes.
#### 2.2 Layer Actions
This sets `default layer` into `current layer`. With this action you can return to `default layer`.
ACTION_LAYER_DEFAULT
`Layer Set` action sets given layer argument to `current layer`. `Layer Set` action can take 0 to 15 as argument.
ACTION_LAYER_SET(layer)
ACTION_LAYER_SET_TOGGLE(layer)
ACTION_LAYER_SET_TAP_KEY(layer, key)
ACTION_LAYER_SET_TAP_TOGGLE(layer)
`Layer Bit` action XOR given bits with `current layer`. `Layer Bit` action can take 0 to 15 as argument.
ACTION_LAYER_BIT(bits)
ACTION_LAYER_BIT_TOGGLE(bits)
ACTION_LAYER_BIT_TAP_KEY(bits, key)
ACTION_LAYER_BIT_TAP_TOGGLE(bits)
These acitons change `default layer`.
ACTION_LAYER_SET_DEFAULT(layer)
ACTION_LAYER_BIT_DEFAULT(bits)
#### 2.3 Macro action
***NOT FIXED***
`Macro` action indicates complex key strokes.
MACRO( MD(LSHIFT), D(D), END )
MACRO( U(D), MU(LSHIFT), END )
MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )
##### 2.3.1 Normal mode
- **I()** change interavl of stroke.
- **D()** press key
- **U()** release key
- **T()** type key(press and release)
- **W()** wait
- **MD()** modifier down
- **MU()** modifier up
- **END** end mark
##### 2.3.2 Extended mode
***TODO: sample impl***
See `keyboard/hhkb/keymap.c` for sample.
#### 2.4 Function action
***NOT FIXED***
There are two type of action, normal `Function` and tappable `Function`.
These actions call user defined function with `id`, `opt`, and key event information as arguments.
##### 2.4.1 Function
To define normal `Function` action in keymap use this.
ACTION_FUNCTION(id, opt)
##### 2.4.2 Function with tap
To define tappable `Function` action in keymap use this.
ACTION_FUNCTION_TAP(id, opt)
##### 2.4.3 Implement user function
`Function` actions can be defined freely with C by user in callback function:
void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt)
This 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.
`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.
typedef struct {
keyevent_t event;
uint8_t tap_count;
} keyrecord_t;
typedef struct {
key_t key;
bool pressed;
uint16_t time;
} keyevent_t;
typedef struct {
uint8_t col;
uint8_t row;
} key_t;
***TODO: sample impl***
See `keyboard/hhkb/keymap.c` for sample.
### 3. Layer
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.
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.
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.
### 4. Layer switching
You can have some ways to switch layer with these actions.
There are two kind of layer switch action `Layer Set` and `Layer Bit` and two type of switching behaviour **Momentary** and **Toggle**.
#### 4.1 Momentary switching
Momentary switching changes layer only while holding Fn key.
##### 4.1.1 Momentary Set
This `Layer Set` action sets new layer `Layer 1` to `current layer` on key press event.
ACTION_LAYER_SET(1)
It 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.
ACTION_LAYER_DEFAULT
##### 4.1.2 Momentary Bit
This `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.
ACTION_LAYER_BIT(1)
#### 4.2 Toggle switching
Toggle switching changes layer after press then release. You keep being on the layer until you press key to return.
##### 4.2.1 Toggle Set
This `Layer Set Toggle` action is to set `Layer 1` to `current layer` on release and do none on press.
ACTION_LAYER_SET_TOGGLE(1)
To get back to `default layer` you can use this action.
ACTION_LAYER_DEFAULT
##### 4.2.2 Toggle Bit
This `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.
ACTION_LAYER_BIT_TOGGLE(1)
#### 4.3 Momentary switching with Tap key
These actions switch to layer only while holding `Fn` key and register key on tap. **Tap** means to press and release key quickly.
ACTION_LAYER_SET_TAP_KEY(2, KC_SCLN)
ACTION_LAYER_SET_BIT_KEY(2, KC_SCLN)
With these you can place layer switching function on normal alphabet key like `;` without losing its original register function.
#### 4.4 Momentary switching with Tap Toggle
This changes layer only while holding `Fn` key and toggle layer after several taps. **Tap** means to press and release key quickly.
ACTION_LAYER_SET_TAP_TOGGLE(layer)
ACTION_LAYER_BIT_TAP_TOGGLE(layer)
Number of taps can be defined with `TAPPING_TOGGLE` in `config.h`, `5` by default.
Legacy Keymap
-------------
This 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.
In 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.
In 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.
static const uint8_t PROGMEM fn_layer[] = {
1, // Fn0
2, // Fn1
2, // Fn2
};
static const uint8_t PROGMEM fn_keycode[] = {
KC_NO, // Fn0
KC_NO, // Fn1
KC_SPC, // Fn2
};

View file

@ -3,6 +3,7 @@ SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/keyboard.c \
$(COMMON_DIR)/action.c \
$(COMMON_DIR)/action_macro.c \
$(COMMON_DIR)/layer_switch.c \
$(COMMON_DIR)/keymap.c \
$(COMMON_DIR)/command.c \
$(COMMON_DIR)/timer.c \

View file

@ -23,15 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "command.h"
#include "util.h"
#include "debug.h"
#include "layer_switch.h"
#include "action_macro.h"
#include "action.h"
/* default layer indicates base layer */
uint8_t default_layer = 0;
/* current layer indicates active layer at this time */
uint8_t current_layer = 0;
static void process_action(keyrecord_t *record);
static bool process_tapping(keyrecord_t *record);
static void waiting_buffer_scan_tap(void);
@ -207,28 +203,18 @@ void action_exec(keyevent_t event)
}
}
static action_t get_action(key_t key)
{
action_t action = action_for_key(current_layer, key);
/* Transparently use default layer */
if (action.code == ACTION_TRANSPARENT) {
// TODO: layer stacking
action = action_for_key(default_layer, key);
debug("TRNASPARENT: "); debug_hex16(action.code); debug("\n");
}
return action;
}
static void process_action(keyrecord_t *record)
{
keyevent_t event = record->event;
uint8_t tap_count = record->tap_count;
uint8_t tap_count = record->tap.count;
if (IS_NOEVENT(event)) { return; }
action_t action = get_action(event.key);
debug("ACTION: "); debug_action(action); debug("\n");
action_t action = layer_switch_get_action(event.key);
debug("ACTION: "); debug_action(action);
debug(" overlays: "); overlay_debug();
debug(" keymaps: "); keymap_debug();
debug(" default_layer: "); debug_dec(default_layer); debug("\n");
switch (action.kind.id) {
/* Key and Mods */
@ -287,7 +273,7 @@ static void process_action(keyrecord_t *record)
} else {
if (tap_count == 0) {
debug("MODS_TAP: Oneshot: cancel/del_mods\n");
// cancel oneshot by holding.
// cancel oneshot on hold
oneshot_cancel();
del_mods(mods);
}
@ -309,7 +295,7 @@ static void process_action(keyrecord_t *record)
if (waiting_buffer_has_anykey_pressed()) {
debug("MODS_TAP: Tap: Cancel: add_mods\n");
// ad hoc: set 0 to cancel tap
record->tap_count = 0;
record->tap.count = 0;
add_mods(mods);
} else {
debug("MODS_TAP: Tap: register_code\n");
@ -368,145 +354,316 @@ static void process_action(keyrecord_t *record)
#endif
break;
/* Layer key */
case ACT_LAYER:
case ACT_KEYMAP:
switch (action.layer.code) {
case LAYER_MOMENTARY: /* momentary */
if (event.pressed) {
layer_switch(action.layer.val);
}
else {
// NOTE: This is needed by legacy keymap support
layer_switch(default_layer);
}
break;
case LAYER_ON_PRESS:
if (event.pressed) {
layer_switch(action.layer.val);
}
break;
case LAYER_ON_RELEASE:
if (!event.pressed) {
layer_switch(action.layer.val);
}
break;
case LAYER_DEFAULT: /* default layer */
switch (action.layer.val) {
case DEFAULT_ON_BOTH:
layer_switch(default_layer);
/* Keymap clear */
case OP_RESET:
switch (action.layer.val & 0x03) {
case 0:
// NOTE: reserved
overlay_clear();
keymap_clear();
break;
case DEFAULT_ON_PRESS:
case ON_PRESS:
if (event.pressed) {
layer_switch(default_layer);
overlay_clear();
keymap_clear();
}
break;
case DEFAULT_ON_RELEASE:
case ON_RELEASE:
if (!event.pressed) {
layer_switch(default_layer);
overlay_clear();
keymap_clear();
}
break;
case ON_BOTH:
overlay_clear();
keymap_clear();
break;
/* NOTE: 4-7 rserved */
}
break;
case LAYER_TAP_TOGGLE: /* switch on hold and toggle on several taps */
/* Keymap Reset default layer */
case (OP_RESET | ON_PRESS):
if (event.pressed) {
default_layer_set(action.layer.val);
}
break;
case (OP_RESET | ON_RELEASE):
if (!event.pressed) {
default_layer_set(action.layer.val);
}
break;
case (OP_RESET | ON_BOTH):
default_layer_set(action.layer.val);
break;
/* Keymap Bit invert */
case OP_INV:
/* with tap toggle */
if (event.pressed) {
if (tap_count < TAPPING_TOGGLE) {
layer_switch(action.layer.val);
debug("KEYMAP_INV: tap toggle(press).\n");
keymap_invert(action.layer.val);
}
} else {
if (tap_count >= TAPPING_TOGGLE) {
debug("LAYER_PRESSED: tap toggle.\n");
layer_switch(action.layer.val);
if (tap_count <= TAPPING_TOGGLE) {
debug("KEYMAP_INV: tap toggle(release).\n");
keymap_invert(action.layer.val);
}
}
break;
case LAYER_CHANGE_DEFAULT: /* change default layer */
case (OP_INV | ON_PRESS):
if (event.pressed) {
default_layer = action.layer.val;
layer_switch(default_layer);
keymap_invert(action.layer.val);
}
break;
default: /* switch layer on hold and key on tap*/
case (OP_INV | ON_RELEASE):
if (!event.pressed) {
keymap_invert(action.layer.val);
}
break;
case (OP_INV | ON_BOTH):
keymap_invert(action.layer.val);
break;
/* Keymap Bit on */
case OP_ON:
if (event.pressed) {
if (tap_count > 0) {
debug("LAYER_PRESSED: Tap: register_code\n");
keymap_on(action.layer.val);
} else {
keymap_off(action.layer.val);
}
break;
case (OP_ON | ON_PRESS):
if (event.pressed) {
keymap_on(action.layer.val);
}
break;
case (OP_ON | ON_RELEASE):
if (!event.pressed) {
keymap_on(action.layer.val);
}
break;
case (OP_ON | ON_BOTH):
keymap_on(action.layer.val);
break;
/* Keymap Bit off */
case OP_OFF:
if (event.pressed) {
keymap_off(action.layer.val);
} else {
keymap_on(action.layer.val);
}
break;
case (OP_OFF | ON_PRESS):
if (event.pressed) {
keymap_off(action.layer.val);
}
break;
case (OP_OFF | ON_RELEASE):
if (!event.pressed) {
keymap_off(action.layer.val);
}
break;
case (OP_OFF | ON_BOTH):
keymap_off(action.layer.val);
break;
/* Keymap Bit set */
case OP_SET:
if (event.pressed) {
keymap_set(action.layer.val);
} else {
keymap_clear();
}
break;
case (OP_SET | ON_PRESS):
if (event.pressed) {
keymap_set(action.layer.val);
}
break;
case (OP_SET | ON_RELEASE):
if (!event.pressed) {
keymap_set(action.layer.val);
}
break;
case (OP_SET | ON_BOTH):
keymap_set(action.layer.val);
break;
/* Keymap Bit invert with tap key */
default:
if (event.pressed) {
if (tap_count > 0) {
debug("KEYMAP_TAP_KEY: Tap: register_code\n");
register_code(action.layer.code);
} else {
debug("LAYER_PRESSED: No tap: layer_switch\n");
layer_switch(action.layer.val);
}
} else {
debug("KEYMAP_TAP_KEY: No tap: On on press\n");
keymap_on(action.layer.val);
}
} else {
if (tap_count > 0) {
debug("LAYER_PRESSED: Tap: unregister_code\n");
debug("KEYMAP_TAP_KEY: Tap: unregister_code\n");
unregister_code(action.layer.code);
} else {
//debug("LAYER_PRESSED: No tap: NO ACTION\n");
// NOTE: This is needed by legacy keymap support
debug("LAYER_PRESSED: No tap: return to default layer\n");
layer_switch(default_layer);
debug("KEYMAP_TAP_KEY: No tap: Off on release\n");
keymap_off(action.layer.val);
}
}
break;
}
break;
case ACT_LAYER_BIT:
case ACT_OVERLAY:
switch (action.layer.code) {
case LAYER_MOMENTARY: /* momentary */
if (event.pressed) {
layer_switch(current_layer ^ action.layer.val);
// Overlay Invert bit4
case OP_INV4 | 0:
if (action.layer.val == 0) {
// NOTE: reserved for future use
overlay_clear();
} else {
layer_switch(current_layer ^ action.layer.val);
overlay_set(overlay_stat ^ action.layer.val);
}
break;
case LAYER_ON_PRESS:
if (event.pressed) {
layer_switch(current_layer ^ action.layer.val);
case OP_INV4 | 1:
if (action.layer.val == 0) {
// on pressed
if (event.pressed) overlay_clear();
} else {
overlay_set(overlay_stat ^ action.layer.val<<4);
}
break;
case LAYER_ON_RELEASE:
if (!event.pressed) {
layer_switch(current_layer ^ action.layer.val);
case OP_INV4 | 2:
if (action.layer.val == 0) {
// on released
if (!event.pressed) overlay_clear();
} else {
overlay_set(overlay_stat ^ action.layer.val<<8);
}
break;
case LAYER_TAP_TOGGLE: /* switch on hold and toggle on several taps */
case OP_INV4 | 3:
if (action.layer.val == 0) {
// on both
overlay_clear();
} else {
overlay_set(overlay_stat ^ action.layer.val<<12);
}
break;
/* Overlay Bit invert */
case OP_INV:
/* with tap toggle */
if (event.pressed) {
if (tap_count < TAPPING_TOGGLE) {
debug("LAYER_BIT: tap toggle(press).\n");
layer_switch(current_layer ^ action.layer.val);
debug("OVERLAY_INV: tap toggle(press).\n");
overlay_invert(action.layer.val);
}
} else {
if (tap_count <= TAPPING_TOGGLE) {
debug("LAYER_BIT: tap toggle(release).\n");
layer_switch(current_layer ^ action.layer.val);
debug("OVERLAY_INV: tap toggle(release).\n");
overlay_invert(action.layer.val);
}
}
break;
case 0xFF:
// change default layer
case (OP_INV | ON_PRESS):
if (event.pressed) {
default_layer = current_layer ^ action.layer.val;
layer_switch(default_layer);
} else {
default_layer = current_layer ^ action.layer.val;
layer_switch(default_layer);
overlay_invert(action.layer.val);
}
break;
default:
// with tap key
case (OP_INV | ON_RELEASE):
if (!event.pressed) {
overlay_invert(action.layer.val);
}
break;
case (OP_INV | ON_BOTH):
overlay_invert(action.layer.val);
break;
/* Overlay Bit on */
case OP_ON:
if (event.pressed) {
if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
debug("LAYER_BIT: Tap: register_code\n");
overlay_on(action.layer.val);
} else {
overlay_off(action.layer.val);
}
break;
case (OP_ON | ON_PRESS):
if (event.pressed) {
overlay_on(action.layer.val);
}
break;
case (OP_ON | ON_RELEASE):
if (!event.pressed) {
overlay_on(action.layer.val);
}
break;
case (OP_ON | ON_BOTH):
overlay_on(action.layer.val);
break;
/* Overlay Bit off */
case OP_OFF:
if (event.pressed) {
overlay_off(action.layer.val);
} else {
overlay_on(action.layer.val);
}
break;
case (OP_OFF | ON_PRESS):
if (event.pressed) {
overlay_off(action.layer.val);
}
break;
case (OP_OFF | ON_RELEASE):
if (!event.pressed) {
overlay_off(action.layer.val);
}
break;
case (OP_OFF | ON_BOTH):
overlay_off(action.layer.val);
break;
/* Overlay Bit set */
case OP_SET:
if (event.pressed) {
overlay_move(action.layer.val);
} else {
overlay_clear();
}
break;
case (OP_SET | ON_PRESS):
if (event.pressed) {
overlay_move(action.layer.val);
}
break;
case (OP_SET | ON_RELEASE):
if (!event.pressed) {
overlay_move(action.layer.val);
}
break;
case (OP_SET | ON_BOTH):
overlay_move(action.layer.val);
break;
/* Overlay Bit invert with tap key */
default:
if (event.pressed) {
if (tap_count > 0) {
debug("OVERLAY_TAP_KEY: Tap: register_code\n");
register_code(action.layer.code);
} else {
debug("LAYER_BIT: No tap: layer_switch(bit on)\n");
layer_switch(current_layer ^ action.layer.val);
debug("OVERLAY_TAP_KEY: No tap: On on press\n");
overlay_on(action.layer.val);
}
} else {
if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
debug("LAYER_BIT: Tap: unregister_code\n");
if (tap_count > 0) {
debug("OVERLAY_TAP_KEY: Tap: unregister_code\n");
unregister_code(action.layer.code);
} else {
debug("LAYER_BIT: No tap: layer_switch(bit off)\n");
layer_switch(current_layer ^ action.layer.val);
debug("OVERLAY_TAP_KEY: No tap: Off on release\n");
overlay_off(action.layer.val);
}
}
break;
@ -515,7 +672,7 @@ static void process_action(keyrecord_t *record)
/* Extentions */
case ACT_MACRO:
// TODO
action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
break;
case ACT_COMMAND:
break;
@ -540,16 +697,17 @@ static bool process_tapping(keyrecord_t *keyp)
// if tapping
if (IS_TAPPING_PRESSED()) {
if (WITHIN_TAPPING_TERM(event)) {
if (tapping_key.tap_count == 0) {
if (tapping_key.tap.count == 0) {
if (IS_TAPPING_KEY(event.key) && !event.pressed) {
// first tap!
debug("Tapping: First tap(0->1).\n");
tapping_key.tap_count = 1;
tapping_key.tap.count = 1;
tapping_key.tap.interrupted = (waiting_buffer_has_anykey_pressed() ? true : false);
debug_tapping_key();
process_action(&tapping_key);
// enqueue
keyp->tap_count = tapping_key.tap_count;
keyp->tap = tapping_key.tap;
return false;
}
#if TAPPING_TERM >= 500
@ -573,19 +731,19 @@ static bool process_tapping(keyrecord_t *keyp)
// tap_count > 0
else {
if (IS_TAPPING_KEY(event.key) && !event.pressed) {
debug("Tapping: Tap release("); debug_dec(tapping_key.tap_count); debug(")\n");
keyp->tap_count = tapping_key.tap_count;
debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n");
keyp->tap = tapping_key.tap;
process_action(keyp);
tapping_key = *keyp;
debug_tapping_key();
return true;
}
else if (is_tap_key(keyp->event.key) && event.pressed) {
if (tapping_key.tap_count > 1) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last tap(>1).\n");
// unregister key
process_action(&(keyrecord_t){
.tap_count = tapping_key.tap_count,
.tap = tapping_key.tap,
.event.key = tapping_key.event.key,
.event.time = event.time,
.event.pressed = false
@ -609,7 +767,7 @@ static bool process_tapping(keyrecord_t *keyp)
}
// after TAPPING_TERM
else {
if (tapping_key.tap_count == 0) {
if (tapping_key.tap.count == 0) {
debug("Tapping: End. Timeout. Not tap(0): ");
debug_event(event); debug("\n");
process_action(&tapping_key);
@ -619,17 +777,17 @@ static bool process_tapping(keyrecord_t *keyp)
} else {
if (IS_TAPPING_KEY(event.key) && !event.pressed) {
debug("Tapping: End. last timeout tap release(>0).");
keyp->tap_count = tapping_key.tap_count;
keyp->tap = tapping_key.tap;
process_action(keyp);
tapping_key = (keyrecord_t){};
return true;
}
else if (is_tap_key(keyp->event.key) && event.pressed) {
if (tapping_key.tap_count > 1) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
// unregister key
process_action(&(keyrecord_t){
.tap_count = tapping_key.tap_count,
.tap = tapping_key.tap,
.event.key = tapping_key.event.key,
.event.time = event.time,
.event.pressed = false
@ -653,10 +811,11 @@ static bool process_tapping(keyrecord_t *keyp)
}
} else if (IS_TAPPING_RELEASED()) {
if (WITHIN_TAPPING_TERM(event)) {
if (tapping_key.tap_count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
if (tapping_key.tap.count > 0 && IS_TAPPING_KEY(event.key) && event.pressed) {
// sequential tap.
keyp->tap_count = tapping_key.tap_count + 1;
debug("Tapping: Tap press("); debug_dec(keyp->tap_count); debug(")\n");
keyp->tap = tapping_key.tap;
keyp->tap.count += 1;
debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
process_action(keyp);
tapping_key = *keyp;
debug_tapping_key();
@ -701,16 +860,16 @@ static bool process_tapping(keyrecord_t *keyp)
static void waiting_buffer_scan_tap(void)
{
// tapping already is settled
if (tapping_key.tap_count > 0) return;
// invalid state: tapping_key released && tap_count == 0
if (tapping_key.tap.count > 0) return;
// invalid state: tapping_key released && tap.count == 0
if (!tapping_key.event.pressed) return;
for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
!waiting_buffer[i].event.pressed &&
WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
tapping_key.tap_count = 1;
waiting_buffer[i].tap_count = 1;
tapping_key.tap.count = 1;
waiting_buffer[i].tap.count = 1;
process_action(&tapping_key);
debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
@ -813,39 +972,24 @@ bool sending_anykey(void)
host_last_sysytem_report() || host_last_consumer_report());
}
void layer_switch(uint8_t new_layer)
{
if (current_layer != new_layer) {
debug("Layer Switch: "); debug_hex(current_layer);
debug(" -> "); debug_hex(new_layer); debug("\n");
current_layer = new_layer;
clear_keyboard_but_mods(); // To avoid stuck keys
// NOTE: update mods with full scan of matrix? if modifier changes between layers
}
}
bool is_tap_key(key_t key)
{
action_t action = get_action(key);
action_t action = layer_switch_get_action(key);
switch (action.kind.id) {
case ACT_LMODS_TAP:
case ACT_RMODS_TAP:
return true;
case ACT_LAYER:
case ACT_LAYER_BIT:
case ACT_KEYMAP:
case ACT_OVERLAY:
switch (action.layer.code) {
case LAYER_MOMENTARY:
case LAYER_ON_PRESS:
case LAYER_ON_RELEASE:
case LAYER_DEFAULT:
return false;
case LAYER_TAP_TOGGLE:
default: /* tap key */
case 0x04 ... 0xEF: /* tap key */
case OP_INV:
return true;
default:
return false;
}
return false;
case ACT_MACRO:
case ACT_FUNCTION:
if (action.func.opt & FUNC_TAP) { return true; }
return false;
@ -865,7 +1009,8 @@ static void debug_event(keyevent_t event)
}
static void debug_record(keyrecord_t record)
{
debug_event(record.event); debug(":"); debug_dec(record.tap_count);
debug_event(record.event); debug(":"); debug_dec(record.tap.count);
if (record.tap.interrupted) debug("-");
}
static void debug_action(action_t action)
{
@ -876,8 +1021,8 @@ static void debug_action(action_t action)
case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break;
case ACT_USAGE: debug("ACT_USAGE"); break;
case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break;
case ACT_LAYER: debug("ACT_LAYER"); break;
case ACT_LAYER_BIT: debug("ACT_LAYER_BIT"); break;
case ACT_KEYMAP: debug("ACT_KEYMAP"); break;
case ACT_OVERLAY: debug("ACT_OVERLAY"); break;
case ACT_MACRO: debug("ACT_MACRO"); break;
case ACT_COMMAND: debug("ACT_COMMAND"); break;
case ACT_FUNCTION: debug("ACT_FUNCTION"); break;

View file

@ -19,12 +19,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keyboard.h"
#include "keycode.h"
#include "action_macro.h"
/* Struct to record event and tap count */
typedef union {
struct {
bool interrupted :1;
bool reserved2 :1;
bool reserved1 :1;
bool reserved0 :1;
uint8_t count :4;
};
} tap_t;
typedef struct {
keyevent_t event;
uint8_t tap_count;
tap_t tap;
} keyrecord_t;
/* Action struct.
@ -76,17 +87,15 @@ typedef union {
/* layer used currently */
extern uint8_t current_layer;
/* layer to return or start with */
extern uint8_t default_layer;
/* Execute action per keyevent */
void action_exec(keyevent_t event);
/* action for key */
action_t action_for_key(uint8_t layer, key_t key);
/* macro */
const prog_macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt);
/* user defined special function */
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
@ -112,8 +121,8 @@ bool waiting_buffer_has_anykey_pressed(void);
* ============
* 16bit code: action_kind(4bit) + action_parameter(12bit)
*
* Keyboard Keys
* -------------
* Keyboard Keys(00XX)
* -------------------
* ACT_LMODS(0000):
* 0000|0000|000000|00 No action
* 0000|0000|000000|01 Transparent
@ -143,8 +152,8 @@ bool waiting_buffer_has_anykey_pressed(void);
* 0011|mods| keycode Right mods + tap Key
*
*
* Other HID Usage
* ---------------
* Other keys(01XX)
* --------------------
* This action handles other usages than keyboard.
* ACT_USAGE(0100):
* 0100|00| usage(10) System control(0x80) - General Desktop page(0x01)
@ -152,41 +161,45 @@ bool waiting_buffer_has_anykey_pressed(void);
* 0100|10| usage(10) (reserved)
* 0100|11| usage(10) (reserved)
*
*
* Mouse Keys
* ----------
* TODO: can be combined with 'Other HID Usage'? to save action kind id.
* ACT_MOUSEKEY(0110):
* 0101|XXXX| keycode Mouse key
*
*
* Layer Actions
* -------------
* ACT_LAYER(1000): Set layer
* ACT_LAYER_BIT(1001): Bit-op layer
*
* 1000|LLLL|0000 0000 set L to layer on press and set default on release(momentary)
* 1000|LLLL|0000 0001 set L to layer on press
* 1000|LLLL|0000 0010 set L to layer on release
* 1000|----|0000 0011 set default to layer on both(return to default layer)
* 1000|LLLL| keycode set L to layer while hold and send key on tap
* 1000|LLLL|1111 0000 set L to layer while hold and toggle on several taps
* 1000|LLLL|1111 1111 set L to default and layer(on press)
*
* 1001|BBBB|0000 0000 (not used)
* 1001|BBBB|0000 0001 bit-xor layer with B on press
* 1001|BBBB|0000 0010 bit-xor layer with B on release
* 1001|BBBB|0000 0011 bit-xor layer with B on both(momentary)
* 1001|BBBB| keycode bit-xor layer with B while hold and send key on tap
* 1001|BBBB|1111 0000 bit-xor layer with B while hold and toggle on several taps
* 1001|BBBB|1111 1111 bit-xor default with B and set layer(on press)
* Layer Actions(10XX)
* -------------------
* ACT_KEYMAP:
* 1000|--xx|0000 0000 Clear keyamp and overlay
* 1000|LLLL|0000 00xx Reset default layer and clear keymap and overlay
* 1000|LLLL| keycode Invert with tap key
* 1000|LLLL|1111 0000 Invert with tap toggle
* 1000|LLLL|1111 00xx Invert[^= 1<<L]
* 1000|LLLL|1111 0100 On/Off
* 1000|LLLL|1111 01xx On[|= 1<<L]
* 1000|LLLL|1111 1000 Off/On
* 1000|LLLL|1111 10xx Off[&= ~(1<<L)]
* 1000|LLLL|1111 1100 Set/Clear
* 1000|LLLL|1111 11xx Set[= 1<<L]
* default layer: 0-15(4bit)
* xx: On {00:for special use, 01:press, 10:release, 11:both}
*
* ACT_OVERLAY:
* 1011|0000|0000 0000 Clear overlay
* 1011|LLLL|0000 00ss Invert 4-bit chunk [^= L<<(4*ss)]
* 1011|LLLL| keycode Invert with tap key
* 1011|LLLL|1111 0000 Invert with tap toggle
* 1011|LLLL|1111 00xx Invert[^= 1<<L]
* 1011|LLLL|1111 0100 On/Off(momentary)
* 1011|LLLL|1111 01xx On[|= 1<<L]
* 1011|LLLL|1111 1000 Off/On
* 1011|LLLL|1111 10xx Off[&= ~(1<<L)]
* 1011|LLLL|1111 1100 Set/Clear
* 1011|LLLL|1111 11xx Set[= 1<<L]
* overlays: 16-layer on/off status(16bit)
* xx: On {00:for special use, 01:press, 10:release, 11:both}
*
*
* Extensions(11XX)
* ----------------
* NOTE: NOT FIXED
*
* ACT_MACRO(1100):
* 1100|opt | id(8) Macro play?
* 1100|1111| id(8) Macro record?
@ -208,8 +221,8 @@ enum action_kind_id {
ACT_USAGE = 0b0100,
ACT_MOUSEKEY = 0b0101,
ACT_LAYER = 0b1000,
ACT_LAYER_BIT = 0b1001,
ACT_KEYMAP = 0b1000,
ACT_OVERLAY = 0b1001,
ACT_MACRO = 0b1100,
ACT_COMMAND = 0b1110,
@ -223,20 +236,20 @@ enum action_kind_id {
#define ACTION(kind, param) ((kind)<<12 | (param))
#define MODS4(mods) (((mods)>>4 | (mods)) & 0x0F)
/* Key */
/*
* Key
*/
#define ACTION_KEY(key) ACTION(ACT_LMODS, key)
/* Mods & key */
#define ACTION_LMODS(mods) ACTION(ACT_LMODS, MODS4(mods)<<8 | 0x00)
#define ACTION_LMODS_KEY(mods, key) ACTION(ACT_LMODS, MODS4(mods)<<8 | (key))
#define ACTION_RMODS(mods) ACTION(ACT_RMODS, MODS4(mods)<<8 | 0x00)
#define ACTION_RMODS_KEY(mods, key) ACTION(ACT_RMODS, MODS4(mods)<<8 | (key))
/* Mod & key */
#define ACTION_LMOD(mod) ACTION(ACT_LMODS, MODS4(MOD_BIT(mod))<<8 | 0x00)
#define ACTION_LMOD_KEY(mod, key) ACTION(ACT_LMODS, MODS4(MOD_BIT(mod))<<8 | (key))
#define ACTION_RMOD(mod) ACTION(ACT_RMODS, MODS4(MOD_BIT(mod))<<8 | 0x00)
#define ACTION_RMOD_KEY(mod, key) ACTION(ACT_RMODS, MODS4(MOD_BIT(mod))<<8 | (key))
/* Mods + Tap key */
/* Tap key */
enum mods_codes {
MODS_ONESHOT = 0x00,
};
@ -244,80 +257,11 @@ enum mods_codes {
#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS_TAP, MODS4(mods)<<8 | MODS_ONESHOT)
#define ACTION_RMODS_TAP_KEY(mods, key) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | (key))
#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS_TAP, MODS4(mods)<<8 | MODS_ONESHOT)
/* Mod + Tap key */
#define ACTION_LMOD_TAP_KEY(mod, key) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key))
#define ACTION_LMOD_ONESHOT(mod) ACTION(ACT_LMODS_TAP, MODS4(MOD_BIT(mod))<<8 | MODS_ONESHOT)
#define ACTION_RMOD_TAP_KEY(mod, key) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | (key))
#define ACTION_RMOD_ONESHOT(mod) ACTION(ACT_RMODS_TAP, MODS4(MOD_BIT(mod))<<8 | MODS_ONESHOT)
/*
* Switch layer
*/
enum layer_codes {
LAYER_MOMENTARY = 0,
LAYER_ON_PRESS = 1,
LAYER_ON_RELEASE = 2,
LAYER_DEFAULT =3,
LAYER_TAP_TOGGLE = 0xF0,
LAYER_CHANGE_DEFAULT = 0xFF
};
enum layer_vals_default {
DEFAULT_ON_PRESS = 1,
DEFAULT_ON_RELEASE = 2,
DEFAULT_ON_BOTH = 3,
};
/*
* return to default layer
*/
#define ACTION_LAYER_DEFAULT ACTION_LAYER_DEFAULT_R
/* set default layer on press */
#define ACTION_LAYER_DEFAULT_P ACTION(ACT_LAYER, DEFAULT_ON_PRESS<<8 | LAYER_DEFAULT)
/* set default layer on release */
#define ACTION_LAYER_DEFAULT_R ACTION(ACT_LAYER, DEFAULT_ON_RELEASE<<8 | LAYER_DEFAULT)
/* change default layer and set layer */
/*
* Set layer
*/
/* set layer on press and none on release */
#define ACTION_LAYER_SET(layer) ACTION_LAYER_SET_P(layer)
/* set layer on press and set default on release (This is needed by legacy keymap support.) */
#define ACTION_LAYER_SET_MOMENTARY(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_MOMENTARY)
/* set layer on press and none on release */
#define ACTION_LAYER_SET_TOGGLE(layer) ACTION_LAYER_SET_R(layer)
/* set layer while hold and send key on tap */
#define ACTION_LAYER_SET_TAP_KEY(layer, key) ACTION(ACT_LAYER, (layer)<<8 | (key))
/* set layer on press */
#define ACTION_LAYER_SET_P(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_ON_PRESS)
/* set layer on release */
#define ACTION_LAYER_SET_R(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_ON_RELEASE)
/* set layer on hold and toggle on several taps */
#define ACTION_LAYER_SET_TAP_TOGGLE(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_TAP_TOGGLE)
/* set default layer on both press and release */
#define ACTION_LAYER_SET_DEFAULT(layer) ACTION(ACT_LAYER, (layer)<<8 | LAYER_CHANGE_DEFAULT)
/*
* Bit-op layer
*/
/* bit-xor on both press and release */
#define ACTION_LAYER_BIT(bits) ACTION_LAYER_BIT_MOMENTARY(bits)
#define ACTION_LAYER_BIT_MOMENTARY(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_MOMENTARY)
/* bit-xor on press */
#define ACTION_LAYER_BIT_TOGGLE(bits) ACTION_LAYER_BIT_R(bits)
/* bit-xor while hold and send key on tap */
#define ACTION_LAYER_BIT_TAP_KEY(bits, key) ACTION(ACT_LAYER_BIT, (bits)<<8 | (key))
/* bit-xor on press */
#define ACTION_LAYER_BIT_P(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_ON_PRESS)
/* bit-xor on release */
#define ACTION_LAYER_BIT_R(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_ON_RELEASE)
/* bit-xor while hold and toggle on several taps */
#define ACTION_LAYER_BIT_TAP_TOGGLE(bits) ACTION(ACT_LAYER_BIT, (bits)<<8 | LAYER_TAP_TOGGLE)
/* bit-xor default layer and set layer */
#define ACTION_LAYER_BIT_DEFAULT(bits) ACTION(ACT_LAYER, (bits)<<8 | LAYER_CHANGE_DEFAULT)
/* HID Usage */
enum usage_pages {
PAGE_SYSTEM,
@ -329,17 +273,96 @@ enum usage_pages {
/* Mousekey */
#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key)
/* Layer Actions:
* Invert layer ^= (1<<layer)
* On layer |= (1<<layer)
* Off layer &= ~(1<<layer)
* Set layer = (1<<layer)
* Clear layer = 0
*/
enum layer_params {
ON_PRESS = 1,
ON_RELEASE = 2,
ON_BOTH = 3,
OP_RESET = 0x00,
OP_INV4 = 0x00,
OP_INV = 0xF0,
OP_ON = 0xF4,
OP_OFF = 0xF8,
OP_SET = 0xFC,
};
/*
* Default Layer
*/
#define ACTION_DEFAULT_LAYER ACTION(ACT_KEYMAP, ON_RELEASE<<8 | OP_RESET | 0)
#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_TO(layer, ON_RELEASE)
#define ACTION_DEFAULT_LAYER_TO(layer, on) ACTION(ACT_KEYMAP, (layer)<<8 | OP_RESET | (on))
/*
* Keymap Layer
*/
#define ACTION_KEYMAP_MOMENTARY(layer) ACTION_KEYMAP_ON_OFF(layer)
#define ACTION_KEYMAP_TOGGLE(layer) ACTION_KEYMAP_INV(layer, ON_RELEASE)
/* Keymap Invert */
#define ACTION_KEYMAP_INV(layer, on) ACTION(ACT_KEYMAP, (layer)<<8 | OP_INV | (on))
#define ACTION_KEYMAP_TAP_TOGGLE(layer) ACTION(ACT_KEYMAP, (layer)<<8 | OP_INV | 0)
/* Keymap On */
#define ACTION_KEYMAP_ON(layer, on) ACTION(ACT_KEYMAP, (layer)<<8 | OP_ON | (on))
#define ACTION_KEYMAP_ON_OFF(layer) ACTION(ACT_KEYMAP, (layer)<<8 | OP_ON | 0)
/* Keymap Off */
#define ACTION_KEYMAP_OFF(layer, on) ACTION(ACT_KEYMAP, (layer)<<8 | OP_OFF | (on))
#define ACTION_KEYMAP_OFF_ON(layer) ACTION(ACT_KEYMAP, (layer)<<8 | OP_OFF | 0)
/* Keymap Set */
#define ACTION_KEYMAP_SET(layer, on) ACTION(ACT_KEYMAP, (layer)<<8 | OP_SET | (on))
#define ACTION_KEYMAP_SET_CLEAR(layer) ACTION(ACT_KEYMAP, (layer)<<8 | OP_SET | 0)
/* Keymap Invert with tap key */
#define ACTION_KEYMAP_TAP_KEY(layer, key) ACTION(ACT_KEYMAP, (layer)<<8 | (key))
/*
* Overlay Layer
*/
#define ACTION_OVERLAY_MOMENTARY(layer) ACTION_OVERLAY_ON_OFF(layer)
#define ACTION_OVERLAY_TOGGLE(layer) ACTION_OVERLAY_INV(layer, ON_RELEASE)
/* Overlay Clear */
#define ACTION_OVERLAY_CLEAR(on) ACTION(ACT_OVERLAY, 0<<8 | OP_INV4 | (on))
/* Overlay Invert 4-bit chunk */
#define ACTION_OVERLAY_INV4(bits, shift) ACTION(ACT_OVERLAY, (bits)<<8 | OP_INV4 | shift)
/* Overlay Invert */
#define ACTION_OVERLAY_INV(layer, on) ACTION(ACT_OVERLAY, (layer)<<8 | OP_INV | (on))
#define ACTION_OVERLAY_TAP_TOGGLE(layer) ACTION(ACT_OVERLAY, (layer)<<8 | OP_INV | 0)
/* Overlay On */
#define ACTION_OVERLAY_ON(layer, on) ACTION(ACT_OVERLAY, (layer)<<8 | OP_ON | (on))
#define ACTION_OVERLAY_ON_OFF(layer) ACTION(ACT_OVERLAY, (layer)<<8 | OP_ON | 0)
/* Overlay Off */
#define ACTION_OVERLAY_OFF(layer, on) ACTION(ACT_OVERLAY, (layer)<<8 | OP_OFF | (on))
#define ACTION_OVERLAY_OFF_ON(layer) ACTION(ACT_OVERLAY, (layer)<<8 | OP_OFF | 0)
/* Overlay Set */
#define ACTION_OVERLAY_SET(layer, on) ACTION(ACT_OVERLAY, (layer)<<8 | OP_SET | (on))
#define ACTION_OVERLAY_SET_CLEAR(layer) ACTION(ACT_OVERLAY, (layer)<<8 | OP_SET | 0)
/* Overlay Invert with tap key */
#define ACTION_OVERLAY_TAP_KEY(layer, key) ACTION(ACT_OVERLAY, (layer)<<8 | (key))
/*
* Extensions
*/
/* Macro */
#define ACTION_MACRO(opt, id) ACTION(ACT_FUNCTION, (opt)<<8 | (addr))
#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id))
#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP<<8 | (id))
#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt)<<8 | (id))
/* Command */
#define ACTION_COMMAND(opt, id) ACTION(ACT_COMMAND, (opt)<<8 | (addr))
#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (addr))
/* Function */
enum function_opts {
FUNC_TAP = 0x8, /* indciates function is tappable */
};
#define ACTION_FUNCTION(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | id)
#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | id)
#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id))
#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | (id))
#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | (id))
#endif /* ACTION_H */

View file

@ -41,7 +41,6 @@ void action_macro_play(const prog_macro_t *macro_p)
case MODS_DOWN:
MACRO_READ();
debug("MODS_DOWN("); debug_hex(macro); debug(")\n");
debug("MODS_UP("); debug_hex(macro); debug(")\n");
add_mods(macro);
break;
case MODS_UP:

View file

@ -20,6 +20,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <avr/pgmspace.h>
#define MACRO_NONE 0
#define MACRO(...) ({ static prog_macro_t _m[] PROGMEM = { __VA_ARGS__ }; _m; })
typedef uint8_t macro_t;
typedef macro_t prog_macro_t PROGMEM;

View file

@ -26,7 +26,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "timer.h"
#include "keyboard.h"
#include "bootloader.h"
#include "layer_switch.h"
#include "command.h"
#ifdef MOUSEKEY_ENABLE
#include "mousekey.h"
#endif
@ -53,7 +55,7 @@ static void mousekey_console_help(void);
#endif
static uint8_t numkey2num(uint8_t code);
static void switch_layer(uint8_t layer);
static void switch_default_layer(uint8_t layer);
typedef enum { ONESHOT, CONSOLE, MOUSEKEY } cmdstate_t;
@ -261,18 +263,16 @@ static bool command_common(uint8_t code)
#endif
break;
#endif
case KC_ESC:
case KC_GRV:
case KC_0:
case KC_F10:
clear_keyboard();
switch_layer(0);
switch_default_layer(0);
break;
case KC_1 ... KC_9:
clear_keyboard();
switch_layer((code - KC_1) + 1);
switch_default_layer((code - KC_1) + 1);
break;
case KC_F1 ... KC_F9:
clear_keyboard();
switch_layer((code - KC_F1) + 1);
case KC_F1 ... KC_F12:
switch_default_layer((code - KC_F1) + 1);
break;
default:
print("?");
@ -541,11 +541,10 @@ static uint8_t numkey2num(uint8_t code)
return 0;
}
static void switch_layer(uint8_t layer)
static void switch_default_layer(uint8_t layer)
{
print_val_hex8(current_layer);
print_val_hex8(default_layer);
current_layer = layer;
default_layer = layer;
print("switch to "); print_val_hex8(layer);
print("switch_default_layer: "); print_dec(default_layer); print(" to "); print_dec(layer); print("\n");
default_layer_set(layer);
overlay_clear();
clear_keyboard();
}

View file

@ -14,13 +14,71 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <avr/pgmspace.h>
#include "keymap.h"
#include "report.h"
#include "keycode.h"
#include "layer_switch.h"
#include "action.h"
#include "action_macro.h"
#include "debug.h"
action_t keymap_keycode_to_action(uint8_t keycode)
static action_t keycode_to_action(uint8_t keycode);
#ifdef USE_KEYMAP_V2
/* converts key to action */
action_t action_for_key(uint8_t layer, key_t key)
{
uint8_t keycode = keymap_key_to_keycode(layer, key);
switch (keycode) {
case KC_FN0 ... KC_FN31:
return keymap_fn_to_action(keycode);
default:
return keycode_to_action(keycode);
}
}
#else
/*
* legacy keymap support
*/
/* translation for legacy keymap */
action_t action_for_key(uint8_t layer, key_t key)
{
/* convert from legacy keycode to action */
/* layer 16-31 indicate 'overlay' but not supported in legacy keymap */
uint8_t keycode = keymap_get_keycode((layer & OVERLAY_MASK), key.row, key.col);
action_t action;
switch (keycode) {
case KC_FN0 ... KC_FN31:
{
uint8_t layer = keymap_fn_layer(FN_INDEX(keycode));
uint8_t key = keymap_fn_keycode(FN_INDEX(keycode));
if (key) {
action.code = ACTION_KEYMAP_TAP_KEY(layer, key);
} else {
action.code = ACTION_KEYMAP_MOMENTARY(layer);
}
}
return action;
default:
return keycode_to_action(keycode);
}
}
#endif
__attribute__ ((weak))
const prog_macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { return MACRO_NONE; }
__attribute__ ((weak))
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {}
/* translates keycode to action */
static action_t keycode_to_action(uint8_t keycode)
{
action_t action;
switch (keycode) {
@ -51,34 +109,3 @@ action_t keymap_keycode_to_action(uint8_t keycode)
}
return action;
}
#ifndef NO_LEGACY_KEYMAP_SUPPORT
/* legacy support with weak reference */
__attribute__ ((weak))
action_t action_for_key(uint8_t layer, key_t key)
{
/* convert from legacy keycode to action */
uint8_t keycode = keymap_get_keycode(layer, key.row, key.col);
action_t action;
switch (keycode) {
case KC_FN0 ... KC_FN31:
{
uint8_t layer = keymap_fn_layer(FN_INDEX(keycode));
uint8_t key = keymap_fn_keycode(FN_INDEX(keycode));
if (key) {
action.code = ACTION_LAYER_SET_TAP_KEY(layer, key);
} else {
action.code = ACTION_LAYER_SET_MOMENTARY(layer);
}
}
return action;
default:
return keymap_keycode_to_action(keycode);
}
}
#endif
__attribute__ ((weak))
void action_function(keyrecord_t *event, uint8_t id, uint8_t opt)
{
}

View file

@ -23,16 +23,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action.h"
/* translates key_t to keycode */
#ifdef USE_KEYMAP_V2
/* translates key to keycode
* layer: 0-15 for base layers
* 16-31 for overlays
*/
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key);
/* translates keycode to action */
action_t keymap_keycode_to_action(uint8_t keycode);
/* translates Fn keycode to action */
action_t keymap_fn_to_action(uint8_t keycode);
#ifndef NO_LEGACY_KEYMAP_SUPPORT
#else
#warning "You are using LEGACY KEYAMP. Consider using NEW KEYMAP."
/*
* legacy keymap support
*/
/* keycode of key */
uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col);
/* layer to move during press Fn key */

201
common/layer_switch.c Normal file
View file

@ -0,0 +1,201 @@
#include <stdint.h>
#include "keyboard.h"
#include "action.h"
#include "debug.h"
#include "util.h"
#include "layer_switch.h"
/*
* Default Layer (0-15)
*/
uint8_t default_layer = 0;
void default_layer_set(uint8_t layer)
{
debug("default_layer_set: ");
debug_dec(default_layer); debug(" to ");
default_layer = layer;
debug_dec(default_layer); debug("\n");
clear_keyboard_but_mods(); // To avoid stuck keys
}
/*
* Keymap Layer (0-15)
*/
uint16_t keymap_stat = 0;
/* return highest layer whose state is on */
uint8_t keymap_get_layer(void)
{
return biton16(keymap_stat);
}
static void keymap_stat_set(uint16_t stat)
{
debug("keymap: ");
keymap_debug(); debug(" to ");
keymap_stat = stat;
keymap_debug(); debug("\n");
clear_keyboard_but_mods(); // To avoid stuck keys
}
void keymap_clear(void)
{
keymap_stat_set(0);
}
void keymap_set(uint16_t stat)
{
keymap_stat_set(stat);
}
void keymap_move(uint8_t layer)
{
keymap_stat_set(1<<layer);
}
void keymap_on(uint8_t layer)
{
keymap_stat_set(keymap_stat | (1<<layer));
}
void keymap_off(uint8_t layer)
{
keymap_stat_set(keymap_stat & ~(1<<layer));
}
void keymap_invert(uint8_t layer)
{
keymap_stat_set(keymap_stat ^ (1<<layer));
}
void keymap_or(uint16_t stat)
{
keymap_stat_set(keymap_stat | stat);
}
void keymap_and(uint16_t stat)
{
keymap_stat_set(keymap_stat & stat);
}
void keymap_xor(uint16_t stat)
{
keymap_stat_set(keymap_stat ^ stat);
}
void keymap_debug(void)
{
debug_hex16(keymap_stat); debug("("); debug_dec(keymap_get_layer()); debug(")");
}
/*
* Overlay Layer (16-31 = 0-15|0x10)
*/
uint16_t overlay_stat = 0;
/* return highest layer whose state is on */
uint8_t overlay_get_layer(void)
{
return biton16(overlay_stat);
}
static void overlay_stat_set(uint16_t stat)
{
debug("overlay: ");
overlay_debug(); debug(" to ");
overlay_stat = stat;
overlay_debug(); debug("\n");
clear_keyboard_but_mods(); // To avoid stuck keys
}
void overlay_clear(void)
{
overlay_stat_set(0);
}
void overlay_set(uint16_t stat)
{
overlay_stat_set(stat);
}
void overlay_move(uint8_t layer)
{
overlay_stat_set(1<<layer);
}
void overlay_on(uint8_t layer)
{
overlay_stat_set(overlay_stat | (1<<layer));
}
void overlay_off(uint8_t layer)
{
overlay_stat_set(overlay_stat & ~(1<<layer));
}
void overlay_invert(uint8_t layer)
{
overlay_stat_set(overlay_stat ^ (1<<layer));
}
void overlay_or(uint16_t stat)
{
overlay_stat_set(overlay_stat | stat);
}
void overlay_and(uint16_t stat)
{
overlay_stat_set(overlay_stat & stat);
}
void overlay_xor(uint16_t stat)
{
overlay_stat_set(overlay_stat ^ stat);
}
void overlay_debug(void)
{
debug_hex16(overlay_stat); debug("("); debug_dec(overlay_get_layer()); debug(")");
}
action_t layer_switch_get_action(key_t key)
{
action_t action;
action.code = ACTION_TRANSPARENT;
/* overlay: top layer first */
for (int8_t i = 15; i >= 0; i--) {
if (overlay_stat & (1<<i)) {
action = action_for_key(i | OVERLAY_BIT, key);
if (action.code != ACTION_TRANSPARENT) {
return action;
}
}
}
/* keymap: top layer first */
for (int8_t i = 15; i >= 0; i--) {
if (keymap_stat & (1<<i)) {
action = action_for_key(i, key);
if (action.code != ACTION_TRANSPARENT) {
return action;
}
}
}
/* default layer */
action = action_for_key(default_layer, key);
return action;
}

80
common/layer_switch.h Normal file
View file

@ -0,0 +1,80 @@
/*
Copyright 2013 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LAYER_SWITCH_H
#define LAYER_SWITCH_H
#include <stdint.h>
#include "keyboard.h"
#include "action.h"
/* overlays are asigned at layer 16-31 */
#define OVERLAY_BIT 0x10
#define OVERLAY_MASK 0x0F
/*
* Default Layer
*/
/* base layer to fall back */
extern uint8_t default_layer;
void default_layer_set(uint8_t layer);
/*
* Keymap Layer
*/
extern uint16_t keymap_stat;
/* return current active layer */
uint8_t keymap_get_layer(void);
void keymap_clear(void);
void keymap_set(uint16_t stat);
void keymap_move(uint8_t layer);
void keymap_on(uint8_t layer);
void keymap_off(uint8_t layer);
void keymap_invert(uint8_t layer);
/* bitwise operation */
void keymap_or(uint16_t stat);
void keymap_and(uint16_t stat);
void keymap_xor(uint16_t stat);
void keymap_debug(void);
/*
* Overlay Layer
*/
extern uint16_t overlay_stat;
/* return current active layer */
uint8_t overlay_get_layer(void);
void overlay_clear(void);
void overlay_set(uint16_t stat);
void overlay_move(uint8_t layer);
void overlay_on(uint8_t layer);
void overlay_off(uint8_t layer);
void overlay_invert(uint8_t layer);
/* bitwise operation */
void overlay_or(uint16_t stat);
void overlay_and(uint16_t stat);
void overlay_xor(uint16_t stat);
void overlay_debug(void);
/* return action depending on current layer status */
action_t layer_switch_get_action(key_t key);
#endif

View file

@ -39,6 +39,7 @@ uint8_t bitpop16(uint16_t bits)
}
// most significant on-bit - return highest location of on-bit
// NOTE: return 0 when bit0 is on or all bits are off
uint8_t biton(uint8_t bits)
{
uint8_t n = 0;
@ -47,3 +48,13 @@ uint8_t biton(uint8_t bits)
if (bits >> 1) { bits >>= 1; n += 1;}
return n;
}
uint8_t biton16(uint16_t bits)
{
uint8_t n = 0;
if (bits >> 8) { bits >>= 8; n += 8;}
if (bits >> 4) { bits >>= 4; n += 4;}
if (bits >> 2) { bits >>= 2; n += 2;}
if (bits >> 1) { bits >>= 1; n += 1;}
return n;
}

View file

@ -31,5 +31,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
uint8_t bitpop(uint8_t bits);
uint8_t bitpop16(uint16_t bits);
uint8_t biton(uint8_t bits);
uint8_t biton16(uint16_t bits);
#endif

View file

@ -0,0 +1,91 @@
# Target file name (without extension).
TARGET = m0110_lufa
# Directory common source filess exist
TOP_DIR = ../..
# Directory keyboard dependent files exist
TARGET_DIR = .
# keyboard dependent files
SRC = keymap.c \
matrix.c \
led.c \
m0110.c
CONFIG_H = config.h
# MCU name, you MUST set this to match the board you are using
# type "make clean" after changing this, so all files will be rebuilt
#MCU = at90usb162 # Teensy 1.0
MCU = atmega32u4 # Teensy 2.0
#MCU = at90usb646 # Teensy++ 1.0
#MCU = at90usb1286 # Teensy++ 2.0
# Processor frequency.
# Normally the first thing your program should do is set the clock prescaler,
# so your program will run at the correct speed. You should also set this
# variable to same clock speed. The _delay_ms() macro uses this, and many
# examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 16000000
#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8
# Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)
# Interrupt driven control endpoint task
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Build Options
# *Comment out* to disable the options.
#
MOUSEKEY_ENABLE = yes # Mouse keys
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = yes # Console for debug
#NKRO_ENABLE = yes # USB Nkey Rollover
# Boot Section Size in bytes
# Teensy halfKay 512
# Atmel DFU loader 4096
# LUFA bootloader 4096
OPT_DEFS += -DBOOT_SIZE=4096
#---------------- Programming Options --------------------------
PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/protocol.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk
hasu: EXTRAFLAGS += -DHASU
hasu: all

View file

@ -53,7 +53,8 @@ You can edit *Makefile* and *config.h* to change compile options and pin configu
$ git clone git://github.com/tmk/tmk_keyboard.git (or download source)
$ cd m0110_usb
$ make
$ make -f Makefile.lufa clean
$ make -f Makefile.lufa
and program your Teensy with [PJRC Teensy loader](http://www.pjrc.com/teensy/loader.html).
@ -74,7 +75,7 @@ You can change keymaps by editing *keymap.c*.
|---------------------------------------------------------| |---------------|
|Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | | 1| 2| 3| |
`---------------------------------------------------------' |-----------|Ent|
|Alt|Gui | Space |Ctl |Alt| | 0| .| |
|Ctl|Alt | Space |Gui |Ctl| | 0| .| |
`-----------------------------------------------' `---------------'
#### *HHKB/WASD Layer(WASD/IJKL)*
,---------------------------------------------------------. ,---------------.
@ -86,7 +87,7 @@ You can change keymaps by editing *keymap.c*.
|---------------------------------------------------------| |---------------|
|Shift |End| |PgD| | | |PgD| |End| |Shift | | 1| 2| 3| |
`---------------------------------------------------------' |-----------|Ent|
|Alt|Gui | Space |Ctl |Alt| | 0| .| |
|Ctl|Alt | Space |Gui |Ctl| | 0| .| |
`-----------------------------------------------' `---------------'
### M0110A

View file

@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x0110
#define DEVICE_VER 0x0100
#define MANUFACTURER t.m.k.
#define PRODUCT M0110 keyboard converter
#define DESCRIPTION convert M0110 keyboard to USB

View file

@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "usb_keyboard.h"
#include "keycode.h"
#include "print.h"
#include "debug.h"
@ -148,7 +147,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |---------------------------------------------------------| |---------------|
* |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| |
* |---------------------------------------------------------| |-----------|Ent|
* |Alt |Gui | Space |Ctl| \|Lft|Rgt|Dn | | 0| .| |
* |Ctl |Alt | Space |Gui| \|Lft|Rgt|Dn | | 0| .| |
* `---------------------------------------------------------' `---------------'
*/
KEYMAP(
@ -156,7 +155,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC, P7, P8, P9, PMNS,
FN0, A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS,
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, UP, P1, P2, P3, PENT,
LALT,LGUI, SPC, LCTL,BSLS,LEFT,RGHT,DOWN, P0, PDOT
LCTL,LALT, SPC, LGUI,BSLS,LEFT,RGHT,DOWN, P0, PDOT
),
/* Cursor Layer(WASD, IJKL)
* ,---------------------------------------------------------. ,---------------.
@ -168,7 +167,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |---------------------------------------------------------| |---------------|
* |Shift |End| |PgD| | | |PgD| |End| |Shif|PgU| | 1| 2| 3| |
* |---------------------------------------------------------| |-----------|Ent|
* |Alt |Gui | Space |Gui |Ins|Hom|End|PgD| | 0| .| |
* |Ctl |Alt | Space |Gui |Ins|Hom|End|PgD| | 0| .| |
* `---------------------------------------------------------' `---------------'
*/
KEYMAP(
@ -176,7 +175,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
CAPS,HOME,UP, PGUP,NO, NO, NO, PGUP,UP, HOME,PSCR,SLCK,PAUS, P7, P8, P9, PMNS,
FN0, LEFT,DOWN,RGHT,NO, NO, NO, LEFT,DOWN,RGHT,NO, NO, ENT, P4, P5, P6, PPLS,
LSFT,END, NO, PGDN,NO, NO, NO, PGDN,NO, END, NO, PGUP, P1, P2, P3, PENT,
LALT,LGUI, SPC, LCTL,INS, HOME,END, PGDN, P0, PDOT
LCTL,LALT, SPC, LGUI,INS, HOME,END, PGDN, P0, PDOT
),
};

View file

@ -0,0 +1,83 @@
# Target file name (without extension).
TARGET = pc98_usb
# Directory common source filess exist
TOP_DIR = ../..
# Directory keyboard dependent files exist
TARGET_DIR = .
# keyboard dependent files
SRC = keymap.c \
matrix.c \
led.c \
protocol/serial_uart.c
# protocol/serial_soft.c
CONFIG_H = config.h
# MCU name, you MUST set this to match the board you are using
# type "make clean" after changing this, so all files will be rebuilt
#MCU = at90usb162 # Teensy 1.0
MCU = atmega32u4 # Teensy 2.0
#MCU = at90usb646 # Teensy++ 1.0
#MCU = at90usb1286 # Teensy++ 2.0
# Processor frequency.
# Normally the first thing your program should do is set the clock prescaler,
# so your program will run at the correct speed. You should also set this
# variable to same clock speed. The _delay_ms() macro uses this, and many
# examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 16000000
#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8
# Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)
# Interrupt driven control endpoint task
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
# Build Options
# *Comment out* to disable the options.
#
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = yes # Console for debug
#NKRO_ENABLE = yes # USB Nkey Rollover
# Boot Section Size in bytes
# Teensy halfKay 512
# Atmel DFU loader 4096
# LUFA bootloader 4096
OPT_DEFS += -DBOOT_SIZE=4096
# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/protocol.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk

70
converter/pc98_usb/README Normal file
View file

@ -0,0 +1,70 @@
PC98 to USB keyboard protocol converter
=======================================
Target MCU is ATMega32u4 but other USB capable AVR will also work.
Connector
---------
8Pin mini DIN
___ ___
/ |_| \
/ 8 7 6 \
| 5 4 3 |
\_ 2 1 _/
\_____/
(receptacle)
Wiring: You can change this with ediging config.h.
Pin mini DIN MCU
----------------------------------
1 ~RST PD1
2 GND GND
3 ~RDY PD4
4 RXD PD2
5 ~RTY PD5
6 NC
7 NC
8 5V VCC
Protocol
--------
Singnal: Asynchronous, Positive logic, 19200baud, Least bit first
Frame format: 1-Start bit(Lo), 8-Data bits, Odd-Parity, 1-Stop bit
This converter uses software method for testing purpose. AVR UART engine will work better.
Build Firmware
--------------
Just use 'make'
$ cd pc98_usb
$ make
Then, load the binary to MCU with your favorite programmer.
Other PC98 converter projects and resource
------------------------------------------
PC98 to USB
http://davy.nyacom.net/kbd98usb/
PC98 to PS/2
http://www.tsp.ne.jp/~sawada/mago/c_gka98at.htm
http://www.tsp.ne.jp/~sawada/mago/src/gka98at.asm
PC98 keyboard commands
http://www.webtech.co.jp/company/doc/undocumented_mem/io_kb.txt
Inhibit repeating key:
0x9C, 0x70

126
converter/pc98_usb/config.h Normal file
View file

@ -0,0 +1,126 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIG_H
#define CONFIG_H
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x9898
#define DEVICE_VER 0x0100
#define MANUFACTURER t.m.k.
#define PRODUCT PC98 keyboard converter
#define DESCRIPTION converts PC98 keyboard protocol into USB
/* matrix size */
#define MATRIX_ROWS 16
#define MATRIX_COLS 8
/* To use new keymap framework */
#define USE_KEYMAP_V2
/* key combination for command */
#define IS_COMMAND() ( \
host_get_first_key() == KC_CANCEL \
)
/* PC98 Reset Port shared with TXD */
#define PC98_RST_DDR DDRD
#define PC98_RST_PORT PORTD
#define PC98_RST_BIT 3
/* PC98 Ready Port */
#define PC98_RDY_DDR DDRD
#define PC98_RDY_PORT PORTD
#define PC98_RDY_BIT 4
/* PC98 Retry Port */
#define PC98_RTY_DDR DDRD
#define PC98_RTY_PORT PORTD
#define PC98_RTY_BIT 5
/*
* PC98 Serial(USART) configuration
* asynchronous, positive logic, 19200baud, bit order: LSB first
* 1-start bit, 8-data bit, odd parity, 1-stop bit
*/
/*
* Software Serial
*/
#define SERIAL_SOFT_BAUD 19200
#define SERIAL_SOFT_PARITY_ODD
#define SERIAL_SOFT_BIT_ORDER_LSB
#define SERIAL_SOFT_LOGIC_POSITIVE
/* RXD Port */
#define SERIAL_SOFT_RXD_DDR DDRD
#define SERIAL_SOFT_RXD_PORT PORTD
#define SERIAL_SOFT_RXD_PIN PIND
#define SERIAL_SOFT_RXD_BIT 2
#define SERIAL_SOFT_RXD_READ() (SERIAL_SOFT_RXD_PIN&(1<<SERIAL_SOFT_RXD_BIT))
/* RXD Interupt */
#define SERIAL_SOFT_RXD_VECT INT2_vect
#define SERIAL_SOFT_RXD_INIT() do { \
/* pin configuration: input with pull-up */ \
SERIAL_SOFT_RXD_DDR &= ~(1<<SERIAL_SOFT_RXD_BIT); \
SERIAL_SOFT_RXD_PORT |= (1<<SERIAL_SOFT_RXD_BIT); \
/* enable interrupt: INT2(falling edge) */ \
EICRA |= ((1<<ISC21)|(0<<ISC20)); \
EIMSK |= (1<<INT2); \
sei(); \
} while (0)
#define SERIAL_SOFT_RXD_INT_ENTER()
#define SERIAL_SOFT_RXD_INT_EXIT() do { \
/* clear interrupt flag */ \
EIFR = (1<<INTF2); \
} while (0)
/* TXD Port */
#define SERIAL_SOFT_TXD_DDR DDRD
#define SERIAL_SOFT_TXD_PORT PORTD
#define SERIAL_SOFT_TXD_PIN PIND
#define SERIAL_SOFT_TXD_BIT 3
#define SERIAL_SOFT_TXD_HI() do { SERIAL_SOFT_TXD_PORT |= (1<<SERIAL_SOFT_TXD_BIT); } while (0)
#define SERIAL_SOFT_TXD_LO() do { SERIAL_SOFT_TXD_PORT &= ~(1<<SERIAL_SOFT_TXD_BIT); } while (0)
#define SERIAL_SOFT_TXD_INIT() do { \
/* pin configuration: output */ \
SERIAL_SOFT_TXD_DDR |= (1<<SERIAL_SOFT_TXD_BIT); \
/* idle */ \
SERIAL_SOFT_TXD_ON(); \
} while (0)
/*
* Hardware Serial(UART)
*/
#ifdef __AVR_ATmega32U4__
#define SERIAL_UART_BAUD 19200
#define SERIAL_UART_DATA UDR1
#define SERIAL_UART_UBRR ((F_CPU/(16UL*SERIAL_UART_BAUD))-1)
#define SERIAL_UART_RXD_VECT USART1_RX_vect
#define SERIAL_UART_TXD_READY (UCSR1A&(1<<UDRE1))
#define SERIAL_UART_INIT() do { \
UBRR1L = (uint8_t) SERIAL_UART_UBRR; /* baud rate */ \
UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8); /* baud rate */ \
UCSR1B |= (1<<RXCIE1) | (1<<RXEN1); /* RX interrupt, RX: enable */ \
UCSR1B |= (0<<TXCIE1) | (1<<TXEN1); /* TX interrupt, TX: enable */ \
UCSR1C |= (1<<UPM11) | (1<<UPM10); /* parity: none(00), even(01), odd(11) */ \
sei(); \
} while(0)
#else
#error "USART configuration is needed."
#endif
#endif

222
converter/pc98_usb/keymap.c Normal file
View file

@ -0,0 +1,222 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "keycode.h"
#include "action.h"
#include "action_macro.h"
#include "layer_switch.h"
#include "util.h"
#include "keymap.h"
/* PC-9801-98-S02 Raku Raku keyboard(Luckyboard) Normal Mode
,---------------------------------------------------------------.
| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 6A| 6B| 36| 37| 3F| 3E|
`---------------------------------------------------------------'
,---------------------------------------------------------------.
| 00| 01| 02| 03| 04| 05| 58| 71| 06| 07| 08| 09| 0A| 0E|
|---------------------------------------------------------------|
| 0F| 10| 11| 12| 13| 14| 3A | 15| 16| 17| 18| 19| 1C|
|---------------------------------------------------------'. |
| 74| 20| 21| 22| 23| 24| 3B | 3C | 25| 26| 27| 28| 29| |
|---------------------------------------------------------------|
| 70| 2A| 2B| 2C| 2D| 2E| 38| 3D | 39| 2F| 30| 31| 32| 33| 70|
`---------------------------------------------------------------'
| 73| 51| 5B| 59| 34| 5A| 35| xx|
`-----------------------------------------------'
xx: 74 35 F4 B5
*/
#define KEYMAP( \
K60, K61, K62, K63, K64, K65, K66, K67, K68, K69, K6A, K6B, K36, K37, K3F, K3E, \
K00, K01, K02, K03, K04, K05, K58, K71, K06, K07, K08, K09, K0A, K0E, \
K0F, K10, K11, K12, K13, K14, K3A, K15, K16, K17, K18, K19, K1C, \
K74, K20, K21, K22, K23, K24, K3B, K3C, K25, K26, K27, K28, K29, \
K70,K2A, K2B, K2C, K2D, K2E, K38, K3D, K39, K2F, K30, K31, K32, K33, \
K73, K51, K5B, K59, K34, K5A, K35 \
) { \
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
{ KC_##K08, KC_##K09, KC_##K0A, KC_NO, KC_NO, KC_NO, KC_##K0E, KC_##K0F }, \
{ KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
{ KC_##K18, KC_##K19, KC_NO, KC_NO, KC_##K1C, KC_NO, KC_NO, KC_NO }, \
{ KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \
{ KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F }, \
{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \
{ KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D, KC_##K3E, KC_##K3F }, \
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_NO, KC_##K51, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67 }, \
{ KC_##K68, KC_##K69, KC_##K6A, KC_##K6B, KC_NO, KC_NO, KC_NO, KC_NO }, \
{ KC_##K70, KC_##K71, KC_NO, KC_##K73, KC_##K74, KC_NO, KC_NO, KC_NO }, \
{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO } \
}
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
,---------------------------------------------------------------.
| 60| 61| 62| 63| 64| 65| 66| 67| 68| 69| 6A| 6B| 36| 37| 3F| 3E|
`---------------------------------------------------------------'
,---------------------------------------------------------------.
| 00| 01| 02| 03| 04| 05| 58| 71| 06| 07| 08| 09| 0A| 0E|
|---------------------------------------------------------------|
| 0F| 10| 11| 12| 13| 14| 3A | 15| 16| 17| 18| 19| 1C|
|---------------------------------------------------------------|
| 74| 20| 21| 22| 23| 24| MINS| EQL| 25| 26| 27| 28| 29| |
|---------------------------------------------------------------|
| 70| 2A| 2B| 2C| 2D| 2E| 38| 3D | 39| 2F| 30| 31| 32| 33| 70|
`---------------------------------------------------------------'
| 73| 51| 5B| 59| 34| 5A| 35| xx|
`-----------------------------------------------'
*/
KEYMAP(
CANCEL,COPY, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, FN6,
ESC, 1, 2, 3, 4, 5, FN4, FN5, 6, 7, 8, 9, 0, BSPC,
TAB, Q, W, E, R, T, UP, Y, U, I, O, P, ENT,
LCTL, A, S, D, F, G, MINS, EQL, H, J, K, L, FN2,
LSFT, Z, X, C, V, B, GRV, BSLS, QUOT, N, M,COMM, DOT, FN1,
LGUI, LALT, LCTL, LSFT, SPC, SPC, RALT
),
KEYMAP(
PAUS,COPY, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14,
GRV, F1, F2, F3, F4, F5, NO, NO, F6, F7, F8, F9, F10, DEL,
TAB, Q, W, E, R, T, UP, HOME,PGDN,PGUP, END, P, ENT,
LCTL, A, S, D, F, G, MINS, EQL, LEFT,DOWN, UP,RGHT,SCLN,
LSFT, Z, X, C, V, B, INS, DOWN, DEL,HOME,PGDN,PGUP, END,TRNS,
LGUI, LALT, LCTL, LSFT, SPC, SPC, RALT
),
KEYMAP(
PAUS,COPY, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14,
GRV, F1, F2, F3, F4, F5, NO, NO, F6, F7, F8, F9, F10, DEL,
TAB, Q, W, E, R, T, UP, WH_L,WH_D,WH_U,WH_R, P, ENT,
LCTL, A, S, D, F, G, MINS, EQL, MS_L,MS_D,MS_U,MS_R,TRNS,
LSFT, Z, X, C, V, B, INS, DOWN, BTN3,BTN2,BTN1,BTN4,BTN5,TRNS,
LGUI, LALT, LCTL, LSFT, SPC, SPC, RALT
),
};
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {};
/*
* Macro definition
*/
enum macro_id {
LBRACKET,
RBRACKET,
DUMMY,
};
const prog_macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
keyevent_t event = record->event;
//uint8_t tap_count = record->tap_count;
switch (id) {
case LBRACKET:
return (event.pressed ?
MACRO( T(LBRC), END ) :
MACRO( T(LBRC), END ) );
case RBRACKET:
return (event.pressed ?
MACRO( T(RBRC), END ) :
MACRO( T(RBRC), END ) );
}
return MACRO_NONE;
}
/*
* Action function
*/
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
/*
keyevent_t event = record->event;
uint8_t tap_count = record->tap_count;
switch (id) {
case 0xFF:
action_macro_play(get_macro(opt, event.pressed));
break;
}
*/
}
/*
* Fn actions
*/
static const uint16_t PROGMEM fn_actions[] = {
ACTION_KEYMAP_TAP_TOGGLE(0), // FN0
ACTION_KEYMAP_TAP_KEY(1, KC_SLASH), // FN1
ACTION_KEYMAP_TAP_KEY(2, KC_SCLN), // FN2
ACTION_KEYMAP_MOMENTARY(2), // FN3
ACTION_MACRO(LBRACKET), // FN4
ACTION_MACRO(RBRACKET), // FN5
ACTION_MACRO(DUMMY), // FN6
};
/*
* No need to edit.
*/
#define KEYMAPS_SIZE (sizeof(keymaps) / sizeof(keymaps[0]))
#define OVERLAYS_SIZE (sizeof(overlays) / sizeof(overlays[0]))
#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0]))
/* translates key to keycode */
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
{
/* Overlay: 16-31(OVERLAY_BIT(0x10) | overlay_layer) */
if (layer & OVERLAY_BIT) {
layer &= OVERLAY_MASK;
if (layer < OVERLAYS_SIZE) {
return pgm_read_byte(&overlays[(layer)][(key.row)][(key.col)]);
} else {
return KC_TRANSPARENT;
}
}
/* Keymap: 0-15 */
else {
if (layer < KEYMAPS_SIZE) {
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
} else {
// fall back to layer 0
return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]);
}
}
}
/* translates Fn keycode to action */
action_t keymap_fn_to_action(uint8_t keycode)
{
action_t action;
if (FN_INDEX(keycode) < FN_ACTIONS_SIZE) {
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
} else {
action.code = ACTION_NO;
}
return action;
}

33
converter/pc98_usb/led.c Normal file
View file

@ -0,0 +1,33 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdint.h"
#include "serial.h"
#include "led.h"
void led_set(uint8_t usb_led)
{
uint8_t sun_led = 0;
if (usb_led & (1<<USB_LED_NUM_LOCK)) sun_led |= (1<<0);
if (usb_led & (1<<USB_LED_COMPOSE)) sun_led |= (1<<1);
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) sun_led |= (1<<2);
if (usb_led & (1<<USB_LED_CAPS_LOCK)) sun_led |= (1<<3);
serial_send(0x0E);
serial_send(sun_led);
}

215
converter/pc98_usb/matrix.c Normal file
View file

@ -0,0 +1,215 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "print.h"
#include "util.h"
#include "matrix.h"
#include "debug.h"
#include "protocol/serial.h"
/*
* Matrix Array usage:
*
* ROW: 16(4bits)
* COL: 8(3bits)
*
* 8bit wide
* +---------+
* 0|00 ... 07|
* 1|08 ... 0F|
* :| ... |
* :| ... |
* E|70 ... 77|
* F|78 ... 7F|
* +---------+
*/
static uint8_t matrix[MATRIX_ROWS];
#define ROW(code) ((code>>3)&0xF)
#define COL(code) (code&0x07)
static bool is_modified = false;
inline
uint8_t matrix_rows(void)
{
return MATRIX_ROWS;
}
inline
uint8_t matrix_cols(void)
{
return MATRIX_COLS;
}
static void pc98_inhibit_repeat(void)
{
uint8_t code;
while (serial_recv()) ;
RETRY:
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
_delay_ms(500);
serial_send(0x9C);
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
_delay_ms(100);
while (!(code = serial_recv())) ;
print("PC98: send 9C: "); print_hex8(code); print("\n");
if (code != 0xFA) goto RETRY;
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
_delay_ms(100);
serial_send(0x70);
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
_delay_ms(100);
//code = serial_recv();
while (!(code = serial_recv())) ;
print("PC98: send 70: "); print_hex8(code); print("\n");
if (code != 0xFA) goto RETRY;
}
void matrix_init(void)
{
print_enable = true;
// debug_enable = true;
// debug_matrix = true;
PC98_RST_DDR |= (1<<PC98_RST_BIT);
PC98_RDY_DDR |= (1<<PC98_RDY_BIT);
PC98_RTY_DDR |= (1<<PC98_RTY_BIT);
PC98_RST_PORT |= (1<<PC98_RST_BIT);
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
PC98_RTY_PORT |= (1<<PC98_RTY_BIT);
serial_init();
// PC98 reset
/*
PC98_RST_PORT &= ~(1<<PC98_RST_BIT);
_delay_us(15);
PC98_RST_PORT |= (1<<PC98_RST_BIT);
_delay_us(13);
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
*/
_delay_ms(500);
pc98_inhibit_repeat();
// PC98 ready
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) matrix[i] = 0x00;
debug("init\n");
return;
}
uint8_t matrix_scan(void)
{
is_modified = false;
uint16_t code;
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
_delay_us(30);
code = serial_recv2();
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
if (code == -1) return 0;
if (code == 0x60) {
pc98_inhibit_repeat();
/*
PC98_RDY_PORT |= (1<<PC98_RDY_BIT);
_delay_ms(100);
serial_send(0x96);
PC98_RDY_PORT &= ~(1<<PC98_RDY_BIT);
*/
return 0;
}
print_hex8(code); print(" ");
if (code&0x80) {
// break code
if (matrix_is_on(ROW(code), COL(code))) {
matrix[ROW(code)] &= ~(1<<COL(code));
is_modified = true;
}
} else {
// make code
if (!matrix_is_on(ROW(code), COL(code))) {
matrix[ROW(code)] |= (1<<COL(code));
is_modified = true;
}
}
return code;
}
bool matrix_is_modified(void)
{
return is_modified;
}
inline
bool matrix_has_ghost(void)
{
return false;
}
inline
bool matrix_is_on(uint8_t row, uint8_t col)
{
return (matrix[row] & (1<<col));
}
inline
uint8_t matrix_get_row(uint8_t row)
{
return matrix[row];
}
void matrix_print(void)
{
print("\nr/c 01234567\n");
for (uint8_t row = 0; row < matrix_rows(); row++) {
phex(row); print(": ");
pbin_reverse(matrix_get_row(row));
print("\n");
}
}
uint8_t matrix_key_count(void)
{
uint8_t count = 0;
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
count += bitpop(matrix[i]);
}
return count;
}

View file

@ -43,40 +43,46 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* asynchronous, negative logic, 1200baud, no flow control
* 1-start bit, 8-data bit, non parity, 1-stop bit
*/
#define SERIAL_BAUD 1200
#define SERIAL_RXD_DDR DDRD
#define SERIAL_RXD_PORT PORTD
#define SERIAL_RXD_PIN PIND
#define SERIAL_RXD_BIT 2
#define SERIAL_RXD_VECT INT2_vect
#define SERIAL_RXD_INIT() do { \
#define SERIAL_SOFT_BAUD 1200
#define SERIAL_SOFT_PARITY_NONE
#define SERIAL_SOFT_BIT_ORDER_LSB
#define SERIAL_SOFT_LOGIC_NEGATIVE
/* RXD Port */
#define SERIAL_SOFT_RXD_ENABLE
#define SERIAL_SOFT_RXD_DDR DDRD
#define SERIAL_SOFT_RXD_PORT PORTD
#define SERIAL_SOFT_RXD_PIN PIND
#define SERIAL_SOFT_RXD_BIT 2
#define SERIAL_SOFT_RXD_VECT INT2_vect
/* RXD Interupt */
#define SERIAL_SOFT_RXD_INIT() do { \
/* pin configuration: input with pull-up */ \
SERIAL_RXD_DDR &= ~(1<<SERIAL_RXD_BIT); \
SERIAL_RXD_PORT |= (1<<SERIAL_RXD_BIT); \
/* enable interrupt: INT2(rising edge) */ \
EICRA |= ((1<<ISC21)|(1<<ISC20)); \
EIMSK |= (1<<INT2); \
SERIAL_SOFT_RXD_DDR &= ~(1<<SERIAL_SOFT_RXD_BIT); \
SERIAL_SOFT_RXD_PORT |= (1<<SERIAL_SOFT_RXD_BIT); \
/* enable interrupt: INT2(rising edge) */ \
EICRA |= ((1<<ISC21)|(1<<ISC20)); \
EIMSK |= (1<<INT2); \
sei(); \
} while (0)
#define SERIAL_RXD_INT_ENTER()
#define SERIAL_RXD_INT_EXIT() do { \
/* clear interrupt flag */ \
EIFR = (1<<INTF2); \
#define SERIAL_SOFT_RXD_INT_ENTER()
#define SERIAL_SOFT_RXD_INT_EXIT() do { \
/* clear interrupt flag */ \
EIFR = (1<<INTF2); \
} while (0)
#define SERIAL_RXD_READ() (~SERIAL_RXD_PIN&(1<<SERIAL_RXD_BIT))
#define SERIAL_TXD_DDR DDRD
#define SERIAL_TXD_PORT PORTD
#define SERIAL_TXD_PIN PIND
#define SERIAL_TXD_BIT 3
/* negative logic */
#define SERIAL_TXD_ON() do { SERIAL_TXD_PORT &= ~(1<<SERIAL_TXD_BIT); } while (0)
#define SERIAL_TXD_OFF() do { SERIAL_TXD_PORT |= (1<<SERIAL_TXD_BIT); } while (0)
#define SERIAL_TXD_INIT() do { \
/* pin configuration: output */ \
SERIAL_TXD_DDR |= (1<<SERIAL_TXD_BIT); \
/* idle */ \
SERIAL_TXD_ON(); \
#define SERIAL_SOFT_RXD_READ() (SERIAL_SOFT_RXD_PIN&(1<<SERIAL_SOFT_RXD_BIT))
/* TXD Port */
#define SERIAL_SOFT_TXD_ENABLE
#define SERIAL_SOFT_TXD_DDR DDRD
#define SERIAL_SOFT_TXD_PORT PORTD
#define SERIAL_SOFT_TXD_PIN PIND
#define SERIAL_SOFT_TXD_BIT 3
#define SERIAL_SOFT_TXD_HI() do { SERIAL_SOFT_TXD_PORT |= (1<<SERIAL_SOFT_TXD_BIT); } while (0)
#define SERIAL_SOFT_TXD_LO() do { SERIAL_SOFT_TXD_PORT &= ~(1<<SERIAL_SOFT_TXD_BIT); } while (0)
#define SERIAL_SOFT_TXD_INIT() do { \
/* pin configuration: output */ \
SERIAL_SOFT_TXD_DDR |= (1<<SERIAL_SOFT_TXD_BIT); \
/* idle */ \
SERIAL_SOFT_TXD_ON(); \
} while (0)
#endif

514
doc/keymap.md Normal file
View file

@ -0,0 +1,514 @@
Keymap framework - how to define your keymap
============================================
***NOTE: This is not final version, may be inconsistent with source code and changed occasionally for a while.***
## 0. Keymap and layers
**Keymap** is comprised of multiple layers of key layout, you can define **16** layers at most.
**Layer** is an array of **keycodes** to define **actions** on each physical keys.
respective layers can be validated simultaneously. Layers are indexed with 0 to 15 and higher layer has precedence.
Keymap with 16 Layers Layer: array of Keycodes
--------------------- ------------------------
stack of layers content of layer
____________ precedence _______________________
/ / | high / ESC / F1 / F2 / F3 ....
15 /___________// | /-----/-----/-----/-----
14 /___________// | / TAB / / / ....
13 /___________/_ | /-----/-----/-----/-----
: / : : : : : / | /LCtrl/ / / ....
3 /___________// | : / : : : :
2 /___________// | 2 `--------------------------
1 /___________// | 1 `--------------------------
0 /___________/ V low 0 `--------------------------
### 0.1 Keymap status
Keymap has its state in two parameters:
**`default_layer`** indicates a base keymap layer(0-15) which is always valid and to be referred, **`keymap_stat`** is 16bit variable which has current on/off status of layers on its each bit.
Keymap layer '0' is usually `default_layer` and which is the only valid layer and other layers is initially off after boot up firmware, though, you can configured them in `config.h`.
To change `default_layer` will be useful when you want to switch key layout completely, say you use Colmak instead of Qwerty.
Initial state of Keymap Change base layout
----------------------- ------------------
15 15
14 14
13 13
: :
3 3 ____________
2 ____________ 2 / /
1 / / ,->1 /___________/
,->0 /___________/ | 0
| |
`--- default_layer = 0 `--- default_layer = 1
keymap_stat = 0x0001 keymap_stat = 0x0002
On the other hand, you shall change `keymap_state` to overlay base layer with some layers for feature such as navigation keys, function key(F1-F12), media keys or special actions.
Overlay feature layer
--------------------- bit|status
____________ ---+------
15 / / 15 | 0
14 /___________// -----> 14 | 1
13 /___________/ -----> 13 | 1
: : |
3 ____________ 3 | 0
2 / / 2 | 0
,->1 /___________/ -----> 1 | 1
| 0 0 | 0
| |
`--- default_layer = 1 |
keymap_stat = 0x6002 <-----'
### 0.2 Layer Precedence and Transparency
Note that ***higher layer has higher priority on stack of layers***, namely firmware falls down from top layer to bottom to look up keycode. Once it spots keycode other than **`KC_TRNS`**(transparent) on a layer it stops searching and lower layers aren't referred.
You can place `KC_TRNS` on overlay layer changes just part of layout to fall back on lower or base layer.
Key with `KC_TRANS` doen't has its own keycode and refers to lower valid layers for keycode, instead.
See example below.
### 0.3 Keymap Example
Keymap is **`keymaps[]`** C array in fact and you can define layers in it with **`KEYMAP()`** C macro and keycodes. To use complex actions you need to define `Fn` keycode in **`fn_actions[]`** array.
This is a keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard.
This example has three layers, 'Qwerty' as base layer, 'Cursor' and 'Mousekey'.
In this example,
`Fn0` is a **momentary layer switching** key, you can use keys on Cursor layer while holding the key.
`Fn1` is a momentary layer switching key with tapping feature, you can get semicolon **';'** with taping the key and switch layers while holding the key. The word **'tap'** or **'tapping'** mean to press and release a key quickly.
`Fn2` is a **toggle layer switch** key, you can stay switched layer after releasing the key unlike momentary switching.
You can find other keymap definitions in file `keymap.c` located on project directories.
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* 0: Qwerty
* ,-----------------------------------------------------------.
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `|
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs|
* |-----------------------------------------------------------|
* |Contro| A| S| D| F| G| H| J| K| L|Fn1| '|Enter |
* |-----------------------------------------------------------|
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
* `-----------------------------------------------------------'
* |Gui|Alt |Space |Alt |Fn2|
* `-------------------------------------------'
*/
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT,ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN0, \
LGUI,LALT, SPC, RALT,FN2),
/* 1: Cursor(HHKB mode)
* ,-----------------------------------------------------------.
* |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
* |-----------------------------------------------------------|
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
* |-----------------------------------------------------------|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift | |
* `-----------------------------------------------------------'
* |Gui |Alt |Space |Alt |Gui|
* `--------------------------------------------'
*/
KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, TRNS,BSPC, \
LCTL,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
LSFT,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
LGUI,LALT, SPC, RALT,RGUI),
/* 2: Mousekey
* ,-----------------------------------------------------------.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
* |-----------------------------------------------------------|
* |Contro| | | | | |McL|McD|McU|McR| | |Return |
* |-----------------------------------------------------------|
* |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
* `-----------------------------------------------------------'
* |Gui |Alt |Mb1 |Alt | |
* `--------------------------------------------'
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
*/
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
TAB, TRNS,TRNS,TRNS,TRNS,TRNS,WH_L,WH_D,WH_U,WH_R,TRNS,TRNS,TRNS,BSPC, \
LCTL,TRNS,ACL0,ACL1,ACL2,TRNS,MS_L,MS_D,MS_U,MS_R,TRNS,QUOT,ENT, \
LSFT,TRNS,TRNS,TRNS,TRNS,BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,TRNS, \
LGUI,LALT, BTN1, RALT,TRNS),
};
static const uint16_t PROGMEM fn_actions[] = {
ACTION_KEYMAP_MOMENTARY(1), // FN0
ACTION_KEYMAP_TAP_KEY(2, KC_SCLN), // FN1
ACTION_KEYMAP_TOGGLE(2), // FN2
};
## 1. Keycode
See [`common/keycode.h`](../common/keycode.h) or keycode table below for the detail. Keycode is internal **8bit code** to inidicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like `KC_A` have simple action registers key to host on press and unregister on release, while some of other keycodes has some special actions like `Fn` keys, Media contorl keys, System control keys and Mousekeys.
***In `KEYMAP()` macro you should 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()`.
### 1.0 Other key
- `KC_NO` for no aciton
- `KC_TRNS` for layer transparency (See above)
### 1.1 Normal key
- `KC_A` to `KC_Z`, `KC_1` to `KC_0` for alpha numeric key
- `KC_MINS`, `KC_EQL`, `KC_GRV`, `KC_RBRC`, `KC_LBRC`, `KC_COMM`, `KC_DOT`, `KC_BSLS`, `KC_SLSH`, `KC_SCLN`, `KC_QUOT`
- `KC_ESC`, `KC_TAB`, `KC_SPC`, `KC_BSPC`, `KC_ENT`, `KC_DEL`, `KC_INS`
- `KC_UP`, `KC_DOWN`, `KC_RGHT`, `KC_LEFT`, `KC_PGUP`, `KC_PGDN`, `KC_HOME`, `KC_END`
- `KC_CAPS`, `KC_NLCK`, `KC_SLCK`, `KC_PSCR`, `KC_PAUS`, `KC_APP`, `KC_F1` to `KC_F24`
- `KC_P1` to `KC_P0`, `KC_PDOT`, `KC_PCMM`, `KC_PSLS`, `KC_PAST`, `KC_PMNS`, `KC_PPLS`, `KC_PEQL`, `KC_PENT` for keypad.
### 1.2 Modifier
There are 8 modifiers which has discrimination between left and right.
- `KC_LCTL` and `KC_RCTL` for Control
- `KC_LSFT` and `KC_RSFT` for Shift
- `KC_LALT` and `KC_RALT` for Alt
- `KC_LGUI` and `KC_RGUI` for Windows key or Command key in Mac
### 1.3 Mousekey
- `KC_MS_U`, `KC_MS_D`, `KC_MS_L`, `KC_MS_R` for mouse cursor
- `KC_WH_U`, `KC_WH_D`, `KC_WH_L`, `KC_WH_R` for mouse wheel
- `KC_BTN1`, `KC_BTN2`, `KC_BTN3`, `KC_BTN4`, `KC_BTN5` for mouse buttons
### 1.4 System & Media key
- `KC_PWR`, `KC_SLEP`, `KC_WAKE` for Power, Sleep, Wake
- `KC_MUTE`, `KC_VOLU`, `KC_VOLD` for audio volume control
- `KC_MNXT`, `KC_MPRV`, `KC_MSTP`, `KC_MPLY`, `KC_MSEL` for media control
- `KC_MAIL`, `KC_CALC`, `KC_MYCM` for application launch
- `KC_WSCH`, `KC_WHOM`, `KC_WBAK`, `KC_WFWD`, `KC_WSTP`, `KC_WREF`, `KC_WFAV` for web browser operation
### 1.5 Fn key
`KC_FNnn` are keycodes for `Fn` key which not given any actions at the beginning unlike most of keycodes has its own inborn action. To use these keycodes in `KEYMAP` you need to assign action you want at first. Action of `Fn` key is defined in `fn_actions[]` and its index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` keyocde indicates the action defined in first element of the array. ***32 `Fn` keys can be defined at most.***
### 1.6 Keycode Table
See keycode table in [`doc/keycode.txt`](./keycode.txt) for description of keycodes.
In regard to implementation side most of keycodes are identical with [HID usage][HID_usage](pdf) sent to host for real and some virtual keycodes are defined to support special actions.
[HID_usage]: http://www.usb.org/developers/devclass_docs/Hut1_11.pdf
## 2. Action
See [`common/action.h`](../common/action.h). Action is a **16bit code** and defines function to perform on events of a key like press, release, holding and tapping.
Most of keys just register 8bit scancode to host, but to support other complex features needs 16bit extended action codes internally. However, using 16bit action codes in keymap results in double size in memory against using jsut keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP` instead of action codes.
***You can just use keycodes of `Normal key`, `Modifier`, `Mousekey` and `System & Media key` in keymap*** to indicate corresponding actions instead of using action codes. While ***to use other special actions you should use keycode of `Fn` key defined in `fn_actions[]`.***
Usually action codes are needed only when you want to use layer switching, or
### 2.1 Key action
This is a simple action that registers scancodes(HID usage in fact) to host on press event of key and unregister on release.
#### 2.1.1 Normal key and Modifier
This action usually won't be used expressly because you can use keycodes in `KEYMAP()` instead.
You can define `Key` action on *'A'* key and *'left shift'* modifier with:
ACTION_KEY(KC_A)
ACTION_KEY(KC_LSHIFT)
#### 2.1.2 Key with modifiers
This action is comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes.
Say you want to assign a key to `Shift + 1` to get charactor *'!'* or `Alt + Tab` to switch application windows.
ACTION_LMOD_KEY(KC_LSHIFT, KC_1)
ACTION_LMOD_KEY(KC_LALT, KC_TAB)
Or `Alt,Shift + Tab` can be defined. `ACTION_LMODS_KEY()` requires **4-bit modifier state** and a **keycode** as arguments. See `keycode.h` for `MOD_BIT()` macro.
ACTION_LMODS_KEY((MOD_BIT(KC_LALT) | MOD_BIT(KC_LSHIFT)), KC_TAB)
### 2.2 Layer Action
These actions operate layers of keymap.
Parameters:
- layer: 0-15
- on: { press | release | both }
#### 2.2.0 Default Layer
`default_layer` is layer which always is valid and referred to when actions is not defined on other layers.
##### Return to Default Layer
Turns on only `default layer` with clearing other all layers.
ACTION_DEFAULT_LAYER
##### Set Default Layer
Sets 'default layer' to layer and turn it on.
ACTION_DEFAULT_LAYER_SET_TO(layer)
ACTION_DEFAULT_LAYER_SET(layer, on)
#### 2.2.1 Keymap
These actions operate layer status of keymap.
##### Momentary Switch
Turns on layer momentary while holding, in other words turn on when key is pressed and off when released.
ACTION_KEYMAP_MOMENTARY(layer)
##### Toggle Switch
Turns on layer on first type and turns off on next.
ACTION_KEYMAP_TOGGLE(layer)
##### Momentary Switch with tap key
Turns on layer momentary while holding but registers key on tap.
ACTION_KEYMAP_TAP_KEY(layer, key)
##### Momentary Switch with tap toggle
Turns on layer momentary while holding but toggles it with serial taps.
ACTION_KEYMAP_TAP_TOGGLE(layer)
##### Invert layer
Inverts current layer state. If the layer is on it becomes off with this action.
ACTION_KEYMAP_INV(layer, on)
##### Turn On layer
Turns on layer state.
ACTION_KEYMAP_ON(layer, on)
Turns on layer state on press and turn off on release. This is identical to **'Switch to layer'** action.
ACTION_KEYMAP_ON_OFF(layer)
##### Turn Off layer
Turns off layer state.
ACTION_KEYMAP_OFF(layer, on)
##### Set layer
Turn on layer only.
`keymap_stat = (1<<layer) [layer: 0-15]`
ACTION_KEYMAP_SET(layer, on)
Turns on layer only and clear all layer on release..
ACTION_KEYMAP_SET_CLEAR(layer)
#### 2.2.2 Overlay
***TBD***
In addition to actions of `Keymap` above these actions are also available.
##### Invert 4bit layer states
Invert 4bits out of 16bits of overlay status on both press and release.
`overlay_stat = (overlay_stat ^ bits<<(shift*4)) [bits: 0-15, shift: 0-3]`
ACTION_OVERLAY_INV4(bits, shift)
### 2.3 Macro action
***TBD***
`Macro` action indicates complex key strokes.
MACRO( MD(LSHIFT), D(D), END )
MACRO( U(D), MU(LSHIFT), END )
MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )
#### 2.3.1 Normal mode
- **I()** change interavl of stroke.
- **D()** press key
- **U()** release key
- **T()** type key(press and release)
- **W()** wait
- **MD()** modifier down
- **MU()** modifier up
- **END** end mark
#### 2.3.2 Extended mode
***TODO: sample impl***
See `keyboard/hhkb/keymap.c` for sample.
### 2.4 Function action
***TBD***
There are two type of action, normal `Function` and tappable `Function`.
These actions call user defined function with `id`, `opt`, and key event information as arguments.
#### 2.4.1 Function
To define normal `Function` action in keymap use this.
ACTION_FUNCTION(id, opt)
#### 2.4.2 Function with tap
To define tappable `Function` action in keymap use this.
ACTION_FUNCTION_TAP(id, opt)
#### 2.4.3 Implement user function
`Function` actions can be defined freely with C by user in callback function:
void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt)
This 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.
`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.
typedef struct {
keyevent_t event;
uint8_t tap_count;
} keyrecord_t;
typedef struct {
key_t key;
bool pressed;
uint16_t time;
} keyevent_t;
typedef struct {
uint8_t col;
uint8_t row;
} key_t;
***TODO: sample impl***
See `keyboard/hhkb/keymap.c` for sample.
## 4. Layer switching Example
There are some ways to switch layer with 'Layer' actions.
### 4.1 Momentary switching
Momentary switching changes layer only while holding Fn key.
This action makes 'Layer 1' active(valid) on key press event and inactive on release event. Namely you can overlay a layer on base layer temporarily with this.
ACTION_KEYMAP_MOMENTARY(1)
After switch actions of destination layer are 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. Usually you need to palce same action or 'KC_TRNS` on destination layer to get back.
### 4.2 Toggle switching
Toggle switching changes layer after press then release. With this you can keep staying on the layer until you press the key again to return.
This is toggle action of 'Layer 2'.
ACTION_KEYMAP_TOGGLE(2)
### 4.3 Momentary switching with Tap key
These actions switch layer only while holding `Fn` key and register key on tap. **Tap** means to press and release key quickly.
ACTION_KEYMAP_TAP_KEY(2, KC_SCLN)
With this you can place layer switching function on normal key like ';' without losing its original key register function.
### 4.4 Momentary switching with Tap Toggle
This switches layer only while holding `Fn` key and toggle layer after several taps. **Tap** means to press and release key quickly.
ACTION_KEYMAP_TAP_TOGGLE(1)
Number of taps can be defined with `TAPPING_TOGGLE` in `config.h`, `5` by default.
## Tapping
Tapping is to press and release key quickly. Tapping speed is determined with setting of `TAPPING_TERM`, which can be defined in `config.h`, 200ms by default.
### Tap Key
This is feature to assign normal key action and modifier including `Fn` to just one physical key. This is a kind of [Dual role modifier][dual_role]. It works as modifier or `Fn` when holding a key but registers normal key when tapping.
Action for modifier with tap key.
ACTION_LMODS_TAP_KEY(mods, key)
Action for `Fn` with tap key.
ACTION_KEYMAP_TAP_KEY(layer, key)
[dual_role]: http://en.wikipedia.org/wiki/Modifier_key#Dual-role_modifier_keys
### Tap Toggle
This is feature to assign both toggle layer and momentary switch layer action to just one physical key. It works as mementary switch when holding a key but toggle switch when tapping.
ACTION_KEYMAP_TAP_TOGGLE(layer)
### One Shot Modifier
This adds oneshot feature to modifier key. 'One Shot Modifier' is one time modifier which has effect only on following one alpha key.
It works as normal modifier key when holding but oneshot modifier when tapping.
ACTION_LMODS_ONESHOT(mods)
Say you want to type 'The', you have to push and hold Shift before type 't' then release Shift before type 'h' and 'e' or you'll get 'THe'. With One Shot Modifier you can tap Shift then type 't', 'h' and 'e' normally, you don't need to holding Shift key properly here.
## Legacy Keymap
This 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.
In 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.
In 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.
static const uint8_t PROGMEM fn_layer[] = {
1, // Fn0
2, // Fn1
2, // Fn2
};
static const uint8_t PROGMEM fn_keycode[] = {
KC_NO, // Fn0
KC_NO, // Fn1
KC_SPC, // Fn2
};
## Terminology
- keymap
- layer
- layout
- key
- keycode
- scancode
- action
- layer transparency
- layer precedence
- register
- tap
- Fn key

View file

Before

Width:  |  Height:  |  Size: 322 KiB

After

Width:  |  Height:  |  Size: 322 KiB

View file

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View file

@ -124,3 +124,9 @@ plain: all
poker: OPT_DEFS += -DKEYMAP_POKER
poker: all
poker_set: OPT_DEFS += -DKEYMAP_POKER_SET
poker_set: all
poker_bit: OPT_DEFS += -DKEYMAP_POKER_BIT
poker_bit: all

View file

@ -94,3 +94,9 @@ plain: all
poker: OPT_DEFS += -DKEYMAP_POKER
poker: all
poker_set: OPT_DEFS += -DKEYMAP_POKER_SET
poker_set: all
poker_bit: OPT_DEFS += -DKEYMAP_POKER_BIT
poker_bit: all

View file

@ -47,9 +47,10 @@ See [keymap_plain.h](keymap_plain.h) for detail.
`-----------------------------------------------------------'
### 2 Poker keymap
Poker layer emulation without Esc/grave bug :)
See [keymap_poker.h](keymap_poker.h) for detail.
See [keymap_poker.h](keymap_poker.h) for Poker layer emulation, [keymap_poker_bit.h](keymap_poker_bit.h) and [keymap_poker_set.h](keymap_poker_set.h) for better support of Esc and arrow.
These keymap supports Colemak, Dvorak and Workmans, use `Magic` + {`1`, `2`, `3`} to switch and `Magic` + `0` to return to Qwerty.
#### 2.0 Poker Default Layer
,-----------------------------------------------------------.
@ -108,7 +109,7 @@ See [keymap_poker.h](keymap_poker.h) for detail.
### 3. Funky keymap
This is my keymap(default) with HHKB, Vi cursor and Mousekey layer.
See [keymap.h](keymap.h) for detail.
See [keymap.c](keymap.c) for detail.
#### 3.0 Funky Default Layer
,-----------------------------------------------------------.

View file

@ -41,6 +41,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Set 0 if need no debouncing */
#define DEBOUNCE 5
/* To use new keymap framework */
#define USE_KEYMAP_V2
/* key combination for command */
#define IS_COMMAND() ( \

View file

@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keycode.h"
#include "action.h"
#include "action_macro.h"
#include "layer_switch.h"
#include "report.h"
#include "host.h"
#include "print.h"
@ -64,12 +65,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keymap_plain.h"
#elif defined(KEYMAP_POKER)
#include "keymap_poker.h"
#elif defined(KEYMAP_POKER_SET)
#include "keymap_poker_set.h"
#elif defined(KEYMAP_POKER_BIT)
#include "keymap_poker_bit.h"
#else
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
* Funky
*/
/* Layer 0: Default Layer
/* Keymap 0: Default Layer
* ,-----------------------------------------------------------.
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
* |-----------------------------------------------------------|
@ -85,10 +90,32 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KEYMAP_ANSI(
ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT, ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,FN4, FN4, FN1),
/* Layer 1: HHKB mode
LCTL,A, S, D, F, G, H, J, K, L, FN2, QUOT, ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN1, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,FN3, FN3, FN0),
/* Keymap 1: colemak */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, W, F, P, G, J, L, U, Y, SCLN,LBRC,RBRC,BSLS, \
BSPC,A, R, S, T, D, H, N, E, I, O, QUOT, ENT, \
LSFT,Z, X, C, V, B, K, M, COMM,DOT, SLSH, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, FN0),
/* Keymap 2: dvorak */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, LBRC,RBRC,BSPC, \
TAB, QUOT,COMM,DOT, P, Y, F, G, C, R, L, SLSH,EQL, BSLS, \
CAPS,A, O, E, U, I, D, H, T, N, S, MINS, ENT, \
LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, FN0),
/* Keymap 3: workman */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, D, R, W, B, J, F, U, P, SCLN,LBRC,RBRC,BSLS, \
BSPC,A, S, H, T, G, Y, N, E, O, I, QUOT, ENT, \
LSFT,Z, X, M, C, V, K, L, COMM,DOT, SLSH, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, FN0),
/* Overlay 4: HHKB mode
* ,-----------------------------------------------------------.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete |
* |-----------------------------------------------------------|
@ -98,16 +125,16 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |-----------------------------------------------------------|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift |
* |-----------------------------------------------------------|
* |Ctrl|Gui |Alt | Space |Alt |Gui |App |Fn0 |
* |Ctrl|Gui |Alt | Space |Alt |Gui |App | |
* `-----------------------------------------------------------'
*/
KEYMAP_ANSI(
PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, \
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS,UP, NO, INS, \
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT, ENT, \
LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, FN0),
/* Layer 2: Vi mode (Slash)
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, DEL, \
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, TRNS,INS, \
LCTL,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT, ENT, \
LSFT,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,RGUI,FN4, TRNS),
/* Overlay 5: Vi mode (Slash)
* ,-----------------------------------------------------------.
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backsp |
* |-----------------------------------------------------------|
@ -115,79 +142,119 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |-----------------------------------------------------------|
* |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | |Return |
* |-----------------------------------------------------------|
* |Shift | | | | | |Hom|PgD|PgU|End|Fn0|Shift |
* |Shift | | | | | |Hom|PgD|PgU|End| |Shift |
* |-----------------------------------------------------------|
* |Ctrl|Gui |Alt | Space |Alt |Gui |App |Ctrl|
* `-----------------------------------------------------------'
*/
KEYMAP_ANSI(
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, BSPC, \
TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, NO, \
LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \
LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN0, RSFT, \
TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, TRNS,TRNS,TRNS,TRNS, \
LCTL,TRNS,LEFT,DOWN,RGHT,TRNS,LEFT,DOWN,UP, RGHT,TRNS,TRNS, ENT, \
LSFT,TRNS,TRNS,TRNS,TRNS,TRNS,HOME,PGDN,PGUP,END, TRNS, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL),
/* Layer 3: Mouse mode (Semicolon/App)
/* Overlay 6: Mouse mode (Semicolon/App)
* ,-----------------------------------------------------------.
* | `| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Backsp |
* |-----------------------------------------------------------|
* |Tab | | | | | |MwL|MwD|MwU|MwR| | | | |
* |-----------------------------------------------------------|
* |Contro| |Ac0|Ac1|Ac1| |McL|McD|McU|McR|Fn0| |Return |
* |Contro| |Ac0|Ac1|Ac1| |McL|McD|McU|McR| | |Return |
* |-----------------------------------------------------------|
* |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift |
* |-----------------------------------------------------------|
* |Ctrl|Gui |Alt | Space | |Fn0 |Fn0 | |
* |Ctrl|Gui |Alt | Space | | | | |
* `-----------------------------------------------------------'
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
*/
KEYMAP_ANSI(
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, BSPC, \
TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, NO, \
LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, \
LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT, \
LCTL,LGUI,LALT, BTN1, NO, FN0, FN0, NO ),
TAB, TRNS,TRNS,TRNS,TRNS,TRNS,WH_L,WH_D,WH_U,WH_R,TRNS,TRNS,TRNS,TRNS, \
LCTL,TRNS,ACL0,ACL1,ACL2,TRNS,MS_L,MS_D,MS_U,MS_R,TRNS,TRNS, ENT, \
LSFT,TRNS,TRNS,TRNS,TRNS,BTN3,BTN2,BTN1,BTN4,BTN5,TRNS, RSFT, \
LCTL,LGUI,LALT, BTN1, TRNS,TRNS,TRNS,RCTL),
/* Overlay 7: Layout selector
* ,-----------------------------------------------------------.
* | Lq| Lc| Ld| Lw| | | | | | | | | | |
* |-----------------------------------------------------------|
* | |Lq |Lw | | | | | | | | | | | |
* |-----------------------------------------------------------|
* | | | |Ld | | | | | | | | | |
* |-----------------------------------------------------------|
* | | | |Lc | | | | | | | | |
* |-----------------------------------------------------------|
* | | | | | | | | |
* `-----------------------------------------------------------'
* Lq: set Qwerty layout
* Lc: set Colemak layout
* Ld: set Dvorak layout
* Lw: set Workman layout
*/
KEYMAP_ANSI(
FN5, FN6, FN7, FN8, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,FN5, FN8, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,FN7, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,FN6, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
};
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {};
/*
* Fn action definition
*/
static const uint16_t PROGMEM fn_actions[] = {
ACTION_LAYER_DEFAULT, // FN0
ACTION_LAYER_SET(1), // FN1
ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH), // FN2 Layer with Slash
ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // FN3 Layer with Semicolon
ACTION_LAYER_SET(3), // FN4
[0] = ACTION_KEYMAP_MOMENTARY(4),
[1] = ACTION_KEYMAP_TAP_KEY(5, KC_SLASH),
[2] = ACTION_KEYMAP_TAP_KEY(6, KC_SCLN),
[3] = ACTION_KEYMAP_MOMENTARY(6),
[4] = ACTION_KEYMAP_MOMENTARY(7), // to Layout selector
[5] = ACTION_DEFAULT_LAYER_SET(0), // set qwerty layout
[6] = ACTION_DEFAULT_LAYER_SET(1), // set colemak layout
[7] = ACTION_DEFAULT_LAYER_SET(2), // set dvorak layout
[8] = ACTION_DEFAULT_LAYER_SET(3), // set workman layout
};
#endif
#define KEYMAPS_SIZE (sizeof(keymaps) / sizeof(keymaps[0]))
#define OVERLAYS_SIZE (sizeof(overlays) / sizeof(overlays[0]))
#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0]))
/* translates key to keycode */
uint8_t keymap_key_to_keycode(uint8_t layer, key_t key)
{
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
/* Overlay: 16-31(OVERLAY_BIT(0x10) | overlay_layer) */
if (layer & OVERLAY_BIT) {
layer &= OVERLAY_MASK;
if (layer < OVERLAYS_SIZE) {
return pgm_read_byte(&overlays[(layer)][(key.row)][(key.col)]);
} else {
debug("key_to_keycode: overlay "); debug_dec(layer); debug(" is invalid.\n");
return KC_TRANSPARENT;
}
}
/* Keymap: 0-15 */
else {
if (layer < KEYMAPS_SIZE) {
return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
} else {
// fall back to layer 0
debug("key_to_keycode: base "); debug_dec(layer); debug(" is invalid.\n");
return pgm_read_byte(&keymaps[0][(key.row)][(key.col)]);
}
}
}
/* translates Fn index to action */
/* translates Fn keycode to action */
action_t keymap_fn_to_action(uint8_t keycode)
{
action_t action;
if (FN_INDEX(keycode) < sizeof(fn_actions) / sizeof(fn_actions[0])) {
if (FN_INDEX(keycode) < FN_ACTIONS_SIZE) {
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
} else {
action.code = ACTION_NO;
}
return action;
}
/* convert key to action */
action_t action_for_key(uint8_t layer, key_t key)
{
uint8_t keycode = keymap_key_to_keycode(layer, key);
switch (keycode) {
case KC_FN0 ... KC_FN31:
return keymap_fn_to_action(keycode);
default:
return keymap_keycode_to_action(keycode);
}
}

View file

@ -1,24 +1,10 @@
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
* Plain
*/
/* Layer 0: Default Layer
* ,-----------------------------------------------------------.
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
* |-----------------------------------------------------------|
* |Caps | A| S| D| F| G| H| J| K| L| ;| '|Return |
* |-----------------------------------------------------------|
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |
* |-----------------------------------------------------------|
* |Ctrl|Gui |Alt | Space |Alt |Gui |App |Ctrl|
* `-----------------------------------------------------------'
*/
/* Keymap 0: qwerty */
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,NO, ENT, \
LSFT,NO, Z, X, C, V, B, N, M, COMM,DOT, SLSH,NO, RSFT, \
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL),
};
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {};
static const uint16_t PROGMEM fn_actions[] = {};

View file

@ -1,88 +1,104 @@
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
* Poker Layer
*/
/* Layer x000: Poker Default Layer
* ,-----------------------------------------------------------.
* | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
* |-----------------------------------------------------------|
* |Caps | A| S| D| F| G| H| J| K| L| ;| '|Return |
* |-----------------------------------------------------------|
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |
* |-----------------------------------------------------------|
* |Ctrl|Gui |Alt | Space |Fn |Gui |App |Ctrl|
* `-----------------------------------------------------------'
*/
/* Keymap 0: qwerty */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, \
LCTL,LGUI,LALT, SPC, FN2, RGUI,APP, RCTL),
/* Layer x001: Poker with Arrow */
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
/* Keymap 1: colemak */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, W, F, P, G, J, L, U, Y, SCLN,LBRC,RBRC,BSLS, \
BSPC,A, R, S, T, D, H, N, E, I, O, QUOT, ENT, \
LSFT,Z, X, C, V, B, K, M, COMM,DOT, SLSH, RSFT, \
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
/* Keymap 2: dvorak */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, LBRC,RBRC,BSPC, \
TAB, QUOT,COMM,DOT, P, Y, F, G, C, R, L, SLSH,EQL, BSLS, \
CAPS,A, O, E, U, I, D, H, T, N, S, MINS, ENT, \
LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, \
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
/* Keymap: workman */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, D, R, W, B, J, F, U, P, SCLN,LBRC,RBRC,BSLS, \
BSPC,A, S, H, T, G, Y, N, E, O, I, QUOT, ENT, \
LSFT,Z, X, M, C, V, K, L, COMM,DOT, SLSH, RSFT, \
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
};
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {
/* Overlay 0: Poker with Arrow */
KEYMAP_ANSI(
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \
TRNS,TRNS,TRNS, TRNS, FN2, LEFT,DOWN,RGHT),
/* Layer x010: Poker with Esc */
TRNS,TRNS,TRNS, TRNS, TRNS,LEFT,DOWN,RGHT),
/* Overlay 1: Poker with Esc */
KEYMAP_ANSI(
ESC, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS, TRNS, FN2, TRNS,TRNS,TRNS),
/* Layer x011: Poker with Arrow and Esc */
KEYMAP_ANSI(
ESC, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \
TRNS,TRNS,TRNS, TRNS, FN2, LEFT,DOWN,RGHT),
/*
* Poker Momentary Fn Layer
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
/* Overlay 2: Poker Fn
* ,-----------------------------------------------------------.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| |
* |-----------------------------------------------------------|
* | |FnQ| Up| | | | | | |Cal| |Hom|Ins|FnL |
* |-----------------------------------------------------------|
* | |Lef|Dow|Rig| | |Psc|Slk|Pau| |Tsk|End| |
* |-----------------------------------------------------------|
* | |Del| |Web|Mut|VoU|VoD| |PgU|PgD|Del| |
* |-----------------------------------------------------------|
* | | | | FnS | | | | |
* `-----------------------------------------------------------'
* Fn: to Fn overlay
* FnL: to Layout selector overaly
* FnQ: toggle Esc overlay
* FnS: toggle Arrow overlay
*/
/* Layer x100: Poker Default + Fn'd */
KEYMAP_ANSI(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
TRNS,FN1, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,FN2, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, FN4, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN3, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, TRNS, \
TRNS,TRNS,TRNS, FN0, FN2, TRNS,TRNS,TRNS),
/* Layer x101: Poker with Arrow + Fn'd */
TRNS,TRNS,TRNS, FN1, TRNS,TRNS,TRNS,TRNS),
/* Overlay 3: Layout selector
* ,-----------------------------------------------------------.
* | Lq| Lc| Ld| Lw| | | | | | | | | | |
* |-----------------------------------------------------------|
* | |Lq |Lw | | | | | | | | | | | |
* |-----------------------------------------------------------|
* | | | |Ld | | | | | | | | | |
* |-----------------------------------------------------------|
* | | | |Lc | | | | | | | | |
* |-----------------------------------------------------------|
* | | | | | | | | |
* `-----------------------------------------------------------'
* Lq: set Qwerty layout
* Lc: set Colemak layout
* Ld: set Dvorak layout
* Lw: set Workman layout
*/
KEYMAP_ANSI(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
TRNS,FN1, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN3, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, UP, \
TRNS,TRNS,TRNS, FN0, FN2, LEFT,DOWN,RGHT),
/* Layer x110: Poker with Esc + Fn'd */
KEYMAP_ANSI(
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
TRNS,FN1, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN3, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, TRNS, \
TRNS,TRNS,TRNS, FN0, FN2, TRNS,TRNS,TRNS),
/* Layer x111: Poker with Arrow and Esc + Fn'd */
KEYMAP_ANSI(
GRV, F9, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
TRNS,FN1, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN3, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, UP, \
TRNS,TRNS,TRNS, FN0, FN2, LEFT,DOWN,RGHT),
FN5, FN6, FN7, FN8, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,FN5, FN8, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,FN7, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,FN6, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
};
/*
* Fn action definition
*/
static const uint16_t PROGMEM fn_actions[] = {
/* Poker Layout */
[0] = ACTION_LAYER_BIT_TOGGLE(1), // FN0 Poker Arrow toggle(Space)
[1] = ACTION_LAYER_BIT_TOGGLE(2), // FN1 Poker Esc toggle(Q)
[2] = ACTION_LAYER_BIT(4), // FN2 Poker Fn
[3] = ACTION_RMODS_KEY(MOD_BIT(KC_RCTL)|MOD_BIT(KC_RSFT), KC_ESC), // FN3 Task(RControl,RShift+Esc)
[0] = ACTION_OVERLAY_MOMENTARY(2), // to Fn overlay
[1] = ACTION_OVERLAY_TOGGLE(0), // toggle arrow overlay
[2] = ACTION_OVERLAY_TOGGLE(1), // toggle Esc overlay
[3] = ACTION_RMODS_KEY(MOD_BIT(KC_RCTL)|MOD_BIT(KC_RSFT), KC_ESC), // Task(RControl,RShift+Esc)
[4] = ACTION_OVERLAY_MOMENTARY(3), // to Layout selector
[5] = ACTION_DEFAULT_LAYER_SET(0), // set qwerty layout
[6] = ACTION_DEFAULT_LAYER_SET(1), // set colemak layout
[7] = ACTION_DEFAULT_LAYER_SET(2), // set dvorak layout
[8] = ACTION_DEFAULT_LAYER_SET(3), // set workman layout
};

View file

@ -0,0 +1,50 @@
// Poker fix with toggle and bit operation
// Fn + Esc = `
// Fn + {left, down, up, right} = {home, pgdown, pgup, end}
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: qwerty */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, \
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
};
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {
/* Overlay 0: Poker Default + Fn'd */
KEYMAP_ANSI(
TRNS,F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
CAPS,FN2, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN4, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, TRNS, \
TRNS,TRNS,TRNS, FN1, TRNS,TRNS,TRNS,TRNS),
/* Overlay 1: Poker with Arrow */
KEYMAP_ANSI(
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, PGUP, \
TRNS,TRNS,TRNS, TRNS, FN3, HOME,PGDN,END),
/* Overlay 2: Poker with Esc */
KEYMAP_ANSI(
ESC, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
/* Overlay 3: Poker with Arrow + Fn'd */
KEYMAP_ANSI(
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \
TRNS,TRNS,TRNS, TRNS, TRNS,LEFT,DOWN,RGHT),
};
static const uint16_t PROGMEM fn_actions[] = {
/* Poker Layout */
[0] = ACTION_OVERLAY_INV4(0b0101, 0), // Poker Fn(with fix for Esc)
[1] = ACTION_OVERLAY_TOGGLE(1), // Poker Arrow toggle
[2] = ACTION_OVERLAY_TOGGLE(2), // Poker Esc toggle
[3] = ACTION_OVERLAY_INV4(0b1101, 0), // Poker Fn(with fix for Arrow)
[4] = ACTION_RMODS_KEY(MOD_BIT(KC_RCTL)|MOD_BIT(KC_RSFT), KC_ESC), // FN3 Task(RControl,RShift+Esc)
};

View file

@ -0,0 +1,81 @@
// Poker fix with set(state transition)
// Fn + Esc = `
// Fn + {left, down, up, right} = {home, pgdown, pgup, end}
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap 0: qwerty */
KEYMAP_ANSI(
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, \
LCTL,LGUI,LALT, SPC, FN0, RGUI,APP, RCTL),
};
static const uint8_t PROGMEM overlays[][MATRIX_ROWS][MATRIX_COLS] = {
/* Overlay 0: Poker with Arrow */
KEYMAP_ANSI(
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \
TRNS,TRNS,TRNS, TRNS, FN1, LEFT,DOWN,RGHT),
/* Overlay 1: Poker with Esc */
KEYMAP_ANSI(
ESC, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS, TRNS, FN2, TRNS,TRNS,TRNS),
/* Overlay 2: Poker with Arrow and Esc */
KEYMAP_ANSI(
ESC, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, UP, \
TRNS,TRNS,TRNS, TRNS, FN3, LEFT,DOWN,RGHT),
/* Overlay 3: Poker Fn'd */
KEYMAP_ANSI(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
TRNS,FN6, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN8, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, TRNS, \
TRNS,TRNS,TRNS, FN5, FN4, TRNS,TRNS,TRNS),
/* Overlay 4: Poker Fn'd arrow */
KEYMAP_ANSI(
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
TRNS,FN7, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN8, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, PGUP, \
TRNS,TRNS,TRNS, FN4, FN5, HOME,PGDN,END),
/* Overlay 5: Poker Fn'd Esc */
KEYMAP_ANSI(
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
TRNS,FN4, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN8, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, TRNS, \
TRNS,TRNS,TRNS, FN7, FN6, TRNS,TRNS,TRNS),
/* Overlay 6: Poker Fn'd Arrow + Esc */
KEYMAP_ANSI(
GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
TRNS,FN5, UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,CALC,TRNS,HOME,INS, TRNS, \
TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,FN8, END, TRNS, \
TRNS,DEL, TRNS,WHOM,MUTE,VOLU,VOLD,TRNS,PGUP,PGDN,DEL, PGUP, \
TRNS,TRNS,TRNS, FN6, FN7, HOME,PGDN,END),
};
/*
* Fn action definition
*/
static const uint16_t PROGMEM fn_actions[] = {
/* Poker Layout */
[0] = ACTION_OVERLAY_SET(3, ON_PRESS), // FN0 move to Fn'd when press
[1] = ACTION_OVERLAY_SET(4, ON_PRESS), // FN1 move to Fn'd arrow when press
[2] = ACTION_OVERLAY_SET(5, ON_PRESS), // FN2 move to Fn'd Esc when press
[3] = ACTION_OVERLAY_SET(6, ON_PRESS), // FN3 move to Fn'd arrow + Esc when press
[4] = ACTION_OVERLAY_CLEAR(ON_RELEASE), // FN4 clear overlay when release
[5] = ACTION_OVERLAY_SET(0, ON_RELEASE), // FN5 move to arrow when release
[6] = ACTION_OVERLAY_SET(1, ON_RELEASE), // FN6 move to Esc when release
[7] = ACTION_OVERLAY_SET(2, ON_RELEASE), // FN7 move to arrow + Esc when release
[8] = ACTION_RMODS_KEY(MOD_BIT(KC_RCTL)|MOD_BIT(KC_RSFT), KC_ESC), // FN8 Task(RControl,RShift+Esc)
};

View file

@ -36,6 +36,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_ROWS 8
#define MATRIX_COLS 8
/* To use new keymap framework */
#define USE_KEYMAP_V2
/*
* Boot magic keys

View file

@ -31,6 +31,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_ROWS 8
#define MATRIX_COLS 8
/* To use new keymap framework */
#define USE_KEYMAP_V2
/* key combination for command */
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))

View file

@ -56,18 +56,18 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs|
* |-----------------------------------------------------------|
* |Fn6 | A| S| D| F| G| H| J| K| L|Fn3| '|Return |
* |Contro| A| S| D| F| G| H| J| K| L|Fn3| '|Fn4 |
* |-----------------------------------------------------------|
* |Fn8 | Z| X| C| V| B| N| M| ,| .|Fn2|Fn12 |Fn1|
* |Fn5 | Z| X| C| V| B| N| M| ,| .|Fn2|Shift |Fn1|
* `-----------------------------------------------------------'
* |Gui|Alt | Fn5 |Alt |Fn4|
* |Gui|Alt | Fn6 |Alt |Fn7|
* `-------------------------------------------'
*/
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
FN6, A, S, D, F, G, H, J, K, L, FN3, QUOT,FN7, \
FN8, Z, X, C, V, B, N, M, COMM,DOT, FN2, FN12,FN9, \
LGUI,LALT, FN5, FN13,FN4),
LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,FN4, \
FN5,Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \
LGUI,LALT, FN6, RALT,FN7),
/* Layer 1: HHKB mode (HHKB Fn)
* ,-----------------------------------------------------------.
@ -77,15 +77,15 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |-----------------------------------------------------------|
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
* |-----------------------------------------------------------|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift |Fn0|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift | |
* `-----------------------------------------------------------'
* |Gui|Alt | Space |Alt |Gui|
* `-------------------------------------------'
*/
KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
CAPS,NO, NO, NO, NO, NO, NO, NO, PSCR,SLCK,PAUS, UP, NO, BSPC, \
LCTL,VOLD,VOLU,MUTE,NO, NO, PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,FN0, \
LSFT,NO, NO, NO, NO, NO, PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
LGUI,LALT, SPC, RALT,RGUI),
/* Layer 2: Vi mode (Slash)
@ -101,10 +101,10 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* |Gui|Alt | Space |Alt |Gui|
* `-------------------------------------------'
*/
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \
LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \
LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN0, RSFT,NO, \
LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, TRNS,RSFT,NO, \
LGUI,LALT, SPC, RALT,RGUI),
/* Layer 3: Mouse mode (Semicolon)
@ -121,13 +121,13 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `--------------------------------------------'
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
*/
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \
LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,FN0, QUOT,ENT, \
LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,TRNS,QUOT,ENT, \
LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,NO, \
LGUI,LALT, BTN1, RALT,FN0),
LGUI,LALT, BTN1, RALT,TRNS),
/* Layer 4: Matias half keyboard style (Space)
/* Layer 4: Matias half-qwerty keyboard style (Space)
* ,-----------------------------------------------------------.
* | -| 0| 9| 8| 7| 6| 5| 4| 3| 2| 1| | | |Esc|
* |-----------------------------------------------------------|
@ -144,7 +144,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
BSPC,P, O, I, U, Y, T, R, E, W, Q, NO, NO, TAB, \
LCTL,SCLN,L, K, J, H, G, F, D, S, A, RCTL,RCTL, \
LSFT,SLSH,DOT, COMM,M, N, B, V, C, X, Z, RSFT,NO, \
LGUI,LALT, FN0, RALT,RGUI),
LGUI,LALT, TRNS, RALT,RGUI),
/* Layer5: another Mouse mode (Space)
* ,-----------------------------------------------------------.
@ -164,7 +164,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
TAB, NO, NO, NO, NO, NO, WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSPC, \
LCTL,NO, ACL0,ACL1,ACL2,NO, MS_L,MS_D,MS_U,MS_R,NO, NO, ENT, \
LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,BTN4,BTN5,NO, RSFT,NO, \
LGUI,LALT, FN0, RALT,RGUI),
LGUI,LALT, TRNS, RALT,RGUI),
};
@ -173,56 +173,72 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
enum function_id {
LSHIFT_LPAREN,
RSHIFT_RPAREN,
MACRO = 0xff
};
enum macro_id {
LSHIFT_PAREN,
RSHIFT_PAREN,
HELLO,
};
/*
* Fn action definition
*/
// TODO: use [1] = KEYMAP(...) to prevent from changing index of element?
static const uint16_t PROGMEM fn_actions[] = {
ACTION_LAYER_DEFAULT, // FN0
ACTION_LAYER_SET(1), // FN1
ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH), // FN2 Layer with Slash
ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN), // FN3 Layer with Semicolon
[0] = ACTION_DEFAULT_LAYER, // Default layer(not used)
// [1] = ACTION_KEYMAP(1), // HHKB layer
[1] = ACTION_KEYMAP_TAP_TOGGLE(1), // HHKB layer(toggle with 5 taps)
[2] = ACTION_KEYMAP_TAP_KEY(2, KC_SLASH), // Cursor layer with Slash*
[3] = ACTION_KEYMAP_TAP_KEY(3, KC_SCLN), // Mousekey layer with Semicolon*
[4] = ACTION_RMOD_TAP_KEY(KC_RCTL, KC_ENT), // RControl with tap Enter*
[5] = ACTION_LMOD_ONESHOT(KC_LSFT), // Oneshot Shift*
// [6] = ACTION_KEYMAP_TAP_KEY(4, KC_SPC), // Half-qwerty layer with Space
[6] = ACTION_KEYMAP_TAP_KEY(5, KC_SPC), // Mousekey layer with Space
// [7] = ACTION_KEYMAP(3), // Mousekey layer
[7] = ACTION_KEYMAP_TOGGLE(3), // Mousekey layer(toggle)
ACTION_LAYER_SET(3), // FN4
// ACTION_LAYER_SET_TOGGLE(3), // FN4
// ACTION_FUNCTION(MACRO, 0), // FN4
ACTION_LAYER_SET_TAP_KEY(5, KC_SPC), // FN5
// ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // FN6 Control with tap Backspace
ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC), // FN6 Control with tap Backspace
ACTION_RMOD_TAP_KEY(KC_RCTL, KC_ENT), // FN7 Control with tap Enter
ACTION_LMOD_ONESHOT(KC_LSFT), // FN8 Oneshot Shift
ACTION_LAYER_SET_TAP_TOGGLE(1), // FN9
ACTION_LAYER_BIT_TAP_KEY(1, KC_GRV), // FN10 Layer with Grave
//ACTION_LAYER_BIT(1), // FN10
//ACTION_LAYER_BIT_TAP_TOGGLE(1), // FN10
ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // FN11 Function: LShift with tap '('
ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // FN12 Function: RShift with tap ')'
ACTION_FUNCTION(MACRO, 1), // FN13 Macro:
// [8] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_BSPC), // LControl with tap Backspace
// [9] = ACTION_LMOD_TAP_KEY(KC_LCTL, KC_ESC), // LControl with tap Esc
// [11] = ACTION_FUNCTION_TAP(LSHIFT_LPAREN), // Function: LShift with tap '('
// [12] = ACTION_FUNCTION_TAP(RSHIFT_RPAREN), // Function: RShift with tap ')'
// [13] = ACTION_MACRO_TAP(LSHIFT_PAREN), // Macro: LShift with tap '('
// [14] = ACTION_MACRO_TAP(RSHIFT_PAREN), // Macro: RShift with tap ')'
// [15] = ACTION_MACRO(HELLO), // Macro: say hello
};
/*
* Macro definition
*/
#define MACRO(...) ({ static prog_macro_t _m[] PROGMEM = { __VA_ARGS__ }; _m; })
#define MACRO_NONE 0
static const prog_macro_t *get_macro(uint8_t id, bool pressed)
const prog_macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
keyevent_t event = record->event;
tap_t tap = record->tap;
switch (id) {
case 0:
return (pressed ?
MACRO( MD(LSHIFT), D(D), END ) :
MACRO( U(D), MU(LSHIFT), END ) );
case 1:
return (pressed ?
MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END ) :
case LSHIFT_PAREN:
if (tap.count > 0 && !tap.interrupted) {
return (event.pressed ?
MACRO( MD(LSHIFT), D(9), U(9), MU(LSHIFT), END ) : MACRO_NONE);
} else {
return (event.pressed ?
MACRO( MD(LSHIFT), END ) : MACRO( MU(LSHIFT), END ) );
}
case RSHIFT_PAREN:
if (tap.count > 0 && !tap.interrupted) {
return (event.pressed ?
MACRO( MD(RSHIFT), D(0), U(0), MU(RSHIFT), END ) : MACRO_NONE);
} else {
return (event.pressed ?
MACRO( MD(RSHIFT), END ) : MACRO( MU(RSHIFT), END ) );
}
case HELLO:
return (event.pressed ?
MACRO( I(0), T(H), T(E), T(L), T(L), W(255), T(O), END ) :
MACRO_NONE );
}
return 0;
return MACRO_NONE;
}
@ -230,82 +246,51 @@ static const prog_macro_t *get_macro(uint8_t id, bool pressed)
/*
* user defined action function
*/
void keymap_call_function(keyrecord_t *record, uint8_t id, uint8_t opt)
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
keyevent_t event = record->event;
uint8_t tap_count = record->tap_count;
debug("action_call_function: ");
if (event.pressed) debug("pressed"); else debug("released");
debug(" id: "); debug_hex(id);
debug(" tap_count: "); debug_dec(tap_count);
debug("\n");
tap_t tap = record->tap;
switch (id) {
case LSHIFT_LPAREN:
// LShft + tap '('
// NOTE: cant use register_code to avoid conflicting with magic key bind
if (event.pressed) {
if (tap_count == 0) {
if (tap.count == 0 || tap.interrupted) {
add_mods(MOD_BIT(KC_LSHIFT));
} else {
if (waiting_buffer_has_anykey_pressed()) {
// ad hoc: set 0 to cancel tap
record->tap_count = 0;
add_mods(MOD_BIT(KC_LSHIFT));
} else {
// NOTE to avoid conflicting command key bind(LShift+RShift)
//register_code(KC_LSHIFT);
//register_code(KC_9);
host_add_mods(MOD_BIT(KC_LSHIFT));
host_add_key(KC_9);
host_send_keyboard_report();
}
}
} else {
if (tap_count == 0) {
del_mods(MOD_BIT(KC_LSHIFT));
} else {
//unregister_code(KC_9);
//unregister_code(KC_LSHIFT);
host_add_mods(MOD_BIT(KC_LSHIFT));
host_add_key(KC_9);
host_send_keyboard_report();
host_del_mods(MOD_BIT(KC_LSHIFT));
host_del_key(KC_9);
host_send_keyboard_report();
}
} else {
if (tap.count == 0 || tap.interrupted) {
del_mods(MOD_BIT(KC_LSHIFT));
}
}
break;
case RSHIFT_RPAREN:
// RShift + tap ')'
if (event.pressed) {
if (tap_count == 0) {
if (tap.count == 0 || tap.interrupted) {
add_mods(MOD_BIT(KC_RSHIFT));
} else {
if (waiting_buffer_has_anykey_pressed()) {
// ad hoc: set 0 to cancel tap
record->tap_count = 0;
add_mods(MOD_BIT(KC_RSHIFT));
} else {
//register_code(KC_RSHIFT);
//register_code(KC_0);
host_add_mods(MOD_BIT(KC_RSHIFT));
host_add_key(KC_0);
host_send_keyboard_report();
}
}
} else {
if (tap_count == 0) {
del_mods(MOD_BIT(KC_RSHIFT));
} else {
//unregister_code(KC_0);
//unregister_code(KC_RSHIFT);
host_add_mods(MOD_BIT(KC_RSHIFT));
host_add_key(KC_0);
host_send_keyboard_report();
host_del_mods(MOD_BIT(KC_RSHIFT));
host_del_key(KC_0);
host_send_keyboard_report();
}
} else {
if (tap.count == 0 || tap.interrupted) {
del_mods(MOD_BIT(KC_RSHIFT));
}
}
break;
case MACRO:
action_macro_play(get_macro(opt, event.pressed));
break;
}
}
@ -328,15 +313,3 @@ action_t keymap_fn_to_action(uint8_t keycode)
}
return action;
}
/* convert key to action */
action_t action_for_key(uint8_t layer, key_t key)
{
uint8_t keycode = keymap_key_to_keycode(layer, key);
switch (keycode) {
case KC_FN0 ... KC_FN31:
return keymap_fn_to_action(keycode);
default:
return keymap_keycode_to_action(keycode);
}
}

View file

@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* host role */
void serial_init(void);
uint8_t serial_recv(void);
int16_t serial_recv2(void);
void serial_send(uint8_t data);
#endif

View file

@ -43,15 +43,47 @@ POSSIBILITY OF SUCH DAMAGE.
/*
* Stupid Inefficient Busy-wait Software Serial
* is still useful for negative logic signal like Sun protocol not supported by hardware USART.
* which is still useful for negative logic signal like Sun protocol
* if it is not supported by hardware UART.
*
* TODO: delay is not accurate enough. Instruction cycle should be counted and inline assemby is needed.
*/
#define WAIT_US (1000000/SERIAL_BAUD)
#define WAIT_US (1000000L/SERIAL_SOFT_BAUD)
#ifdef SERIAL_SOFT_LOGIC_NEGATIVE
#define SERIAL_SOFT_RXD_IN() !(SERIAL_SOFT_RXD_READ())
#define SERIAL_SOFT_TXD_ON() SERIAL_SOFT_TXD_LO()
#define SERIAL_SOFT_TXD_OFF() SERIAL_SOFT_TXD_HI()
#else
#define SERIAL_SOFT_RXD_IN() !!(SERIAL_SOFT_RXD_READ())
#define SERIAL_SOFT_TXD_ON() SERIAL_SOFT_TXD_HI()
#define SERIAL_SOFT_TXD_OFF() SERIAL_SOFT_TXD_LO()
#endif
#ifdef SERIAL_SOFT_PARITY_EVEN
#define SERIAL_SOFT_PARITY_VAL 0
#elif defined(SERIAL_SOFT_PARITY_ODD)
#define SERIAL_SOFT_PARITY_VAL 1
#endif
/* debug for signal timing, see debug pin with oscilloscope */
#define SERIAL_SOFT_DEBUG
#ifdef SERIAL_SOFT_DEBUG
#define SERIAL_SOFT_DEBUG_INIT() (DDRD |= 1<<7)
#define SERIAL_SOFT_DEBUG_TGL() (PORTD ^= 1<<7)
#else
#define SERIAL_SOFT_DEBUG_INIT()
#define SERIAL_SOFT_DEBUG_TGL()
#endif
void serial_init(void)
{
SERIAL_RXD_INIT();
SERIAL_TXD_INIT();
SERIAL_SOFT_DEBUG_INIT();
SERIAL_SOFT_RXD_INIT();
SERIAL_SOFT_TXD_INIT();
}
/* RX ring buffer */
@ -60,6 +92,7 @@ static uint8_t rbuf[RBUF_SIZE];
static uint8_t rbuf_head = 0;
static uint8_t rbuf_tail = 0;
uint8_t serial_recv(void)
{
uint8_t data = 0;
@ -72,68 +105,120 @@ uint8_t serial_recv(void)
return data;
}
int16_t serial_recv2(void)
{
uint8_t data = 0;
if (rbuf_head == rbuf_tail) {
return -1;
}
data = rbuf[rbuf_tail];
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
return data;
}
void serial_send(uint8_t data)
{
/* signal state: IDLE: ON, START: OFF, STOP: ON, DATA0: OFF, DATA1: ON */
/* start bit */
SERIAL_TXD_OFF();
_delay_us(WAIT_US);
#ifdef SERIAL_BIT_ORDER_MSB
#ifdef SERIAL_SOFT_BIT_ORDER_MSB
uint8_t mask = 0x80;
#else
uint8_t mask = 0x01;
#endif
uint8_t parity = 0;
/* start bit */
SERIAL_SOFT_TXD_OFF();
_delay_us(WAIT_US);
while (mask) {
if (data&mask) { SERIAL_TXD_ON(); } else { SERIAL_TXD_OFF(); }
if (data&mask) {
SERIAL_SOFT_TXD_ON();
parity ^= 1;
} else {
SERIAL_SOFT_TXD_OFF();
}
_delay_us(WAIT_US);
#ifdef SERIAL_BIT_ORDER_MSB
#ifdef SERIAL_SOFT_BIT_ORDER_MSB
mask >>= 1;
#else
mask <<= 1;
#endif
}
#if defined(SERIAL_SOFT_PARITY_EVEN) || defined(SERIAL_SOFT_PARITY_ODD)
/* to center of parity bit */
if (parity != SERIAL_SOFT_PARITY_VAL) {
SERIAL_SOFT_TXD_ON();
} else {
SERIAL_SOFT_TXD_OFF();
}
_delay_us(WAIT_US);
#endif
/* stop bit */
SERIAL_TXD_ON();
SERIAL_SOFT_TXD_ON();
_delay_us(WAIT_US);
}
/* detect edge of start bit */
ISR(SERIAL_RXD_VECT)
ISR(SERIAL_SOFT_RXD_VECT)
{
SERIAL_RXD_INT_ENTER()
SERIAL_SOFT_DEBUG_TGL();
SERIAL_SOFT_RXD_INT_ENTER()
uint8_t data = 0;
#ifdef SERIAL_BIT_ORDER_MSB
#ifdef SERIAL_SOFT_BIT_ORDER_MSB
uint8_t mask = 0x80;
#else
uint8_t mask = 0x01;
#endif
uint8_t parity = 0;
/* to center of start bit */
_delay_us(WAIT_US/2);
SERIAL_SOFT_DEBUG_TGL();
do {
/* to center of next bit */
_delay_us(WAIT_US);
if (SERIAL_RXD_READ()) {
SERIAL_SOFT_DEBUG_TGL();
if (SERIAL_SOFT_RXD_IN()) {
data |= mask;
parity ^= 1;
}
#ifdef SERIAL_BIT_ORDER_MSB
#ifdef SERIAL_SOFT_BIT_ORDER_MSB
mask >>= 1;
#else
mask <<= 1;
#endif
} while (mask);
#if defined(SERIAL_SOFT_PARITY_EVEN) || defined(SERIAL_SOFT_PARITY_ODD)
/* to center of parity bit */
_delay_us(WAIT_US);
if (SERIAL_SOFT_RXD_IN()) { parity ^= 1; }
SERIAL_SOFT_DEBUG_TGL();
#endif
/* to center of stop bit */
_delay_us(WAIT_US);
uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
#if defined(SERIAL_SOFT_PARITY_EVEN) || defined(SERIAL_SOFT_PARITY_ODD)
if ((parity == SERIAL_SOFT_PARITY_VAL) && next != rbuf_tail) {
#else
if (next != rbuf_tail) {
#endif
rbuf[rbuf_head] = data;
rbuf_head = next;
}
SERIAL_RXD_INT_EXIT();
SERIAL_SOFT_RXD_INT_EXIT();
SERIAL_SOFT_DEBUG_TGL();
}

93
protocol/serial_uart.c Normal file
View file

@ -0,0 +1,93 @@
/*
Copyright 2013 Jun WAKO <wakojun@gmail.com>
This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
GPL-compatible, and OK to use in both free and proprietary applications.
Additions and corrections to this file are welcome.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "serial.h"
void serial_init(void)
{
SERIAL_UART_INIT();
}
// RX ring buffer
#define RBUF_SIZE 8
static uint8_t rbuf[RBUF_SIZE];
static uint8_t rbuf_head = 0;
static uint8_t rbuf_tail = 0;
uint8_t serial_recv(void)
{
uint8_t data = 0;
if (rbuf_head == rbuf_tail) {
return 0;
}
data = rbuf[rbuf_tail];
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
return data;
}
int16_t serial_recv2(void)
{
uint8_t data = 0;
if (rbuf_head == rbuf_tail) {
return -1;
}
data = rbuf[rbuf_tail];
rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
return data;
}
void serial_send(uint8_t data)
{
while (!SERIAL_UART_TXD_READY) ;
SERIAL_UART_DATA = data;
}
// USART RX complete interrupt
ISR(SERIAL_UART_RXD_VECT)
{
uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
if (next != rbuf_tail) {
rbuf[rbuf_head] = SERIAL_UART_DATA;
rbuf_head = next;
}
}

View file

@ -88,6 +88,10 @@ static void send_keyboard(report_keyboard_t *report)
} else {
debug("kbuf: full\n");
}
// NOTE: send key strokes of Macro
usbPoll();
vusb_transfer_keyboard();
}

View file

@ -340,7 +340,8 @@ LST = $(patsubst %.c,$(OBJDIR)/%.lst,$(patsubst %.cpp,$(OBJDIR)/%.lst,$(patsubst
# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
#GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
GENDEPFLAGS = -MMD -MP -MF .dep/$(subst /,_,$@).d
# Combine all necessary flags and optional flags.