]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/quantum.c
dd5d84f826a37562205710ec2105b6f9156e84ae
[qmk_firmware.git] / quantum / quantum.c
1 #include "quantum.h"
2
3 __attribute__ ((weak))
4 void matrix_init_kb(void) {}
5
6 __attribute__ ((weak))
7 void matrix_scan_kb(void) {}
8
9 __attribute__ ((weak))
10 bool process_action_kb(keyrecord_t *record) {
11   return true;
12 }
13
14 __attribute__ ((weak))
15 void leader_start(void) {}
16
17 __attribute__ ((weak))
18 void leader_end(void) {}
19
20 #ifdef AUDIO_ENABLE
21   uint8_t starting_note = 0x0C;
22   int offset = 0;
23   bool music_activated = false;
24   float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
25 #endif
26
27 // Leader key stuff
28 bool leading = false;
29 uint16_t leader_time = 0;
30
31 uint16_t leader_sequence[3] = {0, 0, 0};
32 uint8_t leader_sequence_size = 0;
33
34 // Chording stuff
35 #define CHORDING_MAX 4
36 bool chording = false;
37
38 uint8_t chord_keys[CHORDING_MAX] = {0};
39 uint8_t chord_key_count = 0;
40 uint8_t chord_key_down = 0;
41
42 bool keys_chord(uint8_t keys[]) {
43   uint8_t keys_size = sizeof(keys)/sizeof(keys[0]);
44   bool pass = true;
45   uint8_t in = 0;
46   for (uint8_t i = 0; i < chord_key_count; i++) {
47     bool found = false;
48     for (uint8_t j = 0; j < keys_size; j++) {
49       if (chord_keys[i] == (keys[j] & 0xFF)) {
50         in++; // detects key in chord
51         found = true;
52         break;
53       }
54     }
55     if (found)
56       continue;
57     if (chord_keys[i] != 0)  {
58       pass = false; // makes sure rest are blank
59     }
60   }
61   return (pass && (in == keys_size));
62 }
63
64 static bool music_sequence_recording = false;
65 static bool music_sequence_playing = false;
66 static float music_sequence[16] = {0};
67 static uint8_t music_sequence_count = 0;
68 static uint8_t music_sequence_position = 0;
69
70 static uint16_t music_sequence_timer = 0;
71 static uint16_t music_sequence_interval = 100;
72
73 bool process_record_quantum(keyrecord_t *record) {
74
75   /* This gets the keycode from the key pressed */
76   keypos_t key = record->event.key;
77   uint16_t keycode;
78
79   #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
80     uint8_t layer;
81
82     if (record->event.pressed) {
83       layer = layer_switch_get_layer(key);
84       update_source_layers_cache(key, layer);
85     } else {
86       layer = read_source_layers_cache(key);
87     }
88     keycode = keymap_key_to_keycode(layer, key);
89   #else
90     keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
91   #endif
92
93     // This is how you use actions here
94     // if (keycode == KC_LEAD) {
95     //   action_t action;
96     //   action.code = ACTION_DEFAULT_LAYER_SET(0);
97     //   process_action(record, action);
98     //   return false;
99     // }
100
101   #ifdef AUDIO_ENABLE
102     if (keycode == AU_ON && record->event.pressed) {
103       audio_on();
104       audio_on_callback();
105       return false;
106     }
107
108     if (keycode == AU_OFF && record->event.pressed) {
109       audio_off();
110       return false;
111     }
112
113     if (keycode == MU_ON && record->event.pressed) {
114       music_activated = true;
115       PLAY_NOTE_ARRAY(music_scale, false, 0);
116       return false;
117     }
118
119     if (keycode == MU_OFF && record->event.pressed) {
120       music_activated = false;
121       stop_all_notes();
122       return false;
123     }
124
125     if (keycode == MUV_IN && record->event.pressed) {
126       voice_iterate();
127       PLAY_NOTE_ARRAY(music_scale, false, 0);
128       return false;
129     }
130
131     if (keycode == MUV_DE && record->event.pressed) {
132       voice_deiterate();
133       PLAY_NOTE_ARRAY(music_scale, false, 0);
134       return false;
135     }
136
137     if (music_activated) {   
138
139       if (keycode == KC_LCTL && record->event.pressed) { // Start recording
140         stop_all_notes();
141         music_sequence_recording = true;
142         music_sequence_playing = false;
143         music_sequence_count = 0;
144         return false;
145       }
146       if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing
147         stop_all_notes();
148         music_sequence_recording = false;
149         music_sequence_playing = false;
150         return false;
151       }
152       if (keycode == KC_LGUI && record->event.pressed) { // Start playing
153         stop_all_notes();
154         music_sequence_recording = false;
155         music_sequence_playing = true;
156         music_sequence_position = 0;
157         music_sequence_timer = 0;
158         return false;
159       }
160
161       if (keycode == KC_UP) {
162         if (record->event.pressed)
163           music_sequence_interval-=10;
164         return false;
165       }
166       if (keycode == KC_DOWN) {
167         if (record->event.pressed)
168           music_sequence_interval+=10;
169         return false;
170       }
171
172       float freq = ((float)220.0)*pow(2.0, -4.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row));
173       if (record->event.pressed) {
174         play_note(freq, 0xF);
175         if (music_sequence_recording) {
176           music_sequence[music_sequence_count] = freq;
177           music_sequence_count++;
178         }
179       } else {
180         stop_note(freq);
181       }  
182
183       if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
184         return false;
185     }
186   #endif
187
188
189
190 #ifndef DISABLE_LEADER
191   // Leader key set-up
192   if (record->event.pressed) {
193     if (!leading && keycode == KC_LEAD) {
194       leader_start();
195       leading = true;
196       leader_time = timer_read();
197       leader_sequence_size = 0;
198       leader_sequence[0] = 0;
199       leader_sequence[1] = 0;
200       leader_sequence[2] = 0;
201       return false;
202     }
203     if (leading && timer_elapsed(leader_time) < LEADER_TIMEOUT) {
204       leader_sequence[leader_sequence_size] = keycode;
205       leader_sequence_size++;
206       return false;
207     }
208   }
209 #endif
210
211 #define DISABLE_CHORDING
212 #ifndef DISABLE_CHORDING
213
214   if (keycode >= 0x5700 && keycode <= 0x57FF) {
215     if (record->event.pressed) {
216       if (!chording) {
217         chording = true;
218         for (uint8_t i = 0; i < CHORDING_MAX; i++)
219           chord_keys[i] = 0;
220         chord_key_count = 0;
221         chord_key_down = 0;
222       }
223       chord_keys[chord_key_count] = (keycode & 0xFF);
224       chord_key_count++;
225       chord_key_down++;
226       return false;
227     } else {
228       if (chording) {
229         chord_key_down--;
230         if (chord_key_down == 0) {
231           chording = false;
232           // Chord Dictionary
233           if (keys_chord((uint8_t[]){KC_ENTER, KC_SPACE})) {
234             register_code(KC_A);
235             unregister_code(KC_A);
236             return false;
237           }
238           for (uint8_t i = 0; i < chord_key_count; i++) {
239             register_code(chord_keys[i]);
240             unregister_code(chord_keys[i]);
241             return false;
242           }
243         }
244       }
245     }
246   }
247
248 #endif
249
250
251   return process_action_kb(record);
252 }
253
254 void matrix_init_quantum() {
255   matrix_init_kb();
256 }
257
258 void matrix_scan_quantum() {
259   #ifdef AUDIO_ENABLE
260   if (music_sequence_playing) {
261     if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
262       music_sequence_timer = timer_read();
263       stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]);
264       play_note(music_sequence[music_sequence_position], 0xF);
265       music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
266     }
267   }
268
269   #endif
270   
271   matrix_scan_kb();
272 }