aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/config_common.h6
-rw-r--r--quantum/keymap_common.c5
-rwxr-xr-xquantum/light_ws2812.c6
-rw-r--r--quantum/matrix.c14
-rw-r--r--quantum/process_keycode/process_combo.c134
-rw-r--r--quantum/process_keycode/process_combo.h43
-rw-r--r--quantum/process_keycode/process_unicode.c11
-rw-r--r--quantum/quantum.c41
-rw-r--r--quantum/quantum.h5
-rw-r--r--quantum/quantum_keycodes.h13
-rw-r--r--quantum/template/config.h2
11 files changed, 264 insertions, 16 deletions
diff --git a/quantum/config_common.h b/quantum/config_common.h
index 4bdb2065d..28f68b9c7 100644
--- a/quantum/config_common.h
+++ b/quantum/config_common.h
@@ -2,8 +2,10 @@
2#define CONFIG_DEFINITIONS_H 2#define CONFIG_DEFINITIONS_H
3 3
4/* diode directions */ 4/* diode directions */
5#define COL2ROW 0 5#define COL2ROW 0
6#define ROW2COL 1 6#define ROW2COL 1
7#define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */
8
7/* I/O pins */ 9/* I/O pins */
8#ifndef F0 10#ifndef F0
9 #define B0 0x30 11 #define B0 0x30
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index eced3d2bb..5190f24e8 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -80,7 +80,10 @@ action_t action_for_key(uint8_t layer, keypos_t key)
80 action.code = keymap_function_id_to_action( (int)keycode & 0xFFF ); 80 action.code = keymap_function_id_to_action( (int)keycode & 0xFFF );
81 break; 81 break;
82 case QK_MACRO ... QK_MACRO_MAX: 82 case QK_MACRO ... QK_MACRO_MAX:
83 action.code = ACTION_MACRO(keycode & 0xFF); 83 if (keycode & 0x800) // tap macros have upper bit set
84 action.code = ACTION_MACRO_TAP(keycode & 0xFF);
85 else
86 action.code = ACTION_MACRO(keycode & 0xFF);
84 break; 87 break;
85 case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: 88 case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
86 action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF); 89 action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
diff --git a/quantum/light_ws2812.c b/quantum/light_ws2812.c
index a883b1388..55bdd9cd8 100755
--- a/quantum/light_ws2812.c
+++ b/quantum/light_ws2812.c
@@ -70,7 +70,7 @@ void I2C_WriteBit(unsigned char c)
70 70
71// Inits bitbanging port, must be called before using the functions below 71// Inits bitbanging port, must be called before using the functions below
72// 72//
73void I2C_Init() 73void I2C_Init(void)
74{ 74{
75 I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); 75 I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
76 76
@@ -82,7 +82,7 @@ void I2C_Init()
82 82
83// Send a START Condition 83// Send a START Condition
84// 84//
85void I2C_Start() 85void I2C_Start(void)
86{ 86{
87 // set both to high at the same time 87 // set both to high at the same time
88 I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); 88 I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
@@ -97,7 +97,7 @@ void I2C_Start()
97 97
98// Send a STOP Condition 98// Send a STOP Condition
99// 99//
100void I2C_Stop() 100void I2C_Stop(void)
101{ 101{
102 I2C_CLOCK_HI(); 102 I2C_CLOCK_HI();
103 _delay_us(I2C_DELAY); 103 _delay_us(I2C_DELAY);
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 07eb87bc3..ac523482a 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -60,13 +60,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
60 extern const matrix_row_t matrix_mask[]; 60 extern const matrix_row_t matrix_mask[];
61#endif 61#endif
62 62
63#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
63static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; 64static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
64static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; 65static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
66#endif
65 67
66/* matrix state(1:on, 0:off) */ 68/* matrix state(1:on, 0:off) */
67static matrix_row_t matrix[MATRIX_ROWS]; 69static matrix_row_t matrix[MATRIX_ROWS];
68 70
69static matrix_row_t matrix_raw[MATRIX_ROWS];
70static matrix_row_t matrix_debouncing[MATRIX_ROWS]; 71static matrix_row_t matrix_debouncing[MATRIX_ROWS];
71 72
72 73
@@ -76,7 +77,7 @@ static matrix_row_t matrix_debouncing[MATRIX_ROWS];
76 static void unselect_rows(void); 77 static void unselect_rows(void);
77 static void select_row(uint8_t row); 78 static void select_row(uint8_t row);
78 static void unselect_row(uint8_t row); 79 static void unselect_row(uint8_t row);
79#else // ROW2COL 80#elif (DIODE_DIRECTION == ROW2COL)
80 static void init_rows(void); 81 static void init_rows(void);
81 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); 82 static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col);
82 static void unselect_cols(void); 83 static void unselect_cols(void);
@@ -133,7 +134,7 @@ uint8_t matrix_cols(void) {
133// /* PORTxn */ 134// /* PORTxn */
134// _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); 135// _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
135// } 136// }
136// #else 137// #elif (DIODE_DIRECTION == ROW2COL)
137// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { 138// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
138// /* DDRxn */ 139// /* DDRxn */
139// _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); 140// _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
@@ -158,7 +159,7 @@ void matrix_init(void) {
158#if (DIODE_DIRECTION == COL2ROW) 159#if (DIODE_DIRECTION == COL2ROW)
159 unselect_rows(); 160 unselect_rows();
160 init_cols(); 161 init_cols();
161#else // ROW2COL 162#elif (DIODE_DIRECTION == ROW2COL)
162 unselect_cols(); 163 unselect_cols();
163 init_rows(); 164 init_rows();
164#endif 165#endif
@@ -166,7 +167,6 @@ void matrix_init(void) {
166 // initialize matrix state: all keys off 167 // initialize matrix state: all keys off
167 for (uint8_t i=0; i < MATRIX_ROWS; i++) { 168 for (uint8_t i=0; i < MATRIX_ROWS; i++) {
168 matrix[i] = 0; 169 matrix[i] = 0;
169 matrix_raw[i] = 0;
170 matrix_debouncing[i] = 0; 170 matrix_debouncing[i] = 0;
171 } 171 }
172 172
@@ -194,7 +194,7 @@ uint8_t matrix_scan(void)
194 194
195 } 195 }
196 196
197#else // ROW2COL 197#elif (DIODE_DIRECTION == ROW2COL)
198 198
199 // Set col, read rows 199 // Set col, read rows
200 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 200 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
@@ -336,7 +336,7 @@ static void unselect_rows(void)
336 } 336 }
337} 337}
338 338
339#else // ROW2COL 339#elif (DIODE_DIRECTION == ROW2COL)
340 340
341static void init_rows(void) 341static void init_rows(void)
342{ 342{
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c
new file mode 100644
index 000000000..e2189ad98
--- /dev/null
+++ b/quantum/process_keycode/process_combo.c
@@ -0,0 +1,134 @@
1#include "process_combo.h"
2#include "print.h"
3
4
5#define COMBO_TIMER_ELAPSED -1
6
7
8__attribute__ ((weak))
9combo_t key_combos[] = {
10
11};
12
13__attribute__ ((weak))
14void process_combo_event(uint8_t combo_index, bool pressed) {
15
16}
17
18static uint8_t current_combo_index = 0;
19
20static inline void send_combo(uint16_t action, bool pressed)
21{
22 if (action) {
23 if (pressed) {
24 register_code16(action);
25 } else {
26 unregister_code16(action);
27 }
28 } else {
29 process_combo_event(current_combo_index, pressed);
30 }
31}
32
33#define ALL_COMBO_KEYS_ARE_DOWN (((1<<count)-1) == combo->state)
34#define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state)
35#define KEY_STATE_DOWN(key) do{ combo->state |= (1<<key); } while(0)
36#define KEY_STATE_UP(key) do{ combo->state &= ~(1<<key); } while(0)
37static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record)
38{
39 uint8_t count = 0;
40 uint8_t index = -1;
41 /* Find index of keycode and number of combo keys */
42 for (const uint16_t *keys = combo->keys; ;++count) {
43 uint16_t key = pgm_read_word(&keys[count]);
44 if (keycode == key) index = count;
45 if (COMBO_END == key) break;
46 }
47
48 /* Return if not a combo key */
49 if (-1 == (int8_t)index) return false;
50
51 /* The combos timer is used to signal whether the combo is active */
52 bool is_combo_active = COMBO_TIMER_ELAPSED == combo->timer ? false : true;
53
54 if (record->event.pressed) {
55 KEY_STATE_DOWN(index);
56
57 if (is_combo_active) {
58 if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */
59 send_combo(combo->keycode, true);
60 combo->timer = COMBO_TIMER_ELAPSED;
61 } else { /* Combo key was pressed */
62 combo->timer = timer_read();
63#ifdef COMBO_ALLOW_ACTION_KEYS
64 combo->prev_record = *record;
65#else
66 combo->prev_key = keycode;
67#endif
68 }
69 }
70 } else {
71 if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was released */
72 send_combo(combo->keycode, false);
73 }
74
75 if (is_combo_active) { /* Combo key was tapped */
76#ifdef COMBO_ALLOW_ACTION_KEYS
77 record->event.pressed = true;
78 process_action(record, store_or_get_action(record->event.pressed, record->event.key));
79 record->event.pressed = false;
80 process_action(record, store_or_get_action(record->event.pressed, record->event.key));
81#else
82 register_code16(keycode);
83 send_keyboard_report();
84 unregister_code16(keycode);
85#endif
86 combo->timer = 0;
87 }
88
89 KEY_STATE_UP(index);
90 }
91
92 if (NO_COMBO_KEYS_ARE_DOWN) {
93 combo->timer = 0;
94 }
95
96 return is_combo_active;
97}
98
99bool process_combo(uint16_t keycode, keyrecord_t *record)
100{
101 bool is_combo_key = false;
102
103 for (current_combo_index = 0; current_combo_index < COMBO_COUNT; ++current_combo_index) {
104 combo_t *combo = &key_combos[current_combo_index];
105 is_combo_key |= process_single_combo(combo, keycode, record);
106 }
107
108 return !is_combo_key;
109}
110
111void matrix_scan_combo(void)
112{
113 for (int i = 0; i < COMBO_COUNT; ++i) {
114 combo_t *combo = &key_combos[i];
115 if (combo->timer &&
116 combo->timer != COMBO_TIMER_ELAPSED &&
117 timer_elapsed(combo->timer) > COMBO_TERM) {
118
119 /* This disables the combo, meaning key events for this
120 * combo will be handled by the next processors in the chain
121 */
122 combo->timer = COMBO_TIMER_ELAPSED;
123
124#ifdef COMBO_ALLOW_ACTION_KEYS
125 process_action(&combo->prev_record,
126 store_or_get_action(combo->prev_record.event.pressed,
127 combo->prev_record.event.key));
128#else
129 unregister_code16(combo->prev_key);
130 register_code16(combo->prev_key);
131#endif
132 }
133 }
134}
diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h
new file mode 100644
index 000000000..847f2b737
--- /dev/null
+++ b/quantum/process_keycode/process_combo.h
@@ -0,0 +1,43 @@
1#ifndef PROCESS_COMBO_H
2#define PROCESS_COMBO_H
3
4#include <stdint.h>
5#include "progmem.h"
6#include "quantum.h"
7
8typedef struct
9{
10 const uint16_t *keys;
11 uint16_t keycode;
12#ifdef EXTRA_EXTRA_LONG_COMBOS
13 uint32_t state;
14#elif EXTRA_LONG_COMBOS
15 uint16_t state;
16#else
17 uint8_t state;
18#endif
19 uint16_t timer;
20#ifdef COMBO_ALLOW_ACTION_KEYS
21 keyrecord_t prev_record;
22#else
23 uint16_t prev_key;
24#endif
25} combo_t;
26
27
28#define COMBO(ck, ca) {.keys = &(ck)[0], .keycode = (ca)}
29#define COMBO_ACTION(ck) {.keys = &(ck)[0]}
30
31#define COMBO_END 0
32#ifndef COMBO_COUNT
33#define COMBO_COUNT 0
34#endif
35#ifndef COMBO_TERM
36#define COMBO_TERM TAPPING_TERM
37#endif
38
39bool process_combo(uint16_t keycode, keyrecord_t *record);
40void matrix_scan_combo(void);
41void process_combo_event(uint8_t combo_index, bool pressed);
42
43#endif
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
index a30e93ae3..9995ba9bd 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -141,7 +141,16 @@ bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
141 const uint32_t* map = unicode_map; 141 const uint32_t* map = unicode_map;
142 uint16_t index = keycode & 0x7FF; 142 uint16_t index = keycode & 0x7FF;
143 uint32_t code = pgm_read_dword_far(&map[index]); 143 uint32_t code = pgm_read_dword_far(&map[index]);
144 if ((code > 0xFFFF && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) { 144 if (code > 0xFFFF && code <= 0x10ffff && input_mode == UC_OSX) {
145 // Convert to UTF-16 surrogate pair
146 code -= 0x10000;
147 uint32_t lo = code & 0x3ff;
148 uint32_t hi = (code & 0xffc00) >> 10;
149 unicode_input_start();
150 register_hex32(hi + 0xd800);
151 register_hex32(lo + 0xdc00);
152 unicode_input_finish();
153 } else if ((code > 0x10ffff && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
145 // when character is out of range supported by the OS 154 // when character is out of range supported by the OS
146 unicode_map_input_error(); 155 unicode_map_input_error();
147 } else { 156 } else {
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 0aecd238e..d3905decf 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -1,4 +1,7 @@
1#include "quantum.h" 1#include "quantum.h"
2#ifdef PROTOCOL_LUFA
3#include "outputselect.h"
4#endif
2 5
3#ifndef TAPPING_TERM 6#ifndef TAPPING_TERM
4#define TAPPING_TERM 200 7#define TAPPING_TERM 200
@@ -158,6 +161,9 @@ bool process_record_quantum(keyrecord_t *record) {
158 #ifndef DISABLE_CHORDING 161 #ifndef DISABLE_CHORDING
159 process_chording(keycode, record) && 162 process_chording(keycode, record) &&
160 #endif 163 #endif
164 #ifdef COMBO_ENABLE
165 process_combo(keycode, record) &&
166 #endif
161 #ifdef UNICODE_ENABLE 167 #ifdef UNICODE_ENABLE
162 process_unicode(keycode, record) && 168 process_unicode(keycode, record) &&
163 #endif 169 #endif
@@ -240,6 +246,36 @@ bool process_record_quantum(keyrecord_t *record) {
240 return false; 246 return false;
241 break; 247 break;
242 #endif 248 #endif
249 #ifdef PROTOCOL_LUFA
250 case OUT_AUTO:
251 if (record->event.pressed) {
252 set_output(OUTPUT_AUTO);
253 }
254 return false;
255 break;
256 case OUT_USB:
257 if (record->event.pressed) {
258 set_output(OUTPUT_USB);
259 }
260 return false;
261 break;
262 #ifdef BLUETOOTH_ENABLE
263 case OUT_BT:
264 if (record->event.pressed) {
265 set_output(OUTPUT_BLUETOOTH);
266 }
267 return false;
268 break;
269 #endif
270 #ifdef ADAFRUIT_BLE_ENABLE
271 case OUT_BLE:
272 if (record->event.pressed) {
273 set_output(OUTPUT_ADAFRUIT_BLE);
274 }
275 return false;
276 break;
277 #endif
278 #endif
243 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO: 279 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
244 if (record->event.pressed) { 280 if (record->event.pressed) {
245 // MAGIC actions (BOOTMAGIC without the boot) 281 // MAGIC actions (BOOTMAGIC without the boot)
@@ -536,6 +572,11 @@ void matrix_scan_quantum() {
536 #ifdef TAP_DANCE_ENABLE 572 #ifdef TAP_DANCE_ENABLE
537 matrix_scan_tap_dance(); 573 matrix_scan_tap_dance();
538 #endif 574 #endif
575
576 #ifdef COMBO_ENABLE
577 matrix_scan_combo();
578 #endif
579
539 matrix_scan_kb(); 580 matrix_scan_kb();
540} 581}
541 582
diff --git a/quantum/quantum.h b/quantum/quantum.h
index e6adf974a..18f072189 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -15,7 +15,6 @@
15#ifdef RGBLIGHT_ENABLE 15#ifdef RGBLIGHT_ENABLE
16 #include "rgblight.h" 16 #include "rgblight.h"
17#endif 17#endif
18
19#include "action_layer.h" 18#include "action_layer.h"
20#include "eeconfig.h" 19#include "eeconfig.h"
21#include <stddef.h> 20#include <stddef.h>
@@ -63,6 +62,10 @@ extern uint32_t default_layer_state;
63 #include "process_printer.h" 62 #include "process_printer.h"
64#endif 63#endif
65 64
65#ifdef COMBO_ENABLE
66 #include "process_combo.h"
67#endif
68
66#define SEND_STRING(str) send_string(PSTR(str)) 69#define SEND_STRING(str) send_string(PSTR(str))
67void send_string(const char *str); 70void send_string(const char *str);
68 71
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 4853655f9..8a78a58c9 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -141,6 +141,16 @@ enum quantum_keycodes {
141 PRINT_ON, 141 PRINT_ON,
142 PRINT_OFF, 142 PRINT_OFF,
143 143
144 // output selection
145 OUT_AUTO,
146 OUT_USB,
147#ifdef BLUETOOTH_ENABLE
148 OUT_BT,
149#endif
150#ifdef ADAFRUIT_BLE_ENABLE
151 OUT_BLE,
152#endif
153
144 // always leave at the end 154 // always leave at the end
145 SAFE_RANGE 155 SAFE_RANGE
146}; 156};
@@ -246,8 +256,10 @@ enum quantum_keycodes {
246 256
247#define M(kc) (kc | QK_MACRO) 257#define M(kc) (kc | QK_MACRO)
248 258
259#define MACROTAP(kc) (kc | QK_MACRO | FUNC_TAP<<8)
249#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE) 260#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
250 261
262
251// L-ayer, T-ap - 256 keycode max, 16 layer max 263// L-ayer, T-ap - 256 keycode max, 16 layer max
252#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8)) 264#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
253 265
@@ -290,6 +302,7 @@ enum quantum_keycodes {
290#define CTL_T(kc) MT(MOD_LCTL, kc) 302#define CTL_T(kc) MT(MOD_LCTL, kc)
291#define SFT_T(kc) MT(MOD_LSFT, kc) 303#define SFT_T(kc) MT(MOD_LSFT, kc)
292#define ALT_T(kc) MT(MOD_LALT, kc) 304#define ALT_T(kc) MT(MOD_LALT, kc)
305#define ALGR_T(kc) MT(MOD_RALT, kc) // dual-function AltGR
293#define GUI_T(kc) MT(MOD_LGUI, kc) 306#define GUI_T(kc) MT(MOD_LGUI, kc)
294#define C_S_T(kc) MT((MOD_LCTL | MOD_LSFT), kc) // Control + Shift e.g. for gnome-terminal 307#define C_S_T(kc) MT((MOD_LCTL | MOD_LSFT), kc) // Control + Shift e.g. for gnome-terminal
295#define MEH_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT), kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl 308#define MEH_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT), kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl
diff --git a/quantum/template/config.h b/quantum/template/config.h
index b02f0c7eb..c61c4a618 100644
--- a/quantum/template/config.h
+++ b/quantum/template/config.h
@@ -46,7 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
46#define MATRIX_COL_PINS { F1, F0, B0 } 46#define MATRIX_COL_PINS { F1, F0, B0 }
47#define UNUSED_PINS 47#define UNUSED_PINS
48 48
49/* COL2ROW or ROW2COL */ 49/* COL2ROW, ROW2COL, or CUSTOM_MATRIX */
50#define DIODE_DIRECTION COL2ROW 50#define DIODE_DIRECTION COL2ROW
51 51
52// #define BACKLIGHT_PIN B7 52// #define BACKLIGHT_PIN B7