aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/process_keycode')
-rw-r--r--quantum/process_keycode/process_audio.c62
-rw-r--r--quantum/process_keycode/process_audio.h11
-rw-r--r--quantum/process_keycode/process_chording.c18
-rw-r--r--quantum/process_keycode/process_chording.h18
-rw-r--r--quantum/process_keycode/process_combo.c150
-rw-r--r--quantum/process_keycode/process_combo.h59
-rw-r--r--quantum/process_keycode/process_leader.c18
-rw-r--r--quantum/process_keycode/process_leader.h18
-rw-r--r--quantum/process_keycode/process_midi.c307
-rw-r--r--quantum/process_keycode/process_midi.h243
-rw-r--r--quantum/process_keycode/process_music.c133
-rw-r--r--quantum/process_keycode/process_music.h24
-rw-r--r--quantum/process_keycode/process_printer.c18
-rw-r--r--quantum/process_keycode/process_printer.h18
-rw-r--r--quantum/process_keycode/process_printer_bb.c18
-rw-r--r--quantum/process_keycode/process_tap_dance.c22
-rw-r--r--quantum/process_keycode/process_tap_dance.h16
-rw-r--r--quantum/process_keycode/process_ucis.c149
-rw-r--r--quantum/process_keycode/process_ucis.h51
-rw-r--r--quantum/process_keycode/process_unicode.c291
-rw-r--r--quantum/process_keycode/process_unicode.h175
-rw-r--r--quantum/process_keycode/process_unicode_common.c101
-rw-r--r--quantum/process_keycode/process_unicode_common.h148
-rw-r--r--quantum/process_keycode/process_unicodemap.c72
-rw-r--r--quantum/process_keycode/process_unicodemap.h25
25 files changed, 1405 insertions, 760 deletions
diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c
new file mode 100644
index 000000000..0b6380ed3
--- /dev/null
+++ b/quantum/process_keycode/process_audio.c
@@ -0,0 +1,62 @@
1#include "audio.h"
2#include "process_audio.h"
3
4static float compute_freq_for_midi_note(uint8_t note)
5{
6 // https://en.wikipedia.org/wiki/MIDI_tuning_standard
7 return pow(2.0, (note - 69) / 12.0) * 440.0f;
8}
9
10bool process_audio(uint16_t keycode, keyrecord_t *record) {
11
12 if (keycode == AU_ON && record->event.pressed) {
13 audio_on();
14 return false;
15 }
16
17 if (keycode == AU_OFF && record->event.pressed) {
18 audio_off();
19 return false;
20 }
21
22 if (keycode == AU_TOG && record->event.pressed) {
23 if (is_audio_on())
24 {
25 audio_off();
26 }
27 else
28 {
29 audio_on();
30 }
31 return false;
32 }
33
34 if (keycode == MUV_IN && record->event.pressed) {
35 voice_iterate();
36 music_scale_user();
37 return false;
38 }
39
40 if (keycode == MUV_DE && record->event.pressed) {
41 voice_deiterate();
42 music_scale_user();
43 return false;
44 }
45
46 return true;
47}
48
49void process_audio_noteon(uint8_t note) {
50 play_note(compute_freq_for_midi_note(note), 0xF);
51}
52
53void process_audio_noteoff(uint8_t note) {
54 stop_note(compute_freq_for_midi_note(note));
55}
56
57void process_audio_all_notes_off(void) {
58 stop_all_notes();
59}
60
61__attribute__ ((weak))
62void audio_on_user() {} \ No newline at end of file
diff --git a/quantum/process_keycode/process_audio.h b/quantum/process_keycode/process_audio.h
new file mode 100644
index 000000000..7ac15b733
--- /dev/null
+++ b/quantum/process_keycode/process_audio.h
@@ -0,0 +1,11 @@
1#ifndef PROCESS_AUDIO_H
2#define PROCESS_AUDIO_H
3
4bool process_audio(uint16_t keycode, keyrecord_t *record);
5void process_audio_noteon(uint8_t note);
6void process_audio_noteoff(uint8_t note);
7void process_audio_all_notes_off(void);
8
9void audio_on_user(void);
10
11#endif \ No newline at end of file
diff --git a/quantum/process_keycode/process_chording.c b/quantum/process_keycode/process_chording.c
index d7814629f..6c6ebe300 100644
--- a/quantum/process_keycode/process_chording.c
+++ b/quantum/process_keycode/process_chording.c
@@ -1,3 +1,19 @@
1/* Copyright 2016 Jack Humbert
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#include "process_chording.h" 17#include "process_chording.h"
2 18
3bool keys_chord(uint8_t keys[]) { 19bool keys_chord(uint8_t keys[]) {
@@ -57,4 +73,4 @@ bool process_chording(uint16_t keycode, keyrecord_t *record) {
57 } 73 }
58 } 74 }
59 return true; 75 return true;
60} \ No newline at end of file 76}
diff --git a/quantum/process_keycode/process_chording.h b/quantum/process_keycode/process_chording.h
index 49c97db3b..8c0f4862a 100644
--- a/quantum/process_keycode/process_chording.h
+++ b/quantum/process_keycode/process_chording.h
@@ -1,3 +1,19 @@
1/* Copyright 2016 Jack Humbert
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 PROCESS_CHORDING_H 17#ifndef PROCESS_CHORDING_H
2#define PROCESS_CHORDING_H 18#define PROCESS_CHORDING_H
3 19
@@ -13,4 +29,4 @@ uint8_t chord_key_down = 0;
13 29
14bool process_chording(uint16_t keycode, keyrecord_t *record); 30bool process_chording(uint16_t keycode, keyrecord_t *record);
15 31
16#endif \ No newline at end of file 32#endif
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c
new file mode 100644
index 000000000..58d45add2
--- /dev/null
+++ b/quantum/process_keycode/process_combo.c
@@ -0,0 +1,150 @@
1/* Copyright 2016 Jack Humbert
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
17#include "process_combo.h"
18#include "print.h"
19
20
21#define COMBO_TIMER_ELAPSED -1
22
23
24__attribute__ ((weak))
25combo_t key_combos[] = {
26
27};
28
29__attribute__ ((weak))
30void process_combo_event(uint8_t combo_index, bool pressed) {
31
32}
33
34static uint8_t current_combo_index = 0;
35
36static inline void send_combo(uint16_t action, bool pressed)
37{
38 if (action) {
39 if (pressed) {
40 register_code16(action);
41 } else {
42 unregister_code16(action);
43 }
44 } else {
45 process_combo_event(current_combo_index, pressed);
46 }
47}
48
49#define ALL_COMBO_KEYS_ARE_DOWN (((1<<count)-1) == combo->state)
50#define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state)
51#define KEY_STATE_DOWN(key) do{ combo->state |= (1<<key); } while(0)
52#define KEY_STATE_UP(key) do{ combo->state &= ~(1<<key); } while(0)
53static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record)
54{
55 uint8_t count = 0;
56 uint8_t index = -1;
57 /* Find index of keycode and number of combo keys */
58 for (const uint16_t *keys = combo->keys; ;++count) {
59 uint16_t key = pgm_read_word(&keys[count]);
60 if (keycode == key) index = count;
61 if (COMBO_END == key) break;
62 }
63
64 /* Return if not a combo key */
65 if (-1 == (int8_t)index) return false;
66
67 /* The combos timer is used to signal whether the combo is active */
68 bool is_combo_active = COMBO_TIMER_ELAPSED == combo->timer ? false : true;
69
70 if (record->event.pressed) {
71 KEY_STATE_DOWN(index);
72
73 if (is_combo_active) {
74 if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */
75 send_combo(combo->keycode, true);
76 combo->timer = COMBO_TIMER_ELAPSED;
77 } else { /* Combo key was pressed */
78 combo->timer = timer_read();
79#ifdef COMBO_ALLOW_ACTION_KEYS
80 combo->prev_record = *record;
81#else
82 combo->prev_key = keycode;
83#endif
84 }
85 }
86 } else {
87 if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was released */
88 send_combo(combo->keycode, false);
89 }
90
91 if (is_combo_active) { /* Combo key was tapped */
92#ifdef COMBO_ALLOW_ACTION_KEYS
93 record->event.pressed = true;
94 process_action(record, store_or_get_action(record->event.pressed, record->event.key));
95 record->event.pressed = false;
96 process_action(record, store_or_get_action(record->event.pressed, record->event.key));
97#else
98 register_code16(keycode);
99 send_keyboard_report();
100 unregister_code16(keycode);
101#endif
102 combo->timer = 0;
103 }
104
105 KEY_STATE_UP(index);
106 }
107
108 if (NO_COMBO_KEYS_ARE_DOWN) {
109 combo->timer = 0;
110 }
111
112 return is_combo_active;
113}
114
115bool process_combo(uint16_t keycode, keyrecord_t *record)
116{
117 bool is_combo_key = false;
118
119 for (current_combo_index = 0; current_combo_index < COMBO_COUNT; ++current_combo_index) {
120 combo_t *combo = &key_combos[current_combo_index];
121 is_combo_key |= process_single_combo(combo, keycode, record);
122 }
123
124 return !is_combo_key;
125}
126
127void matrix_scan_combo(void)
128{
129 for (int i = 0; i < COMBO_COUNT; ++i) {
130 combo_t *combo = &key_combos[i];
131 if (combo->timer &&
132 combo->timer != COMBO_TIMER_ELAPSED &&
133 timer_elapsed(combo->timer) > COMBO_TERM) {
134
135 /* This disables the combo, meaning key events for this
136 * combo will be handled by the next processors in the chain
137 */
138 combo->timer = COMBO_TIMER_ELAPSED;
139
140#ifdef COMBO_ALLOW_ACTION_KEYS
141 process_action(&combo->prev_record,
142 store_or_get_action(combo->prev_record.event.pressed,
143 combo->prev_record.event.key));
144#else
145 unregister_code16(combo->prev_key);
146 register_code16(combo->prev_key);
147#endif
148 }
149 }
150}
diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h
new file mode 100644
index 000000000..a5dbd788a
--- /dev/null
+++ b/quantum/process_keycode/process_combo.h
@@ -0,0 +1,59 @@
1/* Copyright 2016 Jack Humbert
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
17#ifndef PROCESS_COMBO_H
18#define PROCESS_COMBO_H
19
20#include <stdint.h>
21#include "progmem.h"
22#include "quantum.h"
23
24typedef struct
25{
26 const uint16_t *keys;
27 uint16_t keycode;
28#ifdef EXTRA_EXTRA_LONG_COMBOS
29 uint32_t state;
30#elif EXTRA_LONG_COMBOS
31 uint16_t state;
32#else
33 uint8_t state;
34#endif
35 uint16_t timer;
36#ifdef COMBO_ALLOW_ACTION_KEYS
37 keyrecord_t prev_record;
38#else
39 uint16_t prev_key;
40#endif
41} combo_t;
42
43
44#define COMBO(ck, ca) {.keys = &(ck)[0], .keycode = (ca)}
45#define COMBO_ACTION(ck) {.keys = &(ck)[0]}
46
47#define COMBO_END 0
48#ifndef COMBO_COUNT
49#define COMBO_COUNT 0
50#endif
51#ifndef COMBO_TERM
52#define COMBO_TERM TAPPING_TERM
53#endif
54
55bool process_combo(uint16_t keycode, keyrecord_t *record);
56void matrix_scan_combo(void);
57void process_combo_event(uint8_t combo_index, bool pressed);
58
59#endif
diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c
index e53d221e7..473906d65 100644
--- a/quantum/process_keycode/process_leader.c
+++ b/quantum/process_keycode/process_leader.c
@@ -1,3 +1,19 @@
1/* Copyright 2016 Jack Humbert
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#include "process_leader.h" 17#include "process_leader.h"
2 18
3__attribute__ ((weak)) 19__attribute__ ((weak))
@@ -35,4 +51,4 @@ bool process_leader(uint16_t keycode, keyrecord_t *record) {
35 } 51 }
36 } 52 }
37 return true; 53 return true;
38} \ No newline at end of file 54}
diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h
index c83db8abb..da7a3d2ef 100644
--- a/quantum/process_keycode/process_leader.h
+++ b/quantum/process_keycode/process_leader.h
@@ -1,3 +1,19 @@
1/* Copyright 2016 Jack Humbert
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 PROCESS_LEADER_H 17#ifndef PROCESS_LEADER_H
2#define PROCESS_LEADER_H 18#define PROCESS_LEADER_H
3 19
@@ -20,4 +36,4 @@ void leader_end(void);
20#define LEADER_EXTERNS() extern bool leading; extern uint16_t leader_time; extern uint16_t leader_sequence[5]; extern uint8_t leader_sequence_size 36#define LEADER_EXTERNS() extern bool leading; extern uint16_t leader_time; extern uint16_t leader_sequence[5]; extern uint8_t leader_sequence_size
21#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT) 37#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT)
22 38
23#endif \ No newline at end of file 39#endif
diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c
index 577dad43a..9184feaae 100644
--- a/quantum/process_keycode/process_midi.c
+++ b/quantum/process_keycode/process_midi.c
@@ -1,68 +1,253 @@
1/* Copyright 2016 Jack Humbert
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 */
1#include "process_midi.h" 16#include "process_midi.h"
2 17
3bool midi_activated = false; 18#ifdef MIDI_ENABLE
4uint8_t midi_starting_note = 0x0C; 19#include "midi.h"
5int midi_offset = 7; 20
6 21#ifdef MIDI_BASIC
7bool process_midi(uint16_t keycode, keyrecord_t *record) { 22
8 if (keycode == MI_ON && record->event.pressed) { 23void process_midi_basic_noteon(uint8_t note)
9 midi_activated = true; 24{
10#ifdef AUDIO_ENABLE 25 midi_send_noteon(&midi_device, 0, note, 128);
11 music_scale_user(); 26}
12#endif 27
13 return false; 28void process_midi_basic_noteoff(uint8_t note)
14 } 29{
30 midi_send_noteoff(&midi_device, 0, note, 0);
31}
32
33void process_midi_all_notes_off(void)
34{
35 midi_send_cc(&midi_device, 0, 0x7B, 0);
36}
37
38#endif // MIDI_BASIC
39
40#ifdef MIDI_ADVANCED
41
42#include "timer.h"
43
44static uint8_t tone_status[MIDI_TONE_COUNT];
45
46static uint8_t midi_modulation;
47static int8_t midi_modulation_step;
48static uint16_t midi_modulation_timer;
49
50inline uint8_t compute_velocity(uint8_t setting)
51{
52 return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1));
53}
15 54
16 if (keycode == MI_OFF && record->event.pressed) { 55void midi_init(void)
17 midi_activated = false; 56{
18 midi_send_cc(&midi_device, 0, 0x7B, 0); 57 midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN;
19 return false; 58 midi_config.transpose = 0;
59 midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN);
60 midi_config.channel = 0;
61 midi_config.modulation_interval = 8;
62
63 for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++)
64 {
65 tone_status[i] = MIDI_INVALID_NOTE;
20 } 66 }
21 67
22 if (midi_activated) { 68 midi_modulation = 0;
23 if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) { 69 midi_modulation_step = 0;
24 if (record->event.pressed) { 70 midi_modulation_timer = 0;
25 midi_starting_note++; // Change key 71}
26 midi_send_cc(&midi_device, 0, 0x7B, 0); 72
27 } 73void midi_task(void)
28 return false; 74{
29 } 75 if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval)
30 if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) { 76 return;
31 if (record->event.pressed) { 77 midi_modulation_timer = timer_read();
32 midi_starting_note--; // Change key 78
33 midi_send_cc(&midi_device, 0, 0x7B, 0); 79 if (midi_modulation_step != 0)
34 } 80 {
35 return false; 81 dprintf("midi modulation %d\n", midi_modulation);
36 } 82 midi_send_cc(&midi_device, midi_config.channel, 0x1, midi_modulation);
37 if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { 83
38 midi_offset++; // Change scale 84 if (midi_modulation_step < 0 && midi_modulation < -midi_modulation_step) {
39 midi_send_cc(&midi_device, 0, 0x7B, 0); 85 midi_modulation = 0;
40 return false; 86 midi_modulation_step = 0;
41 } 87 return;
42 if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { 88 }
43 midi_offset--; // Change scale 89
44 midi_send_cc(&midi_device, 0, 0x7B, 0); 90 midi_modulation += midi_modulation_step;
45 return false; 91
46 } 92 if (midi_modulation > 127)
47 // basic 93 midi_modulation = 127;
48 // uint8_t note = (midi_starting_note + SCALE[record->event.key.col + midi_offset])+12*(MATRIX_ROWS - record->event.key.row);
49 // advanced
50 // uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+12*(MATRIX_ROWS - record->event.key.row);
51 // guitar
52 uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+5*(MATRIX_ROWS - record->event.key.row);
53 // violin
54 // uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+7*(MATRIX_ROWS - record->event.key.row);
55
56 if (record->event.pressed) {
57 // midi_send_noteon(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127);
58 midi_send_noteon(&midi_device, 0, note, 127);
59 } else {
60 // midi_send_noteoff(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127);
61 midi_send_noteoff(&midi_device, 0, note, 127);
62 }
63
64 if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
65 return false;
66 } 94 }
67 return true;
68} 95}
96
97uint8_t midi_compute_note(uint16_t keycode)
98{
99 return 12 * midi_config.octave + (keycode - MIDI_TONE_MIN) + midi_config.transpose;
100}
101
102bool process_midi(uint16_t keycode, keyrecord_t *record)
103{
104 switch (keycode) {
105 case MIDI_TONE_MIN ... MIDI_TONE_MAX:
106 {
107 uint8_t channel = midi_config.channel;
108 uint8_t tone = keycode - MIDI_TONE_MIN;
109 uint8_t velocity = compute_velocity(midi_config.velocity);
110 if (record->event.pressed) {
111 uint8_t note = midi_compute_note(keycode);
112 midi_send_noteon(&midi_device, channel, note, velocity);
113 dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
114 tone_status[tone] = note;
115 }
116 else {
117 uint8_t note = tone_status[tone];
118 if (note != MIDI_INVALID_NOTE)
119 {
120 midi_send_noteoff(&midi_device, channel, note, velocity);
121 dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity);
122 }
123 tone_status[tone] = MIDI_INVALID_NOTE;
124 }
125 return false;
126 }
127 case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX:
128 if (record->event.pressed) {
129 midi_config.octave = keycode - MIDI_OCTAVE_MIN;
130 dprintf("midi octave %d\n", midi_config.octave);
131 }
132 return false;
133 case MI_OCTD:
134 if (record->event.pressed && midi_config.octave > 0) {
135 midi_config.octave--;
136 dprintf("midi octave %d\n", midi_config.octave);
137 }
138 return false;
139 case MI_OCTU:
140 if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) {
141 midi_config.octave++;
142 dprintf("midi octave %d\n", midi_config.octave);
143 }
144 return false;
145 case MIDI_TRANSPOSE_MIN ... MIDI_TRANSPOSE_MAX:
146 if (record->event.pressed) {
147 midi_config.transpose = keycode - MI_TRNS_0;
148 dprintf("midi transpose %d\n", midi_config.transpose);
149 }
150 return false;
151 case MI_TRNSD:
152 if (record->event.pressed && midi_config.transpose > (MIDI_TRANSPOSE_MIN - MI_TRNS_0)) {
153 midi_config.transpose--;
154 dprintf("midi transpose %d\n", midi_config.transpose);
155 }
156 return false;
157 case MI_TRNSU:
158 if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - MI_TRNS_0)) {
159 const bool positive = midi_config.transpose > 0;
160 midi_config.transpose++;
161 if (positive && midi_config.transpose < 0)
162 midi_config.transpose--;
163 dprintf("midi transpose %d\n", midi_config.transpose);
164 }
165 return false;
166 case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX:
167 if (record->event.pressed) {
168 midi_config.velocity = keycode - MIDI_VELOCITY_MIN;
169 dprintf("midi velocity %d\n", midi_config.velocity);
170 }
171 return false;
172 case MI_VELD:
173 if (record->event.pressed && midi_config.velocity > 0) {
174 midi_config.velocity--;
175 dprintf("midi velocity %d\n", midi_config.velocity);
176 }
177 return false;
178 case MI_VELU:
179 if (record->event.pressed) {
180 midi_config.velocity++;
181 dprintf("midi velocity %d\n", midi_config.velocity);
182 }
183 return false;
184 case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX:
185 if (record->event.pressed) {
186 midi_config.channel = keycode - MIDI_CHANNEL_MIN;
187 dprintf("midi channel %d\n", midi_config.channel);
188 }
189 return false;
190 case MI_CHD:
191 if (record->event.pressed) {
192 midi_config.channel--;
193 dprintf("midi channel %d\n", midi_config.channel);
194 }
195 return false;
196 case MI_CHU:
197 if (record->event.pressed) {
198 midi_config.channel++;
199 dprintf("midi channel %d\n", midi_config.channel);
200 }
201 return false;
202 case MI_ALLOFF:
203 if (record->event.pressed) {
204 midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0);
205 dprintf("midi all notes off\n");
206 }
207 return false;
208 case MI_SUS:
209 midi_send_cc(&midi_device, midi_config.channel, 0x40, record->event.pressed ? 127 : 0);
210 dprintf("midi sustain %d\n", record->event.pressed);
211 return false;
212 case MI_PORT:
213 midi_send_cc(&midi_device, midi_config.channel, 0x41, record->event.pressed ? 127 : 0);
214 dprintf("midi portamento %d\n", record->event.pressed);
215 return false;
216 case MI_SOST:
217 midi_send_cc(&midi_device, midi_config.channel, 0x42, record->event.pressed ? 127 : 0);
218 dprintf("midi sostenuto %d\n", record->event.pressed);
219 return false;
220 case MI_SOFT:
221 midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
222 dprintf("midi soft %d\n", record->event.pressed);
223 return false;
224 case MI_LEG:
225 midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
226 dprintf("midi legato %d\n", record->event.pressed);
227 return false;
228 case MI_MOD:
229 midi_modulation_step = record->event.pressed ? 1 : -1;
230 return false;
231 case MI_MODSD:
232 if (record->event.pressed) {
233 midi_config.modulation_interval++;
234 // prevent overflow
235 if (midi_config.modulation_interval == 0)
236 midi_config.modulation_interval--;
237 dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
238 }
239 return false;
240 case MI_MODSU:
241 if (record->event.pressed && midi_config.modulation_interval > 0) {
242 midi_config.modulation_interval--;
243 dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
244 }
245 return false;
246 };
247
248 return true;
249}
250
251#endif // MIDI_ADVANCED
252
253#endif // MIDI_ENABLE
diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h
index acd4fc1b1..ccac8981a 100644
--- a/quantum/process_keycode/process_midi.h
+++ b/quantum/process_keycode/process_midi.h
@@ -1,207 +1,56 @@
1/* Copyright 2016 Jack Humbert
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 PROCESS_MIDI_H 17#ifndef PROCESS_MIDI_H
2#define PROCESS_MIDI_H 18#define PROCESS_MIDI_H
3 19
4#include "quantum.h" 20#include "quantum.h"
5 21
6bool process_midi(uint16_t keycode, keyrecord_t *record); 22#ifdef MIDI_ENABLE
23
24#ifdef MIDI_BASIC
25void process_midi_basic_noteon(uint8_t note);
26void process_midi_basic_noteoff(uint8_t note);
27void process_midi_all_notes_off(void);
28#endif
7 29
8#define MIDI(n) ((n) | 0x6000) 30#ifdef MIDI_ADVANCED
9#define MIDI12 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000 31typedef union {
32 uint32_t raw;
33 struct {
34 uint8_t octave :4;
35 int8_t transpose :4;
36 uint8_t velocity :4;
37 uint8_t channel :4;
38 uint8_t modulation_interval :4;
39 };
40} midi_config_t;
41
42midi_config_t midi_config;
43
44void midi_init(void);
45void midi_task(void);
46bool process_midi(uint16_t keycode, keyrecord_t *record);
10 47
11#define CHNL(note, channel) (note + (channel << 8)) 48#define MIDI_INVALID_NOTE 0xFF
49#define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1)
12 50
13#define SCALE (int8_t []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \ 51uint8_t midi_compute_note(uint16_t keycode);
14 0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \ 52#endif // MIDI_ADVANCED
15 0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
16 0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
17 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
18 53
19#define N_CN1 (0x600C + (12 * -1) + 0 ) 54#endif // MIDI_ENABLE
20#define N_CN1S (0x600C + (12 * -1) + 1 )
21#define N_DN1F (0x600C + (12 * -1) + 1 )
22#define N_DN1 (0x600C + (12 * -1) + 2 )
23#define N_DN1S (0x600C + (12 * -1) + 3 )
24#define N_EN1F (0x600C + (12 * -1) + 3 )
25#define N_EN1 (0x600C + (12 * -1) + 4 )
26#define N_FN1 (0x600C + (12 * -1) + 5 )
27#define N_FN1S (0x600C + (12 * -1) + 6 )
28#define N_GN1F (0x600C + (12 * -1) + 6 )
29#define N_GN1 (0x600C + (12 * -1) + 7 )
30#define N_GN1S (0x600C + (12 * -1) + 8 )
31#define N_AN1F (0x600C + (12 * -1) + 8 )
32#define N_AN1 (0x600C + (12 * -1) + 9 )
33#define N_AN1S (0x600C + (12 * -1) + 10)
34#define N_BN1F (0x600C + (12 * -1) + 10)
35#define N_BN1 (0x600C + (12 * -1) + 11)
36#define N_C0 (0x600C + (12 * 0) + 0 )
37#define N_C0S (0x600C + (12 * 0) + 1 )
38#define N_D0F (0x600C + (12 * 0) + 1 )
39#define N_D0 (0x600C + (12 * 0) + 2 )
40#define N_D0S (0x600C + (12 * 0) + 3 )
41#define N_E0F (0x600C + (12 * 0) + 3 )
42#define N_E0 (0x600C + (12 * 0) + 4 )
43#define N_F0 (0x600C + (12 * 0) + 5 )
44#define N_F0S (0x600C + (12 * 0) + 6 )
45#define N_G0F (0x600C + (12 * 0) + 6 )
46#define N_G0 (0x600C + (12 * 0) + 7 )
47#define N_G0S (0x600C + (12 * 0) + 8 )
48#define N_A0F (0x600C + (12 * 0) + 8 )
49#define N_A0 (0x600C + (12 * 0) + 9 )
50#define N_A0S (0x600C + (12 * 0) + 10)
51#define N_B0F (0x600C + (12 * 0) + 10)
52#define N_B0 (0x600C + (12 * 0) + 11)
53#define N_C1 (0x600C + (12 * 1) + 0 )
54#define N_C1S (0x600C + (12 * 1) + 1 )
55#define N_D1F (0x600C + (12 * 1) + 1 )
56#define N_D1 (0x600C + (12 * 1) + 2 )
57#define N_D1S (0x600C + (12 * 1) + 3 )
58#define N_E1F (0x600C + (12 * 1) + 3 )
59#define N_E1 (0x600C + (12 * 1) + 4 )
60#define N_F1 (0x600C + (12 * 1) + 5 )
61#define N_F1S (0x600C + (12 * 1) + 6 )
62#define N_G1F (0x600C + (12 * 1) + 6 )
63#define N_G1 (0x600C + (12 * 1) + 7 )
64#define N_G1S (0x600C + (12 * 1) + 8 )
65#define N_A1F (0x600C + (12 * 1) + 8 )
66#define N_A1 (0x600C + (12 * 1) + 9 )
67#define N_A1S (0x600C + (12 * 1) + 10)
68#define N_B1F (0x600C + (12 * 1) + 10)
69#define N_B1 (0x600C + (12 * 1) + 11)
70#define N_C2 (0x600C + (12 * 2) + 0 )
71#define N_C2S (0x600C + (12 * 2) + 1 )
72#define N_D2F (0x600C + (12 * 2) + 1 )
73#define N_D2 (0x600C + (12 * 2) + 2 )
74#define N_D2S (0x600C + (12 * 2) + 3 )
75#define N_E2F (0x600C + (12 * 2) + 3 )
76#define N_E2 (0x600C + (12 * 2) + 4 )
77#define N_F2 (0x600C + (12 * 2) + 5 )
78#define N_F2S (0x600C + (12 * 2) + 6 )
79#define N_G2F (0x600C + (12 * 2) + 6 )
80#define N_G2 (0x600C + (12 * 2) + 7 )
81#define N_G2S (0x600C + (12 * 2) + 8 )
82#define N_A2F (0x600C + (12 * 2) + 8 )
83#define N_A2 (0x600C + (12 * 2) + 9 )
84#define N_A2S (0x600C + (12 * 2) + 10)
85#define N_B2F (0x600C + (12 * 2) + 10)
86#define N_B2 (0x600C + (12 * 2) + 11)
87#define N_C3 (0x600C + (12 * 3) + 0 )
88#define N_C3S (0x600C + (12 * 3) + 1 )
89#define N_D3F (0x600C + (12 * 3) + 1 )
90#define N_D3 (0x600C + (12 * 3) + 2 )
91#define N_D3S (0x600C + (12 * 3) + 3 )
92#define N_E3F (0x600C + (12 * 3) + 3 )
93#define N_E3 (0x600C + (12 * 3) + 4 )
94#define N_F3 (0x600C + (12 * 3) + 5 )
95#define N_F3S (0x600C + (12 * 3) + 6 )
96#define N_G3F (0x600C + (12 * 3) + 6 )
97#define N_G3 (0x600C + (12 * 3) + 7 )
98#define N_G3S (0x600C + (12 * 3) + 8 )
99#define N_A3F (0x600C + (12 * 3) + 8 )
100#define N_A3 (0x600C + (12 * 3) + 9 )
101#define N_A3S (0x600C + (12 * 3) + 10)
102#define N_B3F (0x600C + (12 * 3) + 10)
103#define N_B3 (0x600C + (12 * 3) + 11)
104#define N_C4 (0x600C + (12 * 4) + 0 )
105#define N_C4S (0x600C + (12 * 4) + 1 )
106#define N_D4F (0x600C + (12 * 4) + 1 )
107#define N_D4 (0x600C + (12 * 4) + 2 )
108#define N_D4S (0x600C + (12 * 4) + 3 )
109#define N_E4F (0x600C + (12 * 4) + 3 )
110#define N_E4 (0x600C + (12 * 4) + 4 )
111#define N_F4 (0x600C + (12 * 4) + 5 )
112#define N_F4S (0x600C + (12 * 4) + 6 )
113#define N_G4F (0x600C + (12 * 4) + 6 )
114#define N_G4 (0x600C + (12 * 4) + 7 )
115#define N_G4S (0x600C + (12 * 4) + 8 )
116#define N_A4F (0x600C + (12 * 4) + 8 )
117#define N_A4 (0x600C + (12 * 4) + 9 )
118#define N_A4S (0x600C + (12 * 4) + 10)
119#define N_B4F (0x600C + (12 * 4) + 10)
120#define N_B4 (0x600C + (12 * 4) + 11)
121#define N_C5 (0x600C + (12 * 5) + 0 )
122#define N_C5S (0x600C + (12 * 5) + 1 )
123#define N_D5F (0x600C + (12 * 5) + 1 )
124#define N_D5 (0x600C + (12 * 5) + 2 )
125#define N_D5S (0x600C + (12 * 5) + 3 )
126#define N_E5F (0x600C + (12 * 5) + 3 )
127#define N_E5 (0x600C + (12 * 5) + 4 )
128#define N_F5 (0x600C + (12 * 5) + 5 )
129#define N_F5S (0x600C + (12 * 5) + 6 )
130#define N_G5F (0x600C + (12 * 5) + 6 )
131#define N_G5 (0x600C + (12 * 5) + 7 )
132#define N_G5S (0x600C + (12 * 5) + 8 )
133#define N_A5F (0x600C + (12 * 5) + 8 )
134#define N_A5 (0x600C + (12 * 5) + 9 )
135#define N_A5S (0x600C + (12 * 5) + 10)
136#define N_B5F (0x600C + (12 * 5) + 10)
137#define N_B5 (0x600C + (12 * 5) + 11)
138#define N_C6 (0x600C + (12 * 6) + 0 )
139#define N_C6S (0x600C + (12 * 6) + 1 )
140#define N_D6F (0x600C + (12 * 6) + 1 )
141#define N_D6 (0x600C + (12 * 6) + 2 )
142#define N_D6S (0x600C + (12 * 6) + 3 )
143#define N_E6F (0x600C + (12 * 6) + 3 )
144#define N_E6 (0x600C + (12 * 6) + 4 )
145#define N_F6 (0x600C + (12 * 6) + 5 )
146#define N_F6S (0x600C + (12 * 6) + 6 )
147#define N_G6F (0x600C + (12 * 6) + 6 )
148#define N_G6 (0x600C + (12 * 6) + 7 )
149#define N_G6S (0x600C + (12 * 6) + 8 )
150#define N_A6F (0x600C + (12 * 6) + 8 )
151#define N_A6 (0x600C + (12 * 6) + 9 )
152#define N_A6S (0x600C + (12 * 6) + 10)
153#define N_B6F (0x600C + (12 * 6) + 10)
154#define N_B6 (0x600C + (12 * 6) + 11)
155#define N_C7 (0x600C + (12 * 7) + 0 )
156#define N_C7S (0x600C + (12 * 7) + 1 )
157#define N_D7F (0x600C + (12 * 7) + 1 )
158#define N_D7 (0x600C + (12 * 7) + 2 )
159#define N_D7S (0x600C + (12 * 7) + 3 )
160#define N_E7F (0x600C + (12 * 7) + 3 )
161#define N_E7 (0x600C + (12 * 7) + 4 )
162#define N_F7 (0x600C + (12 * 7) + 5 )
163#define N_F7S (0x600C + (12 * 7) + 6 )
164#define N_G7F (0x600C + (12 * 7) + 6 )
165#define N_G7 (0x600C + (12 * 7) + 7 )
166#define N_G7S (0x600C + (12 * 7) + 8 )
167#define N_A7F (0x600C + (12 * 7) + 8 )
168#define N_A7 (0x600C + (12 * 7) + 9 )
169#define N_A7S (0x600C + (12 * 7) + 10)
170#define N_B7F (0x600C + (12 * 7) + 10)
171#define N_B7 (0x600C + (12 * 7) + 11)
172#define N_C8 (0x600C + (12 * 8) + 0 )
173#define N_C8S (0x600C + (12 * 8) + 1 )
174#define N_D8F (0x600C + (12 * 8) + 1 )
175#define N_D8 (0x600C + (12 * 8) + 2 )
176#define N_D8S (0x600C + (12 * 8) + 3 )
177#define N_E8F (0x600C + (12 * 8) + 3 )
178#define N_E8 (0x600C + (12 * 8) + 4 )
179#define N_F8 (0x600C + (12 * 8) + 5 )
180#define N_F8S (0x600C + (12 * 8) + 6 )
181#define N_G8F (0x600C + (12 * 8) + 6 )
182#define N_G8 (0x600C + (12 * 8) + 7 )
183#define N_G8S (0x600C + (12 * 8) + 8 )
184#define N_A8F (0x600C + (12 * 8) + 8 )
185#define N_A8 (0x600C + (12 * 8) + 9 )
186#define N_A8S (0x600C + (12 * 8) + 10)
187#define N_B8F (0x600C + (12 * 8) + 10)
188#define N_B8 (0x600C + (12 * 8) + 11)
189#define N_C8 (0x600C + (12 * 8) + 0 )
190#define N_C8S (0x600C + (12 * 8) + 1 )
191#define N_D8F (0x600C + (12 * 8) + 1 )
192#define N_D8 (0x600C + (12 * 8) + 2 )
193#define N_D8S (0x600C + (12 * 8) + 3 )
194#define N_E8F (0x600C + (12 * 8) + 3 )
195#define N_E8 (0x600C + (12 * 8) + 4 )
196#define N_F8 (0x600C + (12 * 8) + 5 )
197#define N_F8S (0x600C + (12 * 8) + 6 )
198#define N_G8F (0x600C + (12 * 8) + 6 )
199#define N_G8 (0x600C + (12 * 8) + 7 )
200#define N_G8S (0x600C + (12 * 8) + 8 )
201#define N_A8F (0x600C + (12 * 8) + 8 )
202#define N_A8 (0x600C + (12 * 8) + 9 )
203#define N_A8S (0x600C + (12 * 8) + 10)
204#define N_B8F (0x600C + (12 * 8) + 10)
205#define N_B8 (0x600C + (12 * 8) + 11)
206 55
207#endif \ No newline at end of file 56#endif
diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c
index 1e2648bff..217dca280 100644
--- a/quantum/process_keycode/process_music.c
+++ b/quantum/process_keycode/process_music.c
@@ -1,5 +1,29 @@
1/* Copyright 2016 Jack Humbert
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 */
1#include "process_music.h" 16#include "process_music.h"
2 17
18#ifdef AUDIO_ENABLE
19#include "process_audio.h"
20#endif
21#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
22#include "process_midi.h"
23#endif
24
25#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
26
3bool music_activated = false; 27bool music_activated = false;
4uint8_t music_starting_note = 0x0C; 28uint8_t music_starting_note = 0x0C;
5int music_offset = 7; 29int music_offset = 7;
@@ -8,36 +32,41 @@ int music_offset = 7;
8static bool music_sequence_recording = false; 32static bool music_sequence_recording = false;
9static bool music_sequence_recorded = false; 33static bool music_sequence_recorded = false;
10static bool music_sequence_playing = false; 34static bool music_sequence_playing = false;
11static float music_sequence[16] = {0}; 35static uint8_t music_sequence[16] = {0};
12static uint8_t music_sequence_count = 0; 36static uint8_t music_sequence_count = 0;
13static uint8_t music_sequence_position = 0; 37static uint8_t music_sequence_position = 0;
14 38
15static uint16_t music_sequence_timer = 0; 39static uint16_t music_sequence_timer = 0;
16static uint16_t music_sequence_interval = 100; 40static uint16_t music_sequence_interval = 100;
17 41
18bool process_music(uint16_t keycode, keyrecord_t *record) { 42static void music_noteon(uint8_t note) {
43 #ifdef AUDIO_ENABLE
44 process_audio_noteon(note);
45 #endif
46 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
47 process_midi_basic_noteon(note);
48 #endif
49}
19 50
20 if (keycode == AU_ON && record->event.pressed) { 51static void music_noteoff(uint8_t note) {
21 audio_on(); 52 #ifdef AUDIO_ENABLE
22 return false; 53 process_audio_noteoff(note);
23 } 54 #endif
55 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
56 process_midi_basic_noteoff(note);
57 #endif
58}
24 59
25 if (keycode == AU_OFF && record->event.pressed) { 60void music_all_notes_off(void) {
26 audio_off(); 61 #ifdef AUDIO_ENABLE
27 return false; 62 process_audio_all_notes_off();
28 } 63 #endif
64 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
65 process_midi_all_notes_off();
66 #endif
67}
29 68
30 if (keycode == AU_TOG && record->event.pressed) { 69bool process_music(uint16_t keycode, keyrecord_t *record) {
31 if (is_audio_on())
32 {
33 audio_off();
34 }
35 else
36 {
37 audio_on();
38 }
39 return false;
40 }
41 70
42 if (keycode == MU_ON && record->event.pressed) { 71 if (keycode == MU_ON && record->event.pressed) {
43 music_on(); 72 music_on();
@@ -61,22 +90,10 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
61 return false; 90 return false;
62 } 91 }
63 92
64 if (keycode == MUV_IN && record->event.pressed) {
65 voice_iterate();
66 music_scale_user();
67 return false;
68 }
69
70 if (keycode == MUV_DE && record->event.pressed) {
71 voice_deiterate();
72 music_scale_user();
73 return false;
74 }
75
76 if (music_activated) { 93 if (music_activated) {
77 94
78 if (keycode == KC_LCTL && record->event.pressed) { // Start recording 95 if (keycode == KC_LCTL && record->event.pressed) { // Start recording
79 stop_all_notes(); 96 music_all_notes_off();
80 music_sequence_recording = true; 97 music_sequence_recording = true;
81 music_sequence_recorded = false; 98 music_sequence_recorded = false;
82 music_sequence_playing = false; 99 music_sequence_playing = false;
@@ -85,7 +102,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
85 } 102 }
86 103
87 if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing 104 if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing
88 stop_all_notes(); 105 music_all_notes_off();
89 if (music_sequence_recording) { // was recording 106 if (music_sequence_recording) { // was recording
90 music_sequence_recorded = true; 107 music_sequence_recorded = true;
91 } 108 }
@@ -95,7 +112,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
95 } 112 }
96 113
97 if (keycode == KC_LGUI && record->event.pressed && music_sequence_recorded) { // Start playing 114 if (keycode == KC_LGUI && record->event.pressed && music_sequence_recorded) { // Start playing
98 stop_all_notes(); 115 music_all_notes_off();
99 music_sequence_recording = false; 116 music_sequence_recording = false;
100 music_sequence_playing = true; 117 music_sequence_playing = true;
101 music_sequence_position = 0; 118 music_sequence_position = 0;
@@ -114,32 +131,34 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
114 music_sequence_interval+=10; 131 music_sequence_interval+=10;
115 return false; 132 return false;
116 } 133 }
134
117 #define MUSIC_MODE_GUITAR 135 #define MUSIC_MODE_GUITAR
118 136
119 #ifdef MUSIC_MODE_CHROMATIC 137 #ifdef MUSIC_MODE_CHROMATIC
120 float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(MATRIX_ROWS - record->event.key.row)); 138 uint8_t note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row);
121 #elif defined(MUSIC_MODE_GUITAR) 139 #elif defined(MUSIC_MODE_GUITAR)
122 float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(float)(MATRIX_ROWS - record->event.key.row + 7)*5.0/12); 140 uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row);
123 #elif defined(MUSIC_MODE_VIOLIN) 141 #elif defined(MUSIC_MODE_VIOLIN)
124 float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(float)(MATRIX_ROWS - record->event.key.row + 5)*7.0/12); 142 uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row);
125 #else 143 #else
126 float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + SCALE[record->event.key.col + music_offset])/12.0+(MATRIX_ROWS - record->event.key.row)); 144 uint8_t note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row);
127 #endif 145 #endif
128 146
129 if (record->event.pressed) { 147 if (record->event.pressed) {
130 play_note(freq, 0xF); 148 music_noteon(note);
131 if (music_sequence_recording) { 149 if (music_sequence_recording) {
132 music_sequence[music_sequence_count] = freq; 150 music_sequence[music_sequence_count] = note;
133 music_sequence_count++; 151 music_sequence_count++;
134 } 152 }
135 } else { 153 } else {
136 stop_note(freq); 154 music_noteoff(note);
137 } 155 }
138 156
139 if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through 157 if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
140 return false; 158 return false;
141 } 159 }
142 return true; 160
161 return true;
143} 162}
144 163
145bool is_music_on(void) { 164bool is_music_on(void) {
@@ -161,26 +180,26 @@ void music_on(void) {
161 180
162void music_off(void) { 181void music_off(void) {
163 music_activated = 0; 182 music_activated = 0;
164 stop_all_notes(); 183 music_all_notes_off();
165} 184}
166 185
167
168__attribute__ ((weak))
169void music_on_user() {}
170
171__attribute__ ((weak))
172void audio_on_user() {}
173
174__attribute__ ((weak))
175void music_scale_user() {}
176
177void matrix_scan_music(void) { 186void matrix_scan_music(void) {
178 if (music_sequence_playing) { 187 if (music_sequence_playing) {
179 if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) { 188 if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
180 music_sequence_timer = timer_read(); 189 music_sequence_timer = timer_read();
181 stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]); 190 uint8_t prev_note = music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)];
182 play_note(music_sequence[music_sequence_position], 0xF); 191 uint8_t next_note = music_sequence[music_sequence_position];
192 music_noteoff(prev_note);
193 music_noteon(next_note);
183 music_sequence_position = (music_sequence_position + 1) % music_sequence_count; 194 music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
184 } 195 }
185 } 196 }
186} 197}
198
199__attribute__ ((weak))
200void music_on_user() {}
201
202__attribute__ ((weak))
203void music_scale_user() {}
204
205#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) \ No newline at end of file
diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h
index 318b3e387..8dfbf041f 100644
--- a/quantum/process_keycode/process_music.h
+++ b/quantum/process_keycode/process_music.h
@@ -1,8 +1,26 @@
1/* Copyright 2016 Jack Humbert
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 PROCESS_MUSIC_H 17#ifndef PROCESS_MUSIC_H
2#define PROCESS_MUSIC_H 18#define PROCESS_MUSIC_H
3 19
4#include "quantum.h" 20#include "quantum.h"
5 21
22#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
23
6bool process_music(uint16_t keycode, keyrecord_t *record); 24bool process_music(uint16_t keycode, keyrecord_t *record);
7 25
8bool is_music_on(void); 26bool is_music_on(void);
@@ -10,9 +28,9 @@ void music_toggle(void);
10void music_on(void); 28void music_on(void);
11void music_off(void); 29void music_off(void);
12 30
13void audio_on_user(void);
14void music_on_user(void); 31void music_on_user(void);
15void music_scale_user(void); 32void music_scale_user(void);
33void music_all_notes_off(void);
16 34
17void matrix_scan_music(void); 35void matrix_scan_music(void);
18 36
@@ -24,4 +42,6 @@ void matrix_scan_music(void);
24 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), } 42 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
25#endif 43#endif
26 44
27#endif \ No newline at end of file 45#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
46
47#endif
diff --git a/quantum/process_keycode/process_printer.c b/quantum/process_keycode/process_printer.c
index 2e11dd366..807f7a0b9 100644
--- a/quantum/process_keycode/process_printer.c
+++ b/quantum/process_keycode/process_printer.c
@@ -1,3 +1,19 @@
1/* Copyright 2016 Jack Humbert
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#include "process_printer.h" 17#include "process_printer.h"
2#include "action_util.h" 18#include "action_util.h"
3 19
@@ -251,4 +267,4 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
251 } 267 }
252 return true; 268 return true;
253 269
254} \ No newline at end of file 270}
diff --git a/quantum/process_keycode/process_printer.h b/quantum/process_keycode/process_printer.h
index fdd36d75a..aa494ac8a 100644
--- a/quantum/process_keycode/process_printer.h
+++ b/quantum/process_keycode/process_printer.h
@@ -1,3 +1,19 @@
1/* Copyright 2016 Jack Humbert
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 PROCESS_PRINTER_H 17#ifndef PROCESS_PRINTER_H
2#define PROCESS_PRINTER_H 18#define PROCESS_PRINTER_H
3 19
@@ -5,4 +21,4 @@
5 21
6#include "protocol/serial.h" 22#include "protocol/serial.h"
7 23
8#endif \ No newline at end of file 24#endif
diff --git a/quantum/process_keycode/process_printer_bb.c b/quantum/process_keycode/process_printer_bb.c
index 1924d0377..55d3b552b 100644
--- a/quantum/process_keycode/process_printer_bb.c
+++ b/quantum/process_keycode/process_printer_bb.c
@@ -1,3 +1,19 @@
1/* Copyright 2016 Jack Humbert
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#include "process_printer.h" 17#include "process_printer.h"
2#include "action_util.h" 18#include "action_util.h"
3 19
@@ -257,4 +273,4 @@ bool process_printer(uint16_t keycode, keyrecord_t *record) {
257 } 273 }
258 return true; 274 return true;
259 275
260} \ No newline at end of file 276}
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index 6ae362c4c..68c8425bb 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -1,3 +1,18 @@
1/* Copyright 2016 Jack Humbert
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 */
1#include "quantum.h" 16#include "quantum.h"
2#include "action_tapping.h" 17#include "action_tapping.h"
3 18
@@ -43,12 +58,16 @@ static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_acti
43 if (action->state.finished) 58 if (action->state.finished)
44 return; 59 return;
45 action->state.finished = true; 60 action->state.finished = true;
61 add_mods(action->state.oneshot_mods);
62 send_keyboard_report();
46 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished); 63 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
47} 64}
48 65
49static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action) 66static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
50{ 67{
51 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset); 68 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
69 del_mods(action->state.oneshot_mods);
70 send_keyboard_report();
52} 71}
53 72
54bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { 73bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
@@ -70,6 +89,7 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
70 action->state.keycode = keycode; 89 action->state.keycode = keycode;
71 action->state.count++; 90 action->state.count++;
72 action->state.timer = timer_read(); 91 action->state.timer = timer_read();
92 action->state.oneshot_mods = get_oneshot_mods();
73 process_tap_dance_action_on_each_tap (action); 93 process_tap_dance_action_on_each_tap (action);
74 94
75 if (last_td && last_td != keycode) { 95 if (last_td && last_td != keycode) {
@@ -109,7 +129,7 @@ void matrix_scan_tap_dance () {
109 if (highest_td == -1) 129 if (highest_td == -1)
110 return; 130 return;
111 131
112 for (int i = 0; i <= highest_td; i++) { 132for (int i = 0; i <= highest_td; i++) {
113 qk_tap_dance_action_t *action = &tap_dance_actions[i]; 133 qk_tap_dance_action_t *action = &tap_dance_actions[i];
114 134
115 if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) { 135 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..330809f83 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -1,3 +1,18 @@
1/* Copyright 2016 Jack Humbert
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 */
1#ifndef PROCESS_TAP_DANCE_H 16#ifndef PROCESS_TAP_DANCE_H
2#define PROCESS_TAP_DANCE_H 17#define PROCESS_TAP_DANCE_H
3 18
@@ -9,6 +24,7 @@
9typedef struct 24typedef struct
10{ 25{
11 uint8_t count; 26 uint8_t count;
27 uint8_t oneshot_mods;
12 uint16_t keycode; 28 uint16_t keycode;
13 uint16_t timer; 29 uint16_t timer;
14 bool interrupted; 30 bool interrupted;
diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c
new file mode 100644
index 000000000..86c0937f5
--- /dev/null
+++ b/quantum/process_keycode/process_ucis.c
@@ -0,0 +1,149 @@
1/* Copyright 2017 Jack Humbert
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
17#include "process_ucis.h"
18
19qk_ucis_state_t qk_ucis_state;
20
21void qk_ucis_start(void) {
22 qk_ucis_state.count = 0;
23 qk_ucis_state.in_progress = true;
24
25 qk_ucis_start_user();
26}
27
28__attribute__((weak))
29void qk_ucis_start_user(void) {
30 unicode_input_start();
31 register_hex(0x2328);
32 unicode_input_finish();
33}
34
35static bool is_uni_seq(char *seq) {
36 uint8_t i;
37
38 for (i = 0; seq[i]; i++) {
39 uint16_t code;
40 if (('1' <= seq[i]) && (seq[i] <= '0'))
41 code = seq[i] - '1' + KC_1;
42 else
43 code = seq[i] - 'a' + KC_A;
44
45 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
46 return false;
47 }
48
49 return (qk_ucis_state.codes[i] == KC_ENT ||
50 qk_ucis_state.codes[i] == KC_SPC);
51}
52
53__attribute__((weak))
54void qk_ucis_symbol_fallback (void) {
55 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
56 uint8_t code = qk_ucis_state.codes[i];
57 register_code(code);
58 unregister_code(code);
59 wait_ms(UNICODE_TYPE_DELAY);
60 }
61}
62
63void register_ucis(const char *hex) {
64 for(int i = 0; hex[i]; i++) {
65 uint8_t kc = 0;
66 char c = hex[i];
67
68 switch (c) {
69 case '0':
70 kc = KC_0;
71 break;
72 case '1' ... '9':
73 kc = c - '1' + KC_1;
74 break;
75 case 'a' ... 'f':
76 kc = c - 'a' + KC_A;
77 break;
78 case 'A' ... 'F':
79 kc = c - 'A' + KC_A;
80 break;
81 }
82
83 if (kc) {
84 register_code (kc);
85 unregister_code (kc);
86 wait_ms (UNICODE_TYPE_DELAY);
87 }
88 }
89}
90
91bool process_ucis (uint16_t keycode, keyrecord_t *record) {
92 uint8_t i;
93
94 if (!qk_ucis_state.in_progress)
95 return true;
96
97 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
98 !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
99 return false;
100 }
101
102 if (!record->event.pressed)
103 return true;
104
105 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
106 qk_ucis_state.count++;
107
108 if (keycode == KC_BSPC) {
109 if (qk_ucis_state.count >= 2) {
110 qk_ucis_state.count -= 2;
111 return true;
112 } else {
113 qk_ucis_state.count--;
114 return false;
115 }
116 }
117
118 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
119 bool symbol_found = false;
120
121 for (i = qk_ucis_state.count; i > 0; i--) {
122 register_code (KC_BSPC);
123 unregister_code (KC_BSPC);
124 wait_ms(UNICODE_TYPE_DELAY);
125 }
126
127 if (keycode == KC_ESC) {
128 qk_ucis_state.in_progress = false;
129 return false;
130 }
131
132 unicode_input_start();
133 for (i = 0; ucis_symbol_table[i].symbol; i++) {
134 if (is_uni_seq (ucis_symbol_table[i].symbol)) {
135 symbol_found = true;
136 register_ucis(ucis_symbol_table[i].code + 2);
137 break;
138 }
139 }
140 if (!symbol_found) {
141 qk_ucis_symbol_fallback();
142 }
143 unicode_input_finish();
144
145 qk_ucis_state.in_progress = false;
146 return false;
147 }
148 return true;
149}
diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h
new file mode 100644
index 000000000..3f736a709
--- /dev/null
+++ b/quantum/process_keycode/process_ucis.h
@@ -0,0 +1,51 @@
1/* Copyright 2017 Jack Humbert
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
17#ifndef PROCESS_UCIS_H
18#define PROCESS_UCIS_H
19
20#include "quantum.h"
21#include "process_unicode_common.h"
22
23#ifndef UCIS_MAX_SYMBOL_LENGTH
24#define UCIS_MAX_SYMBOL_LENGTH 32
25#endif
26
27typedef struct {
28 char *symbol;
29 char *code;
30} qk_ucis_symbol_t;
31
32typedef struct {
33 uint8_t count;
34 uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
35 bool in_progress:1;
36} qk_ucis_state_t;
37
38extern qk_ucis_state_t qk_ucis_state;
39
40#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
41#define UCIS_SYM(name, code) {name, #code}
42
43extern const qk_ucis_symbol_t ucis_symbol_table[];
44
45void qk_ucis_start(void);
46void qk_ucis_start_user(void);
47void qk_ucis_symbol_fallback (void);
48void register_ucis(const char *hex);
49bool process_ucis (uint16_t keycode, keyrecord_t *record);
50
51#endif
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
index a30e93ae3..26571ea03 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -1,103 +1,21 @@
1/* Copyright 2016 Jack Humbert
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 */
1#include "process_unicode.h" 16#include "process_unicode.h"
2#include "action_util.h" 17#include "action_util.h"
3 18
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) { 19bool process_unicode(uint16_t keycode, keyrecord_t *record) {
102 if (keycode > QK_UNICODE && record->event.pressed) { 20 if (keycode > QK_UNICODE && record->event.pressed) {
103 uint16_t unicode = keycode & 0x7FFF; 21 uint16_t unicode = keycode & 0x7FFF;
@@ -108,182 +26,3 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record) {
108 return true; 26 return true;
109} 27}
110 28
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..c525b74f0 100644
--- a/quantum/process_keycode/process_unicode.h
+++ b/quantum/process_keycode/process_unicode.h
@@ -1,167 +1,24 @@
1/* Copyright 2016 Jack Humbert
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 */
1#ifndef PROCESS_UNICODE_H 16#ifndef PROCESS_UNICODE_H
2#define PROCESS_UNICODE_H 17#define PROCESS_UNICODE_H
3 18
4#include "quantum.h" 19#include "quantum.h"
5 20#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 21
22bool process_unicode(uint16_t keycode, keyrecord_t *record); 22bool process_unicode(uint16_t keycode, keyrecord_t *record);
23 23
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 24#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..6012b4f07
--- /dev/null
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -0,0 +1,101 @@
1/* Copyright 2017 Jack Humbert
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
17#include "process_unicode_common.h"
18
19uint8_t mods;
20
21void set_unicode_input_mode(uint8_t os_target)
22{
23 input_mode = os_target;
24}
25
26uint8_t get_unicode_input_mode(void) {
27 return input_mode;
28}
29
30__attribute__((weak))
31void unicode_input_start (void) {
32 // save current mods
33 mods = keyboard_report->mods;
34
35 // unregister all mods to start from clean state
36 if (mods & MOD_BIT(KC_LSFT)) unregister_code(KC_LSFT);
37 if (mods & MOD_BIT(KC_RSFT)) unregister_code(KC_RSFT);
38 if (mods & MOD_BIT(KC_LCTL)) unregister_code(KC_LCTL);
39 if (mods & MOD_BIT(KC_RCTL)) unregister_code(KC_RCTL);
40 if (mods & MOD_BIT(KC_LALT)) unregister_code(KC_LALT);
41 if (mods & MOD_BIT(KC_RALT)) unregister_code(KC_RALT);
42 if (mods & MOD_BIT(KC_LGUI)) unregister_code(KC_LGUI);
43 if (mods & MOD_BIT(KC_RGUI)) unregister_code(KC_RGUI);
44
45 switch(input_mode) {
46 case UC_OSX:
47 register_code(KC_LALT);
48 break;
49 case UC_LNX:
50 register_code(KC_LCTL);
51 register_code(KC_LSFT);
52 register_code(KC_U);
53 unregister_code(KC_U);
54 unregister_code(KC_LSFT);
55 unregister_code(KC_LCTL);
56 break;
57 case UC_WIN:
58 register_code(KC_LALT);
59 register_code(KC_PPLS);
60 unregister_code(KC_PPLS);
61 break;
62 case UC_WINC:
63 register_code(KC_RALT);
64 unregister_code(KC_RALT);
65 register_code(KC_U);
66 unregister_code(KC_U);
67 }
68 wait_ms(UNICODE_TYPE_DELAY);
69}
70
71__attribute__((weak))
72void unicode_input_finish (void) {
73 switch(input_mode) {
74 case UC_OSX:
75 case UC_WIN:
76 unregister_code(KC_LALT);
77 break;
78 case UC_LNX:
79 register_code(KC_SPC);
80 unregister_code(KC_SPC);
81 break;
82 }
83
84 // reregister previously set mods
85 if (mods & MOD_BIT(KC_LSFT)) register_code(KC_LSFT);
86 if (mods & MOD_BIT(KC_RSFT)) register_code(KC_RSFT);
87 if (mods & MOD_BIT(KC_LCTL)) register_code(KC_LCTL);
88 if (mods & MOD_BIT(KC_RCTL)) register_code(KC_RCTL);
89 if (mods & MOD_BIT(KC_LALT)) register_code(KC_LALT);
90 if (mods & MOD_BIT(KC_RALT)) register_code(KC_RALT);
91 if (mods & MOD_BIT(KC_LGUI)) register_code(KC_LGUI);
92 if (mods & MOD_BIT(KC_RGUI)) register_code(KC_RGUI);
93}
94
95void register_hex(uint16_t hex) {
96 for(int i = 3; i >= 0; i--) {
97 uint8_t digit = ((hex >> (i*4)) & 0xF);
98 register_code(hex_to_keycode(digit));
99 unregister_code(hex_to_keycode(digit));
100 }
101}
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
new file mode 100644
index 000000000..f5be1da5c
--- /dev/null
+++ b/quantum/process_keycode/process_unicode_common.h
@@ -0,0 +1,148 @@
1/* Copyright 2017 Jack Humbert
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
17#ifndef PROCESS_UNICODE_COMMON_H
18#define PROCESS_UNICODE_COMMON_H
19
20#include "quantum.h"
21
22#ifndef UNICODE_TYPE_DELAY
23#define UNICODE_TYPE_DELAY 10
24#endif
25
26__attribute__ ((unused))
27static uint8_t input_mode;
28
29void set_unicode_input_mode(uint8_t os_target);
30uint8_t get_unicode_input_mode(void);
31void unicode_input_start(void);
32void unicode_input_finish(void);
33void register_hex(uint16_t hex);
34
35#define UC_OSX 0 // Mac OS X
36#define UC_LNX 1 // Linux
37#define UC_WIN 2 // Windows 'HexNumpad'
38#define UC_BSD 3 // BSD (not implemented)
39#define UC_WINC 4 // WinCompose https://github.com/samhocevar/wincompose
40
41#define UC_BSPC UC(0x0008)
42
43#define UC_SPC UC(0x0020)
44
45#define UC_EXLM UC(0x0021)
46#define UC_DQUT UC(0x0022)
47#define UC_HASH UC(0x0023)
48#define UC_DLR UC(0x0024)
49#define UC_PERC UC(0x0025)
50#define UC_AMPR UC(0x0026)
51#define UC_QUOT UC(0x0027)
52#define UC_LPRN UC(0x0028)
53#define UC_RPRN UC(0x0029)
54#define UC_ASTR UC(0x002A)
55#define UC_PLUS UC(0x002B)
56#define UC_COMM UC(0x002C)
57#define UC_DASH UC(0x002D)
58#define UC_DOT UC(0x002E)
59#define UC_SLSH UC(0x002F)
60
61#define UC_0 UC(0x0030)
62#define UC_1 UC(0x0031)
63#define UC_2 UC(0x0032)
64#define UC_3 UC(0x0033)
65#define UC_4 UC(0x0034)
66#define UC_5 UC(0x0035)
67#define UC_6 UC(0x0036)
68#define UC_7 UC(0x0037)
69#define UC_8 UC(0x0038)
70#define UC_9 UC(0x0039)
71
72#define UC_COLN UC(0x003A)
73#define UC_SCLN UC(0x003B)
74#define UC_LT UC(0x003C)
75#define UC_EQL UC(0x003D)
76#define UC_GT UC(0x003E)
77#define UC_QUES UC(0x003F)
78#define UC_AT UC(0x0040)
79
80#define UC_A UC(0x0041)
81#define UC_B UC(0x0042)
82#define UC_C UC(0x0043)
83#define UC_D UC(0x0044)
84#define UC_E UC(0x0045)
85#define UC_F UC(0x0046)
86#define UC_G UC(0x0047)
87#define UC_H UC(0x0048)
88#define UC_I UC(0x0049)
89#define UC_J UC(0x004A)
90#define UC_K UC(0x004B)
91#define UC_L UC(0x004C)
92#define UC_M UC(0x004D)
93#define UC_N UC(0x004E)
94#define UC_O UC(0x004F)
95#define UC_P UC(0x0050)
96#define UC_Q UC(0x0051)
97#define UC_R UC(0x0052)
98#define UC_S UC(0x0053)
99#define UC_T UC(0x0054)
100#define UC_U UC(0x0055)
101#define UC_V UC(0x0056)
102#define UC_W UC(0x0057)
103#define UC_X UC(0x0058)
104#define UC_Y UC(0x0059)
105#define UC_Z UC(0x005A)
106
107#define UC_LBRC UC(0x005B)
108#define UC_BSLS UC(0x005C)
109#define UC_RBRC UC(0x005D)
110#define UC_CIRM UC(0x005E)
111#define UC_UNDR UC(0x005F)
112
113#define UC_GRV UC(0x0060)
114
115#define UC_a UC(0x0061)
116#define UC_b UC(0x0062)
117#define UC_c UC(0x0063)
118#define UC_d UC(0x0064)
119#define UC_e UC(0x0065)
120#define UC_f UC(0x0066)
121#define UC_g UC(0x0067)
122#define UC_h UC(0x0068)
123#define UC_i UC(0x0069)
124#define UC_j UC(0x006A)
125#define UC_k UC(0x006B)
126#define UC_l UC(0x006C)
127#define UC_m UC(0x006D)
128#define UC_n UC(0x006E)
129#define UC_o UC(0x006F)
130#define UC_p UC(0x0070)
131#define UC_q UC(0x0071)
132#define UC_r UC(0x0072)
133#define UC_s UC(0x0073)
134#define UC_t UC(0x0074)
135#define UC_u UC(0x0075)
136#define UC_v UC(0x0076)
137#define UC_w UC(0x0077)
138#define UC_x UC(0x0078)
139#define UC_y UC(0x0079)
140#define UC_z UC(0x007A)
141
142#define UC_LCBR UC(0x007B)
143#define UC_PIPE UC(0x007C)
144#define UC_RCBR UC(0x007D)
145#define UC_TILD UC(0x007E)
146#define UC_DEL UC(0x007F)
147
148#endif
diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c
new file mode 100644
index 000000000..0227fbdd7
--- /dev/null
+++ b/quantum/process_keycode/process_unicodemap.c
@@ -0,0 +1,72 @@
1/* Copyright 2017 Jack Humbert
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
17#include "process_unicodemap.h"
18#include "process_unicode_common.h"
19
20__attribute__((weak))
21const uint32_t PROGMEM unicode_map[] = {
22};
23
24void register_hex32(uint32_t hex) {
25 bool onzerostart = true;
26 for(int i = 7; i >= 0; i--) {
27 if (i <= 3) {
28 onzerostart = false;
29 }
30 uint8_t digit = ((hex >> (i*4)) & 0xF);
31 if (digit == 0) {
32 if (!onzerostart) {
33 register_code(hex_to_keycode(digit));
34 unregister_code(hex_to_keycode(digit));
35 }
36 } else {
37 register_code(hex_to_keycode(digit));
38 unregister_code(hex_to_keycode(digit));
39 onzerostart = false;
40 }
41 }
42}
43
44__attribute__((weak))
45void unicode_map_input_error() {}
46
47bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
48 uint8_t input_mode = get_unicode_input_mode();
49 if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
50 const uint32_t* map = unicode_map;
51 uint16_t index = keycode - QK_UNICODE_MAP;
52 uint32_t code = pgm_read_dword_far(&map[index]);
53 if (code > 0xFFFF && code <= 0x10ffff && input_mode == UC_OSX) {
54 // Convert to UTF-16 surrogate pair
55 code -= 0x10000;
56 uint32_t lo = code & 0x3ff;
57 uint32_t hi = (code & 0xffc00) >> 10;
58 unicode_input_start();
59 register_hex32(hi + 0xd800);
60 register_hex32(lo + 0xdc00);
61 unicode_input_finish();
62 } else if ((code > 0x10ffff && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
63 // when character is out of range supported by the OS
64 unicode_map_input_error();
65 } else {
66 unicode_input_start();
67 register_hex32(code);
68 unicode_input_finish();
69 }
70 }
71 return true;
72}
diff --git a/quantum/process_keycode/process_unicodemap.h b/quantum/process_keycode/process_unicodemap.h
new file mode 100644
index 000000000..929c88c0b
--- /dev/null
+++ b/quantum/process_keycode/process_unicodemap.h
@@ -0,0 +1,25 @@
1/* Copyright 2017 Jack Humbert
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
17#ifndef PROCESS_UNICODEMAP_H
18#define PROCESS_UNICODEMAP_H
19
20#include "quantum.h"
21#include "process_unicode_common.h"
22
23void unicode_map_input_error(void);
24bool process_unicode_map(uint16_t keycode, keyrecord_t *record);
25#endif