Merge pull request #543 from VoodaGod/bone2planck
[jackhill/qmk/firmware.git] / tmk_core / common / action_layer.c
CommitLineData
a074364c 1#include <stdint.h>
2#include "keyboard.h"
3#include "action.h"
4#include "util.h"
5#include "action_layer.h"
6
2bbf3d58 7#ifdef DEBUG_ACTION
a074364c 8#include "debug.h"
2bbf3d58
JH
9#else
10#include "nodebug.h"
11#endif
a074364c 12
13
d5b72e7b 14/*
a074364c 15 * Default Layer State
16 */
17uint32_t default_layer_state = 0;
18
19static void default_layer_state_set(uint32_t state)
20{
21 debug("default_layer_state: ");
22 default_layer_debug(); debug(" to ");
23 default_layer_state = state;
24 default_layer_debug(); debug("\n");
25 clear_keyboard_but_mods(); // To avoid stuck keys
26}
27
28void default_layer_debug(void)
29{
30 dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
31}
32
33void default_layer_set(uint32_t state)
34{
35 default_layer_state_set(state);
36}
37
38#ifndef NO_ACTION_LAYER
39void default_layer_or(uint32_t state)
40{
41 default_layer_state_set(default_layer_state | state);
42}
43void default_layer_and(uint32_t state)
44{
45 default_layer_state_set(default_layer_state & state);
46}
47void default_layer_xor(uint32_t state)
48{
49 default_layer_state_set(default_layer_state ^ state);
50}
51#endif
52
53
54#ifndef NO_ACTION_LAYER
d5b72e7b 55/*
a074364c 56 * Keymap Layer State
57 */
58uint32_t layer_state = 0;
59
60static void layer_state_set(uint32_t state)
61{
62 dprint("layer_state: ");
63 layer_debug(); dprint(" to ");
64 layer_state = state;
65 layer_debug(); dprintln();
66 clear_keyboard_but_mods(); // To avoid stuck keys
67}
68
69void layer_clear(void)
70{
71 layer_state_set(0);
72}
73
74void layer_move(uint8_t layer)
75{
76 layer_state_set(1UL<<layer);
77}
78
79void layer_on(uint8_t layer)
80{
81 layer_state_set(layer_state | (1UL<<layer));
82}
83
84void layer_off(uint8_t layer)
85{
86 layer_state_set(layer_state & ~(1UL<<layer));
87}
88
89void layer_invert(uint8_t layer)
90{
91 layer_state_set(layer_state ^ (1UL<<layer));
92}
93
94void layer_or(uint32_t state)
95{
96 layer_state_set(layer_state | state);
97}
98void layer_and(uint32_t state)
99{
100 layer_state_set(layer_state & state);
101}
102void layer_xor(uint32_t state)
103{
104 layer_state_set(layer_state ^ state);
105}
106
107void layer_debug(void)
108{
109 dprintf("%08lX(%u)", layer_state, biton32(layer_state));
110}
111#endif
112
567f256c 113#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
02a3d779 114uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {0};
567f256c
WS
115
116void update_source_layers_cache(keypos_t key, uint8_t layer)
117{
118 const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
119 const uint8_t storage_row = key_number / 8;
120 const uint8_t storage_bit = key_number % 8;
121
122 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
02a3d779 123 source_layers_cache[storage_row][bit_number] ^=
567f256c 124 (-((layer & (1U << bit_number)) != 0)
02a3d779 125 ^ source_layers_cache[storage_row][bit_number])
567f256c
WS
126 & (1U << storage_bit);
127 }
128}
129
130uint8_t read_source_layers_cache(keypos_t key)
131{
132 const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
133 const uint8_t storage_row = key_number / 8;
134 const uint8_t storage_bit = key_number % 8;
135 uint8_t layer = 0;
136
137 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
138 layer |=
02a3d779 139 ((source_layers_cache[storage_row][bit_number]
567f256c
WS
140 & (1U << storage_bit)) != 0)
141 << bit_number;
142 }
143
144 return layer;
145}
146#endif
147
148/*
149 * Make sure the action triggered when the key is released is the same
150 * one as the one triggered on press. It's important for the mod keys
151 * when the layer is switched after the down event but before the up
152 * event as they may get stuck otherwise.
153 */
154action_t store_or_get_action(bool pressed, keypos_t key)
155{
156#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
157 if (disable_action_cache) {
158 return layer_switch_get_action(key);
159 }
160
161 uint8_t layer;
162
163 if (pressed) {
164 layer = layer_switch_get_layer(key);
165 update_source_layers_cache(key, layer);
166 }
167 else {
168 layer = read_source_layers_cache(key);
169 }
170 return action_for_key(layer, key);
171#else
172 return layer_switch_get_action(key);
173#endif
174}
175
a074364c 176
b4f442df 177int8_t layer_switch_get_layer(keypos_t key)
a074364c 178{
179 action_t action;
180 action.code = ACTION_TRANSPARENT;
181
182#ifndef NO_ACTION_LAYER
183 uint32_t layers = layer_state | default_layer_state;
184 /* check top layer first */
185 for (int8_t i = 31; i >= 0; i--) {
186 if (layers & (1UL<<i)) {
187 action = action_for_key(i, key);
188 if (action.code != ACTION_TRANSPARENT) {
b4f442df 189 return i;
a074364c 190 }
191 }
192 }
193 /* fall back to layer 0 */
b4f442df 194 return 0;
a074364c 195#else
b4f442df 196 return biton32(default_layer_state);
a074364c 197#endif
198}
b4f442df
WS
199
200action_t layer_switch_get_action(keypos_t key)
201{
202 return action_for_key(layer_switch_get_layer(key), key);
203}