~ruther/qmk_firmware

9f95e9cc27f2edf4336124b01c05d03dcd5ee5ac — tmk 12 years ago f609712
Add support partly for modifier with tap key.
3 files changed, 239 insertions(+), 189 deletions(-)

M common/action.c
M common/action.h
M keyboard/hhkb/keymap.c
M common/action.c => common/action.c +155 -94
@@ 10,11 10,12 @@
#include "action.h"




static void process(keyevent_t event, action_t action);
static void register_code(uint8_t code);
static void unregister_code(uint8_t code);
static void add_mods(uint8_t mods);
static void del_mods(uint8_t mods);
static void set_mods(uint8_t mods);
static void clear_keyboard(void);
static void clear_keyboard_but_mods(void);
static bool sending_anykey(void);


@@ 24,7 25,6 @@ static void layer_switch(uint8_t new_layer);
/* tap */
#define TAP_TIME    200
static keyevent_t last_event = {};
static uint16_t last_event_time = 0;
static uint8_t tap_count = 0;

/* layer */


@@ 32,6 32,7 @@ uint8_t default_layer = 0;
uint8_t current_layer = 0;
keyrecord_t delaying_layer = {};

/* waiting keys buffer */
#define WAITING_KEYS_BUFFER 3
static keyrecord_t waiting_keys[WAITING_KEYS_BUFFER] = {};
static uint8_t waiting_keys_head = 0;


@@ 75,16 76,87 @@ static void waiting_keys_process_in_current_layer(void)
}


void action_exec(keyevent_t event)
{
    /* When delaying layer switch */
    if (delaying_layer.action.code) {
        /* Layer switch when tap time elapses or waiting key is released */
        if ((timer_elapsed(delaying_layer.event.time) > TAP_TIME) ||
            (!event.pressed && waiting_keys_has(event.key))) {
            /* layer switch */
            switch (delaying_layer.action.kind.id) {
                case ACT_LAYER_PRESSED:
                    layer_switch(delaying_layer.action.layer.opt);
                    break;
                case ACT_LAYER_BIT:
                    layer_switch(current_layer | delaying_layer.action.layer.opt);
                    break;
            }
            delaying_layer = (keyrecord_t){};

            /* Process waiting keys in new layer */
            waiting_keys_process_in_current_layer();
        }
        /* when delaying layer key is released within delay term */
        else if (!event.pressed && KEYEQ(event.key, delaying_layer.event.key)) {
            /* tap key down */
            debug("tap[delaying_layer](register): fist\n");
            uint8_t tmp_mods = host_get_mods();
            host_set_mods(delaying_layer.mods);
            register_code(delaying_layer.action.layer.code);
            delaying_layer = (keyrecord_t){};
            host_set_mods(tmp_mods);

            /* process waiting keys */
            waiting_keys_process_in_current_layer();
        }
    }

    // not real event. event just to update delaying layer.
    if (IS_NOEVENT(event)) {
        return;
    }

    /* count tap when key is up */
    if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) {
        if (!event.pressed) tap_count++;
    } else {
        tap_count = 0;
    }

    action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);

    // TODO: all key events(pressed, released) should be recorded?
    /* postpone key-down events while delaying layer */
    if (delaying_layer.action.code) {
        if (event.pressed) {
            waiting_keys_enqueue(event, action);
        } else {
            process(event, action);
        }
    } else {
        process(event, action);
    }

    /* last event */
    last_event = event;
}


static void process(keyevent_t event, action_t action)
{
    //action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);
    debug("action: "); debug_hex16(action.code); debug("\n");

    debug("action: "); debug_hex16(action.code);
    if (event.pressed) debug("[down]\n"); else debug("[up]\n");

    switch (action.kind.id) {
        /* Key and Mods */
        case ACT_LMODS:
            // normal key or key plus mods
            //               |pressed                          |released
            // --------------+---------------------------------+------------
            // key           |down(key)                        |up(key)
            // mods          |add(mods)                        |del(mods)
            // key with mods |add(mods), down(key), unset(mods)|up(key)
            if (event.pressed) {
                uint8_t tmp_mods = host_get_mods();
                if (action.key.mods) {


@@ 105,6 177,11 @@ static void process(keyevent_t event, action_t action)
            }
            break;
        case ACT_RMODS:
            //               |pressed                          |released
            // --------------+---------------------------------+------------
            // key           |down(key)                        |up(key)
            // mods          |add(mods)                        |del(mods)
            // key with mods |add(mods), down(key), unset(mods)|up(key)
            if (event.pressed) {
                uint8_t tmp_mods = host_get_mods();
                if (action.key.mods) {


@@ 124,9 201,49 @@ static void process(keyevent_t event, action_t action)
                unregister_code(action.key.code);
            }
            break;
        case ACT_LMOD_TAP:
        case ACT_LMODS_TAP:
            if (event.pressed) {
                if (tap_count == 0) {
                    add_mods(action.key.mods);
                } else {
                    debug("tap[lmods](register): "); debug_hex(tap_count); debug("\n");
                    register_code(action.key.code);
                }
            } else {
                if (tap_count == 0) {
                    del_mods(action.key.mods);
                } else if (tap_count == 1) {
                    debug("tap[lmods](register/unregister): "); debug_hex(tap_count); debug("\n");
                    del_mods(action.key.mods);
                    register_code(action.key.code);
                    unregister_code(action.key.code);
                } else {
                    debug("tap[lmods](unregister): "); debug_hex(tap_count); debug("\n");
                    unregister_code(action.key.code);
                }
            }
            break;
        case ACT_RMOD_TAP:
        case ACT_RMODS_TAP:
            if (event.pressed) {
                if (tap_count == 0) {
                    add_mods(action.key.mods<<4);
                } else {
                    debug("tap[rmods](register): "); debug_hex(tap_count); debug("\n");
                    register_code(action.key.code);
                }
            } else {
                if (tap_count == 0) {
                    del_mods(action.key.mods<<4);
                } else if (tap_count == 1) {
                    debug("tap[rmods](register/unregister): "); debug_hex(tap_count); debug("\n");
                    del_mods(action.key.mods<<4);
                    register_code(action.key.code);
                    unregister_code(action.key.code);
                } else {
                    debug("tap[rmods](unregister): "); debug_hex(tap_count); debug("\n");
                    unregister_code(action.key.code);
                }
            }
            break;

        /* other HID usage */


@@ 186,6 303,7 @@ static void process(keyevent_t event, action_t action)
                    // with tap key
                    if (event.pressed) {
                        if (tap_count == 0) {
                            // not tapping yet
                            if (host_has_anykey()) {
                                register_code(action.layer.code);
                            } else {


@@ 197,22 315,14 @@ static void process(keyevent_t event, action_t action)
                                };
                            }
                        } else if (tap_count > 0) {
                            debug("tap: "); debug_hex(tap_count); debug("\n");
                            // pressed after tapping
                            debug("tap[layer](register): "); debug_hex(tap_count); debug("\n");
                            register_code(action.layer.code);
                        }
                    } else {
                        // tap key
                        if (KEYEQ(event.key, delaying_layer.event.key) &&
                                timer_elapsed(delaying_layer.event.time) <= TAP_TIME) {
                            uint8_t tmp_mods = host_get_mods();
                            host_set_mods(delaying_layer.mods);
                            register_code(delaying_layer.action.layer.code);
                            host_set_mods(tmp_mods);
                            unregister_code(delaying_layer.action.layer.code);
                        } else {
                            unregister_code(action.layer.code);
                        }
                        delaying_layer = (keyrecord_t){};
                        // released after tapping
                        debug("tap[layer](unregister): "); debug_hex(tap_count); debug("\n");
                        unregister_code(action.layer.code);
                    }
                    break;
            }


@@ 220,7 330,7 @@ static void process(keyevent_t event, action_t action)
        case ACT_LAYER_RELEASED:
            switch (action.layer.code) {
                case 0x00:
                    if (event.pressed) {
                    if (!event.pressed) {
                        layer_switch(action.layer.opt);
                    }
                    break;


@@ 274,7 384,7 @@ static void process(keyevent_t event, action_t action)
                                };
                            }
                        } else if (tap_count > 0) {
                            debug("tap: "); debug_hex(tap_count); debug("\n");
                            debug("tap[layer_bit](register): "); debug_hex(tap_count); debug("\n");
                            register_code(action.layer.code);
                        }
                    } else {


@@ 348,77 458,6 @@ static void process(keyevent_t event, action_t action)
    }
}

void action_exec(keyevent_t event)
{
/*
    debug("key["); debug_hex8(event.key.row); debug(":"); debug_hex8(event.key.col);
    if (event.pressed) debug("]down\n"); else debug("]up\n");
*/

    /* When delaying layer switch */
    if (delaying_layer.action.code) {
        /* Layer switch when tap time elapses or waiting key is released */
        if ((timer_elapsed(delaying_layer.event.time) > TAP_TIME) ||
            (!event.pressed && waiting_keys_has(event.key))) {
            /* layer switch */
            switch (delaying_layer.action.kind.id) {
                case ACT_LAYER_PRESSED:
                    layer_switch(delaying_layer.action.layer.opt);
                    break;
                case ACT_LAYER_BIT:
                    layer_switch(current_layer | delaying_layer.action.layer.opt);
                    break;
            }
            delaying_layer = (keyrecord_t){};

            /* Process waiting keys in new layer */
            waiting_keys_process_in_current_layer();
        }
        /* when delaying layer key is released within delay term */
        else if (!event.pressed && KEYEQ(event.key, delaying_layer.event.key)) {
            /* tap key down */
            uint8_t tmp_mods = host_get_mods();
            host_set_mods(delaying_layer.mods);
            register_code(delaying_layer.action.layer.code);
            delaying_layer = (keyrecord_t){};
            host_set_mods(tmp_mods);

            /* process waiting keys */
            waiting_keys_process_in_current_layer();
        }
    }

    // not real event. event just to update delaying layer.
    if (IS_NOEVENT(event)) {
        return;
    }

    /* count tap when key is up */
    if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event.time) <= TAP_TIME) {
        if (!event.pressed) tap_count++;
    } else {
        tap_count = 0;
    }

    action_t action = keymap_get_action(current_layer, event.key.row, event.key.col);

    // TODO: all key events(pressed, released) should be recorded?
    /* postpone key-down events while delaying layer */
    if (delaying_layer.action.code) {
        if (event.pressed) {
            waiting_keys_enqueue(event, action);
        } else {
            process(event, action);
        }
    } else {
        process(event, action);
    }

    /* last event */
    last_event = event;
}


static void register_code(uint8_t code)
{
    if (code == KC_NO) {


@@ 449,6 488,28 @@ static void unregister_code(uint8_t code)
    }
}

static void add_mods(uint8_t mods)
{
    if (mods) {
        host_add_mods(mods);
        host_send_keyboard_report();
    }
}

static void del_mods(uint8_t mods)
{
    if (mods) {
        host_del_mods(mods);
        host_send_keyboard_report();
    }
}

static void set_mods(uint8_t mods)
{
    host_set_mods(mods);
    host_send_keyboard_report();
}

static void clear_keyboard(void)
{
    host_clear_mods();

M common/action.h => common/action.h +81 -80
@@ 5,55 5,57 @@


/* Key Action(16bit code)
 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
------------------------------------------------
ACT_LMODS(0000)
  0  0  0  0| 0  0  0  0| 0  0  0  0  0  0| 0  0    No action
  0  0  0  0| 0  0  0  0|     keycode(8)            Key
  0  0  0  0|  mods(4)  | 0  0  0  0  0  0| 0  0    Lmods Momentary
  0  0  0  0|  mods(4)  | 0  0  0  0  0  0| 0  1    Lmods OneShot
  0  0  0  0|  mods(4)  | 0  0  0  0  0  0| 1  0    (reserved)
  0  0  0  0|  mods(4)  | 0  0  0  0  0  0| 1  1    (reserved)
  0  0  0  0|  mods(4)  |     keycode(8)            Key+Lmods

ACT_RMODS(0001)
  0  0  0  1| 0  0  0  0| 0  0  0  0  0  0  0  0    No action(not used)
  0  0  0  1| 0  0  0  0|     keycode(8)            Key(not used)
  0  0  0  1|  mods(4)  | 0  0  0  0  0  0| 0  0    Rmods Momentary
  0  0  0  1|  mods(4)  | 0  0  0  0  0  0| 0  1    Rmods OneShot
  0  0  0  1|  mods(4)  | 0  0  0  0  0  0| 1  0    (reserved)
  0  0  0  1|  mods(4)  | 0  0  0  0  0  0| 1  1    (reserved)
  0  0  0  1|  mods(4)  |     keycode(8)            Key+Rmod

ACT_LMODS_TAP(0010)
  0  0  1  0| 0  0  0  0| X  X  X  X  X  X  X  X    (reserved)[00-FF]
  0  0  1  0|  mods(4)  | 0  0  0  0  0  0| X  X    (reserved)
  0  0  1  0|  mods(4)  |     keycode(8)            Lmods+tap Key
  0  0  1  0|  mods(4)  | 1  1  1  1| X  X  X  X    (reserved)[F0-FF]

ACT_RMODS_TAP(0011)
  0  0  1  1| 0  0  0  0| X  X  X  X  X  X  X  X    (reserved)[00-FF]
  0  0  1  1|  mods(4)  | 0  0  0  0  0  0| X  X    (reserved)
  0  0  1  1|  mods(4)  |     keycode(8)            Rmods+tap Key
  0  0  1  1|  mods(4)  | 1  1  1  1| X  X  X  X    (reserved)[F0-FF]

Keyboard Keys
-------------
ACT_LMODS(0000):
0000|0000|000000|00    No action
0000|mods|000000|00    Left mods Momentary
0000|mods|000000|01    Left mods OneShot
0000|mods|000000|10    (reserved)
0000|mods|000000|11    (reserved)
0000|0000| keycode     Key
0000|mods| keycode     Key+Left mods

ACT_RMODS(0001):
0001|0000|000000|00    No action
0001|mods|000000|00    Right mods Momentary
0001|mods|000000|01    Right mods OneShot
0001|mods|000000|10    (reserved)
0001|mods|000000|11    (reserved)
0001|0000| keycode     Key
0001|mods| keycode     Key+Right mods

ACT_LMODS_TAP(0010):
0010|mods| keycode     Left mods+tap Key

ACT_RMODS_TAP(0011):
0011|mods| keycode     Right mods+tap Key
 
ACT_USAGE - other HID usage than keyboard
  0  1  0  0| 0  0|         usage(10)               System usage
  0  1  0  0| 0  1|         usage(10)               Consumer usage
  0  1  0  0| 1  0|         usage(10)               (reserved)
  0  1  0  0| 1  1|         usage(10)               (reserved)

ACT_MOUSEKEY(0110)
  0  1  0  1| X  X  X  X|        keycode(8)         Mouse key
??? TODO: refactor
  0  1  0  1| 0  0  X  X|  accel(5)    |cursor(3)   Mouse key
  0  1  0  1| 0  1  X  X|  accel(5)    |wheel(3)    Mouse key
  0  1  0  1| 1  0  X  X|        button(8)          Mouse key
  0  1  0  1| 1  1  X  X|        button(8)          Mouse key
???

Layer Action
------------

Other HID Usage
---------------
This action handles other usages than keyboard.
ACT_USAGE(0100):
0100|00| usage(10)     System control(0x80) - General Desktop page(0x01)
0100|01| usage(10)     Consumer control(0x01) - Consumer page(0x0C)
0100|10| usage(10)     (reserved)
0100|11| usage(10)     (reserved)


Mouse Keys
----------
ACT_MOUSEKEY(0110):
0101|XXXX| keycode     Mouse key


Layer Actions
-------------
ACT_LAYER_PRESSED(1000):    Set layer on key pressed
ACT_LAYER_RELEASED(1001):   Set layer on key released
ACT_LAYER_BIT(1010):        On/Off layer bit
ACT_LAYER_EXT(1011):        Extentions

1000|LLLL|0000 0000   set layer L when pressed
1001|LLLL|0000 0000   set layer L when released
1010|BBBB|0000 0000   on/off bit B when pressed/released


@@ 79,16 81,19 @@ Layer Action
1011|0001| keyocde    set default layer when released[tap is ignored/not used]
 

ACT_MACRO(1100)
  1  1  0  0| option(4) |     macro-table id(8)     Macro play(Flash)
  1  1  0  0| option(4) |     macro-table id(8)     Macro play(EEPROM)
  1  1  0  0| 1  1  1  1|     macro-table id(8)     Macro record
Extensions(11XX)
----------------
NOTE: NOT FIXED

ACT_MACRO(1100):
1100|opt | id(8)      Macro play
1100|1111| id(8)      Macro record

ACT_COMMAND(1110)
  1  1  1  0| option(4) |     comamnd id(8)         Built-in Command exec
ACT_COMMAND(1110):
1110|opt | id(8)      Built-in Command exec

ACT_FUNCTION(1111)
  1  1  1  1|   function address(4K range)          Function
ACT_FUNCTION(1111):
1111| address(12)     Function
                                                    Macro record(dynamicly)
                                                    Macro play(dynamicly)
TODO: modifier + [tap key /w mod]


@@ 98,19 103,22 @@ TODO: modifier + [tap key /w mod]
*/

enum action_id {
    ACT_LMODS    = 0b0000,
    ACT_RMODS    = 0b0001,
    ACT_LMOD_TAP = 0b0010,
    ACT_RMOD_TAP = 0b0011,
    ACT_USAGE    = 0b0100,
    ACT_MOUSEKEY = 0b0101,
    ACT_LAYER_PRESSED  = 0b1000,
    ACT_LAYER_RELEASED = 0b1001,
    ACT_LAYER_BIT      = 0b1010,
    ACT_LAYER_EXT      = 0b1011,
    ACT_MACRO    = 0b1100,
    ACT_COMMAND  = 0b1110,
    ACT_FUNCTION = 0b1111
    ACT_LMODS           = 0b0000,
    ACT_RMODS           = 0b0001,
    ACT_LMODS_TAP       = 0b0010,
    ACT_RMODS_TAP       = 0b0011,

    ACT_USAGE           = 0b0100,
    ACT_MOUSEKEY        = 0b0101,

    ACT_LAYER_PRESSED   = 0b1000,
    ACT_LAYER_RELEASED  = 0b1001,
    ACT_LAYER_BIT       = 0b1010,
    ACT_LAYER_EXT       = 0b1011,

    ACT_MACRO           = 0b1100,
    ACT_COMMAND         = 0b1110,
    ACT_FUNCTION        = 0b1111
};

// TODO: not portable across compiler/endianness?


@@ 169,20 177,13 @@ typedef struct {


void action_exec(keyevent_t event);
/*
void key_action(uint8_t code, keyevent_t event);
void mod_action(uint8_t code, keyevent_t event);
void fn_action(uint8_t code, keyevent_t event);
*/


// TODO: proper names
/* action_t utility */
/*
#define ACTION_NO                       { .code = 0 }
#define ACTION(kind, param)             { .code = ((kind)<<12 | (param)) }
*/
#define ACTION_NO                       0
#define ACTION(kind, param)             ((kind)<<12 | (param))
#define MOD_BITS(mods)                  (((mods)>>4 | (mods)) & 0x0F)

/* Key & Mods */
#define ACTION_KEY(key)                 ACTION(ACT_LMODS,    key)


@@ 197,8 198,8 @@ void fn_action(uint8_t code, keyevent_t event);
#define ACTION_RMODS_SWITCH(mods, tap)  ACTION(ACT_RMODS,    (mods)<<8 | 0xF0 | (tap))
#define ACTION_RMODS_TOGGLE(mods, tap)  ACTION(ACT_RMODS,    (mods)<<8 | 0xF1 | (tap))
/* Mods + Tap key */
#define ACTION_LMODS_TAP(mods, key)     ACTION(ACT_LMODS_TAP,(mods)<<8 | (key))
#define ACTION_RMODS_TAP(mods, key)     ACTION(ACT_RMODS_TAP,(mods)<<8 | (key))
#define ACTION_LMODS_TAP(mods, key)     ACTION(ACT_LMODS_TAP, MOD_BITS(mods)<<8 | (key))
#define ACTION_RMODS_TAP(mods, key)     ACTION(ACT_RMODS_TAP, MOD_BITS(mods)<<8 | (key))

/* Layer Switch */
#define ACTION_LAYER_SET_ON_PRESSED(layer)   ACTION(ACT_LAYER_PRESSED,  (layer)<<8 | 0x00)

M keyboard/hhkb/keymap.c => keyboard/hhkb/keymap.c +3 -15
@@ 51,18 51,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
}


/*
static const action_t PROGMEM fn_actions[] = {
    ACTION_LAYER_TO_DEFAULT_ON_RELEASED,    // Fn0
    ACTION_LAYER_SET_ON_PRESSED(1),         // Fn1
    ACTION_LAYER_SET_TAP_KEY(2, KC_SLASH),  // Fn2
    ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN),   // Fn3
    ACTION_LAYER_SET_ON_PRESSED(3),         // Fn4
    ACTION_LAYER_SET_TAP_KEY(5, KC_SPC),    // Fn5
    ACTION_NO,                              // Fn6
    ACTION_NO,                              // Fn7
};
*/
static const uint16_t PROGMEM fn_actions[] = {
    ACTION_LAYER_TO_DEFAULT_ON_RELEASED,    // Fn0
    ACTION_LAYER_SET_ON_PRESSED(1),         // Fn1


@@ 70,8 58,8 @@ static const uint16_t PROGMEM fn_actions[] = {
    ACTION_LAYER_SET_TAP_KEY(3, KC_SCLN),   // Fn3
    ACTION_LAYER_SET_ON_PRESSED(3),         // Fn4
    ACTION_LAYER_SET_TAP_KEY(5, KC_SPC),    // Fn5
    ACTION_NO,                              // Fn6
    ACTION_NO,                              // Fn7
    ACTION_LMODS_TAP(MOD_BIT(KC_LCTL), KC_BSPC), // Fn6
    ACTION_RMODS_TAP(MOD_BIT(KC_RCTL), KC_ENT), // Fn7
};




@@ 91,7 79,7 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
     */
    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,   FN3, QUOT,ENT, \
           FN6, A,   S,   D,   F,   G,   H,   J,   K,   L,   FN3, QUOT,FN7, \
           LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, FN2, RSFT,FN1, \
                LGUI,LALT,          FN5,                RALT,FN4),