aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode
diff options
context:
space:
mode:
authorZay950 <Zay950@users.noreply.github.com>2017-03-29 12:00:38 -0700
committerGitHub <noreply@github.com>2017-03-29 12:00:38 -0700
commit2366ebfbbdeb6ec29cc9a0facda44d666305dd6e (patch)
tree883efed0b7260f3143f5a2a879bc3844a8255e0b /quantum/process_keycode
parent80c5ada3394c5ad8087df00ef878eb2cbcd87d70 (diff)
parent942f2ccee44bdb2e251553e9730cd8d59307d8b2 (diff)
downloadqmk_firmware-2366ebfbbdeb6ec29cc9a0facda44d666305dd6e.tar.gz
qmk_firmware-2366ebfbbdeb6ec29cc9a0facda44d666305dd6e.zip
Merge branch 'master' into to_push
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.c141
-rw-r--r--quantum/process_keycode/process_music.h24
-rw-r--r--quantum/process_keycode/process_printer.c270
-rw-r--r--quantum/process_keycode/process_printer.h24
-rw-r--r--quantum/process_keycode/process_printer_bb.c276
-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.c196
-rw-r--r--quantum/process_keycode/process_unicode.h174
-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, 1935 insertions, 658 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 2d52e47a7..217dca280 100644
--- a/quantum/process_keycode/process_music.c
+++ b/quantum/process_keycode/process_music.c
@@ -1,43 +1,72 @@
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 starting_note = 0x0C; 28uint8_t music_starting_note = 0x0C;
5int offset = 7; 29int music_offset = 7;
6 30
7// music sequencer 31// music sequencer
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;
@@ -115,21 +132,33 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
115 return false; 132 return false;
116 } 133 }
117 134
118 float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)); 135 #define MUSIC_MODE_GUITAR
136
137 #ifdef MUSIC_MODE_CHROMATIC
138 uint8_t note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row);
139 #elif defined(MUSIC_MODE_GUITAR)
140 uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row);
141 #elif defined(MUSIC_MODE_VIOLIN)
142 uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row);
143 #else
144 uint8_t note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row);
145 #endif
146
119 if (record->event.pressed) { 147 if (record->event.pressed) {
120 play_note(freq, 0xF); 148 music_noteon(note);
121 if (music_sequence_recording) { 149 if (music_sequence_recording) {
122 music_sequence[music_sequence_count] = freq; 150 music_sequence[music_sequence_count] = note;
123 music_sequence_count++; 151 music_sequence_count++;
124 } 152 }
125 } else { 153 } else {
126 stop_note(freq); 154 music_noteoff(note);
127 } 155 }
128 156
129 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
130 return false; 158 return false;
131 } 159 }
132 return true; 160
161 return true;
133} 162}
134 163
135bool is_music_on(void) { 164bool is_music_on(void) {
@@ -151,26 +180,26 @@ void music_on(void) {
151 180
152void music_off(void) { 181void music_off(void) {
153 music_activated = 0; 182 music_activated = 0;
154 stop_all_notes(); 183 music_all_notes_off();
155} 184}
156 185
157
158__attribute__ ((weak))
159void music_on_user() {}
160
161__attribute__ ((weak))
162void audio_on_user() {}
163
164__attribute__ ((weak))
165void music_scale_user() {}
166
167void matrix_scan_music(void) { 186void matrix_scan_music(void) {
168 if (music_sequence_playing) { 187 if (music_sequence_playing) {
169 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)) {
170 music_sequence_timer = timer_read(); 189 music_sequence_timer = timer_read();
171 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)];
172 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);
173 music_sequence_position = (music_sequence_position + 1) % music_sequence_count; 194 music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
174 } 195 }
175 } 196 }
176} 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
new file mode 100644
index 000000000..807f7a0b9
--- /dev/null
+++ b/quantum/process_keycode/process_printer.c
@@ -0,0 +1,270 @@
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_printer.h"
18#include "action_util.h"
19
20bool printing_enabled = false;
21uint8_t character_shift = 0;
22
23void enabled_printing() {
24 printing_enabled = true;
25 serial_init();
26}
27
28void disable_printing() {
29 printing_enabled = false;
30}
31
32uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
33
34// uint8_t keycode_to_ascii[0xFF][2];
35
36// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
37
38void print_char(char c) {
39 USB_Disable();
40 serial_send(c);
41 USB_Init();
42}
43
44void print_box_string(uint8_t text[]) {
45 uint8_t len = strlen(text);
46 uint8_t out[len * 3 + 8];
47 out[0] = 0xDA;
48 for (uint8_t i = 0; i < len; i++) {
49 out[i+1] = 0xC4;
50 }
51 out[len + 1] = 0xBF;
52 out[len + 2] = '\n';
53
54 out[len + 3] = 0xB3;
55 for (uint8_t i = 0; i < len; i++) {
56 out[len + 4 + i] = text[i];
57 }
58 out[len * 2 + 4] = 0xB3;
59 out[len * 2 + 5] = '\n';
60
61
62 out[len * 2 + 6] = 0xC0;
63 for (uint8_t i = 0; i < len; i++) {
64 out[len * 2 + 7 + i] = 0xC4;
65 }
66 out[len * 3 + 7] = 0xD9;
67 out[len * 3 + 8] = '\n';
68
69 print_string(out);
70}
71
72void print_string(char c[]) {
73 for(uint8_t i = 0; i < strlen(c); i++)
74 print_char(c[i]);
75}
76
77bool process_printer(uint16_t keycode, keyrecord_t *record) {
78 if (keycode == PRINT_ON) {
79 enabled_printing();
80 return false;
81 }
82 if (keycode == PRINT_OFF) {
83 disable_printing();
84 return false;
85 }
86
87 if (printing_enabled) {
88 switch(keycode) {
89 case KC_EXLM ... KC_RPRN:
90 case KC_UNDS:
91 case KC_PLUS:
92 case KC_LCBR:
93 case KC_RCBR:
94 case KC_PIPE:
95 case KC_TILD:
96 keycode &= 0xFF;
97 case KC_LSFT:
98 case KC_RSFT:
99 if (record->event.pressed) {
100 character_shift++;
101 } else {
102 character_shift--;
103 }
104 return false;
105 break;
106 }
107
108 switch(keycode) {
109 case KC_F1:
110 if (record->event.pressed) {
111 print_box_string("This is a line of text!");
112 }
113 return false;
114 case KC_ESC:
115 if (record->event.pressed) {
116 print_char(0x1B);
117 }
118 return false;
119 break;
120 case KC_SPC:
121 if (record->event.pressed) {
122 print_char(0x20);
123 }
124 return false;
125 break;
126 case KC_A ... KC_Z:
127 if (record->event.pressed) {
128 if (character_shift) {
129 print_char(0x41 + (keycode - KC_A));
130 } else {
131 print_char(0x61 + (keycode - KC_A));
132 }
133 }
134 return false;
135 break;
136 case KC_1 ... KC_0:
137 if (record->event.pressed) {
138 if (character_shift) {
139 print_char(shifted_numbers[keycode - KC_1]);
140 } else {
141 print_char(0x30 + ((keycode - KC_1 + 1) % 10));
142 }
143 }
144 return false;
145 break;
146 case KC_ENT:
147 if (record->event.pressed) {
148 if (character_shift) {
149 print_char(0x0C);
150 } else {
151 print_char(0x0A);
152 }
153 }
154 return false;
155 break;
156 case KC_BSPC:
157 if (record->event.pressed) {
158 if (character_shift) {
159 print_char(0x18);
160 } else {
161 print_char(0x1A);
162 }
163 }
164 return false;
165 break;
166 case KC_DOT:
167 if (record->event.pressed) {
168 if (character_shift) {
169 print_char(0x3E);
170 } else {
171 print_char(0x2E);
172 }
173 }
174 return false;
175 break;
176 case KC_COMM:
177 if (record->event.pressed) {
178 if (character_shift) {
179 print_char(0x3C);
180 } else {
181 print_char(0x2C);
182 }
183 }
184 return false;
185 break;
186 case KC_SLSH:
187 if (record->event.pressed) {
188 if (character_shift) {
189 print_char(0x3F);
190 } else {
191 print_char(0x2F);
192 }
193 }
194 return false;
195 break;
196 case KC_QUOT:
197 if (record->event.pressed) {
198 if (character_shift) {
199 print_char(0x22);
200 } else {
201 print_char(0x27);
202 }
203 }
204 return false;
205 break;
206 case KC_GRV:
207 if (record->event.pressed) {
208 if (character_shift) {
209 print_char(0x7E);
210 } else {
211 print_char(0x60);
212 }
213 }
214 return false;
215 break;
216 case KC_MINS:
217 if (record->event.pressed) {
218 if (character_shift) {
219 print_char(0x5F);
220 } else {
221 print_char(0x2D);
222 }
223 }
224 return false;
225 break;
226 case KC_EQL:
227 if (record->event.pressed) {
228 if (character_shift) {
229 print_char(0x2B);
230 } else {
231 print_char(0x3D);
232 }
233 }
234 return false;
235 break;
236 case KC_LBRC:
237 if (record->event.pressed) {
238 if (character_shift) {
239 print_char(0x7B);
240 } else {
241 print_char(0x5B);
242 }
243 }
244 return false;
245 break;
246 case KC_RBRC:
247 if (record->event.pressed) {
248 if (character_shift) {
249 print_char(0x7D);
250 } else {
251 print_char(0x5D);
252 }
253 }
254 return false;
255 break;
256 case KC_BSLS:
257 if (record->event.pressed) {
258 if (character_shift) {
259 print_char(0x7C);
260 } else {
261 print_char(0x5C);
262 }
263 }
264 return false;
265 break;
266 }
267 }
268 return true;
269
270}
diff --git a/quantum/process_keycode/process_printer.h b/quantum/process_keycode/process_printer.h
new file mode 100644
index 000000000..aa494ac8a
--- /dev/null
+++ b/quantum/process_keycode/process_printer.h
@@ -0,0 +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 */
16
17#ifndef PROCESS_PRINTER_H
18#define PROCESS_PRINTER_H
19
20#include "quantum.h"
21
22#include "protocol/serial.h"
23
24#endif
diff --git a/quantum/process_keycode/process_printer_bb.c b/quantum/process_keycode/process_printer_bb.c
new file mode 100644
index 000000000..55d3b552b
--- /dev/null
+++ b/quantum/process_keycode/process_printer_bb.c
@@ -0,0 +1,276 @@
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_printer.h"
18#include "action_util.h"
19
20bool printing_enabled = false;
21uint8_t character_shift = 0;
22
23#define SERIAL_PIN_DDR DDRD
24#define SERIAL_PIN_PORT PORTD
25#define SERIAL_PIN_MASK _BV(PD3)
26#define SERIAL_DELAY 52
27
28inline static
29void serial_delay(void) {
30 _delay_us(SERIAL_DELAY);
31}
32
33inline static
34void serial_high(void) {
35 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
36}
37
38inline static
39void serial_low(void) {
40 SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
41}
42
43inline static
44void serial_output(void) {
45 SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
46}
47
48
49void enabled_printing() {
50 printing_enabled = true;
51 serial_output();
52 serial_high();
53}
54
55void disable_printing() {
56 printing_enabled = false;
57}
58
59uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
60
61// uint8_t keycode_to_ascii[0xFF][2];
62
63// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
64
65void print_char(char c) {
66 uint8_t b = 8;
67 serial_output();
68 while( b-- ) {
69 if(c & (1 << b)) {
70 serial_high();
71 } else {
72 serial_low();
73 }
74 serial_delay();
75 }
76}
77
78void print_string(char c[]) {
79 for(uint8_t i = 0; i < strlen(c); i++)
80 print_char(c[i]);
81}
82
83bool process_printer(uint16_t keycode, keyrecord_t *record) {
84 if (keycode == PRINT_ON) {
85 enabled_printing();
86 return false;
87 }
88 if (keycode == PRINT_OFF) {
89 disable_printing();
90 return false;
91 }
92
93 if (printing_enabled) {
94 switch(keycode) {
95 case KC_EXLM ... KC_RPRN:
96 case KC_UNDS:
97 case KC_PLUS:
98 case KC_LCBR:
99 case KC_RCBR:
100 case KC_PIPE:
101 case KC_TILD:
102 keycode &= 0xFF;
103 case KC_LSFT:
104 case KC_RSFT:
105 if (record->event.pressed) {
106 character_shift++;
107 } else {
108 character_shift--;
109 }
110 return false;
111 break;
112 }
113
114 switch(keycode) {
115 case KC_F1:
116 if (record->event.pressed) {
117 print_string("This is a line of text!\n\n\n");
118 }
119 return false;
120 case KC_ESC:
121 if (record->event.pressed) {
122 print_char(0x1B);
123 }
124 return false;
125 break;
126 case KC_SPC:
127 if (record->event.pressed) {
128 print_char(0x20);
129 }
130 return false;
131 break;
132 case KC_A ... KC_Z:
133 if (record->event.pressed) {
134 if (character_shift) {
135 print_char(0x41 + (keycode - KC_A));
136 } else {
137 print_char(0x61 + (keycode - KC_A));
138 }
139 }
140 return false;
141 break;
142 case KC_1 ... KC_0:
143 if (record->event.pressed) {
144 if (character_shift) {
145 print_char(shifted_numbers[keycode - KC_1]);
146 } else {
147 print_char(0x30 + ((keycode - KC_1 + 1) % 10));
148 }
149 }
150 return false;
151 break;
152 case KC_ENT:
153 if (record->event.pressed) {
154 if (character_shift) {
155 print_char(0x0C);
156 } else {
157 print_char(0x0A);
158 }
159 }
160 return false;
161 break;
162 case KC_BSPC:
163 if (record->event.pressed) {
164 if (character_shift) {
165 print_char(0x18);
166 } else {
167 print_char(0x1A);
168 }
169 }
170 return false;
171 break;
172 case KC_DOT:
173 if (record->event.pressed) {
174 if (character_shift) {
175 print_char(0x3E);
176 } else {
177 print_char(0x2E);
178 }
179 }
180 return false;
181 break;
182 case KC_COMM:
183 if (record->event.pressed) {
184 if (character_shift) {
185 print_char(0x3C);
186 } else {
187 print_char(0x2C);
188 }
189 }
190 return false;
191 break;
192 case KC_SLSH:
193 if (record->event.pressed) {
194 if (character_shift) {
195 print_char(0x3F);
196 } else {
197 print_char(0x2F);
198 }
199 }
200 return false;
201 break;
202 case KC_QUOT:
203 if (record->event.pressed) {
204 if (character_shift) {
205 print_char(0x22);
206 } else {
207 print_char(0x27);
208 }
209 }
210 return false;
211 break;
212 case KC_GRV:
213 if (record->event.pressed) {
214 if (character_shift) {
215 print_char(0x7E);
216 } else {
217 print_char(0x60);
218 }
219 }
220 return false;
221 break;
222 case KC_MINS:
223 if (record->event.pressed) {
224 if (character_shift) {
225 print_char(0x5F);
226 } else {
227 print_char(0x2D);
228 }
229 }
230 return false;
231 break;
232 case KC_EQL:
233 if (record->event.pressed) {
234 if (character_shift) {
235 print_char(0x2B);
236 } else {
237 print_char(0x3D);
238 }
239 }
240 return false;
241 break;
242 case KC_LBRC:
243 if (record->event.pressed) {
244 if (character_shift) {
245 print_char(0x7B);
246 } else {
247 print_char(0x5B);
248 }
249 }
250 return false;
251 break;
252 case KC_RBRC:
253 if (record->event.pressed) {
254 if (character_shift) {
255 print_char(0x7D);
256 } else {
257 print_char(0x5D);
258 }
259 }
260 return false;
261 break;
262 case KC_BSLS:
263 if (record->event.pressed) {
264 if (character_shift) {
265 print_char(0x7C);
266 } else {
267 print_char(0x5C);
268 }
269 }
270 return false;
271 break;
272 }
273 }
274 return true;
275
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 f42f25538..cecfaeee9 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -1,4 +1,20 @@
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"
17#include "action_util.h"
2 18
3static uint8_t input_mode; 19static uint8_t input_mode;
4static uint8_t first_flag = 0; 20static uint8_t first_flag = 0;
@@ -75,6 +91,7 @@ void register_hex(uint16_t hex) {
75 } 91 }
76} 92}
77 93
94
78bool process_unicode(uint16_t keycode, keyrecord_t *record) { 95bool process_unicode(uint16_t keycode, keyrecord_t *record) {
79 if (keycode > QK_UNICODE && record->event.pressed) { 96 if (keycode > QK_UNICODE && record->event.pressed) {
80 if (first_flag == 0) { 97 if (first_flag == 0) {
@@ -89,182 +106,3 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record) {
89 return true; 106 return true;
90} 107}
91 108
92#ifdef UNICODEMAP_ENABLE
93__attribute__((weak))
94const uint32_t PROGMEM unicode_map[] = {
95};
96
97void register_hex32(uint32_t hex) {
98 uint8_t onzerostart = 1;
99 for(int i = 7; i >= 0; i--) {
100 if (i <= 3) {
101 onzerostart = 0;
102 }
103 uint8_t digit = ((hex >> (i*4)) & 0xF);
104 if (digit == 0) {
105 if (onzerostart == 0) {
106 register_code(hex_to_keycode(digit));
107 unregister_code(hex_to_keycode(digit));
108 }
109 } else {
110 register_code(hex_to_keycode(digit));
111 unregister_code(hex_to_keycode(digit));
112 onzerostart = 0;
113 }
114 }
115}
116
117__attribute__((weak))
118void unicode_map_input_error() {}
119
120bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
121 if ((keycode & QK_UNICODE_MAP) == QK_UNICODE_MAP && record->event.pressed) {
122 const uint32_t* map = unicode_map;
123 uint16_t index = keycode & 0x7FF;
124 uint32_t code = pgm_read_dword_far(&map[index]);
125 if ((code > 0xFFFF && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
126 // when character is out of range supported by the OS
127 unicode_map_input_error();
128 } else {
129 unicode_input_start();
130 register_hex32(code);
131 unicode_input_finish();
132 }
133 }
134 return true;
135}
136#endif
137
138#ifdef UCIS_ENABLE
139qk_ucis_state_t qk_ucis_state;
140
141void qk_ucis_start(void) {
142 qk_ucis_state.count = 0;
143 qk_ucis_state.in_progress = true;
144
145 qk_ucis_start_user();
146}
147
148__attribute__((weak))
149void qk_ucis_start_user(void) {
150 unicode_input_start();
151 register_hex(0x2328);
152 unicode_input_finish();
153}
154
155static bool is_uni_seq(char *seq) {
156 uint8_t i;
157
158 for (i = 0; seq[i]; i++) {
159 uint16_t code;
160 if (('1' <= seq[i]) && (seq[i] <= '0'))
161 code = seq[i] - '1' + KC_1;
162 else
163 code = seq[i] - 'a' + KC_A;
164
165 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
166 return false;
167 }
168
169 return (qk_ucis_state.codes[i] == KC_ENT ||
170 qk_ucis_state.codes[i] == KC_SPC);
171}
172
173__attribute__((weak))
174void qk_ucis_symbol_fallback (void) {
175 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
176 uint8_t code = qk_ucis_state.codes[i];
177 register_code(code);
178 unregister_code(code);
179 wait_ms(UNICODE_TYPE_DELAY);
180 }
181}
182
183void register_ucis(const char *hex) {
184 for(int i = 0; hex[i]; i++) {
185 uint8_t kc = 0;
186 char c = hex[i];
187
188 switch (c) {
189 case '0':
190 kc = KC_0;
191 break;
192 case '1' ... '9':
193 kc = c - '1' + KC_1;
194 break;
195 case 'a' ... 'f':
196 kc = c - 'a' + KC_A;
197 break;
198 case 'A' ... 'F':
199 kc = c - 'A' + KC_A;
200 break;
201 }
202
203 if (kc) {
204 register_code (kc);
205 unregister_code (kc);
206 wait_ms (UNICODE_TYPE_DELAY);
207 }
208 }
209}
210
211bool process_ucis (uint16_t keycode, keyrecord_t *record) {
212 uint8_t i;
213
214 if (!qk_ucis_state.in_progress)
215 return true;
216
217 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
218 !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
219 return false;
220 }
221
222 if (!record->event.pressed)
223 return true;
224
225 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
226 qk_ucis_state.count++;
227
228 if (keycode == KC_BSPC) {
229 if (qk_ucis_state.count >= 2) {
230 qk_ucis_state.count -= 2;
231 return true;
232 } else {
233 qk_ucis_state.count--;
234 return false;
235 }
236 }
237
238 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
239 bool symbol_found = false;
240
241 for (i = qk_ucis_state.count; i > 0; i--) {
242 register_code (KC_BSPC);
243 unregister_code (KC_BSPC);
244 wait_ms(UNICODE_TYPE_DELAY);
245 }
246
247 if (keycode == KC_ESC) {
248 qk_ucis_state.in_progress = false;
249 return false;
250 }
251
252 unicode_input_start();
253 for (i = 0; ucis_symbol_table[i].symbol; i++) {
254 if (is_uni_seq (ucis_symbol_table[i].symbol)) {
255 symbol_found = true;
256 register_ucis(ucis_symbol_table[i].code + 2);
257 break;
258 }
259 }
260 if (!symbol_found) {
261 qk_ucis_symbol_fallback();
262 }
263 unicode_input_finish();
264
265 qk_ucis_state.in_progress = false;
266 return false;
267 }
268 return true;
269}
270#endif
diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h
index 065eeb5f6..c525b74f0 100644
--- a/quantum/process_keycode/process_unicode.h
+++ b/quantum/process_keycode/process_unicode.h
@@ -1,166 +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
25bool process_unicode_map(uint16_t keycode, keyrecord_t *record);
26#endif
27
28#ifdef UCIS_ENABLE
29#ifndef UCIS_MAX_SYMBOL_LENGTH
30#define UCIS_MAX_SYMBOL_LENGTH 32
31#endif
32
33typedef struct {
34 char *symbol;
35 char *code;
36} qk_ucis_symbol_t;
37
38typedef struct {
39 uint8_t count;
40 uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
41 bool in_progress:1;
42} qk_ucis_state_t;
43
44extern qk_ucis_state_t qk_ucis_state;
45
46#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
47#define UCIS_SYM(name, code) {name, #code}
48
49extern const qk_ucis_symbol_t ucis_symbol_table[];
50
51void qk_ucis_start(void);
52void qk_ucis_start_user(void);
53void qk_ucis_symbol_fallback (void);
54void register_ucis(const char *hex);
55bool process_ucis (uint16_t keycode, keyrecord_t *record);
56
57#endif
58
59#define UC_BSPC UC(0x0008)
60
61#define UC_SPC UC(0x0020)
62
63#define UC_EXLM UC(0x0021)
64#define UC_DQUT UC(0x0022)
65#define UC_HASH UC(0x0023)
66#define UC_DLR UC(0x0024)
67#define UC_PERC UC(0x0025)
68#define UC_AMPR UC(0x0026)
69#define UC_QUOT UC(0x0027)
70#define UC_LPRN UC(0x0028)
71#define UC_RPRN UC(0x0029)
72#define UC_ASTR UC(0x002A)
73#define UC_PLUS UC(0x002B)
74#define UC_COMM UC(0x002C)
75#define UC_DASH UC(0x002D)
76#define UC_DOT UC(0x002E)
77#define UC_SLSH UC(0x002F)
78
79#define UC_0 UC(0x0030)
80#define UC_1 UC(0x0031)
81#define UC_2 UC(0x0032)
82#define UC_3 UC(0x0033)
83#define UC_4 UC(0x0034)
84#define UC_5 UC(0x0035)
85#define UC_6 UC(0x0036)
86#define UC_7 UC(0x0037)
87#define UC_8 UC(0x0038)
88#define UC_9 UC(0x0039)
89
90#define UC_COLN UC(0x003A)
91#define UC_SCLN UC(0x003B)
92#define UC_LT UC(0x003C)
93#define UC_EQL UC(0x003D)
94#define UC_GT UC(0x003E)
95#define UC_QUES UC(0x003F)
96#define UC_AT UC(0x0040)
97
98#define UC_A UC(0x0041)
99#define UC_B UC(0x0042)
100#define UC_C UC(0x0043)
101#define UC_D UC(0x0044)
102#define UC_E UC(0x0045)
103#define UC_F UC(0x0046)
104#define UC_G UC(0x0047)
105#define UC_H UC(0x0048)
106#define UC_I UC(0x0049)
107#define UC_J UC(0x004A)
108#define UC_K UC(0x004B)
109#define UC_L UC(0x004C)
110#define UC_M UC(0x004D)
111#define UC_N UC(0x004E)
112#define UC_O UC(0x004F)
113#define UC_P UC(0x0050)
114#define UC_Q UC(0x0051)
115#define UC_R UC(0x0052)
116#define UC_S UC(0x0053)
117#define UC_T UC(0x0054)
118#define UC_U UC(0x0055)
119#define UC_V UC(0x0056)
120#define UC_W UC(0x0057)
121#define UC_X UC(0x0058)
122#define UC_Y UC(0x0059)
123#define UC_Z UC(0x005A)
124
125#define UC_LBRC UC(0x005B)
126#define UC_BSLS UC(0x005C)
127#define UC_RBRC UC(0x005D)
128#define UC_CIRM UC(0x005E)
129#define UC_UNDR UC(0x005F)
130
131#define UC_GRV UC(0x0060)
132
133#define UC_a UC(0x0061)
134#define UC_b UC(0x0062)
135#define UC_c UC(0x0063)
136#define UC_d UC(0x0064)
137#define UC_e UC(0x0065)
138#define UC_f UC(0x0066)
139#define UC_g UC(0x0067)
140#define UC_h UC(0x0068)
141#define UC_i UC(0x0069)
142#define UC_j UC(0x006A)
143#define UC_k UC(0x006B)
144#define UC_l UC(0x006C)
145#define UC_m UC(0x006D)
146#define UC_n UC(0x006E)
147#define UC_o UC(0x006F)
148#define UC_p UC(0x0070)
149#define UC_q UC(0x0071)
150#define UC_r UC(0x0072)
151#define UC_s UC(0x0073)
152#define UC_t UC(0x0074)
153#define UC_u UC(0x0075)
154#define UC_v UC(0x0076)
155#define UC_w UC(0x0077)
156#define UC_x UC(0x0078)
157#define UC_y UC(0x0079)
158#define UC_z UC(0x007A)
159
160#define UC_LCBR UC(0x007B)
161#define UC_PIPE UC(0x007C)
162#define UC_RCBR UC(0x007D)
163#define UC_TILD UC(0x007E)
164#define UC_DEL UC(0x007F)
165
166#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