aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/audio/voices.c1
-rw-r--r--quantum/config_common.h6
-rw-r--r--quantum/fauxclicky.c68
-rw-r--r--quantum/fauxclicky.h99
-rw-r--r--quantum/keymap_common.c10
-rw-r--r--quantum/keymap_extras/keymap_br_abnt2.h16
-rw-r--r--quantum/keymap_extras/keymap_french.h4
-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_tap_dance.c7
-rw-r--r--quantum/process_keycode/process_tap_dance.h1
-rw-r--r--quantum/process_keycode/process_ucis.c133
-rw-r--r--quantum/process_keycode/process_ucis.h35
-rw-r--r--quantum/process_keycode/process_unicode.c276
-rw-r--r--quantum/process_keycode/process_unicode.h160
-rw-r--r--quantum/process_keycode/process_unicode_common.c85
-rw-r--r--quantum/process_keycode/process_unicode_common.h132
-rw-r--r--quantum/process_keycode/process_unicodemap.c56
-rw-r--r--quantum/process_keycode/process_unicodemap.h9
-rw-r--r--quantum/quantum.c204
-rw-r--r--quantum/quantum.h15
-rw-r--r--quantum/quantum_keycodes.h58
-rw-r--r--quantum/rgblight.c35
-rw-r--r--quantum/rgblight.h11
-rw-r--r--quantum/template/config.h2
-rw-r--r--quantum/template/rules.mk1
28 files changed, 1120 insertions, 501 deletions
diff --git a/quantum/audio/voices.c b/quantum/audio/voices.c
index 8326e91ea..c2edb75f0 100644
--- a/quantum/audio/voices.c
+++ b/quantum/audio/voices.c
@@ -24,6 +24,7 @@ void voice_deiterate() {
24 24
25float voice_envelope(float frequency) { 25float voice_envelope(float frequency) {
26 // envelope_index ranges from 0 to 0xFFFF, which is preserved at 880.0 Hz 26 // envelope_index ranges from 0 to 0xFFFF, which is preserved at 880.0 Hz
27 __attribute__ ((unused))
27 uint16_t compensated_index = (uint16_t)((float)envelope_index * (880.0 / frequency)); 28 uint16_t compensated_index = (uint16_t)((float)envelope_index * (880.0 / frequency));
28 29
29 switch (voice) { 30 switch (voice) {
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/fauxclicky.c b/quantum/fauxclicky.c
new file mode 100644
index 000000000..13273e705
--- /dev/null
+++ b/quantum/fauxclicky.c
@@ -0,0 +1,68 @@
1/*
2Copyright 2017 Priyadi Iman Nurcahyo
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11GNU General Public License for more details.
12You should have received a copy of the GNU General Public License
13along with this program. If not, see <http://www.gnu.org/licenses/>.
14*/
15
16#include <avr/interrupt.h>
17#include <avr/io.h>
18#include <timer.h>
19#include <fauxclicky.h>
20#include <stdbool.h>
21#include <musical_notes.h>
22
23__attribute__ ((weak))
24float fauxclicky_pressed_note[2] = MUSICAL_NOTE(_F3, 2);
25__attribute__ ((weak))
26float fauxclicky_released_note[2] = MUSICAL_NOTE(_A3, 2);
27__attribute__ ((weak))
28float fauxclicky_beep_note[2] = MUSICAL_NOTE(_C3, 2);
29
30bool fauxclicky_enabled = true;
31uint16_t note_start = 0;
32bool note_playing = false;
33uint16_t note_period = 0;
34
35void fauxclicky_init()
36{
37 // Set port PC6 (OC3A and /OC4A) as output
38 DDRC |= _BV(PORTC6);
39
40 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
41 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
42 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
43}
44
45void fauxclicky_stop()
46{
47 FAUXCLICKY_DISABLE_OUTPUT;
48 note_playing = false;
49}
50
51void fauxclicky_play(float note[2]) {
52 if (!fauxclicky_enabled) return;
53 if (note_playing) fauxclicky_stop();
54 FAUXCLICKY_TIMER_PERIOD = (uint16_t)(((float)F_CPU) / (note[0] * FAUXCLICKY_CPU_PRESCALER));
55 FAUXCLICKY_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (note[0] * FAUXCLICKY_CPU_PRESCALER)) / 2);
56 note_playing = true;
57 note_period = (note[1] / 16) * (60 / (float)FAUXCLICKY_TEMPO) * 100; // check this
58 note_start = timer_read();
59 FAUXCLICKY_ENABLE_OUTPUT;
60}
61
62void fauxclicky_check() {
63 if (!note_playing) return;
64
65 if (timer_elapsed(note_start) > note_period) {
66 fauxclicky_stop();
67 }
68}
diff --git a/quantum/fauxclicky.h b/quantum/fauxclicky.h
new file mode 100644
index 000000000..109bd0d83
--- /dev/null
+++ b/quantum/fauxclicky.h
@@ -0,0 +1,99 @@
1/*
2Copyright 2017 Priyadi Iman Nurcahyo
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11GNU General Public License for more details.
12You should have received a copy of the GNU General Public License
13along with this program. If not, see <http://www.gnu.org/licenses/>.
14*/
15
16#ifdef AUDIO_ENABLE
17#error "AUDIO_ENABLE and FAUXCLICKY_ENABLE cannot be both enabled"
18#endif
19
20#include "musical_notes.h"
21#include "stdbool.h"
22
23__attribute__ ((weak))
24float fauxclicky_pressed_note[2];
25__attribute__ ((weak))
26float fauxclicky_released_note[2];
27__attribute__ ((weak))
28float fauxclicky_beep_note[2];
29
30bool fauxclicky_enabled;
31
32//
33// tempo in BPM
34//
35
36#ifndef FAUXCLICKY_TEMPO
37#define FAUXCLICKY_TEMPO TEMPO_DEFAULT
38#endif
39
40// beep on press
41#define FAUXCLICKY_ACTION_PRESS fauxclicky_play(fauxclicky_pressed_note)
42
43// beep on release
44#define FAUXCLICKY_ACTION_RELEASE fauxclicky_play(fauxclicky_released_note)
45
46// general purpose beep
47#define FAUXCLICKY_BEEP fauxclicky_play(fauxclicky_beep_note)
48
49// enable
50#define FAUXCLICKY_ON fauxclicky_enabled = true
51
52// disable
53#define FAUXCLICKY_OFF do { \
54 fauxclicky_enabled = false; \
55 fauxclicky_stop(); \
56} while (0)
57
58// toggle
59#define FAUXCLICKY_TOGGLE do { \
60 if (fauxclicky_enabled) { \
61 FAUXCLICKY_OFF; \
62 } else { \
63 FAUXCLICKY_ON; \
64 } \
65} while (0)
66
67//
68// pin configuration
69//
70
71#ifndef FAUXCLICKY_CPU_PRESCALER
72#define FAUXCLICKY_CPU_PRESCALER 8
73#endif
74
75#ifndef FAUXCLICKY_ENABLE_OUTPUT
76#define FAUXCLICKY_ENABLE_OUTPUT TCCR3A |= _BV(COM3A1);
77#endif
78
79#ifndef FAUXCLICKY_DISABLE_OUTPUT
80#define FAUXCLICKY_DISABLE_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
81#endif
82
83#ifndef FAUXCLICKY_TIMER_PERIOD
84#define FAUXCLICKY_TIMER_PERIOD ICR3
85#endif
86
87#ifndef FAUXCLICKY_DUTY_CYCLE
88#define FAUXCLICKY_DUTY_CYCLE OCR3A
89#endif
90
91//
92// definitions
93//
94
95void fauxclicky_init(void);
96void fauxclicky_stop(void);
97void fauxclicky_play(float note[2]);
98void fauxclicky_check(void);
99
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index eced3d2bb..002eabd85 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);
@@ -116,8 +119,11 @@ action_t action_for_key(uint8_t layer, keypos_t key)
116 mod = keycode & 0xFF; 119 mod = keycode & 0xFF;
117 action.code = ACTION_MODS_ONESHOT(mod); 120 action.code = ACTION_MODS_ONESHOT(mod);
118 break; 121 break;
122 case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
123 action.code = ACTION_LAYER_TAP_TOGGLE(keycode & 0xFF);
124 break;
119 case QK_MOD_TAP ... QK_MOD_TAP_MAX: 125 case QK_MOD_TAP ... QK_MOD_TAP_MAX:
120 action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF); 126 action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0x1F, keycode & 0xFF);
121 break; 127 break;
122 #ifdef BACKLIGHT_ENABLE 128 #ifdef BACKLIGHT_ENABLE
123 case BL_0 ... BL_15: 129 case BL_0 ... BL_15:
diff --git a/quantum/keymap_extras/keymap_br_abnt2.h b/quantum/keymap_extras/keymap_br_abnt2.h
index 0df177721..b001139dd 100644
--- a/quantum/keymap_extras/keymap_br_abnt2.h
+++ b/quantum/keymap_extras/keymap_br_abnt2.h
@@ -1,3 +1,19 @@
1/* Copyright 2017 Potiguar Faga
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
1#ifndef KEYMAP_BR_ABNT2_H 17#ifndef KEYMAP_BR_ABNT2_H
2#define KEYMAP_BR_ABNT2_H 18#define KEYMAP_BR_ABNT2_H
3 19
diff --git a/quantum/keymap_extras/keymap_french.h b/quantum/keymap_extras/keymap_french.h
index 834c69650..401bbdf64 100644
--- a/quantum/keymap_extras/keymap_french.h
+++ b/quantum/keymap_extras/keymap_french.h
@@ -4,7 +4,9 @@
4#include "keymap.h" 4#include "keymap.h"
5 5
6// Alt gr 6// Alt gr
7#ifndef ALGR
7#define ALGR(kc) RALT(kc) 8#define ALGR(kc) RALT(kc)
9#endif
8#define NO_ALGR KC_RALT 10#define NO_ALGR KC_RALT
9 11
10// Normal characters 12// Normal characters
@@ -72,7 +74,7 @@
72#define FR_PIPE ALGR(KC_6) 74#define FR_PIPE ALGR(KC_6)
73#define FR_GRV ALGR(KC_7) 75#define FR_GRV ALGR(KC_7)
74#define FR_BSLS ALGR(KC_8) 76#define FR_BSLS ALGR(KC_8)
75#define FR_CIRC ALGR(KC_9) 77#define FR_CCIRC ALGR(KC_9)
76#define FR_AT ALGR(KC_0) 78#define FR_AT ALGR(KC_0)
77#define FR_RBRC ALGR(FR_RPRN) 79#define FR_RBRC ALGR(FR_RPRN)
78#define FR_RCBR ALGR(FR_EQL) 80#define FR_RCBR ALGR(FR_EQL)
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_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index 6ae362c4c..403dca538 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -43,12 +43,16 @@ static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_acti
43 if (action->state.finished) 43 if (action->state.finished)
44 return; 44 return;
45 action->state.finished = true; 45 action->state.finished = true;
46 add_mods(action->state.oneshot_mods);
47 send_keyboard_report();
46 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished); 48 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
47} 49}
48 50
49static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action) 51static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
50{ 52{
51 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset); 53 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
54 del_mods(action->state.oneshot_mods);
55 send_keyboard_report();
52} 56}
53 57
54bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { 58bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
@@ -70,6 +74,7 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
70 action->state.keycode = keycode; 74 action->state.keycode = keycode;
71 action->state.count++; 75 action->state.count++;
72 action->state.timer = timer_read(); 76 action->state.timer = timer_read();
77 action->state.oneshot_mods = get_oneshot_mods();
73 process_tap_dance_action_on_each_tap (action); 78 process_tap_dance_action_on_each_tap (action);
74 79
75 if (last_td && last_td != keycode) { 80 if (last_td && last_td != keycode) {
@@ -109,7 +114,7 @@ void matrix_scan_tap_dance () {
109 if (highest_td == -1) 114 if (highest_td == -1)
110 return; 115 return;
111 116
112 for (int i = 0; i <= highest_td; i++) { 117for (int i = 0; i <= highest_td; i++) {
113 qk_tap_dance_action_t *action = &tap_dance_actions[i]; 118 qk_tap_dance_action_t *action = &tap_dance_actions[i];
114 119
115 if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) { 120 if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
index f753cbba6..726752ecc 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -9,6 +9,7 @@
9typedef struct 9typedef struct
10{ 10{
11 uint8_t count; 11 uint8_t count;
12 uint8_t oneshot_mods;
12 uint16_t keycode; 13 uint16_t keycode;
13 uint16_t timer; 14 uint16_t timer;
14 bool interrupted; 15 bool interrupted;
diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c
new file mode 100644
index 000000000..4ad2533b0
--- /dev/null
+++ b/quantum/process_keycode/process_ucis.c
@@ -0,0 +1,133 @@
1#include "process_ucis.h"
2
3qk_ucis_state_t qk_ucis_state;
4
5void qk_ucis_start(void) {
6 qk_ucis_state.count = 0;
7 qk_ucis_state.in_progress = true;
8
9 qk_ucis_start_user();
10}
11
12__attribute__((weak))
13void qk_ucis_start_user(void) {
14 unicode_input_start();
15 register_hex(0x2328);
16 unicode_input_finish();
17}
18
19static bool is_uni_seq(char *seq) {
20 uint8_t i;
21
22 for (i = 0; seq[i]; i++) {
23 uint16_t code;
24 if (('1' <= seq[i]) && (seq[i] <= '0'))
25 code = seq[i] - '1' + KC_1;
26 else
27 code = seq[i] - 'a' + KC_A;
28
29 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
30 return false;
31 }
32
33 return (qk_ucis_state.codes[i] == KC_ENT ||
34 qk_ucis_state.codes[i] == KC_SPC);
35}
36
37__attribute__((weak))
38void qk_ucis_symbol_fallback (void) {
39 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
40 uint8_t code = qk_ucis_state.codes[i];
41 register_code(code);
42 unregister_code(code);
43 wait_ms(UNICODE_TYPE_DELAY);
44 }
45}
46
47void register_ucis(const char *hex) {
48 for(int i = 0; hex[i]; i++) {
49 uint8_t kc = 0;
50 char c = hex[i];
51
52 switch (c) {
53 case '0':
54 kc = KC_0;
55 break;
56 case '1' ... '9':
57 kc = c - '1' + KC_1;
58 break;
59 case 'a' ... 'f':
60 kc = c - 'a' + KC_A;
61 break;
62 case 'A' ... 'F':
63 kc = c - 'A' + KC_A;
64 break;
65 }
66
67 if (kc) {
68 register_code (kc);
69 unregister_code (kc);
70 wait_ms (UNICODE_TYPE_DELAY);
71 }
72 }
73}
74
75bool process_ucis (uint16_t keycode, keyrecord_t *record) {
76 uint8_t i;
77
78 if (!qk_ucis_state.in_progress)
79 return true;
80
81 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
82 !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
83 return false;
84 }
85
86 if (!record->event.pressed)
87 return true;
88
89 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
90 qk_ucis_state.count++;
91
92 if (keycode == KC_BSPC) {
93 if (qk_ucis_state.count >= 2) {
94 qk_ucis_state.count -= 2;
95 return true;
96 } else {
97 qk_ucis_state.count--;
98 return false;
99 }
100 }
101
102 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
103 bool symbol_found = false;
104
105 for (i = qk_ucis_state.count; i > 0; i--) {
106 register_code (KC_BSPC);
107 unregister_code (KC_BSPC);
108 wait_ms(UNICODE_TYPE_DELAY);
109 }
110
111 if (keycode == KC_ESC) {
112 qk_ucis_state.in_progress = false;
113 return false;
114 }
115
116 unicode_input_start();
117 for (i = 0; ucis_symbol_table[i].symbol; i++) {
118 if (is_uni_seq (ucis_symbol_table[i].symbol)) {
119 symbol_found = true;
120 register_ucis(ucis_symbol_table[i].code + 2);
121 break;
122 }
123 }
124 if (!symbol_found) {
125 qk_ucis_symbol_fallback();
126 }
127 unicode_input_finish();
128
129 qk_ucis_state.in_progress = false;
130 return false;
131 }
132 return true;
133} \ No newline at end of file
diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h
new file mode 100644
index 000000000..4332f57b3
--- /dev/null
+++ b/quantum/process_keycode/process_ucis.h
@@ -0,0 +1,35 @@
1#ifndef PROCESS_UCIS_H
2#define PROCESS_UCIS_H
3
4#include "quantum.h"
5#include "process_unicode_common.h"
6
7#ifndef UCIS_MAX_SYMBOL_LENGTH
8#define UCIS_MAX_SYMBOL_LENGTH 32
9#endif
10
11typedef struct {
12 char *symbol;
13 char *code;
14} qk_ucis_symbol_t;
15
16typedef struct {
17 uint8_t count;
18 uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
19 bool in_progress:1;
20} qk_ucis_state_t;
21
22extern qk_ucis_state_t qk_ucis_state;
23
24#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
25#define UCIS_SYM(name, code) {name, #code}
26
27extern const qk_ucis_symbol_t ucis_symbol_table[];
28
29void qk_ucis_start(void);
30void qk_ucis_start_user(void);
31void qk_ucis_symbol_fallback (void);
32void register_ucis(const char *hex);
33bool process_ucis (uint16_t keycode, keyrecord_t *record);
34
35#endif
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
index a30e93ae3..ccae6fdca 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -1,103 +1,6 @@
1#include "process_unicode.h" 1#include "process_unicode.h"
2#include "action_util.h" 2#include "action_util.h"
3 3
4static uint8_t input_mode;
5uint8_t mods;
6
7__attribute__((weak))
8uint16_t hex_to_keycode(uint8_t hex)
9{
10 if (hex == 0x0) {
11 return KC_0;
12 } else if (hex < 0xA) {
13 return KC_1 + (hex - 0x1);
14 } else {
15 return KC_A + (hex - 0xA);
16 }
17}
18
19void set_unicode_input_mode(uint8_t os_target)
20{
21 input_mode = os_target;
22}
23
24uint8_t get_unicode_input_mode(void) {
25 return input_mode;
26}
27
28__attribute__((weak))
29void unicode_input_start (void) {
30 // save current mods
31 mods = keyboard_report->mods;
32
33 // unregister all mods to start from clean state
34 if (mods & MOD_BIT(KC_LSFT)) unregister_code(KC_LSFT);
35 if (mods & MOD_BIT(KC_RSFT)) unregister_code(KC_RSFT);
36 if (mods & MOD_BIT(KC_LCTL)) unregister_code(KC_LCTL);
37 if (mods & MOD_BIT(KC_RCTL)) unregister_code(KC_RCTL);
38 if (mods & MOD_BIT(KC_LALT)) unregister_code(KC_LALT);
39 if (mods & MOD_BIT(KC_RALT)) unregister_code(KC_RALT);
40 if (mods & MOD_BIT(KC_LGUI)) unregister_code(KC_LGUI);
41 if (mods & MOD_BIT(KC_RGUI)) unregister_code(KC_RGUI);
42
43 switch(input_mode) {
44 case UC_OSX:
45 register_code(KC_LALT);
46 break;
47 case UC_LNX:
48 register_code(KC_LCTL);
49 register_code(KC_LSFT);
50 register_code(KC_U);
51 unregister_code(KC_U);
52 unregister_code(KC_LSFT);
53 unregister_code(KC_LCTL);
54 break;
55 case UC_WIN:
56 register_code(KC_LALT);
57 register_code(KC_PPLS);
58 unregister_code(KC_PPLS);
59 break;
60 case UC_WINC:
61 register_code(KC_RALT);
62 unregister_code(KC_RALT);
63 register_code(KC_U);
64 unregister_code(KC_U);
65 }
66 wait_ms(UNICODE_TYPE_DELAY);
67}
68
69__attribute__((weak))
70void unicode_input_finish (void) {
71 switch(input_mode) {
72 case UC_OSX:
73 case UC_WIN:
74 unregister_code(KC_LALT);
75 break;
76 case UC_LNX:
77 register_code(KC_SPC);
78 unregister_code(KC_SPC);
79 break;
80 }
81
82 // reregister previously set mods
83 if (mods & MOD_BIT(KC_LSFT)) register_code(KC_LSFT);
84 if (mods & MOD_BIT(KC_RSFT)) register_code(KC_RSFT);
85 if (mods & MOD_BIT(KC_LCTL)) register_code(KC_LCTL);
86 if (mods & MOD_BIT(KC_RCTL)) register_code(KC_RCTL);
87 if (mods & MOD_BIT(KC_LALT)) register_code(KC_LALT);
88 if (mods & MOD_BIT(KC_RALT)) register_code(KC_RALT);
89 if (mods & MOD_BIT(KC_LGUI)) register_code(KC_LGUI);
90 if (mods & MOD_BIT(KC_RGUI)) register_code(KC_RGUI);
91}
92
93void register_hex(uint16_t hex) {
94 for(int i = 3; i >= 0; i--) {
95 uint8_t digit = ((hex >> (i*4)) & 0xF);
96 register_code(hex_to_keycode(digit));
97 unregister_code(hex_to_keycode(digit));
98 }
99}
100
101bool process_unicode(uint16_t keycode, keyrecord_t *record) { 4bool process_unicode(uint16_t keycode, keyrecord_t *record) {
102 if (keycode > QK_UNICODE && record->event.pressed) { 5 if (keycode > QK_UNICODE && record->event.pressed) {
103 uint16_t unicode = keycode & 0x7FFF; 6 uint16_t unicode = keycode & 0x7FFF;
@@ -108,182 +11,3 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record) {
108 return true; 11 return true;
109} 12}
110 13
111#ifdef UNICODEMAP_ENABLE
112__attribute__((weak))
113const uint32_t PROGMEM unicode_map[] = {
114};
115
116void register_hex32(uint32_t hex) {
117 uint8_t onzerostart = 1;
118 for(int i = 7; i >= 0; i--) {
119 if (i <= 3) {
120 onzerostart = 0;
121 }
122 uint8_t digit = ((hex >> (i*4)) & 0xF);
123 if (digit == 0) {
124 if (onzerostart == 0) {
125 register_code(hex_to_keycode(digit));
126 unregister_code(hex_to_keycode(digit));
127 }
128 } else {
129 register_code(hex_to_keycode(digit));
130 unregister_code(hex_to_keycode(digit));
131 onzerostart = 0;
132 }
133 }
134}
135
136__attribute__((weak))
137void unicode_map_input_error() {}
138
139bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
140 if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
141 const uint32_t* map = unicode_map;
142 uint16_t index = keycode & 0x7FF;
143 uint32_t code = pgm_read_dword_far(&map[index]);
144 if ((code > 0xFFFF && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
145 // when character is out of range supported by the OS
146 unicode_map_input_error();
147 } else {
148 unicode_input_start();
149 register_hex32(code);
150 unicode_input_finish();
151 }
152 }
153 return true;
154}
155#endif
156
157#ifdef UCIS_ENABLE
158qk_ucis_state_t qk_ucis_state;
159
160void qk_ucis_start(void) {
161 qk_ucis_state.count = 0;
162 qk_ucis_state.in_progress = true;
163
164 qk_ucis_start_user();
165}
166
167__attribute__((weak))
168void qk_ucis_start_user(void) {
169 unicode_input_start();
170 register_hex(0x2328);
171 unicode_input_finish();
172}
173
174static bool is_uni_seq(char *seq) {
175 uint8_t i;
176
177 for (i = 0; seq[i]; i++) {
178 uint16_t code;
179 if (('1' <= seq[i]) && (seq[i] <= '0'))
180 code = seq[i] - '1' + KC_1;
181 else
182 code = seq[i] - 'a' + KC_A;
183
184 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
185 return false;
186 }
187
188 return (qk_ucis_state.codes[i] == KC_ENT ||
189 qk_ucis_state.codes[i] == KC_SPC);
190}
191
192__attribute__((weak))
193void qk_ucis_symbol_fallback (void) {
194 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
195 uint8_t code = qk_ucis_state.codes[i];
196 register_code(code);
197 unregister_code(code);
198 wait_ms(UNICODE_TYPE_DELAY);
199 }
200}
201
202void register_ucis(const char *hex) {
203 for(int i = 0; hex[i]; i++) {
204 uint8_t kc = 0;
205 char c = hex[i];
206
207 switch (c) {
208 case '0':
209 kc = KC_0;
210 break;
211 case '1' ... '9':
212 kc = c - '1' + KC_1;
213 break;
214 case 'a' ... 'f':
215 kc = c - 'a' + KC_A;
216 break;
217 case 'A' ... 'F':
218 kc = c - 'A' + KC_A;
219 break;
220 }
221
222 if (kc) {
223 register_code (kc);
224 unregister_code (kc);
225 wait_ms (UNICODE_TYPE_DELAY);
226 }
227 }
228}
229
230bool process_ucis (uint16_t keycode, keyrecord_t *record) {
231 uint8_t i;
232
233 if (!qk_ucis_state.in_progress)
234 return true;
235
236 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
237 !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
238 return false;
239 }
240
241 if (!record->event.pressed)
242 return true;
243
244 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
245 qk_ucis_state.count++;
246
247 if (keycode == KC_BSPC) {
248 if (qk_ucis_state.count >= 2) {
249 qk_ucis_state.count -= 2;
250 return true;
251 } else {
252 qk_ucis_state.count--;
253 return false;
254 }
255 }
256
257 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
258 bool symbol_found = false;
259
260 for (i = qk_ucis_state.count; i > 0; i--) {
261 register_code (KC_BSPC);
262 unregister_code (KC_BSPC);
263 wait_ms(UNICODE_TYPE_DELAY);
264 }
265
266 if (keycode == KC_ESC) {
267 qk_ucis_state.in_progress = false;
268 return false;
269 }
270
271 unicode_input_start();
272 for (i = 0; ucis_symbol_table[i].symbol; i++) {
273 if (is_uni_seq (ucis_symbol_table[i].symbol)) {
274 symbol_found = true;
275 register_ucis(ucis_symbol_table[i].code + 2);
276 break;
277 }
278 }
279 if (!symbol_found) {
280 qk_ucis_symbol_fallback();
281 }
282 unicode_input_finish();
283
284 qk_ucis_state.in_progress = false;
285 return false;
286 }
287 return true;
288}
289#endif
diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h
index f17cfa6cf..4c21f11eb 100644
--- a/quantum/process_keycode/process_unicode.h
+++ b/quantum/process_keycode/process_unicode.h
@@ -2,166 +2,8 @@
2#define PROCESS_UNICODE_H 2#define PROCESS_UNICODE_H
3 3
4#include "quantum.h" 4#include "quantum.h"
5 5#include "process_unicode_common.h"
6#define UC_OSX 0 // Mac OS X
7#define UC_LNX 1 // Linux
8#define UC_WIN 2 // Windows 'HexNumpad'
9#define UC_BSD 3 // BSD (not implemented)
10#define UC_WINC 4 // WinCompose https://github.com/samhocevar/wincompose
11
12#ifndef UNICODE_TYPE_DELAY
13#define UNICODE_TYPE_DELAY 10
14#endif
15
16void set_unicode_input_mode(uint8_t os_target);
17uint8_t get_unicode_input_mode(void);
18void unicode_input_start(void);
19void unicode_input_finish(void);
20void register_hex(uint16_t hex);
21 6
22bool process_unicode(uint16_t keycode, keyrecord_t *record); 7bool process_unicode(uint16_t keycode, keyrecord_t *record);
23 8
24#ifdef UNICODEMAP_ENABLE
25void unicode_map_input_error(void);
26bool process_unicode_map(uint16_t keycode, keyrecord_t *record);
27#endif
28
29#ifdef UCIS_ENABLE
30#ifndef UCIS_MAX_SYMBOL_LENGTH
31#define UCIS_MAX_SYMBOL_LENGTH 32
32#endif
33
34typedef struct {
35 char *symbol;
36 char *code;
37} qk_ucis_symbol_t;
38
39typedef struct {
40 uint8_t count;
41 uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
42 bool in_progress:1;
43} qk_ucis_state_t;
44
45extern qk_ucis_state_t qk_ucis_state;
46
47#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
48#define UCIS_SYM(name, code) {name, #code}
49
50extern const qk_ucis_symbol_t ucis_symbol_table[];
51
52void qk_ucis_start(void);
53void qk_ucis_start_user(void);
54void qk_ucis_symbol_fallback (void);
55void register_ucis(const char *hex);
56bool process_ucis (uint16_t keycode, keyrecord_t *record);
57
58#endif
59
60#define UC_BSPC UC(0x0008)
61
62#define UC_SPC UC(0x0020)
63
64#define UC_EXLM UC(0x0021)
65#define UC_DQUT UC(0x0022)
66#define UC_HASH UC(0x0023)
67#define UC_DLR UC(0x0024)
68#define UC_PERC UC(0x0025)
69#define UC_AMPR UC(0x0026)
70#define UC_QUOT UC(0x0027)
71#define UC_LPRN UC(0x0028)
72#define UC_RPRN UC(0x0029)
73#define UC_ASTR UC(0x002A)
74#define UC_PLUS UC(0x002B)
75#define UC_COMM UC(0x002C)
76#define UC_DASH UC(0x002D)
77#define UC_DOT UC(0x002E)
78#define UC_SLSH UC(0x002F)
79
80#define UC_0 UC(0x0030)
81#define UC_1 UC(0x0031)
82#define UC_2 UC(0x0032)
83#define UC_3 UC(0x0033)
84#define UC_4 UC(0x0034)
85#define UC_5 UC(0x0035)
86#define UC_6 UC(0x0036)
87#define UC_7 UC(0x0037)
88#define UC_8 UC(0x0038)
89#define UC_9 UC(0x0039)
90
91#define UC_COLN UC(0x003A)
92#define UC_SCLN UC(0x003B)
93#define UC_LT UC(0x003C)
94#define UC_EQL UC(0x003D)
95#define UC_GT UC(0x003E)
96#define UC_QUES UC(0x003F)
97#define UC_AT UC(0x0040)
98
99#define UC_A UC(0x0041)
100#define UC_B UC(0x0042)
101#define UC_C UC(0x0043)
102#define UC_D UC(0x0044)
103#define UC_E UC(0x0045)
104#define UC_F UC(0x0046)
105#define UC_G UC(0x0047)
106#define UC_H UC(0x0048)
107#define UC_I UC(0x0049)
108#define UC_J UC(0x004A)
109#define UC_K UC(0x004B)
110#define UC_L UC(0x004C)
111#define UC_M UC(0x004D)
112#define UC_N UC(0x004E)
113#define UC_O UC(0x004F)
114#define UC_P UC(0x0050)
115#define UC_Q UC(0x0051)
116#define UC_R UC(0x0052)
117#define UC_S UC(0x0053)
118#define UC_T UC(0x0054)
119#define UC_U UC(0x0055)
120#define UC_V UC(0x0056)
121#define UC_W UC(0x0057)
122#define UC_X UC(0x0058)
123#define UC_Y UC(0x0059)
124#define UC_Z UC(0x005A)
125
126#define UC_LBRC UC(0x005B)
127#define UC_BSLS UC(0x005C)
128#define UC_RBRC UC(0x005D)
129#define UC_CIRM UC(0x005E)
130#define UC_UNDR UC(0x005F)
131
132#define UC_GRV UC(0x0060)
133
134#define UC_a UC(0x0061)
135#define UC_b UC(0x0062)
136#define UC_c UC(0x0063)
137#define UC_d UC(0x0064)
138#define UC_e UC(0x0065)
139#define UC_f UC(0x0066)
140#define UC_g UC(0x0067)
141#define UC_h UC(0x0068)
142#define UC_i UC(0x0069)
143#define UC_j UC(0x006A)
144#define UC_k UC(0x006B)
145#define UC_l UC(0x006C)
146#define UC_m UC(0x006D)
147#define UC_n UC(0x006E)
148#define UC_o UC(0x006F)
149#define UC_p UC(0x0070)
150#define UC_q UC(0x0071)
151#define UC_r UC(0x0072)
152#define UC_s UC(0x0073)
153#define UC_t UC(0x0074)
154#define UC_u UC(0x0075)
155#define UC_v UC(0x0076)
156#define UC_w UC(0x0077)
157#define UC_x UC(0x0078)
158#define UC_y UC(0x0079)
159#define UC_z UC(0x007A)
160
161#define UC_LCBR UC(0x007B)
162#define UC_PIPE UC(0x007C)
163#define UC_RCBR UC(0x007D)
164#define UC_TILD UC(0x007E)
165#define UC_DEL UC(0x007F)
166
167#endif 9#endif
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
new file mode 100644
index 000000000..31bc3b7ab
--- /dev/null
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -0,0 +1,85 @@
1#include "process_unicode_common.h"
2
3uint8_t mods;
4
5void set_unicode_input_mode(uint8_t os_target)
6{
7 input_mode = os_target;
8}
9
10uint8_t get_unicode_input_mode(void) {
11 return input_mode;
12}
13
14__attribute__((weak))
15void unicode_input_start (void) {
16 // save current mods
17 mods = keyboard_report->mods;
18
19 // unregister all mods to start from clean state
20 if (mods & MOD_BIT(KC_LSFT)) unregister_code(KC_LSFT);
21 if (mods & MOD_BIT(KC_RSFT)) unregister_code(KC_RSFT);
22 if (mods & MOD_BIT(KC_LCTL)) unregister_code(KC_LCTL);
23 if (mods & MOD_BIT(KC_RCTL)) unregister_code(KC_RCTL);
24 if (mods & MOD_BIT(KC_LALT)) unregister_code(KC_LALT);
25 if (mods & MOD_BIT(KC_RALT)) unregister_code(KC_RALT);
26 if (mods & MOD_BIT(KC_LGUI)) unregister_code(KC_LGUI);
27 if (mods & MOD_BIT(KC_RGUI)) unregister_code(KC_RGUI);
28
29 switch(input_mode) {
30 case UC_OSX:
31 register_code(KC_LALT);
32 break;
33 case UC_LNX:
34 register_code(KC_LCTL);
35 register_code(KC_LSFT);
36 register_code(KC_U);
37 unregister_code(KC_U);
38 unregister_code(KC_LSFT);
39 unregister_code(KC_LCTL);
40 break;
41 case UC_WIN:
42 register_code(KC_LALT);
43 register_code(KC_PPLS);
44 unregister_code(KC_PPLS);
45 break;
46 case UC_WINC:
47 register_code(KC_RALT);
48 unregister_code(KC_RALT);
49 register_code(KC_U);
50 unregister_code(KC_U);
51 }
52 wait_ms(UNICODE_TYPE_DELAY);
53}
54
55__attribute__((weak))
56void unicode_input_finish (void) {
57 switch(input_mode) {
58 case UC_OSX:
59 case UC_WIN:
60 unregister_code(KC_LALT);
61 break;
62 case UC_LNX:
63 register_code(KC_SPC);
64 unregister_code(KC_SPC);
65 break;
66 }
67
68 // reregister previously set mods
69 if (mods & MOD_BIT(KC_LSFT)) register_code(KC_LSFT);
70 if (mods & MOD_BIT(KC_RSFT)) register_code(KC_RSFT);
71 if (mods & MOD_BIT(KC_LCTL)) register_code(KC_LCTL);
72 if (mods & MOD_BIT(KC_RCTL)) register_code(KC_RCTL);
73 if (mods & MOD_BIT(KC_LALT)) register_code(KC_LALT);
74 if (mods & MOD_BIT(KC_RALT)) register_code(KC_RALT);
75 if (mods & MOD_BIT(KC_LGUI)) register_code(KC_LGUI);
76 if (mods & MOD_BIT(KC_RGUI)) register_code(KC_RGUI);
77}
78
79void register_hex(uint16_t hex) {
80 for(int i = 3; i >= 0; i--) {
81 uint8_t digit = ((hex >> (i*4)) & 0xF);
82 register_code(hex_to_keycode(digit));
83 unregister_code(hex_to_keycode(digit));
84 }
85} \ No newline at end of file
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
new file mode 100644
index 000000000..864693cdd
--- /dev/null
+++ b/quantum/process_keycode/process_unicode_common.h
@@ -0,0 +1,132 @@
1#ifndef PROCESS_UNICODE_COMMON_H
2#define PROCESS_UNICODE_COMMON_H
3
4#include "quantum.h"
5
6#ifndef UNICODE_TYPE_DELAY
7#define UNICODE_TYPE_DELAY 10
8#endif
9
10__attribute__ ((unused))
11static uint8_t input_mode;
12
13void set_unicode_input_mode(uint8_t os_target);
14uint8_t get_unicode_input_mode(void);
15void unicode_input_start(void);
16void unicode_input_finish(void);
17void register_hex(uint16_t hex);
18
19#define UC_OSX 0 // Mac OS X
20#define UC_LNX 1 // Linux
21#define UC_WIN 2 // Windows 'HexNumpad'
22#define UC_BSD 3 // BSD (not implemented)
23#define UC_WINC 4 // WinCompose https://github.com/samhocevar/wincompose
24
25#define UC_BSPC UC(0x0008)
26
27#define UC_SPC UC(0x0020)
28
29#define UC_EXLM UC(0x0021)
30#define UC_DQUT UC(0x0022)
31#define UC_HASH UC(0x0023)
32#define UC_DLR UC(0x0024)
33#define UC_PERC UC(0x0025)
34#define UC_AMPR UC(0x0026)
35#define UC_QUOT UC(0x0027)
36#define UC_LPRN UC(0x0028)
37#define UC_RPRN UC(0x0029)
38#define UC_ASTR UC(0x002A)
39#define UC_PLUS UC(0x002B)
40#define UC_COMM UC(0x002C)
41#define UC_DASH UC(0x002D)
42#define UC_DOT UC(0x002E)
43#define UC_SLSH UC(0x002F)
44
45#define UC_0 UC(0x0030)
46#define UC_1 UC(0x0031)
47#define UC_2 UC(0x0032)
48#define UC_3 UC(0x0033)
49#define UC_4 UC(0x0034)
50#define UC_5 UC(0x0035)
51#define UC_6 UC(0x0036)
52#define UC_7 UC(0x0037)
53#define UC_8 UC(0x0038)
54#define UC_9 UC(0x0039)
55
56#define UC_COLN UC(0x003A)
57#define UC_SCLN UC(0x003B)
58#define UC_LT UC(0x003C)
59#define UC_EQL UC(0x003D)
60#define UC_GT UC(0x003E)
61#define UC_QUES UC(0x003F)
62#define UC_AT UC(0x0040)
63
64#define UC_A UC(0x0041)
65#define UC_B UC(0x0042)
66#define UC_C UC(0x0043)
67#define UC_D UC(0x0044)
68#define UC_E UC(0x0045)
69#define UC_F UC(0x0046)
70#define UC_G UC(0x0047)
71#define UC_H UC(0x0048)
72#define UC_I UC(0x0049)
73#define UC_J UC(0x004A)
74#define UC_K UC(0x004B)
75#define UC_L UC(0x004C)
76#define UC_M UC(0x004D)
77#define UC_N UC(0x004E)
78#define UC_O UC(0x004F)
79#define UC_P UC(0x0050)
80#define UC_Q UC(0x0051)
81#define UC_R UC(0x0052)
82#define UC_S UC(0x0053)
83#define UC_T UC(0x0054)
84#define UC_U UC(0x0055)
85#define UC_V UC(0x0056)
86#define UC_W UC(0x0057)
87#define UC_X UC(0x0058)
88#define UC_Y UC(0x0059)
89#define UC_Z UC(0x005A)
90
91#define UC_LBRC UC(0x005B)
92#define UC_BSLS UC(0x005C)
93#define UC_RBRC UC(0x005D)
94#define UC_CIRM UC(0x005E)
95#define UC_UNDR UC(0x005F)
96
97#define UC_GRV UC(0x0060)
98
99#define UC_a UC(0x0061)
100#define UC_b UC(0x0062)
101#define UC_c UC(0x0063)
102#define UC_d UC(0x0064)
103#define UC_e UC(0x0065)
104#define UC_f UC(0x0066)
105#define UC_g UC(0x0067)
106#define UC_h UC(0x0068)
107#define UC_i UC(0x0069)
108#define UC_j UC(0x006A)
109#define UC_k UC(0x006B)
110#define UC_l UC(0x006C)
111#define UC_m UC(0x006D)
112#define UC_n UC(0x006E)
113#define UC_o UC(0x006F)
114#define UC_p UC(0x0070)
115#define UC_q UC(0x0071)
116#define UC_r UC(0x0072)
117#define UC_s UC(0x0073)
118#define UC_t UC(0x0074)
119#define UC_u UC(0x0075)
120#define UC_v UC(0x0076)
121#define UC_w UC(0x0077)
122#define UC_x UC(0x0078)
123#define UC_y UC(0x0079)
124#define UC_z UC(0x007A)
125
126#define UC_LCBR UC(0x007B)
127#define UC_PIPE UC(0x007C)
128#define UC_RCBR UC(0x007D)
129#define UC_TILD UC(0x007E)
130#define UC_DEL UC(0x007F)
131
132#endif \ No newline at end of file
diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c
new file mode 100644
index 000000000..68a593a18
--- /dev/null
+++ b/quantum/process_keycode/process_unicodemap.c
@@ -0,0 +1,56 @@
1#include "process_unicodemap.h"
2#include "process_unicode_common.h"
3
4__attribute__((weak))
5const uint32_t PROGMEM unicode_map[] = {
6};
7
8void register_hex32(uint32_t hex) {
9 bool onzerostart = true;
10 for(int i = 7; i >= 0; i--) {
11 if (i <= 3) {
12 onzerostart = false;
13 }
14 uint8_t digit = ((hex >> (i*4)) & 0xF);
15 if (digit == 0) {
16 if (!onzerostart) {
17 register_code(hex_to_keycode(digit));
18 unregister_code(hex_to_keycode(digit));
19 }
20 } else {
21 register_code(hex_to_keycode(digit));
22 unregister_code(hex_to_keycode(digit));
23 onzerostart = false;
24 }
25 }
26}
27
28__attribute__((weak))
29void unicode_map_input_error() {}
30
31bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
32 uint8_t input_mode = get_unicode_input_mode();
33 if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
34 const uint32_t* map = unicode_map;
35 uint16_t index = keycode - QK_UNICODE_MAP;
36 uint32_t code = pgm_read_dword_far(&map[index]);
37 if (code > 0xFFFF && code <= 0x10ffff && input_mode == UC_OSX) {
38 // Convert to UTF-16 surrogate pair
39 code -= 0x10000;
40 uint32_t lo = code & 0x3ff;
41 uint32_t hi = (code & 0xffc00) >> 10;
42 unicode_input_start();
43 register_hex32(hi + 0xd800);
44 register_hex32(lo + 0xdc00);
45 unicode_input_finish();
46 } else if ((code > 0x10ffff && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
47 // when character is out of range supported by the OS
48 unicode_map_input_error();
49 } else {
50 unicode_input_start();
51 register_hex32(code);
52 unicode_input_finish();
53 }
54 }
55 return true;
56} \ No newline at end of file
diff --git a/quantum/process_keycode/process_unicodemap.h b/quantum/process_keycode/process_unicodemap.h
new file mode 100644
index 000000000..64a7a0109
--- /dev/null
+++ b/quantum/process_keycode/process_unicodemap.h
@@ -0,0 +1,9 @@
1#ifndef PROCESS_UNICODEMAP_H
2#define PROCESS_UNICODEMAP_H
3
4#include "quantum.h"
5#include "process_unicode_common.h"
6
7void unicode_map_input_error(void);
8bool process_unicode_map(uint16_t keycode, keyrecord_t *record);
9#endif \ No newline at end of file
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 63ffe2074..4a6d0355f 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -1,9 +1,16 @@
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
5#endif 8#endif
6 9
10#ifdef FAUXCLICKY_ENABLE
11#include "fauxclicky.h"
12#endif
13
7static void do_code16 (uint16_t code, void (*f) (uint8_t)) { 14static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
8 switch (code) { 15 switch (code) {
9 case QK_MODS ... QK_MODS_MAX: 16 case QK_MODS ... QK_MODS_MAX:
@@ -33,14 +40,42 @@ static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
33 f(KC_RGUI); 40 f(KC_RGUI);
34} 41}
35 42
43static inline void qk_register_weak_mods(uint8_t kc) {
44 add_weak_mods(MOD_BIT(kc));
45 send_keyboard_report();
46}
47
48static inline void qk_unregister_weak_mods(uint8_t kc) {
49 del_weak_mods(MOD_BIT(kc));
50 send_keyboard_report();
51}
52
53static inline void qk_register_mods(uint8_t kc) {
54 add_weak_mods(MOD_BIT(kc));
55 send_keyboard_report();
56}
57
58static inline void qk_unregister_mods(uint8_t kc) {
59 del_weak_mods(MOD_BIT(kc));
60 send_keyboard_report();
61}
62
36void register_code16 (uint16_t code) { 63void register_code16 (uint16_t code) {
37 do_code16 (code, register_code); 64 if (IS_MOD(code) || code == KC_NO) {
65 do_code16 (code, qk_register_mods);
66 } else {
67 do_code16 (code, qk_register_weak_mods);
68 }
38 register_code (code); 69 register_code (code);
39} 70}
40 71
41void unregister_code16 (uint16_t code) { 72void unregister_code16 (uint16_t code) {
42 unregister_code (code); 73 unregister_code (code);
43 do_code16 (code, unregister_code); 74 if (IS_MOD(code) || code == KC_NO) {
75 do_code16 (code, qk_unregister_mods);
76 } else {
77 do_code16 (code, qk_unregister_weak_mods);
78 }
44} 79}
45 80
46__attribute__ ((weak)) 81__attribute__ ((weak))
@@ -130,6 +165,9 @@ bool process_record_quantum(keyrecord_t *record) {
130 #ifndef DISABLE_CHORDING 165 #ifndef DISABLE_CHORDING
131 process_chording(keycode, record) && 166 process_chording(keycode, record) &&
132 #endif 167 #endif
168 #ifdef COMBO_ENABLE
169 process_combo(keycode, record) &&
170 #endif
133 #ifdef UNICODE_ENABLE 171 #ifdef UNICODE_ENABLE
134 process_unicode(keycode, record) && 172 process_unicode(keycode, record) &&
135 #endif 173 #endif
@@ -162,6 +200,26 @@ bool process_record_quantum(keyrecord_t *record) {
162 } 200 }
163 return false; 201 return false;
164 break; 202 break;
203 #ifdef FAUXCLICKY_ENABLE
204 case FC_TOG:
205 if (record->event.pressed) {
206 FAUXCLICKY_TOGGLE;
207 }
208 return false;
209 break;
210 case FC_ON:
211 if (record->event.pressed) {
212 FAUXCLICKY_ON;
213 }
214 return false;
215 break;
216 case FC_OFF:
217 if (record->event.pressed) {
218 FAUXCLICKY_OFF;
219 }
220 return false;
221 break;
222 #endif
165 #ifdef RGBLIGHT_ENABLE 223 #ifdef RGBLIGHT_ENABLE
166 case RGB_TOG: 224 case RGB_TOG:
167 if (record->event.pressed) { 225 if (record->event.pressed) {
@@ -212,6 +270,36 @@ bool process_record_quantum(keyrecord_t *record) {
212 return false; 270 return false;
213 break; 271 break;
214 #endif 272 #endif
273 #ifdef PROTOCOL_LUFA
274 case OUT_AUTO:
275 if (record->event.pressed) {
276 set_output(OUTPUT_AUTO);
277 }
278 return false;
279 break;
280 case OUT_USB:
281 if (record->event.pressed) {
282 set_output(OUTPUT_USB);
283 }
284 return false;
285 break;
286 #ifdef BLUETOOTH_ENABLE
287 case OUT_BT:
288 if (record->event.pressed) {
289 set_output(OUTPUT_BLUETOOTH);
290 }
291 return false;
292 break;
293 #endif
294 #ifdef ADAFRUIT_BLE_ENABLE
295 case OUT_BLE:
296 if (record->event.pressed) {
297 set_output(OUTPUT_ADAFRUIT_BLE);
298 }
299 return false;
300 break;
301 #endif
302 #endif
215 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO: 303 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
216 if (record->event.pressed) { 304 if (record->event.pressed) {
217 // MAGIC actions (BOOTMAGIC without the boot) 305 // MAGIC actions (BOOTMAGIC without the boot)
@@ -508,6 +596,11 @@ void matrix_scan_quantum() {
508 #ifdef TAP_DANCE_ENABLE 596 #ifdef TAP_DANCE_ENABLE
509 matrix_scan_tap_dance(); 597 matrix_scan_tap_dance();
510 #endif 598 #endif
599
600 #ifdef COMBO_ENABLE
601 matrix_scan_combo();
602 #endif
603
511 matrix_scan_kb(); 604 matrix_scan_kb();
512} 605}
513 606
@@ -525,34 +618,45 @@ static const uint8_t backlight_pin = BACKLIGHT_PIN;
525# define COM1x1 COM1A1 618# define COM1x1 COM1A1
526# define OCR1x OCR1A 619# define OCR1x OCR1A
527#else 620#else
528# error "Backlight pin not supported - use B5, B6, or B7" 621# define NO_BACKLIGHT_CLOCK
622#endif
623
624#ifndef BACKLIGHT_ON_STATE
625#define BACKLIGHT_ON_STATE 0
529#endif 626#endif
530 627
531__attribute__ ((weak)) 628__attribute__ ((weak))
532void backlight_init_ports(void) 629void backlight_init_ports(void)
533{ 630{
534 631
535 // Setup backlight pin as output and output low. 632 // Setup backlight pin as output and output to on state.
536 // DDRx |= n 633 // DDRx |= n
537 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); 634 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
538 // PORTx &= ~n 635 #if BACKLIGHT_ON_STATE == 0
539 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); 636 // PORTx &= ~n
637 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
638 #else
639 // PORTx |= n
640 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
641 #endif
540 642
541 // Use full 16-bit resolution. 643 #ifndef NO_BACKLIGHT_CLOCK
542 ICR1 = 0xFFFF; 644 // Use full 16-bit resolution.
645 ICR1 = 0xFFFF;
543 646
544 // I could write a wall of text here to explain... but TL;DW 647 // I could write a wall of text here to explain... but TL;DW
545 // Go read the ATmega32u4 datasheet. 648 // Go read the ATmega32u4 datasheet.
546 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on 649 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
547 650
548 // Pin PB7 = OCR1C (Timer 1, Channel C) 651 // Pin PB7 = OCR1C (Timer 1, Channel C)
549 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0 652 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
550 // (i.e. start high, go low when counter matches.) 653 // (i.e. start high, go low when counter matches.)
551 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0 654 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
552 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1 655 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
553 656
554 TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010; 657 TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
555 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; 658 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
659 #endif
556 660
557 backlight_init(); 661 backlight_init();
558 #ifdef BACKLIGHT_BREATHING 662 #ifdef BACKLIGHT_BREATHING
@@ -564,24 +668,43 @@ __attribute__ ((weak))
564void backlight_set(uint8_t level) 668void backlight_set(uint8_t level)
565{ 669{
566 // Prevent backlight blink on lowest level 670 // Prevent backlight blink on lowest level
567 // PORTx &= ~n 671 #if BACKLIGHT_ON_STATE == 0
568 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); 672 // PORTx &= ~n
673 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
674 #else
675 // PORTx |= n
676 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
677 #endif
569 678
570 if ( level == 0 ) { 679 if ( level == 0 ) {
571 // Turn off PWM control on backlight pin, revert to output low. 680 #ifndef NO_BACKLIGHT_CLOCK
572 TCCR1A &= ~(_BV(COM1x1)); 681 // Turn off PWM control on backlight pin, revert to output low.
573 OCR1x = 0x0; 682 TCCR1A &= ~(_BV(COM1x1));
574 } else if ( level == BACKLIGHT_LEVELS ) { 683 OCR1x = 0x0;
575 // Turn on PWM control of backlight pin 684 #else
576 TCCR1A |= _BV(COM1x1); 685 #if BACKLIGHT_ON_STATE == 0
577 // Set the brightness 686 // PORTx |= n
578 OCR1x = 0xFFFF; 687 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
579 } else { 688 #else
580 // Turn on PWM control of backlight pin 689 // PORTx &= ~n
581 TCCR1A |= _BV(COM1x1); 690 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
582 // Set the brightness 691 #endif
583 OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2)); 692 #endif
584 } 693 }
694 #ifndef NO_BACKLIGHT_CLOCK
695 else if ( level == BACKLIGHT_LEVELS ) {
696 // Turn on PWM control of backlight pin
697 TCCR1A |= _BV(COM1x1);
698 // Set the brightness
699 OCR1x = 0xFFFF;
700 }
701 else {
702 // Turn on PWM control of backlight pin
703 TCCR1A |= _BV(COM1x1);
704 // Set the brightness
705 OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
706 }
707 #endif
585 708
586 #ifdef BACKLIGHT_BREATHING 709 #ifdef BACKLIGHT_BREATHING
587 breathing_intensity_default(); 710 breathing_intensity_default();
@@ -849,6 +972,19 @@ void send_nibble(uint8_t number) {
849 } 972 }
850} 973}
851 974
975
976__attribute__((weak))
977uint16_t hex_to_keycode(uint8_t hex)
978{
979 if (hex == 0x0) {
980 return KC_0;
981 } else if (hex < 0xA) {
982 return KC_1 + (hex - 0x1);
983 } else {
984 return KC_A + (hex - 0xA);
985 }
986}
987
852void api_send_unicode(uint32_t unicode) { 988void api_send_unicode(uint32_t unicode) {
853#ifdef API_ENABLE 989#ifdef API_ENABLE
854 uint8_t chunk[4]; 990 uint8_t chunk[4];
diff --git a/quantum/quantum.h b/quantum/quantum.h
index e6adf974a..580d51202 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>
@@ -57,12 +56,24 @@ extern uint32_t default_layer_state;
57 #include "process_unicode.h" 56 #include "process_unicode.h"
58#endif 57#endif
59 58
59#ifdef UCIS_ENABLE
60 #include "process_ucis.h"
61#endif
62
63#ifdef UNICODEMAP_ENABLE
64 #include "process_unicodemap.h"
65#endif
66
60#include "process_tap_dance.h" 67#include "process_tap_dance.h"
61 68
62#ifdef PRINTING_ENABLE 69#ifdef PRINTING_ENABLE
63 #include "process_printer.h" 70 #include "process_printer.h"
64#endif 71#endif
65 72
73#ifdef COMBO_ENABLE
74 #include "process_combo.h"
75#endif
76
66#define SEND_STRING(str) send_string(PSTR(str)) 77#define SEND_STRING(str) send_string(PSTR(str))
67void send_string(const char *str); 78void send_string(const char *str);
68 79
@@ -114,7 +125,7 @@ void send_dword(uint32_t number);
114void send_word(uint16_t number); 125void send_word(uint16_t number);
115void send_byte(uint8_t number); 126void send_byte(uint8_t number);
116void send_nibble(uint8_t number); 127void send_nibble(uint8_t number);
117 128uint16_t hex_to_keycode(uint8_t hex);
118 129
119void led_set_user(uint8_t usb_led); 130void led_set_user(uint8_t usb_led);
120void led_set_kb(uint8_t usb_led); 131void led_set_kb(uint8_t usb_led);
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 4853655f9..63b626926 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -39,22 +39,27 @@ enum quantum_keycodes {
39 QK_CHORDING = 0x5600, 39 QK_CHORDING = 0x5600,
40 QK_CHORDING_MAX = 0x56FF, 40 QK_CHORDING_MAX = 0x56FF,
41#endif 41#endif
42 QK_TAP_DANCE = 0x5700,
43 QK_TAP_DANCE_MAX = 0x57FF,
44 QK_LAYER_TAP_TOGGLE = 0x5800,
45 QK_LAYER_TAP_TOGGLE_MAX = 0x58FF,
42 QK_MOD_TAP = 0x6000, 46 QK_MOD_TAP = 0x6000,
43 QK_MOD_TAP_MAX = 0x6FFF, 47 QK_MOD_TAP_MAX = 0x7FFF,
44 QK_TAP_DANCE = 0x7100, 48#if defined(UNICODEMAP_ENABLE) && defined(UNICODE_ENABLE)
45 QK_TAP_DANCE_MAX = 0x71FF, 49 #error "Cannot enable both UNICODEMAP && UNICODE"
46#ifdef UNICODEMAP_ENABLE
47 QK_UNICODE_MAP = 0x7800,
48 QK_UNICODE_MAP_MAX = 0x7FFF,
49#endif 50#endif
50#ifdef UNICODE_ENABLE 51#ifdef UNICODE_ENABLE
51 QK_UNICODE = 0x8000, 52 QK_UNICODE = 0x8000,
52 QK_UNICODE_MAX = 0xFFFF, 53 QK_UNICODE_MAX = 0xFFFF,
53#endif 54#endif
55#ifdef UNICODEMAP_ENABLE
56 QK_UNICODE_MAP = 0x8000,
57 QK_UNICODE_MAP_MAX = 0x83FF,
58#endif
54 59
55 // Loose keycodes - to be used directly 60 // Loose keycodes - to be used directly
56 61
57 RESET = 0x7000, 62 RESET = 0x5C00,
58 DEBUG, 63 DEBUG,
59 MAGIC_SWAP_CONTROL_CAPSLOCK, 64 MAGIC_SWAP_CONTROL_CAPSLOCK,
60 MAGIC_CAPSLOCK_TO_CONTROL, 65 MAGIC_CAPSLOCK_TO_CONTROL,
@@ -86,6 +91,13 @@ enum quantum_keycodes {
86 AU_OFF, 91 AU_OFF,
87 AU_TOG, 92 AU_TOG,
88 93
94#ifdef FAUXCLICKY_ENABLE
95 // Faux clicky
96 FC_ON,
97 FC_OFF,
98 FC_TOG,
99#endif
100
89 // Music mode on/off/toggle 101 // Music mode on/off/toggle
90 MU_ON, 102 MU_ON,
91 MU_OFF, 103 MU_OFF,
@@ -141,6 +153,16 @@ enum quantum_keycodes {
141 PRINT_ON, 153 PRINT_ON,
142 PRINT_OFF, 154 PRINT_OFF,
143 155
156 // output selection
157 OUT_AUTO,
158 OUT_USB,
159#ifdef BLUETOOTH_ENABLE
160 OUT_BT,
161#endif
162#ifdef ADAFRUIT_BLE_ENABLE
163 OUT_BLE,
164#endif
165
144 // always leave at the end 166 // always leave at the end
145 SAFE_RANGE 167 SAFE_RANGE
146}; 168};
@@ -246,8 +268,10 @@ enum quantum_keycodes {
246 268
247#define M(kc) (kc | QK_MACRO) 269#define M(kc) (kc | QK_MACRO)
248 270
271#define MACROTAP(kc) (kc | QK_MACRO | FUNC_TAP<<8)
249#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE) 272#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
250 273
274
251// L-ayer, T-ap - 256 keycode max, 16 layer max 275// L-ayer, T-ap - 256 keycode max, 16 layer max
252#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8)) 276#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
253 277
@@ -285,15 +309,33 @@ enum quantum_keycodes {
285// One-shot mod 309// One-shot mod
286#define OSM(mod) (mod | QK_ONE_SHOT_MOD) 310#define OSM(mod) (mod | QK_ONE_SHOT_MOD)
287 311
312// Layer tap-toggle
313#define TT(layer) (layer | QK_LAYER_TAP_TOGGLE)
314
288// M-od, T-ap - 256 keycode max 315// M-od, T-ap - 256 keycode max
289#define MT(mod, kc) (kc | QK_MOD_TAP | ((mod & 0xF) << 8)) 316#define MT(mod, kc) (kc | QK_MOD_TAP | ((mod & 0x1F) << 8))
317
290#define CTL_T(kc) MT(MOD_LCTL, kc) 318#define CTL_T(kc) MT(MOD_LCTL, kc)
319#define LCTL_T(kc) MT(MOD_LCTL, kc)
320#define RCTL_T(kc) MT(MOD_RCTL, kc)
321
291#define SFT_T(kc) MT(MOD_LSFT, kc) 322#define SFT_T(kc) MT(MOD_LSFT, kc)
323#define LSFT_T(kc) MT(MOD_LSFT, kc)
324#define RSFT_T(kc) MT(MOD_RSFT, kc)
325
292#define ALT_T(kc) MT(MOD_LALT, kc) 326#define ALT_T(kc) MT(MOD_LALT, kc)
327#define LALT_T(kc) MT(MOD_LALT, kc)
328#define RALT_T(kc) MT(MOD_RALT, kc)
329#define ALGR_T(kc) MT(MOD_RALT, kc) // dual-function AltGR
330
293#define GUI_T(kc) MT(MOD_LGUI, kc) 331#define GUI_T(kc) MT(MOD_LGUI, kc)
332#define LGUI_T(kc) MT(MOD_LGUI, kc)
333#define RGUI_T(kc) MT(MOD_RGUI, kc)
334
294#define C_S_T(kc) MT((MOD_LCTL | MOD_LSFT), kc) // Control + Shift e.g. for gnome-terminal 335#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 336#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
296#define LCAG_T(kc) MT((MOD_LCTL | MOD_LALT | MOD_LGUI), kc) // Left control alt and gui 337#define LCAG_T(kc) MT((MOD_LCTL | MOD_LALT | MOD_LGUI), kc) // Left control alt and gui
338#define RCAG_T(kc) MT((MOD_RCTL | MOD_RALT | MOD_RGUI), kc) // Right control alt and gui
297#define ALL_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI), kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/ 339#define ALL_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI), kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
298#define SCMD_T(kc) MT((MOD_LGUI | MOD_LSFT), kc) 340#define SCMD_T(kc) MT((MOD_LGUI | MOD_LSFT), kc)
299#define SWIN_T(kc) SCMD_T(kc) 341#define SWIN_T(kc) SCMD_T(kc)
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index 52a09817a..dd1b91c63 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -66,6 +66,8 @@ __attribute__ ((weak))
66const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20}; 66const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
67__attribute__ ((weak)) 67__attribute__ ((weak))
68const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {100, 50, 20}; 68const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {100, 50, 20};
69__attribute__ ((weak))
70const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90};
69 71
70rgblight_config_t rgblight_config; 72rgblight_config_t rgblight_config;
71rgblight_config_t inmem_config; 73rgblight_config_t inmem_config;
@@ -219,6 +221,14 @@ void rgblight_step(void) {
219 } 221 }
220 rgblight_mode(mode); 222 rgblight_mode(mode);
221} 223}
224void rgblight_step_reverse(void) {
225 uint8_t mode = 0;
226 mode = rgblight_config.mode - 1;
227 if (mode < 1) {
228 mode = RGBLIGHT_MODES;
229 }
230 rgblight_mode(mode);
231}
222 232
223void rgblight_mode(uint8_t mode) { 233void rgblight_mode(uint8_t mode) {
224 if (!rgblight_config.enable) { 234 if (!rgblight_config.enable) {
@@ -237,7 +247,7 @@ void rgblight_mode(uint8_t mode) {
237 #ifdef RGBLIGHT_ANIMATIONS 247 #ifdef RGBLIGHT_ANIMATIONS
238 rgblight_timer_disable(); 248 rgblight_timer_disable();
239 #endif 249 #endif
240 } else if (rgblight_config.mode >= 2 && rgblight_config.mode <= 23) { 250 } else if (rgblight_config.mode >= 2 && rgblight_config.mode <= 24) {
241 // MODE 2-5, breathing 251 // MODE 2-5, breathing
242 // MODE 6-8, rainbow mood 252 // MODE 6-8, rainbow mood
243 // MODE 9-14, rainbow swirl 253 // MODE 9-14, rainbow swirl
@@ -247,6 +257,12 @@ void rgblight_mode(uint8_t mode) {
247 #ifdef RGBLIGHT_ANIMATIONS 257 #ifdef RGBLIGHT_ANIMATIONS
248 rgblight_timer_enable(); 258 rgblight_timer_enable();
249 #endif 259 #endif
260 } else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
261 // MODE 25-34, static gradient
262
263 #ifdef RGBLIGHT_ANIMATIONS
264 rgblight_timer_disable();
265 #endif
250 } 266 }
251 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val); 267 rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
252} 268}
@@ -350,6 +366,17 @@ void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
350 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) { 366 } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) {
351 // rainbow mood and rainbow swirl, ignore the change of hue 367 // rainbow mood and rainbow swirl, ignore the change of hue
352 hue = rgblight_config.hue; 368 hue = rgblight_config.hue;
369 } else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
370 // static gradient
371 uint16_t _hue;
372 int8_t direction = ((rgblight_config.mode - 25) % 2) ? -1 : 1;
373 uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[(rgblight_config.mode - 25) / 2]);
374 for (uint8_t i = 0; i < RGBLED_NUM; i++) {
375 _hue = (range / RGBLED_NUM * i * direction + hue + 360) % 360;
376 dprintf("rgblight rainbow set hsv: %u,%u,%d,%u\n", i, _hue, direction, range);
377 sethsv(_hue, sat, val, (LED_TYPE *)&led[i]);
378 }
379 rgblight_set();
353 } 380 }
354 } 381 }
355 rgblight_config.hue = hue; 382 rgblight_config.hue = hue;
@@ -450,7 +477,7 @@ void rgblight_task(void) {
450 } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) { 477 } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
451 // mode = 21 to 23, knight mode 478 // mode = 21 to 23, knight mode
452 rgblight_effect_knight(rgblight_config.mode - 21); 479 rgblight_effect_knight(rgblight_config.mode - 21);
453 } else { 480 } else if (rgblight_config.mode == 24) {
454 // mode = 24, christmas mode 481 // mode = 24, christmas mode
455 rgblight_effect_christmas(); 482 rgblight_effect_christmas();
456 } 483 }
@@ -604,13 +631,13 @@ void rgblight_effect_christmas(void) {
604 static uint16_t last_timer = 0; 631 static uint16_t last_timer = 0;
605 uint16_t hue; 632 uint16_t hue;
606 uint8_t i; 633 uint8_t i;
607 if (timer_elapsed(last_timer) < 1000) { 634 if (timer_elapsed(last_timer) < RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL) {
608 return; 635 return;
609 } 636 }
610 last_timer = timer_read(); 637 last_timer = timer_read();
611 current_offset = (current_offset + 1) % 2; 638 current_offset = (current_offset + 1) % 2;
612 for (i = 0; i < RGBLED_NUM; i++) { 639 for (i = 0; i < RGBLED_NUM; i++) {
613 hue = 0 + ((RGBLED_NUM * (i + current_offset)) % 2) * 80; 640 hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + current_offset) % 2) * 120;
614 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]); 641 sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
615 } 642 }
616 rgblight_set(); 643 rgblight_set();
diff --git a/quantum/rgblight.h b/quantum/rgblight.h
index 726b8de72..2b3e791bf 100644
--- a/quantum/rgblight.h
+++ b/quantum/rgblight.h
@@ -2,7 +2,7 @@
2#define RGBLIGHT_H 2#define RGBLIGHT_H
3 3
4#ifdef RGBLIGHT_ANIMATIONS 4#ifdef RGBLIGHT_ANIMATIONS
5 #define RGBLIGHT_MODES 24 5 #define RGBLIGHT_MODES 34
6#else 6#else
7 #define RGBLIGHT_MODES 1 7 #define RGBLIGHT_MODES 1
8#endif 8#endif
@@ -22,6 +22,14 @@
22#define RGBLIGHT_EFFECT_DUALKNIGHT_LENGTH 4 22#define RGBLIGHT_EFFECT_DUALKNIGHT_LENGTH 4
23#endif 23#endif
24 24
25#ifndef RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL
26#define RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL 1000
27#endif
28
29#ifndef RGBLIGHT_EFFECT_CHRISTMAS_STEP
30#define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2
31#endif
32
25#ifndef RGBLIGHT_HUE_STEP 33#ifndef RGBLIGHT_HUE_STEP
26#define RGBLIGHT_HUE_STEP 10 34#define RGBLIGHT_HUE_STEP 10
27#endif 35#endif
@@ -65,6 +73,7 @@ void rgblight_decrease(void);
65void rgblight_toggle(void); 73void rgblight_toggle(void);
66void rgblight_enable(void); 74void rgblight_enable(void);
67void rgblight_step(void); 75void rgblight_step(void);
76void rgblight_step_reverse(void);
68void rgblight_mode(uint8_t mode); 77void rgblight_mode(uint8_t mode);
69void rgblight_set(void); 78void rgblight_set(void);
70void rgblight_update_dword(uint32_t dword); 79void rgblight_update_dword(uint32_t dword);
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
diff --git a/quantum/template/rules.mk b/quantum/template/rules.mk
index 55898147d..bad3387bf 100644
--- a/quantum/template/rules.mk
+++ b/quantum/template/rules.mk
@@ -65,3 +65,4 @@ MIDI_ENABLE ?= no # MIDI controls
65UNICODE_ENABLE ?= no # Unicode 65UNICODE_ENABLE ?= no # Unicode
66BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID 66BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
67AUDIO_ENABLE ?= no # Audio output on port C6 67AUDIO_ENABLE ?= no # Audio output on port C6
68FAUXCLICKY_ENABLE ?= no # Use buzzer to emulate clicky switches