~ruther/qmk_firmware

28b5f69ce5c8b35d40725b490e7a2d4bfe922ad4 — tmk 12 years ago 1fe820a
Add prototype of Action Function.
5 files changed, 185 insertions(+), 70 deletions(-)

M common/action.c
M common/action.h
M common/keyboard.c
M common/keyboard.h
M keyboard/hhkb/keymap.c
M common/action.c => common/action.c +127 -63
@@ 11,47 11,26 @@


static void process(keyevent_t event);
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);
static void layer_switch(uint8_t new_layer);


/* tap */
#define TAP_TIME    300
/* This counts up when tap occurs */
static uint8_t tap_count = 0;
static bool is_tap_key(keyevent_t event)

void test_func(keyevent_t event, uint8_t opt)
{
    action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col);
    switch (action.kind.id) {
        case ACT_LMODS_TAP:
        case ACT_RMODS_TAP:
            return true;
        case ACT_LAYER_PRESSED:
        case ACT_LAYER_BIT:
            switch (action.layer.code) {
                case 0x00:
                case 0xF1 ... 0xFF:
                    return false;
                case 0xF0:
                default:
                    return true;
            }
            return false;
    if (event.pressed) {
        debug("test_func:pressed: "); debug_hex(opt); debug("\n");
    } else {
        debug("test_func:released: "); debug_hex(opt); debug("\n");
    }
    return false;
}

/* layer */
uint8_t default_layer = 0;
uint8_t current_layer = 0;
static keyevent_t tapping_event = {};

/* tap term(ms) */
#define TAP_TIME    200

/* This counts up when tap occurs */
uint8_t tap_count = 0;
keyevent_t tapping_event = {};

/* TAPPING: This indicates that whether tap or not is not decided yet. */
// NOTE:  keyevent_t.time 0 means no event.


@@ 61,26 40,41 @@ static keyevent_t tapping_event = {};
#define WAITING_KEYS_BUFFER 8
static keyevent_t waiting_events[WAITING_KEYS_BUFFER] = {};
static uint8_t waiting_events_head = 0;
static uint8_t waiting_events_tail = 0;

static bool waiting_events_enqueue(keyevent_t event)
{
    if (IS_NOEVENT(event)) { return true; }

    if (waiting_events_head < WAITING_KEYS_BUFFER) {
        debug("waiting_events["); debug_dec(waiting_events_head); debug("] = ");
        debug_hex16(event.key.raw); debug("\n");
        waiting_events[waiting_events_head++] = event;
        return true;
    if ((waiting_events_head + 1) % WAITING_KEYS_BUFFER == waiting_events_tail) {
        debug("waiting_events_enqueue: Over flow.\n");
        return false;
    }
    debug("waiting_events_enqueue: Over flow.\n");
    return false;

    debug("waiting_events["); debug_dec(waiting_events_head); debug("] = ");
    debug_hex16(event.key.raw); debug("\n");

    waiting_events[waiting_events_head] = event;
    waiting_events_head = (waiting_events_head + 1)% WAITING_KEYS_BUFFER;
    return true;
}
static keyevent_t waiting_events_dequeue(void)
{
    if (waiting_events_head == waiting_events_tail) {
        return (keyevent_t){};
    }
    uint8_t tail = waiting_events_tail;
    waiting_events_tail = waiting_events_tail + 1 % WAITING_KEYS_BUFFER;
    return waiting_events[tail];
}
static void waiting_events_clear(void)
{
    waiting_events_head = 0;
    waiting_events_tail = 0;
}
static bool waiting_events_has(key_t key)
{
    for (uint8_t i = 0; i < waiting_events_head; i++) {
    for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) {
        if KEYEQ(key, waiting_events[i].key) return true;
    }
    return false;


@@ 88,7 82,7 @@ static bool waiting_events_has(key_t key)
static void waiting_events_process_in_current_layer(void)
{
    // TODO: in case of including tap key in waiting keys
    for (uint8_t i = 0; i < waiting_events_head; i++) {
    for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) {
        debug("waiting_events_process_in_current_layer["); debug_dec(i); debug("]\n");
        process(waiting_events[i]);
    }


@@ 96,7 90,7 @@ static void waiting_events_process_in_current_layer(void)
}
static bool waiting_events_has_anykey_pressed(void)
{
    for (uint8_t i = 0; i < waiting_events_head; i++) {
    for (uint8_t i = waiting_events_tail; i != waiting_events_head; i = (i + 1) % WAITING_KEYS_BUFFER) {
        if (waiting_events[i].pressed) return true;
    }
    return false;


@@ 137,7 131,7 @@ void action_exec(keyevent_t event)
                tap_count = 0;
                tapping_event = (keyevent_t){};
            } else {
                //debug("Tapping: pressing tap key.\n");
                if (!IS_NOEVENT(event)) debug("Tapping: other key while tapping.\n");
                if (tap_count == 0) {
                    // store event
                    waiting_events_enqueue(event);


@@ 146,14 140,22 @@ void action_exec(keyevent_t event)
                process(event);
            }
        } else {
            //debug("Tapping after releasing tap.\n");
            // Sequential tap
            // Waiting for sequential tap
            if (tap_count && event.pressed && KEYEQ(tapping_event.key, event.key)) {
                tap_count++;
                tapping_event = event;
                debug("Tapping: Sequential tap("); debug_hex(tap_count); debug(")\n");
                process(event);
            } else if (event.pressed && is_tap_key(event)) {
                // Sequential tap can be interfered with other tap key.
                debug("Tapping: Start with interfering other tap.\n");
                tapping_event = event;
                tap_count = 0;
                waiting_events_clear();
            } else {
                if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
                process(event);
            }
            process(event);
        }
    }
    // Not in tapping term


@@ 162,7 164,7 @@ void action_exec(keyevent_t event)
            if (tapping_event.pressed) {
                if (tap_count == 0) {
                    // Not tap, holding down normal key.
                    debug("Not tap.\n");
                    debug("Tapping: End. Not tap(time out).\n");
                    process(tapping_event);
                    waiting_events_process_in_current_layer();



@@ 170,15 172,27 @@ void action_exec(keyevent_t event)
                    tapping_event = (keyevent_t){};
                    process(event);
                } else {
                    // Holding down last tap key.
                    //debug("Time out with holding last tap.\n");
                    process(event);
                    // Holding down last tap key. waiting for releasing last tap key.
                    if (!event.pressed && KEYEQ(tapping_event.key, event.key)) {
                        debug("Tapping: End(Release holding last tap).\n");
                        debug("Tapping: End. Release holding last tap(time out).\n");
                        process(event);
                        // clear after release last tap key
                        tap_count = 0;
                        tapping_event = (keyevent_t){};
                        waiting_events_clear();
                    } else if (event.pressed && is_tap_key(event)) {
                        debug("Tapping: Start with forcing to release last tap(time out).\n");
                        process((keyevent_t){
                                .key = tapping_event.key,
                                .time = event.time,
                                .pressed = false });

                        tap_count = 0;
                        tapping_event = event;
                        waiting_events_clear();
                    } else {
                        if (!IS_NOEVENT(event)) debug("Tapping: other key while waiting for release of last tap(time out).\n");
                        process(event);
                    }
                }
            } else {


@@ 206,7 220,6 @@ void action_exec(keyevent_t event)
    }
}


static void process(keyevent_t event)
{
    if (IS_NOEVENT(event)) { return; }


@@ 354,6 367,20 @@ static void process(keyevent_t event)
                default:
                    // with tap key
                    if (event.pressed) {
                        if (IS_TAPPING(event.key)) {
                           if (tap_count > 0) {
                                debug("LAYER_PRESSED: Tap: register_code\n");
                                register_code(action.layer.code);
                           } else {
                                debug("LAYER_PRESSED: No tap: layer_switch\n");
                                layer_switch(action.layer.opt);
                           }
                        } else {
                            // TODO: while other key tapping
                                debug("LAYER_PRESSED: No tap: layer_switch\n");
                                layer_switch(action.layer.opt);
                        }
/*
                        if (IS_TAPPING(event.key) && tap_count > 0) {
                            debug("LAYER_PRESSED: Tap: register_code\n");
                            register_code(action.layer.code);


@@ 361,6 388,7 @@ static void process(keyevent_t event)
                            debug("LAYER_PRESSED: No tap: layer_switch\n");
                            layer_switch(action.layer.opt);
                        }
*/
                    } else {
                        if (IS_TAPPING(event.key) && tap_count > 0) {
                            debug("LAYER_PRESSED: Tap: unregister_code\n");


@@ 488,14 516,23 @@ static void process(keyevent_t event)

        /* Extentions */
        case ACT_MACRO:
            break;
        case ACT_COMMAND:
            break;
        case ACT_FUNCTION:
            action_call_function(event, action.func.id);
            //test_func(event, action.func.opt);
            break;
        default:
            break;
    }
}

static void register_code(uint8_t code)

/*
 * Utilities for actions.
 */
void register_code(uint8_t code)
{
    if (code == KC_NO) {
        return;


@@ 513,7 550,7 @@ static void register_code(uint8_t code)
    }
}

static void unregister_code(uint8_t code)
void unregister_code(uint8_t code)
{
    if IS_KEY(code) {
        host_del_key(code);


@@ 525,7 562,7 @@ static void unregister_code(uint8_t code)
    }
}

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


@@ 533,7 570,7 @@ static void add_mods(uint8_t mods)
    }
}

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


@@ 541,19 578,19 @@ static void del_mods(uint8_t mods)
    }
}

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

static void clear_keyboard(void)
void clear_keyboard(void)
{
    host_clear_mods();
    clear_keyboard_but_mods();
}

static void clear_keyboard_but_mods(void)
void clear_keyboard_but_mods(void)
{
    host_clear_keys();
    host_send_keyboard_report();


@@ 567,13 604,13 @@ static void clear_keyboard_but_mods(void)
#endif
}

static bool sending_anykey(void)
bool sending_anykey(void)
{
    return (host_has_anykey() || host_mouse_in_use() ||
            host_last_sysytem_report() || host_last_consumer_report());
}

static void layer_switch(uint8_t new_layer)
void layer_switch(uint8_t new_layer)
{
    if (current_layer != new_layer) {
        debug("Layer Switch: "); debug_hex(current_layer);


@@ 584,3 621,30 @@ static void layer_switch(uint8_t new_layer)
        // TODO: update mods with full scan of matrix? if modifier changes between layers
    }
}

bool is_tap_key(keyevent_t event)
{
    action_t action = keymap_get_action(current_layer, event.key.pos.row, event.key.pos.col);
    switch (action.kind.id) {
        case ACT_LMODS_TAP:
        case ACT_RMODS_TAP:
            return true;
        case ACT_LAYER_PRESSED:
        case ACT_LAYER_BIT:
            switch (action.layer.code) {
                case 0x00:
                case 0xF1 ... 0xFF:
                    return false;
                case 0xF0:
                default:
                    return true;
            }
            return false;
        case ACT_FUNCTION:
            if (action.func.opt & 0x1) {
                return true;
            }
            return false;
    }
    return false;
}

M common/action.h => common/action.h +36 -2
@@ 3,8 3,30 @@

#include "keyboard.h"

extern uint8_t tap_count;
extern keyevent_t tapping_event;

/* Key Action(16bit code)

/*
 * Utilities for actions.
 */
void register_code(uint8_t code);
void unregister_code(uint8_t code);
void add_mods(uint8_t mods);
void del_mods(uint8_t mods);
void set_mods(uint8_t mods);
void clear_keyboard(void);
void clear_keyboard_but_mods(void);
bool sending_anykey(void);
void layer_switch(uint8_t new_layer);
bool is_tap_key(keyevent_t event);




/*
Action codes
16bit code: action_kind(4bit) + action_parameter(12bit)

Keyboard Keys
-------------


@@ 94,6 116,7 @@ ACT_COMMAND(1110):

ACT_FUNCTION(1111):
1111| address(12)     Function
1111|opt | id(8)      Function
                                                    Macro record(dynamicly)
                                                    Macro play(dynamicly)
TODO: modifier + [tap key /w mod]


@@ 160,6 183,11 @@ typedef union {
        uint16_t option :4;
        uint16_t kind   :4;
    } command;
    struct action_function {
        uint8_t  id     :8;
        uint8_t  opt    :4;
        uint8_t  kind   :4;
    } func;
} action_t;




@@ 169,14 197,20 @@ enum stroke_cmd {
    STROKE_ALLUP, /* release all keys in reverse order */
};

// TODO: not needed?
typedef struct {
    keyevent_t  event;
    action_t    action;
    uint8_t     mods;
} keyrecord_t;

/* action function */
typedef void (*action_func_t)(keyevent_t event, uint8_t opt);


// TODO: legacy keymap support
void action_exec(keyevent_t event);
void action_call_function(keyevent_t event, uint8_t id);


// TODO: proper names


@@ 234,7 268,7 @@ void action_exec(keyevent_t event);
/* Command */
#define ACTION_COMMAND(opt, id)         ACTION(ACT_COMMAND,  (opt)<<8 | (addr))
/* Function */
#define ACTION_FUNCTION(addr)           ACTION(ACT_FUNCTION, addr)
#define ACTION_FUNCTION(id, opt)        ACTION(ACT_FUNCTION, (opt)<<8 | id)


/* helpers for readability */

M common/keyboard.c => common/keyboard.c +2 -1
@@ 89,7 89,8 @@ void keyboard_task(void)
            }
        }
    }
    // call to update delaying layer when no real event
    // call with not real event to update state of aciton
    // TODO: use NOEVENT macro
    action_exec((keyevent_t) {
        .key.pos = (keypos_t){ .row = 255, .col = 255 }, // assume this key doesn't exist
        .pressed = false,

M common/keyboard.h => common/keyboard.h +2 -2
@@ 44,10 44,10 @@ typedef struct {

#define KEYEQ(keya, keyb)       (keya.raw == keyb.raw)
#define IS_NOEVENT(event)       (event.time == 0)
#define NOEVENT                 (keyevent_t) {      \
#define NOEVENT                 (keyevent_t){       \
    .key = (keypos_t){ .row = 255, .col = 255 },    \
    .pressed = false,                               \
    .time = 0,                                      \
    .time = 0                                       \
}



M keyboard/hhkb/keymap.c => keyboard/hhkb/keymap.c +18 -2
@@ 56,7 56,8 @@ static const uint16_t PROGMEM fn_actions[] = {
    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_ON_PRESSED(3),         // Fn4
    ACTION_FUNCTION(0x01, 0xA), // Fn4
    ACTION_LAYER_SET_TAP_KEY(5, KC_SPC),    // Fn5
    ACTION_LMODS_TAP(MOD_BIT(KC_LCTL), KC_BSPC), // Fn6
    ACTION_RMODS_TAP(MOD_BIT(KC_RCTL), KC_ENT), // Fn7


@@ 196,7 197,7 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) {
        case KC_MS_UP ... KC_MS_ACCEL2:
            action.code = ACTION_MOUSEKEY(key);
            break;
/*
/* TODO
        case KC_LCTRL ... KC_LGUI:
            action.code = ACTION_LMODS(MOD_BIT(key));
            break;


@@ 214,3 215,18 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) {
    }
    return action;
}

// TODO: how to define action function
void action_call_function(keyevent_t event, uint8_t id)
{
    // '(' Shift+9
    if (event.pressed) {
        register_code(KC_LSHIFT);
        register_code(KC_9);
        debug("action_call_function: pressed: id: "); debug_hex(id); debug("\n");
    } else {
        unregister_code(KC_9);
        unregister_code(KC_LSHIFT);
        debug("action_call_function: released: id: "); debug_hex(id); debug("\n");
    }
}