diff options
Diffstat (limited to 'quantum')
-rw-r--r-- | quantum/audio/audio_arm.c | 612 | ||||
-rw-r--r-- | quantum/keymap_common.c | 2 | ||||
-rw-r--r-- | quantum/keymap_extras/sendstring_german.h | 4 | ||||
-rw-r--r-- | quantum/led_matrix.c | 391 | ||||
-rw-r--r-- | quantum/led_matrix_drivers.c | 149 | ||||
-rw-r--r-- | quantum/ledmatrix.h | 129 | ||||
-rw-r--r-- | quantum/matrix.c | 2 | ||||
-rw-r--r-- | quantum/process_keycode/process_clicky.c | 26 | ||||
-rw-r--r-- | quantum/quantum.c | 69 | ||||
-rw-r--r-- | quantum/quantum.h | 6 | ||||
-rw-r--r-- | quantum/rgblight.c | 13 | ||||
-rw-r--r-- | quantum/template/avr/config.h | 5 | ||||
-rw-r--r-- | quantum/template/ps2avrgb/config.h | 5 |
13 files changed, 1079 insertions, 334 deletions
diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c index 989f7a64be..f24ce4bd01 100644 --- a/quantum/audio/audio_arm.c +++ b/quantum/audio/audio_arm.c @@ -273,19 +273,24 @@ static const DACConversionGroup dacgrpcfg2 = { .trigger = DAC_TRG(0) }; -void audio_init() -{ - - if (audio_initialized) - return; - - // Check EEPROM - // if (!eeconfig_is_enabled()) - // { - // eeconfig_init(); - // } - // audio_config.raw = eeconfig_read_audio(); +void audio_init() { + + if (audio_initialized) { + return; + } + + // Check EEPROM + #if defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE) + if (!eeconfig_is_enabled()) { + eeconfig_init(); + } + audio_config.raw = eeconfig_read_audio(); +#else // ARM EEPROM audio_config.enable = true; + #ifdef AUDIO_CLICKY_ON + audio_config.clicky_enable = true; + #endif +#endif // ARM EEPROM /* * Starting DAC1 driver, setting up the output pin as analog as suggested @@ -308,16 +313,15 @@ void audio_init() dacStartConversion(&DACD1, &dacgrpcfg1, (dacsample_t *)dac_buffer, DAC_BUFFER_SIZE); dacStartConversion(&DACD2, &dacgrpcfg2, (dacsample_t *)dac_buffer_2, DAC_BUFFER_SIZE); - audio_initialized = true; + audio_initialized = true; - if (audio_config.enable) { - PLAY_SONG(startup_song); - } + if (audio_config.enable) { + PLAY_SONG(startup_song); + } } -void stop_all_notes() -{ +void stop_all_notes() { dprintf("audio stop all notes"); if (!audio_initialized) { @@ -342,347 +346,347 @@ void stop_all_notes() } } -void stop_note(float freq) -{ - dprintf("audio stop note freq=%d", (int)freq); +void stop_note(float freq) { + dprintf("audio stop note freq=%d", (int)freq); - if (playing_note) { - if (!audio_initialized) { - audio_init(); - } - for (int i = 7; i >= 0; i--) { - if (frequencies[i] == freq) { - frequencies[i] = 0; - volumes[i] = 0; - for (int j = i; (j < 7); j++) { - frequencies[j] = frequencies[j+1]; - frequencies[j+1] = 0; - volumes[j] = volumes[j+1]; - volumes[j+1] = 0; - } - break; - } - } - voices--; - if (voices < 0) - voices = 0; - if (voice_place >= voices) { - voice_place = 0; - } - if (voices == 0) { - STOP_CHANNEL_1(); - STOP_CHANNEL_2(); - gptStopTimer(&GPTD8); - frequency = 0; - frequency_alt = 0; - volume = 0; - playing_note = false; + if (playing_note) { + if (!audio_initialized) { + audio_init(); + } + for (int i = 7; i >= 0; i--) { + if (frequencies[i] == freq) { + frequencies[i] = 0; + volumes[i] = 0; + for (int j = i; (j < 7); j++) { + frequencies[j] = frequencies[j+1]; + frequencies[j+1] = 0; + volumes[j] = volumes[j+1]; + volumes[j+1] = 0; } + break; + } + } + voices--; + if (voices < 0) { + voices = 0; + } + if (voice_place >= voices) { + voice_place = 0; + } + if (voices == 0) { + STOP_CHANNEL_1(); + STOP_CHANNEL_2(); + gptStopTimer(&GPTD8); + frequency = 0; + frequency_alt = 0; + volume = 0; + playing_note = false; } + } } #ifdef VIBRATO_ENABLE -float mod(float a, int b) -{ - float r = fmod(a, b); - return r < 0 ? r + b : r; +float mod(float a, int b) { + float r = fmod(a, b); + return r < 0 ? r + b : r; } float vibrato(float average_freq) { - #ifdef VIBRATO_STRENGTH_ENABLE - float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength); - #else - float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter]; - #endif - vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH); - return vibrated_freq; + #ifdef VIBRATO_STRENGTH_ENABLE + float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength); + #else + float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter]; + #endif + vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH); + return vibrated_freq; } #endif static void gpt_cb8(GPTDriver *gptp) { - float freq; - - if (playing_note) { - if (voices > 0) { - - float freq_alt = 0; - if (voices > 1) { - if (polyphony_rate == 0) { - if (glissando) { - if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) { - frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2); - } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) { - frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2); - } else { - frequency_alt = frequencies[voices - 2]; - } - } else { - frequency_alt = frequencies[voices - 2]; - } - - #ifdef VIBRATO_ENABLE - if (vibrato_strength > 0) { - freq_alt = vibrato(frequency_alt); - } else { - freq_alt = frequency_alt; - } - #else - freq_alt = frequency_alt; - #endif - } - - if (envelope_index < 65535) { - envelope_index++; - } - - freq_alt = voice_envelope(freq_alt); - - if (freq_alt < 30.517578125) { - freq_alt = 30.52; - } - - if (GET_CHANNEL_2_FREQ != (uint16_t)freq_alt) { - UPDATE_CHANNEL_2_FREQ(freq_alt); - } else { - RESTART_CHANNEL_2(); - } - //note_timbre; - } - - if (polyphony_rate > 0) { - if (voices > 1) { - voice_place %= voices; - if (place++ > (frequencies[voice_place] / polyphony_rate)) { - voice_place = (voice_place + 1) % voices; - place = 0.0; - } - } - - #ifdef VIBRATO_ENABLE - if (vibrato_strength > 0) { - freq = vibrato(frequencies[voice_place]); - } else { - freq = frequencies[voice_place]; - } - #else - freq = frequencies[voice_place]; - #endif + float freq; + + if (playing_note) { + if (voices > 0) { + + float freq_alt = 0; + if (voices > 1) { + if (polyphony_rate == 0) { + if (glissando) { + if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) { + frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2); + } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) { + frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2); } else { - if (glissando) { - if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) { - frequency = frequency * pow(2, 440/frequency/12/2); - } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) { - frequency = frequency * pow(2, -440/frequency/12/2); - } else { - frequency = frequencies[voices - 1]; - } - } else { - frequency = frequencies[voices - 1]; - } - - #ifdef VIBRATO_ENABLE - if (vibrato_strength > 0) { - freq = vibrato(frequency); - } else { - freq = frequency; - } - #else - freq = frequency; - #endif + frequency_alt = frequencies[voices - 2]; } + } else { + frequency_alt = frequencies[voices - 2]; + } - if (envelope_index < 65535) { - envelope_index++; - } - - freq = voice_envelope(freq); - - if (freq < 30.517578125) { - freq = 30.52; - } - - - if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { - UPDATE_CHANNEL_1_FREQ(freq); + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq_alt = vibrato(frequency_alt); } else { - RESTART_CHANNEL_1(); + freq_alt = frequency_alt; } - //note_timbre; + #else + freq_alt = frequency_alt; + #endif } - } - if (playing_notes) { - if (note_frequency > 0) { - #ifdef VIBRATO_ENABLE - if (vibrato_strength > 0) { - freq = vibrato(note_frequency); - } else { - freq = note_frequency; - } - #else - freq = note_frequency; - #endif - - if (envelope_index < 65535) { - envelope_index++; - } - freq = voice_envelope(freq); + if (envelope_index < 65535) { + envelope_index++; + } + freq_alt = voice_envelope(freq_alt); - if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { - UPDATE_CHANNEL_1_FREQ(freq); - UPDATE_CHANNEL_2_FREQ(freq); - } - //note_timbre; + if (freq_alt < 30.517578125) { + freq_alt = 30.52; + } + + if (GET_CHANNEL_2_FREQ != (uint16_t)freq_alt) { + UPDATE_CHANNEL_2_FREQ(freq_alt); } else { - // gptStopTimer(&GPTD6); - // gptStopTimer(&GPTD7); + RESTART_CHANNEL_2(); + } + //note_timbre; + } + + if (polyphony_rate > 0) { + if (voices > 1) { + voice_place %= voices; + if (place++ > (frequencies[voice_place] / polyphony_rate)) { + voice_place = (voice_place + 1) % voices; + place = 0.0; + } } - note_position++; - bool end_of_note = false; - if (GET_CHANNEL_1_FREQ > 0) { - if (!note_resting) - end_of_note = (note_position >= (note_length*8 - 1)); - else - end_of_note = (note_position >= (note_length*8)); + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(frequencies[voice_place]); + } else { + freq = frequencies[voice_place]; + } + #else + freq = frequencies[voice_place]; + #endif + } else { + if (glissando) { + if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) { + frequency = frequency * pow(2, 440/frequency/12/2); + } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) { + frequency = frequency * pow(2, -440/frequency/12/2); + } else { + frequency = frequencies[voices - 1]; + } } else { - end_of_note = (note_position >= (note_length*8)); + frequency = frequencies[voices - 1]; } - if (end_of_note) { - current_note++; - if (current_note >= notes_count) { - if (notes_repeat) { - current_note = 0; - } else { - STOP_CHANNEL_1(); - STOP_CHANNEL_2(); - // gptStopTimer(&GPTD8); - playing_notes = false; - return; - } - } - if (!note_resting) { - note_resting = true; - current_note--; - if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) { - note_frequency = 0; - note_length = 1; - } else { - note_frequency = (*notes_pointer)[current_note][0]; - note_length = 1; - } - } else { - note_resting = false; - envelope_index = 0; - note_frequency = (*notes_pointer)[current_note][0]; - note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); - } + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(frequency); + } else { + freq = frequency; + } + #else + freq = frequency; + #endif + } - note_position = 0; - } - } + if (envelope_index < 65535) { + envelope_index++; + } - if (!audio_config.enable) { - playing_notes = false; - playing_note = false; - } -} + freq = voice_envelope(freq); -void play_note(float freq, int vol) { + if (freq < 30.517578125) { + freq = 30.52; + } - dprintf("audio play note freq=%d vol=%d", (int)freq, vol); - if (!audio_initialized) { - audio_init(); + if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { + UPDATE_CHANNEL_1_FREQ(freq); + } else { + RESTART_CHANNEL_1(); + } + //note_timbre; } + } - if (audio_config.enable && voices < 8) { + if (playing_notes) { + if (note_frequency > 0) { + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(note_frequency); + } else { + freq = note_frequency; + } + #else + freq = note_frequency; + #endif + if (envelope_index < 65535) { + envelope_index++; + } + freq = voice_envelope(freq); - // Cancel notes if notes are playing - if (playing_notes) - stop_all_notes(); - playing_note = true; + if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { + UPDATE_CHANNEL_1_FREQ(freq); + UPDATE_CHANNEL_2_FREQ(freq); + } + //note_timbre; + } else { + // gptStopTimer(&GPTD6); + // gptStopTimer(&GPTD7); + } - envelope_index = 0; + note_position++; + bool end_of_note = false; + if (GET_CHANNEL_1_FREQ > 0) { + if (!note_resting) + end_of_note = (note_position >= (note_length*8 - 1)); + else + end_of_note = (note_position >= (note_length*8)); + } else { + end_of_note = (note_position >= (note_length*8)); + } - if (freq > 0) { - frequencies[voices] = freq; - volumes[voices] = vol; - voices++; + if (end_of_note) { + current_note++; + if (current_note >= notes_count) { + if (notes_repeat) { + current_note = 0; + } else { + STOP_CHANNEL_1(); + STOP_CHANNEL_2(); + // gptStopTimer(&GPTD8); + playing_notes = false; + return; + } + } + if (!note_resting) { + note_resting = true; + current_note--; + if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) { + note_frequency = 0; + note_length = 1; + } else { + note_frequency = (*notes_pointer)[current_note][0]; + note_length = 1; } + } else { + note_resting = false; + envelope_index = 0; + note_frequency = (*notes_pointer)[current_note][0]; + note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); + } - gptStart(&GPTD8, &gpt8cfg1); - gptStartContinuous(&GPTD8, 2U); - RESTART_CHANNEL_1(); - RESTART_CHANNEL_2(); + note_position = 0; } + } + if (!audio_config.enable) { + playing_notes = false; + playing_note = false; + } } -void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) -{ +void play_note(float freq, int vol) { - if (!audio_initialized) { - audio_init(); + dprintf("audio play note freq=%d vol=%d", (int)freq, vol); + + if (!audio_initialized) { + audio_init(); + } + + if (audio_config.enable && voices < 8) { + + // Cancel notes if notes are playing + if (playing_notes) { + stop_all_notes(); } - if (audio_config.enable) { + playing_note = true; - // Cancel note if a note is playing - if (playing_note) - stop_all_notes(); + envelope_index = 0; - playing_notes = true; + if (freq > 0) { + frequencies[voices] = freq; + volumes[voices] = vol; + voices++; + } - notes_pointer = np; - notes_count = n_count; - notes_repeat = n_repeat; + gptStart(&GPTD8, &gpt8cfg1); + gptStartContinuous(&GPTD8, 2U); + RESTART_CHANNEL_1(); + RESTART_CHANNEL_2(); + } - place = 0; - current_note = 0; +} - note_frequency = (*notes_pointer)[current_note][0]; - note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); - note_position = 0; +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) { - gptStart(&GPTD8, &gpt8cfg1); - gptStartContinuous(&GPTD8, 2U); - RESTART_CHANNEL_1(); - RESTART_CHANNEL_2(); + if (!audio_initialized) { + audio_init(); + } + + if (audio_config.enable) { + + // Cancel note if a note is playing + if (playing_note) { + stop_all_notes(); } + playing_notes = true; + + notes_pointer = np; + notes_count = n_count; + notes_repeat = n_repeat; + + place = 0; + current_note = 0; + + note_frequency = (*notes_pointer)[current_note][0]; + note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); + note_position = 0; + + gptStart(&GPTD8, &gpt8cfg1); + gptStartContinuous(&GPTD8, 2U); + RESTART_CHANNEL_1(); + RESTART_CHANNEL_2(); + } } bool is_playing_notes(void) { - return playing_notes; + return playing_notes; } bool is_audio_on(void) { - return (audio_config.enable != 0); + return (audio_config.enable != 0); } void audio_toggle(void) { - audio_config.enable ^= 1; - eeconfig_update_audio(audio_config.raw); - if (audio_config.enable) - audio_on_user(); + audio_config.enable ^= 1; + eeconfig_update_audio(audio_config.raw); + if (audio_config.enable) { + audio_on_user(); + } } void audio_on(void) { - audio_config.enable = 1; - eeconfig_update_audio(audio_config.raw); - audio_on_user(); + audio_config.enable = 1; + eeconfig_update_audio(audio_config.raw); + audio_on_user(); } void audio_off(void) { - audio_config.enable = 0; - eeconfig_update_audio(audio_config.raw); + stop_all_notes(); + audio_config.enable = 0; + eeconfig_update_audio(audio_config.raw); } #ifdef VIBRATO_ENABLE @@ -690,29 +694,29 @@ void audio_off(void) { // Vibrato rate functions void set_vibrato_rate(float rate) { - vibrato_rate = rate; + vibrato_rate = rate; } void increase_vibrato_rate(float change) { - vibrato_rate *= change; + vibrato_rate *= change; } void decrease_vibrato_rate(float change) { - vibrato_rate /= change; + vibrato_rate /= change; } #ifdef VIBRATO_STRENGTH_ENABLE void set_vibrato_strength(float strength) { - vibrato_strength = strength; + vibrato_strength = strength; } void increase_vibrato_strength(float change) { - vibrato_strength *= change; + vibrato_strength *= change; } void decrease_vibrato_strength(float change) { - vibrato_strength /= change; + vibrato_strength /= change; } #endif /* VIBRATO_STRENGTH_ENABLE */ @@ -722,45 +726,45 @@ void decrease_vibrato_strength(float change) { // Polyphony functions void set_polyphony_rate(float rate) { - polyphony_rate = rate; + polyphony_rate = rate; } void enable_polyphony() { - polyphony_rate = 5; + polyphony_rate = 5; } void disable_polyphony() { - polyphony_rate = 0; + polyphony_rate = 0; } void increase_polyphony_rate(float change) { - polyphony_rate *= change; + polyphony_rate *= change; } void decrease_polyphony_rate(float change) { - polyphony_rate /= change; + polyphony_rate /= change; } // Timbre function void set_timbre(float timbre) { - note_timbre = timbre; + note_timbre = timbre; } // Tempo functions void set_tempo(uint8_t tempo) { - note_tempo = tempo; + note_tempo = tempo; } void decrease_tempo(uint8_t tempo_change) { - note_tempo += tempo_change; + note_tempo += tempo_change; } void increase_tempo(uint8_t tempo_change) { - if (note_tempo - tempo_change < 10) { - note_tempo = 10; - } else { - note_tempo -= tempo_change; - } + if (note_tempo - tempo_change < 10) { + note_tempo = 10; + } else { + note_tempo -= tempo_change; + } } diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 1a6af9e08f..9d2d331ce5 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -127,7 +127,7 @@ action_t action_for_key(uint8_t layer, keypos_t key) action.code = ACTION_LAYER_TAP_TOGGLE(keycode & 0xFF); break; case QK_LAYER_MOD ... QK_LAYER_MOD_MAX: - mod = keycode & 0xF; + mod = mod_config(keycode & 0xF); action_layer = (keycode >> 4) & 0xF; action.code = ACTION_LAYER_MODS(action_layer, mod); break; diff --git a/quantum/keymap_extras/sendstring_german.h b/quantum/keymap_extras/sendstring_german.h index 1eaafee317..f20fab77d1 100644 --- a/quantum/keymap_extras/sendstring_german.h +++ b/quantum/keymap_extras/sendstring_german.h @@ -67,7 +67,7 @@ const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = { /* P Q R S T U V W */ KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, /* X Y Z [ \ ] ^ _ */ - KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, DE_CIRC, DE_MINS, + KC_X, DE_Y, DE_Z, KC_LBRC, KC_BSLS, KC_RBRC, DE_CIRC, DE_MINS, /* ` a b c d e f g */ DE_ACUT, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, /* h i j k l m n o */ @@ -75,7 +75,7 @@ const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = { /* p q r s t u v w */ KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, /* x y z { | } ~ DELETE */ - KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL + KC_X, DE_Y, DE_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL }; #endif diff --git a/quantum/led_matrix.c b/quantum/led_matrix.c new file mode 100644 index 0000000000..8ef8abe712 --- /dev/null +++ b/quantum/led_matrix.c @@ -0,0 +1,391 @@ +/* Copyright 2017 Jason Williams + * Copyright 2017 Jack Humbert + * Copyright 2018 Yiancar + * Copyright 2019 Clueboard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <stdbool.h> +#include "quantum.h" +#include "ledmatrix.h" +#include "progmem.h" +#include "config.h" +#include "eeprom.h" +#include <string.h> +#include <math.h> + +led_config_t led_matrix_config; + +#ifndef MAX + #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif + +#ifndef MIN + #define MIN(a,b) ((a) < (b)? (a): (b)) +#endif + +#ifndef LED_DISABLE_AFTER_TIMEOUT + #define LED_DISABLE_AFTER_TIMEOUT 0 +#endif + +#ifndef LED_DISABLE_WHEN_USB_SUSPENDED + #define LED_DISABLE_WHEN_USB_SUSPENDED false +#endif + +#ifndef EECONFIG_LED_MATRIX + #define EECONFIG_LED_MATRIX EECONFIG_RGBLIGHT +#endif + +#if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > 255 + #define LED_MATRIX_MAXIMUM_BRIGHTNESS 255 +#endif + +bool g_suspend_state = false; + +// Global tick at 20 Hz +uint32_t g_tick = 0; + +// Ticks since this key was last hit. +uint8_t g_key_hit[LED_DRIVER_LED_COUNT]; + +// Ticks since any key was last hit. +uint32_t g_any_key_hit = 0; + +uint32_t eeconfig_read_led_matrix(void) { + return eeprom_read_dword(EECONFIG_LED_MATRIX); +} + +void eeconfig_update_led_matrix(uint32_t config_value) { + eeprom_update_dword(EECONFIG_LED_MATRIX, config_value); +} + +void eeconfig_update_led_matrix_default(void) { + dprintf("eeconfig_update_led_matrix_default\n"); + led_matrix_config.enable = 1; + led_matrix_config.mode = LED_MATRIX_UNIFORM_BRIGHTNESS; + led_matrix_config.val = 128; + led_matrix_config.speed = 0; + eeconfig_update_led_matrix(led_matrix_config.raw); +} + +void eeconfig_debug_led_matrix(void) { + dprintf("led_matrix_config eeprom\n"); + dprintf("led_matrix_config.enable = %d\n", led_matrix_config.enable); + dprintf("led_matrix_config.mode = %d\n", led_matrix_config.mode); + dprintf("led_matrix_config.val = %d\n", led_matrix_config.val); + dprintf("led_matrix_config.speed = %d\n", led_matrix_config.speed); +} + +// Last led hit +#ifndef LED_HITS_TO_REMEMBER + #define LED_HITS_TO_REMEMBER 8 +#endif +uint8_t g_last_led_hit[LED_HITS_TO_REMEMBER] = {255}; +uint8_t g_last_led_count = 0; + +void map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i, uint8_t *led_count) { + led_matrix led; + *led_count = 0; + + for (uint8_t i = 0; i < LED_DRIVER_LED_COUNT; i++) { + // map_index_to_led(i, &led); + led = g_leds[i]; + if (row == led.matrix_co.row && column == led.matrix_co.col) { + led_i[*led_count] = i; + (*led_count)++; + } + } +} + +void led_matrix_update_pwm_buffers(void) { + led_matrix_driver.flush(); +} + +void led_matrix_set_index_value(int index, uint8_t value) { + led_matrix_driver.set_value(index, value); +} + +void led_matrix_set_index_value_all(uint8_t value) { + led_matrix_driver.set_value_all(value); +} + +bool process_led_matrix(uint16_t keycode, keyrecord_t *record) { + if (record->event.pressed) { + uint8_t led[8], led_count; + map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count); + if (led_count > 0) { + for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) { + g_last_led_hit[i - 1] = g_last_led_hit[i - 2]; + } + g_last_led_hit[0] = led[0]; + g_last_led_count = MIN(LED_HITS_TO_REMEMBER, g_last_led_count + 1); + } + for(uint8_t i = 0; i < led_count; i++) + g_key_hit[led[i]] = 0; + g_any_key_hit = 0; + } else { + #ifdef LED_MATRIX_KEYRELEASES + uint8_t led[8], led_count; + map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count); + for(uint8_t i = 0; i < led_count; i++) + g_key_hit[led[i]] = 255; + + g_any_key_hit = 255; + #endif + } + return true; +} + +void led_matrix_set_suspend_state(bool state) { + g_suspend_state = state; +} + +// All LEDs off +void led_matrix_all_off(void) { + led_matrix_set_index_value_all(0); +} + +// Uniform brightness +void led_matrix_uniform_brightness(void) { + led_matrix_set_index_value_all(LED_MATRIX_MAXIMUM_BRIGHTNESS / BACKLIGHT_LEVELS * led_matrix_config.val); +} + +void led_matrix_custom(void) {} + +void led_matrix_task(void) { + if (!led_matrix_config.enable) { + led_matrix_all_off(); + led_matrix_indicators(); + return; + } + + g_tick++; + + if (g_any_key_hit < 0xFFFFFFFF) { + g_any_key_hit++; + } + + for (int led = 0; led < LED_DRIVER_LED_COUNT; led++) { + if (g_key_hit[led] < 255) { + if (g_key_hit[led] == 254) + g_last_led_count = MAX(g_last_led_count - 1, 0); + g_key_hit[led]++; + } + } + + // Ideally we would also stop sending zeros to the LED driver PWM buffers + // while suspended and just do a software shutdown. This is a cheap hack for now. + bool suspend_backlight = ((g_suspend_state && LED_DISABLE_WHEN_USB_SUSPENDED) || + (LED_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > LED_DISABLE_AFTER_TIMEOUT * 60 * 20)); + uint8_t effect = suspend_backlight ? 0 : led_matrix_config.mode; + + // this gets ticked at 20 Hz. + // each effect can opt to do calculations + // and/or request PWM buffer updates. + switch (effect) { + case LED_MATRIX_UNIFORM_BRIGHTNESS: + led_matrix_uniform_brightness(); + break; + default: + led_matrix_custom(); + break; + } + + if (!suspend_backlight) { + led_matrix_indicators(); + } |