Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: How to toggle layer in ACTION_FUNCTION? #446

Closed
tywtyw2002 opened this issue Mar 1, 2017 · 1 comment
Closed

Question: How to toggle layer in ACTION_FUNCTION? #446

tywtyw2002 opened this issue Mar 1, 2017 · 1 comment

Comments

@tywtyw2002
Copy link

Is someone give me some example for how to toggle a layer in ACTION_FUNCTION?

I would like to change some LEDs then toggle a layer.

The follow code did not work.

void action_function(keyrecord_t *record, uint8_t id, uint8_t opt){

    static bool led = false;
    switch (id) {
        case TOGGLE_ARROW_LAYER:
            if (led) {
                gh60_esc_led_off();
            }else{
                gh60_esc_led_on();
                led = true;
            }
            return (action_t) ACTION_LAYER_TOGGLE(2);
            break;
    }
}
@tmk
Copy link
Owner

tmk commented Mar 7, 2017

You have to implement toggle logic in action function your self. You will want to know how built-in ACTION_LAYER_TOGGLE action is implemented in tmk_core. First check common/action_code.h to know how the action code is defined. In the end you will know the action is identified as ACT_LAYER.
https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/common/action_code.h#L266

#define ACTION_LAYER_TOGGLE(layer)                  ACTION_LAYER_INVERT(layer, ON_RELEASE)
#define ACTION_LAYER_INVERT(layer, on)              ACTION_LAYER_BIT_XOR((layer)/4,   1<<((layer)%4),  (on))
...
#define ACTION_LAYER_BIT_XOR(part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on))
...
#define ACTION_LAYER_BITOP(op, part, bits, on)      ACTION(ACT_LAYER, (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f))

Next, you can find code of the built-in action in common/action.c using word ACT_LAYER and OP_BIT_XOR.
https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/common/action.c#L216-L245

        case ACT_LAYER:
            if (action.layer_bitop.on == 0) {
                /* Default Layer Bitwise Operation */
                if (!event.pressed) {
                    uint8_t shift = action.layer_bitop.part*4;
                    uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
                    uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
                    switch (action.layer_bitop.op) {
                        case OP_BIT_AND: default_layer_and(bits | mask); break;
                        case OP_BIT_OR:  default_layer_or(bits | mask);  break;
                        case OP_BIT_XOR: default_layer_xor(bits | mask); break;
                        case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
                    }
                }
            } else {
                /* Layer Bitwise Operation */
                if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
                                    (action.layer_bitop.on & ON_RELEASE)) {
                    uint8_t shift = action.layer_bitop.part*4;
                    uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
                    uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
                    switch (action.layer_bitop.op) {
                        case OP_BIT_AND: layer_and(bits | mask); break;
                        case OP_BIT_OR:  layer_or(bits | mask);  break;
                        case OP_BIT_XOR: layer_xor(bits | mask); break;
                        case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
                    }
                }
            }
            break;

You will find something useful if you explore this code more deeply. Search definition of layer_xor() function you will find layer_state_set() finally.

https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/common/action_layer.c#L105-L108
https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/common/action_layer.c#L62-L70

void layer_xor(uint32_t state)
{
    layer_state_set(layer_state ^ state);
}
...
static void layer_state_set(uint32_t state)
{
    dprint("layer_state: ");
    layer_debug(); dprint(" to ");
    layer_state = state;
    hook_layer_change(layer_state);
    layer_debug(); dprintln();
    clear_keyboard_but_mods(); // To avoid stuck keys
}

What you want to do is inverting a bit of layer_state in the end.

I think this code will work in your case probably.

layer_state ^= (1<<2);

@tmk tmk closed this as completed May 4, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants