forked from mirrors/qmk_userspace
		
	Add oneshot modifier action.
This commit is contained in:
		
					parent
					
						
							
								66d5dd2842
							
						
					
				
			
			
				commit
				
					
						bfd7fe5862
					
				
			
		
					 3 changed files with 236 additions and 175 deletions
				
			
		
							
								
								
									
										201
									
								
								common/action.c
									
										
									
									
									
								
							
							
						
						
									
										201
									
								
								common/action.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -97,6 +97,40 @@ static void waiting_buffer_process(void)
 | 
			
		|||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Oneshot modifier
 | 
			
		||||
 *
 | 
			
		||||
 * Problem: Want to capitalize like 'The' but the result tends to be 'THe'.
 | 
			
		||||
 * Solution: Oneshot modifier have its effect on only one key coming next.
 | 
			
		||||
 *           Tap Shift, then type 't', 'h' and 'e'. Not need to hold Shift key.
 | 
			
		||||
 *
 | 
			
		||||
 *  Hold:       works as normal modifier.
 | 
			
		||||
 *  Tap:        one shot modifier.
 | 
			
		||||
 *  2 Tap:      cancel one shot modifier.
 | 
			
		||||
 *  5-Tap:      toggles enable/disable oneshot feature.
 | 
			
		||||
 */
 | 
			
		||||
static struct {
 | 
			
		||||
    uint8_t mods;
 | 
			
		||||
    uint8_t time;
 | 
			
		||||
    bool    ready;
 | 
			
		||||
    bool    disabled;
 | 
			
		||||
}   oneshot_state;
 | 
			
		||||
static void oneshot_start(uint8_t mods, uint16_t time)
 | 
			
		||||
{
 | 
			
		||||
    oneshot_state.mods = mods;
 | 
			
		||||
    oneshot_state.time = time;
 | 
			
		||||
    oneshot_state.ready = true;
 | 
			
		||||
}
 | 
			
		||||
static void oneshot_cancel(void)
 | 
			
		||||
{
 | 
			
		||||
    oneshot_state.mods = 0;
 | 
			
		||||
    oneshot_state.time = 0;
 | 
			
		||||
    oneshot_state.ready = false;
 | 
			
		||||
}
 | 
			
		||||
static void oneshot_toggle(void)
 | 
			
		||||
{
 | 
			
		||||
    oneshot_state.disabled = !oneshot_state.disabled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Rule to judge tap:
 | 
			
		||||
| 
						 | 
				
			
			@ -271,83 +305,102 @@ static void process(keyrecord_t *record)
 | 
			
		|||
    switch (action.kind.id) {
 | 
			
		||||
        /* Key and Mods */
 | 
			
		||||
        case ACT_LMODS:
 | 
			
		||||
            //               |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) {
 | 
			
		||||
                    host_add_mods(action.key.mods);
 | 
			
		||||
                    host_send_keyboard_report();
 | 
			
		||||
                }
 | 
			
		||||
                register_code(action.key.code);
 | 
			
		||||
                if (action.key.mods && action.key.code) {
 | 
			
		||||
                    host_set_mods(tmp_mods);
 | 
			
		||||
                    host_send_keyboard_report();
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (action.key.mods && !action.key.code) {
 | 
			
		||||
                    host_del_mods(action.key.mods);
 | 
			
		||||
                    host_send_keyboard_report();
 | 
			
		||||
                }
 | 
			
		||||
                unregister_code(action.key.code);
 | 
			
		||||
            }
 | 
			
		||||
            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) {
 | 
			
		||||
                    host_add_mods(action.key.mods<<4);
 | 
			
		||||
                    host_send_keyboard_report();
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
 | 
			
		||||
                                                                action.key.mods<<4;
 | 
			
		||||
                if (event.pressed) {
 | 
			
		||||
                    uint8_t tmp_mods = host_get_mods();
 | 
			
		||||
                    if (mods) {
 | 
			
		||||
                        host_add_mods(mods);
 | 
			
		||||
                        host_send_keyboard_report();
 | 
			
		||||
                    }
 | 
			
		||||
                    register_code(action.key.code);
 | 
			
		||||
                    if (mods && action.key.code) {
 | 
			
		||||
                        host_set_mods(tmp_mods);
 | 
			
		||||
                        host_send_keyboard_report();
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (mods && !action.key.code) {
 | 
			
		||||
                        host_del_mods(mods);
 | 
			
		||||
                        host_send_keyboard_report();
 | 
			
		||||
                    }
 | 
			
		||||
                    unregister_code(action.key.code);
 | 
			
		||||
                }
 | 
			
		||||
                register_code(action.key.code);
 | 
			
		||||
                if (action.key.mods && action.key.code) {
 | 
			
		||||
                    host_set_mods(tmp_mods);
 | 
			
		||||
                    host_send_keyboard_report();
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (action.key.mods && !action.key.code) {
 | 
			
		||||
                    host_del_mods(action.key.mods<<4);
 | 
			
		||||
                    host_send_keyboard_report();
 | 
			
		||||
                }
 | 
			
		||||
                unregister_code(action.key.code);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case ACT_LMODS_TAP:
 | 
			
		||||
        case ACT_RMODS_TAP:
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t tmp_mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
 | 
			
		||||
                                                                        action.key.mods<<4;
 | 
			
		||||
                if (event.pressed) {
 | 
			
		||||
                    if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
 | 
			
		||||
                        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;
 | 
			
		||||
                            add_mods(tmp_mods);
 | 
			
		||||
                uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
 | 
			
		||||
                                                                    action.key.mods<<4;
 | 
			
		||||
                switch (action.layer.code) {
 | 
			
		||||
                    case 0x00:
 | 
			
		||||
                        // Oneshot modifier
 | 
			
		||||
                        if (event.pressed) {
 | 
			
		||||
                            if (tap_count == 0) {
 | 
			
		||||
                                debug("MODS_TAP: Oneshot: add_mods\n");
 | 
			
		||||
                                add_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (tap_count == 1) {
 | 
			
		||||
                                debug("MODS_TAP: Oneshot: start\n");
 | 
			
		||||
                                oneshot_start(mods, event.time);
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (tap_count == 5) {
 | 
			
		||||
                                debug("MODS_TAP: Oneshot: toggle\n");
 | 
			
		||||
                                oneshot_toggle();
 | 
			
		||||
                            }
 | 
			
		||||
                            else {
 | 
			
		||||
                                debug("MODS_TAP: Oneshot: cancel&add_mods\n");
 | 
			
		||||
                                // double tap cancels oneshot and works as normal modifier.
 | 
			
		||||
                                oneshot_cancel();
 | 
			
		||||
                                add_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            debug("MODS_TAP: Tap: register_code\n");
 | 
			
		||||
                            register_code(action.key.code);
 | 
			
		||||
                            if (tap_count == 0) {
 | 
			
		||||
                                debug("MODS_TAP: Oneshot: cancel/del_mods\n");
 | 
			
		||||
                                // cancel oneshot by holding.
 | 
			
		||||
                                oneshot_cancel();
 | 
			
		||||
                                del_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (tap_count == 1) {
 | 
			
		||||
                                debug("MODS_TAP: Oneshot: del_mods\n");
 | 
			
		||||
                                // retain Oneshot
 | 
			
		||||
                                del_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                            else {
 | 
			
		||||
                                debug("MODS_TAP: Oneshot: del_mods\n");
 | 
			
		||||
                                // cancel Mods
 | 
			
		||||
                                del_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        debug("MODS_TAP: No tap: add_mods\n");
 | 
			
		||||
                        add_mods(tmp_mods);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (IS_TAPPING_KEY(event.key) && tap_count > 0) {
 | 
			
		||||
                        debug("MODS_TAP: Tap: unregister_code\n");
 | 
			
		||||
                        unregister_code(action.key.code);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        debug("MODS_TAP: No tap: add_mods\n");
 | 
			
		||||
                        del_mods(tmp_mods);
 | 
			
		||||
                    }
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        if (event.pressed) {
 | 
			
		||||
                            if (tap_count > 0) {
 | 
			
		||||
                                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;
 | 
			
		||||
                                    add_mods(mods);
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    debug("MODS_TAP: Tap: register_code\n");
 | 
			
		||||
                                    register_code(action.key.code);
 | 
			
		||||
                                }
 | 
			
		||||
                            } else {
 | 
			
		||||
                                debug("MODS_TAP: No tap: add_mods\n");
 | 
			
		||||
                                add_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            if (tap_count > 0) {
 | 
			
		||||
                                debug("MODS_TAP: Tap: unregister_code\n");
 | 
			
		||||
                                unregister_code(action.key.code);
 | 
			
		||||
                            } else {
 | 
			
		||||
                                debug("MODS_TAP: No tap: add_mods\n");
 | 
			
		||||
                                del_mods(mods);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -579,7 +632,17 @@ void register_code(uint8_t code)
 | 
			
		|||
    }
 | 
			
		||||
    else if IS_KEY(code) {
 | 
			
		||||
        // TODO: should push command_proc out of this block?
 | 
			
		||||
        if (!command_proc(code)) {
 | 
			
		||||
        if (command_proc(code)) return;
 | 
			
		||||
 | 
			
		||||
        if (oneshot_state.mods && oneshot_state.ready && !oneshot_state.disabled) {
 | 
			
		||||
            uint8_t tmp_mods = host_get_mods();
 | 
			
		||||
            host_add_mods(oneshot_state.mods);
 | 
			
		||||
            host_add_key(code);
 | 
			
		||||
            host_send_keyboard_report();
 | 
			
		||||
 | 
			
		||||
            host_set_mods(tmp_mods);
 | 
			
		||||
            oneshot_state.ready = false;
 | 
			
		||||
        } else {
 | 
			
		||||
            host_add_key(code);
 | 
			
		||||
            host_send_keyboard_report();
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										198
									
								
								common/action.h
									
										
									
									
									
								
							
							
						
						
									
										198
									
								
								common/action.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -3,10 +3,79 @@
 | 
			
		|||
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Action struct.
 | 
			
		||||
 *
 | 
			
		||||
 * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15). 
 | 
			
		||||
 * AVR looks like a little endian in avr-gcc.
 | 
			
		||||
 *
 | 
			
		||||
 * TODO: not portable across compiler/endianness?
 | 
			
		||||
 * Byte order and bit order of 0x1234:
 | 
			
		||||
 * Big endian:     15 ...  8 7 ... 210
 | 
			
		||||
 *                |  0x12   |  0x34   |
 | 
			
		||||
 *                 0001 0010 0011 0100
 | 
			
		||||
 * Little endian:  012 ... 7  8 ... 15
 | 
			
		||||
 *                |  0x34   |  0x12   |
 | 
			
		||||
 *                 0010 1100 0100 1000
 | 
			
		||||
 */
 | 
			
		||||
typedef union {
 | 
			
		||||
    uint16_t code;
 | 
			
		||||
    struct action_kind {
 | 
			
		||||
        uint16_t param  :12;
 | 
			
		||||
        uint16_t id     :4;
 | 
			
		||||
    } kind;
 | 
			
		||||
    struct action_key {
 | 
			
		||||
        uint16_t code   :8;
 | 
			
		||||
        uint16_t mods   :4;
 | 
			
		||||
        uint16_t kind   :4;
 | 
			
		||||
    } key;
 | 
			
		||||
    struct action_layer {
 | 
			
		||||
        uint16_t code   :8;
 | 
			
		||||
        uint16_t opt    :4;
 | 
			
		||||
        uint16_t kind   :4;
 | 
			
		||||
    } layer;
 | 
			
		||||
    struct action_usage {
 | 
			
		||||
        uint16_t code   :10;
 | 
			
		||||
        uint16_t page   :2;
 | 
			
		||||
        uint16_t kind   :4;
 | 
			
		||||
    } usage;
 | 
			
		||||
    struct action_command {
 | 
			
		||||
        uint16_t id     :8;
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
/* Action record. For internal use. */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    keyevent_t  event;
 | 
			
		||||
    uint8_t     tap_count;
 | 
			
		||||
} keyrecord_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Tap count: Tap is comprised of press and release within TAP_TERM.
 | 
			
		||||
 * 0    means no tap.
 | 
			
		||||
 * >1   means tap.
 | 
			
		||||
 */
 | 
			
		||||
extern uint8_t tap_count;
 | 
			
		||||
 | 
			
		||||
/* current tap key event */
 | 
			
		||||
extern keyevent_t tapping_event;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* 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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Utilities for actions.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -25,33 +94,36 @@ bool is_tap_key(key_t key);
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
Action codes
 | 
			
		||||
16bit code: action_kind(4bit) + action_parameter(12bit)
 | 
			
		||||
 | 
			
		||||
 * Action codes
 | 
			
		||||
 * ============
 | 
			
		||||
 * 16bit code: action_kind(4bit) + action_parameter(12bit)
 | 
			
		||||
 *
 | 
			
		||||
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
 | 
			
		||||
0010|mods|000000|00    Left mods Momentary
 | 
			
		||||
0000|mods| keycode     Key+Left mods
 | 
			
		||||
 | 
			
		||||
ACT_RMODS(0001):
 | 
			
		||||
0001|0000|000000|00    No action
 | 
			
		||||
0001|0000| keycode     Key(no used)
 | 
			
		||||
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|000000|00    Left mods OneShot
 | 
			
		||||
0010|mods|000000|01    (reserved)
 | 
			
		||||
0010|mods|000000|10    (reserved)
 | 
			
		||||
0010|mods|000000|11    (reserved)
 | 
			
		||||
0010|mods| keycode     Left mods+tap Key
 | 
			
		||||
 | 
			
		||||
ACT_RMODS_TAP(0011):
 | 
			
		||||
0011|mods|000000|00    Right mods OneShot
 | 
			
		||||
0011|mods|000000|01    (reserved)
 | 
			
		||||
0011|mods|000000|10    (reserved)
 | 
			
		||||
0011|mods|000000|11    (reserved)
 | 
			
		||||
0011|mods| keycode     Right mods+tap Key
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -108,24 +180,22 @@ Extensions(11XX)
 | 
			
		|||
NOTE: NOT FIXED
 | 
			
		||||
 | 
			
		||||
ACT_MACRO(1100):
 | 
			
		||||
1100|opt | id(8)      Macro play
 | 
			
		||||
1100|1111| id(8)      Macro record
 | 
			
		||||
1100|opt | id(8)      Macro play?
 | 
			
		||||
1100|1111| id(8)      Macro record?
 | 
			
		||||
 | 
			
		||||
ACT_COMMAND(1110):
 | 
			
		||||
1110|opt | id(8)      Built-in Command exec
 | 
			
		||||
 | 
			
		||||
ACT_FUNCTION(1111):
 | 
			
		||||
1111| address(12)     Function
 | 
			
		||||
1111|opt | id(8)      Function
 | 
			
		||||
                                                    Macro record(dynamicly)
 | 
			
		||||
                                                    Macro play(dynamicly)
 | 
			
		||||
TODO: modifier + [tap key /w mod]
 | 
			
		||||
    : layerkey + [tap key /w mod]
 | 
			
		||||
1111| address(12)     Function?
 | 
			
		||||
1111|opt | id(8)      Function?
 | 
			
		||||
 | 
			
		||||
TODO: modifier + function by tap?
 | 
			
		||||
    for example: LShift + '('[Shift+9] and RShift + ')'[Shift+0]
 | 
			
		||||
    http://deskthority.net/workshop-f7/tmk-keyboard-firmware-collection-t4478.html#p90052
 | 
			
		||||
*/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
enum action_id {
 | 
			
		||||
enum action_kind_id {
 | 
			
		||||
    ACT_LMODS           = 0b0000,
 | 
			
		||||
    ACT_RMODS           = 0b0001,
 | 
			
		||||
    ACT_LMODS_TAP       = 0b0010,
 | 
			
		||||
| 
						 | 
				
			
			@ -144,74 +214,11 @@ enum action_id {
 | 
			
		|||
    ACT_FUNCTION        = 0b1111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TODO: not portable across compiler/endianness?
 | 
			
		||||
/*
 | 
			
		||||
In avr-gcc bit fields seems to be assigned from LSB(bit0) to MSB(bit15). 
 | 
			
		||||
AVR looks like a little endian in avr-gcc.
 | 
			
		||||
 | 
			
		||||
Byte order and bit order of 0x1234:
 | 
			
		||||
Big endian:     15 ...  8 7 ... 210
 | 
			
		||||
               |  0x12   |  0x34   |
 | 
			
		||||
                0001 0010 0011 0100
 | 
			
		||||
Little endian:  012 ... 7  8 ... 15
 | 
			
		||||
               |  0x34   |  0x12   |
 | 
			
		||||
                0010 1100 0100 1000
 | 
			
		||||
*/
 | 
			
		||||
typedef union {
 | 
			
		||||
    uint16_t code;
 | 
			
		||||
    struct action_kind {
 | 
			
		||||
        uint16_t param  :12;
 | 
			
		||||
        uint16_t id     :4;
 | 
			
		||||
    } kind;
 | 
			
		||||
    struct action_key {
 | 
			
		||||
        uint16_t code   :8;
 | 
			
		||||
        uint16_t mods   :4;
 | 
			
		||||
        uint16_t kind   :4;
 | 
			
		||||
    } key;
 | 
			
		||||
    struct action_layer {
 | 
			
		||||
        uint16_t code   :8;
 | 
			
		||||
        uint16_t opt    :4;
 | 
			
		||||
        uint16_t kind   :4;
 | 
			
		||||
    } layer;
 | 
			
		||||
    struct action_usage {
 | 
			
		||||
        uint16_t code   :10;
 | 
			
		||||
        uint16_t page   :2;
 | 
			
		||||
        uint16_t kind   :4;
 | 
			
		||||
    } usage;
 | 
			
		||||
    struct action_command {
 | 
			
		||||
        uint16_t id     :8;
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
enum stroke_cmd {
 | 
			
		||||
    STROKE_DOWN,
 | 
			
		||||
    STROKE_UP,
 | 
			
		||||
    STROKE_ALLUP, /* release all keys in reverse order */
 | 
			
		||||
enum acion_param {
 | 
			
		||||
    ONE_SHOT            = 0x00,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    keyevent_t  event;
 | 
			
		||||
    uint8_t     tap_count;
 | 
			
		||||
} 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
 | 
			
		||||
/* action_t utility */
 | 
			
		||||
#define ACTION_NO                       0
 | 
			
		||||
#define ACTION(kind, param)             ((kind)<<12 | (param))
 | 
			
		||||
| 
						 | 
				
			
			@ -221,16 +228,12 @@ void action_call_function(keyevent_t event, uint8_t id);
 | 
			
		|||
#define ACTION_KEY(key)                 ACTION(ACT_LMODS,    key)
 | 
			
		||||
#define ACTION_LMODS(mods)              ACTION(ACT_LMODS,    (mods)<<8 | 0x00)
 | 
			
		||||
#define ACTION_LMODS_KEY(mods, key)     ACTION(ACT_LMODS,    (mods)<<8 | (key))
 | 
			
		||||
#define ACTION_LMODS_ONESHOT(mods)      ACTION(ACT_LMODS,    (mods)<<8 | 0x01)
 | 
			
		||||
#define ACTION_LMODS_SWITCH(mods, tap)  ACTION(ACT_LMODS,    (mods)<<8 | 0xF0 | (tap))
 | 
			
		||||
#define ACTION_LMODS_TOGGLE(mods, tap)  ACTION(ACT_LMODS,    (mods)<<8 | 0xF1 | (tap))
 | 
			
		||||
#define ACTION_RMODS(mods)              ACTION(ACT_RMODS,    (mods)<<8 | 0x00)
 | 
			
		||||
#define ACTION_RMODS_KEY(mods, key)     ACTION(ACT_RMODS,    (mods)<<8 | (key))
 | 
			
		||||
#define ACTION_RMODS_ONESHOT(mods)      ACTION(ACT_RMODS,    (mods)<<8 | 0x01)
 | 
			
		||||
#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, MOD_BITS(mods)<<8 | (key))
 | 
			
		||||
#define ACTION_LMODS_ONESHOT(mods)      ACTION(ACT_LMODS_TAP, MOD_BITS(mods)<<8 | ONE_SHOT)
 | 
			
		||||
#define ACTION_RMODS_TAP(mods, key)     ACTION(ACT_RMODS_TAP, MOD_BITS(mods)<<8 | (key))
 | 
			
		||||
 | 
			
		||||
/* Layer Switch */
 | 
			
		||||
| 
						 | 
				
			
			@ -268,15 +271,4 @@ void action_call_function(keyevent_t event, uint8_t id);
 | 
			
		|||
/* Function */
 | 
			
		||||
#define ACTION_FUNCTION(id, opt)        ACTION(ACT_FUNCTION, (opt)<<8 | id)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* helpers for readability */
 | 
			
		||||
#define LAYER(layer)    (layer)
 | 
			
		||||
#define TAP(tap)        (tap)
 | 
			
		||||
#define DOUBLE_TAP      2
 | 
			
		||||
#define TRIPLE_TAP      3
 | 
			
		||||
#define QUADRUPLE_TAP   4
 | 
			
		||||
#define QUINTUPLE_TAP   5
 | 
			
		||||
#define DOWN(key)       (key)
 | 
			
		||||
#define UP(key)         STROKE_UP, (key)
 | 
			
		||||
 | 
			
		||||
#endif  /* ACTION_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,6 +61,8 @@ static const uint16_t PROGMEM fn_actions[] = {
 | 
			
		|||
    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
 | 
			
		||||
 | 
			
		||||
    ACTION_LMODS_TAP(MOD_BIT(KC_LSFT), ONE_SHOT),   // Fn8
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +83,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, \
 | 
			
		||||
           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, \
 | 
			
		||||
           FN8, Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, FN2, RSFT,FN1, \
 | 
			
		||||
                LGUI,LALT,          FN5,                RALT,FN4),
 | 
			
		||||
 | 
			
		||||
    /* Layer 1: HHKB mode (HHKB Fn)
 | 
			
		||||
| 
						 | 
				
			
			@ -205,8 +207,12 @@ action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col) {
 | 
			
		|||
            action.code = ACTION_RMODS(MOD_BIT(key)>>4);
 | 
			
		||||
            break;
 | 
			
		||||
*/
 | 
			
		||||
        case KC_FN0 ... KC_FN7:
 | 
			
		||||
            action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]);
 | 
			
		||||
        case KC_FN0 ... FN_MAX:
 | 
			
		||||
            if (FN_INDEX(key) < sizeof(fn_actions) / sizeof(fn_actions[0])) {
 | 
			
		||||
                action.code = pgm_read_word(&fn_actions[FN_INDEX(key)]);
 | 
			
		||||
            } else {
 | 
			
		||||
                action.code = ACTION_NO;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case KC_NO ... KC_UNDEFINED:
 | 
			
		||||
        default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue