diff options
Diffstat (limited to 'quantum')
34 files changed, 1356 insertions, 833 deletions
diff --git a/quantum/analog.c b/quantum/analog.c deleted file mode 100644 index 1ec38df75d..0000000000 --- a/quantum/analog.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2015 Jack Humbert - * - * 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/>. - */ - -// Simple analog to digitial conversion - -#include <avr/io.h> -#include <avr/pgmspace.h> -#include <stdint.h> -#include "analog.h" - - -static uint8_t aref = (1<<REFS0); // default to AREF = Vcc - - -void analogReference(uint8_t mode) -{ - aref = mode & 0xC0; -} - - -// Arduino compatible pin input -int16_t analogRead(uint8_t pin) -{ -#if defined(__AVR_ATmega32U4__) - static const uint8_t PROGMEM pin_to_mux[] = { - 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, - 0x25, 0x24, 0x23, 0x22, 0x21, 0x20}; - if (pin >= 12) return 0; - return adc_read(pgm_read_byte(pin_to_mux + pin)); -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) - if (pin >= 8) return 0; - return adc_read(pin); -#else - return 0; -#endif -} - -// Mux input -int16_t adc_read(uint8_t mux) -{ -#if defined(__AVR_AT90USB162__) - return 0; -#else - uint8_t low; - - ADCSRA = (1<<ADEN) | ADC_PRESCALER; // enable ADC - ADCSRB = (1<<ADHSM) | (mux & 0x20); // high speed mode - ADMUX = aref | (mux & 0x1F); // configure mux input - ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC); // start the conversion - while (ADCSRA & (1<<ADSC)) ; // wait for result - low = ADCL; // must read LSB first - return (ADCH << 8) | low; // must read MSB only once! -#endif -} - - diff --git a/quantum/analog.h b/quantum/analog.h deleted file mode 100644 index 8d93de7dc2..0000000000 --- a/quantum/analog.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2015 Jack Humbert - * - * 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/>. - */ - -#ifndef _analog_h_included__ -#define _analog_h_included__ - -#include <stdint.h> - -void analogReference(uint8_t mode); -int16_t analogRead(uint8_t pin); -int16_t adc_read(uint8_t mux); - -#define ADC_REF_POWER (1<<REFS0) -#define ADC_REF_INTERNAL ((1<<REFS1) | (1<<REFS0)) -#define ADC_REF_EXTERNAL (0) - -// These prescaler values are for high speed mode, ADHSM = 1 -#if F_CPU == 16000000L -#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS1)) -#elif F_CPU == 8000000L -#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS0)) -#elif F_CPU == 4000000L -#define ADC_PRESCALER ((1<<ADPS2)) -#elif F_CPU == 2000000L -#define ADC_PRESCALER ((1<<ADPS1) | (1<<ADPS0)) -#elif F_CPU == 1000000L -#define ADC_PRESCALER ((1<<ADPS1)) -#else -#define ADC_PRESCALER ((1<<ADPS0)) -#endif - -// some avr-libc versions do not properly define ADHSM -#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -#if !defined(ADHSM) -#define ADHSM (7) -#endif -#endif - -#endif diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index c924f2bd58..8e8570d26c 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -13,6 +13,7 @@ * 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 <stdio.h> #include <string.h> //#include <math.h> @@ -98,7 +99,6 @@ uint16_t note_position = 0; float (* notes_pointer)[][2]; uint16_t notes_count; bool notes_repeat; -float notes_rest; bool note_resting = false; uint8_t current_note = 0; @@ -119,9 +119,17 @@ audio_config_t audio_config; uint16_t envelope_index = 0; bool glissando = true; +#ifndef STARTUP_SONG + #define STARTUP_SONG SONG(STARTUP_SOUND) +#endif +float startup_song[][2] = STARTUP_SONG; + void audio_init() { + if (audio_initialized) + return; + // Check EEPROM if (!eeconfig_is_enabled()) { @@ -169,6 +177,11 @@ void audio_init() #endif audio_initialized = true; + + if (audio_config.enable) { + PLAY_SONG(startup_song); + } + } void stop_all_notes() @@ -402,9 +415,12 @@ ISR(TIMER3_COMPA_vect) note_position++; bool end_of_note = false; if (TIMER_3_PERIOD > 0) { - end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF)); + if (!note_resting) + end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF - 1)); + else + end_of_note = (note_position >= (note_length)); } else { - end_of_note = (note_position >= (note_length * 0x7FF)); + end_of_note = (note_position >= (note_length)); } if (end_of_note) { @@ -419,11 +435,16 @@ ISR(TIMER3_COMPA_vect) return; } } - if (!note_resting && (notes_rest > 0)) { + if (!note_resting) { note_resting = true; - note_frequency = 0; - note_length = notes_rest; 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; @@ -534,9 +555,12 @@ ISR(TIMER1_COMPA_vect) note_position++; bool end_of_note = false; if (TIMER_1_PERIOD > 0) { - end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF)); + if (!note_resting) + end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF - 1)); + else + end_of_note = (note_position >= (note_length)); } else { - end_of_note = (note_position >= (note_length * 0x7FF)); + end_of_note = (note_position >= (note_length)); } if (end_of_note) { @@ -551,11 +575,16 @@ ISR(TIMER1_COMPA_vect) return; } } - if (!note_resting && (notes_rest > 0)) { + if (!note_resting) { note_resting = true; - note_frequency = 0; - note_length = notes_rest; 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; @@ -624,7 +653,7 @@ void play_note(float freq, int vol) { } -void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) { if (!audio_initialized) { @@ -649,7 +678,6 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) notes_pointer = np; notes_count = n_count; notes_repeat = n_repeat; - notes_rest = n_rest; place = 0; current_note = 0; diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index 27fdc2ab63..79e0da2295 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -86,7 +86,7 @@ void play_sample(uint8_t * s, uint16_t l, bool r); void play_note(float freq, int vol); void stop_note(float freq); void stop_all_notes(void); -void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest); +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat); #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), \ 0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \ @@ -98,8 +98,10 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) // length. This works around the limitation of C's sizeof operation on pointers. // The global float array for the song must be used here. #define NOTE_ARRAY_SIZE(x) ((int16_t)(sizeof(x) / (sizeof(x[0])))) -#define PLAY_NOTE_ARRAY(note_array, note_repeat, note_rest_style) play_notes(¬e_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat), (note_rest_style)); - +#define PLAY_NOTE_ARRAY(note_array, note_repeat, deprecated_arg) play_notes(¬e_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat)); \ + _Pragma ("message \"'PLAY_NOTE_ARRAY' macro is deprecated\"") +#define PLAY_SONG(note_array) play_notes(¬e_array, NOTE_ARRAY_SIZE((note_array)), false) +#define PLAY_LOOP(note_array) play_notes(¬e_array, NOTE_ARRAY_SIZE((note_array)), true) bool is_playing_notes(void); diff --git a/quantum/audio/musical_notes.h b/quantum/audio/musical_notes.h index a3aaa2f199..647b695640 100644 --- a/quantum/audio/musical_notes.h +++ b/quantum/audio/musical_notes.h @@ -51,12 +51,6 @@ #define ED_NOTE(n) EIGHTH_DOT_NOTE(n) #define SD_NOTE(n) SIXTEENTH_DOT_NOTE(n) -// Note Styles -// Staccato makes sure there is a rest between each note. Think: TA TA TA -// Legato makes notes flow together. Think: TAAA -#define STACCATO 0.01 -#define LEGATO 0 - // Note Timbre // Changes how the notes sound #define TIMBRE_12 0.125 @@ -65,7 +59,6 @@ #define TIMBRE_75 0.750 #define TIMBRE_DEFAULT TIMBRE_50 - // Notes - # = Octave #define NOTE_REST 0.00 diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h index db2d1a94cd..f355d371bd 100644 --- a/quantum/audio/song_list.h +++ b/quantum/audio/song_list.h @@ -18,9 +18,7 @@ #ifndef SONG_LIST_H #define SONG_LIST_H -#define COIN_SOUND \ - E__NOTE(_A5 ),\ - HD_NOTE(_E6 ), +#define NO_SOUND #define ODE_TO_JOY \ Q__NOTE(_E4), Q__NOTE(_E4), Q__NOTE(_F4), Q__NOTE(_G4), \ @@ -55,18 +53,29 @@ E__NOTE(_CS4), E__NOTE(_B4), QD_NOTE(_AS4), \ E__NOTE(_AS4), E__NOTE(_AS4), QD_NOTE(_B4), +#define STARTUP_SOUND \ + E__NOTE(_E6), \ + E__NOTE(_A6), \ + ED_NOTE(_E7), + #define GOODBYE_SOUND \ E__NOTE(_E7), \ E__NOTE(_A6), \ ED_NOTE(_E6), -#define STARTUP_SOUND \ +#define PLANCK_SOUND \ ED_NOTE(_E7 ), \ E__NOTE(_CS7), \ E__NOTE(_E6 ), \ E__NOTE(_A6 ), \ M__NOTE(_CS7, 20), +#define PREONIC_SOUND \ + M__NOTE(_B5, 20), \ + E__NOTE(_B6), \ + M__NOTE(_DS6, 20), \ + E__NOTE(_B6), + #define QWERTY_SOUND \ E__NOTE(_GS6 ), \ E__NOTE(_A6 ), \ @@ -107,7 +116,8 @@ S__NOTE(_REST), \ ED_NOTE(_E7 ), -#define MUSIC_SCALE_SOUND \ + +#define MUSIC_ON_SOUND \ E__NOTE(_A5 ), \ E__NOTE(_B5 ), \ E__NOTE(_CS6), \ @@ -117,6 +127,50 @@ E__NOTE(_GS6), \ E__NOTE(_A6 ), +#define MUSIC_SCALE_SOUND MUSIC_ON_SOUND + +#define MUSIC_OFF_SOUND \ + E__NOTE(_A6 ), \ + E__NOTE(_GS6 ), \ + E__NOTE(_FS6), \ + E__NOTE(_E6 ), \ + E__NOTE(_D6 ), \ + E__NOTE(_CS6), \ + E__NOTE(_B5), \ + E__NOTE(_A5 ), + +#define VOICE_CHANGE_SOUND \ + Q__NOTE(_A5 ), \ + Q__NOTE(_CS6), \ + Q__NOTE(_E6 ), \ + Q__NOTE(_A6 ), + +#define CHROMATIC_SOUND \ + Q__NOTE(_A5 ), \ + Q__NOTE(_AS5 ), \ + Q__NOTE(_B5), \ + Q__NOTE(_C6 ), \ + Q__NOTE(_CS6 ), + +#define MAJOR_SOUND \ + Q__NOTE(_A5 ), \ + Q__NOTE(_B5 ), \ + Q__NOTE(_CS6), \ + Q__NOTE(_D6 ), \ + Q__NOTE(_E6 ), + +#define GUITAR_SOUND \ + Q__NOTE(_E5 ), \ + Q__NOTE(_A5), \ + Q__NOTE(_D6 ), \ + Q__NOTE(_G6 ), + +#define VIOLIN_SOUND \ + Q__NOTE(_G5 ), \ + Q__NOTE(_D6), \ + Q__NOTE(_A6 ), \ + Q__NOTE(_E7 ), + #define CAPS_LOCK_ON_SOUND \ E__NOTE(_A3), \ E__NOTE(_B3), @@ -141,6 +195,16 @@ E__NOTE(_E5), \ E__NOTE(_D5), +#define AG_NORM_SOUND \ + E__NOTE(_A5), \ + E__NOTE(_A5), + +#define AG_SWAP_SOUND \ + SD_NOTE(_B5), \ + SD_NOTE(_A5), \ + SD_NOTE(_B5), \ + SD_NOTE(_A5), + #define UNICODE_WINDOWS \ E__NOTE(_B5), \ S__NOTE(_E6), diff --git a/quantum/config_common.h b/quantum/config_common.h index c88e02d918..4c6a702af4 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -100,4 +100,6 @@ #define API_SYSEX_MAX_SIZE 32 +#include "song_list.h" + #endif diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index b1460c53cc..1c522e8b8b 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -169,7 +169,6 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) } // translates key to keycode -__attribute__ ((weak)) uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) { // Read entire word (16bits) diff --git a/quantum/keymap_extras/keymap_steno.h b/quantum/keymap_extras/keymap_steno.h new file mode 100644 index 0000000000..4ce91cc135 --- /dev/null +++ b/quantum/keymap_extras/keymap_steno.h @@ -0,0 +1,76 @@ +/* Copyright 2017 Joseph Wasson + * + * 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/>. + */ +#ifndef KEYMAP_STENO_H +#define KEYMAP_STENO_H + +#include "keymap.h" + +// List of keycodes for the steno keyboard. To prevent +// errors, this must be <= 42 total entries in order to +// support the GeminiPR protocol. +enum steno_keycodes { + STN__MIN = QK_STENO, + STN_FN = STN__MIN, + STN_NUM, + STN_N1 = STN_NUM, + STN_N2, + STN_N3, + STN_N4, + STN_N5, + STN_N6, + STN_SL, + STN_S1 = STN_SL, + STN_S2, + STN_TL, + STN_KL, + STN_PL, + STN_WL, + STN_HL, + STN_RL, + STN_A, + STN_O, + STN_STR, + STN_ST1 = STN_STR, + STN_ST2, + STN_RES1, + STN_RE1 = STN_RES1, + STN_RES2, + STN_RE2 = STN_RES2, + STN_PWR, + STN_ST3, + STN_ST4, + STN_E, + STN_U, + STN_FR, + STN_RR, + STN_PR, + STN_BR, + STN_LR, + STN_GR, + STN_TR, + STN_SR, + STN_DR, + STN_N7, + STN_N8, + STN_N9, + STN_NA, + STN_NB, + STN_NC, + STN_ZR, + STN__MAX = STN_ZR, // must be less than QK_STENO_BOLT +}; + +#endif diff --git a/quantum/keymap_extras/sendstring_colemak.h b/quantum/keymap_extras/sendstring_colemak.h new file mode 100644 index 0000000000..fa9ace9290 --- /dev/null +++ b/quantum/keymap_extras/sendstring_colemak.h @@ -0,0 +1,41 @@ +/* Copyright 2016 Jack Humbert + * + * 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/>. + */ +/* Sendstring definitions for the Colemak layout */ +#ifndef SENDSTRING_COLEMAK +#define SENDSTRING_COLEMAK + +#include "keymap_colemak.h" + +const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, + KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, KC_ESC, 0, 0, 0, 0, + KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT, + KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, + KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + KC_8, KC_9, CM_SCLN, CM_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH, + KC_2, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G, + CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O, + CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W, + CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS, + KC_GRV, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G, + CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O, + CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W, + CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL +}; + +#endif diff --git a/quantum/keymap_extras/sendstring_dvorak.h b/quantum/keymap_extras/sendstring_dvorak.h new file mode 100644 index 0000000000..f5c5c818b8 --- /dev/null +++ b/quantum/keymap_extras/sendstring_dvorak.h @@ -0,0 +1,41 @@ +/* Copyright 2016 Jack Humbert + * + * 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/>. + */ +/* Sendstring definitions for the Dvorak layout */ +#ifndef SENDSTRING_DVORAK +#define SENDSTRING_DVORAK + +#include "keymap_dvorak.h" + +const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, + KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, KC_ESC, 0, 0, 0, 0, + KC_SPC, DV_1, DV_QUOT, DV_3, DV_4, DV_5, DV_7, DV_QUOT, + DV_9, DV_0, DV_8, DV_EQL, DV_COMM, DV_MINS, DV_DOT, DV_SLSH, + DV_0, DV_1, DV_2, DV_3, DV_4, DV_5, DV_6, DV_7, + DV_8, DV_9, DV_SCLN, DV_SCLN, DV_COMM, DV_EQL, DV_DOT, DV_SLSH, + DV_2, DV_A, DV_B, DV_C, DV_D, DV_E, DV_F, DV_G, + DV_H, DV_I, DV_J, DV_K, DV_L, DV_M, DV_N, DV_O, + DV_P, DV_Q, DV_R, DV_S, DV_T, DV_U, DV_V, DV_W, + DV_X, DV_Y, DV_Z, DV_LBRC, DV_BSLS, DV_RBRC, DV_6, DV_MINS, + DV_GRV, DV_A, DV_B, DV_C, DV_D, DV_E, DV_F, DV_G, + DV_H, DV_I, DV_J, DV_K, DV_L, DV_M, DV_N, DV_O, + DV_P, DV_Q, DV_R, DV_S, DV_T, DV_U, DV_V, DV_W, + DV_X, DV_Y, DV_Z, DV_LBRC, DV_BSLS, DV_RBRC, DV_GRV, KC_DEL +}; + +#endif diff --git a/quantum/keymap_extras/sendstring_jis.h b/quantum/keymap_extras/sendstring_jis.h new file mode 100644 index 0000000000..c5a38c6a5b --- /dev/null +++ b/quantum/keymap_extras/sendstring_jis.h @@ -0,0 +1,58 @@ +/* Copyright 2016 Jack Humbert + * + * 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/>. + */ +/* Sendstring definitions for the JIS keyboard layout */ +#ifndef SENDSTRING_JIS +#define SENDSTRING_JIS + +const bool ascii_to_shift_lut[0x80] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0 +}; + +const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, + KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, KC_ESC, 0, 0, 0, 0, + KC_SPC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + KC_8, KC_9, KC_QUOT, KC_SCLN, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, + KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + KC_8, KC_9, KC_QUOT, KC_SCLN, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, + KC_LBRC, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, + KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + KC_X, KC_Y, KC_Z, KC_RBRC, KC_JYEN, KC_BSLS, KC_EQL, KC_RO, + KC_LBRC, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, + KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + KC_X, KC_Y, KC_Z, KC_RBRC, KC_JYEN, KC_BSLS, KC_EQL, KC_DEL, +}; + +#endif diff --git a/quantum/light_ws2812.c b/quantum/light_ws2812.c deleted file mode 100755 index 2506e3d8ec..0000000000 --- a/quantum/light_ws2812.c +++ /dev/null @@ -1,342 +0,0 @@ -/* -* light weight WS2812 lib V2.0b -* -* Controls WS2811/WS2812/WS2812B RGB-LEDs -* Author: Tim (cpldcpu@gmail.com) -* -* Jan 18th, 2014 v2.0b Initial Version -* Nov 29th, 2015 v2.3 Added SK6812RGBW support -* -* 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 "light_ws2812.h" -#include <avr/interrupt.h> -#include <avr/io.h> -#include <util/delay.h> -#include "debug.h" - -#ifdef RGBW_BB_TWI - -// Port for the I2C -#define I2C_DDR DDRD -#define I2C_PIN PIND -#define I2C_PORT PORTD - -// Pins to be used in the bit banging -#define I2C_CLK 0 -#define I2C_DAT 1 - -#define I2C_DATA_HI()\ -I2C_DDR &= ~ (1 << I2C_DAT);\ -I2C_PORT |= (1 << I2C_DAT); -#define I2C_DATA_LO()\ -I2C_DDR |= (1 << I2C_DAT);\ -I2C_PORT &= ~ (1 << I2C_DAT); - -#define I2C_CLOCK_HI()\ -I2C_DDR &= ~ (1 << I2C_CLK);\ -I2C_PORT |= (1 << I2C_CLK); -#define I2C_CLOCK_LO()\ -I2C_DDR |= (1 << I2C_CLK);\ -I2C_PORT &= ~ (1 << I2C_CLK); - -#define I2C_DELAY 1 - -void I2C_WriteBit(unsigned char c) -{ - if (c > 0) - { - I2C_DATA_HI(); - } - else - { - I2C_DATA_LO(); - } - - I2C_CLOCK_HI(); - _delay_us(I2C_DELAY); - - I2C_CLOCK_LO(); - _delay_us(I2C_DELAY); - - if (c > 0) - { - I2C_DATA_LO(); - } - - _delay_us(I2C_DELAY); -} - -// Inits bitbanging port, must be called before using the functions below -// -void I2C_Init(void) -{ - I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); - - I2C_CLOCK_HI(); - I2C_DATA_HI(); - - _delay_us(I2C_DELAY); -} - -// Send a START Condition -// -void I2C_Start(void) -{ - // set both to high at the same time - I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); - _delay_us(I2C_DELAY); - - I2C_DATA_LO(); - _delay_us(I2C_DELAY); - - I2C_CLOCK_LO(); - _delay_us(I2C_DELAY); -} - -// Send a STOP Condition -// -void I2C_Stop(void) -{ - I2C_CLOCK_HI(); - _delay_us(I2C_DELAY); - - I2C_DATA_HI(); - _delay_us(I2C_DELAY); -} - -// write a byte to the I2C slave device -// -unsigned char I2C_Write(unsigned char c) -{ - for (char i = 0; i < 8; i++) - { - I2C_WriteBit(c & 128); - - c <<= 1; - } - - - I2C_WriteBit(0); - _delay_us(I2C_DELAY); - _delay_us(I2C_DELAY); - - // _delay_us(I2C_DELAY); - //return I2C_ReadBit(); - return 0; -} - - -#endif - -// Setleds for standard RGB -void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds) -{ - // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin)); - ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF)); -} - -void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask) -{ - // ws2812_DDRREG |= pinmask; // Enable DDR - // new universal format (DDR) - _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= pinmask; - - ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask); - _delay_us(50); -} - -// Setleds for SK6812RGBW -void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds) -{ - - #ifdef RGBW_BB_TWI - uint8_t sreg_prev, twcr_prev; - sreg_prev=SREG; - twcr_prev=TWCR; - cli(); - TWCR &= ~(1<<TWEN); - I2C_Init(); - I2C_Start(); - I2C_Write(0x84); - uint16_t datlen = leds<<2; - uint8_t curbyte; - uint8_t * data = (uint8_t*)ledarray; - while (datlen--) { - curbyte=*data++; - I2C_Write(curbyte); - } - I2C_Stop(); - SREG=sreg_prev; - TWCR=twcr_prev; - #endif - - - // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR - // new universal format (DDR) - _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF); - - ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF)); - - - #ifndef RGBW_BB_TWI - _delay_us(80); - #endif -} - -void ws2812_sendarray(uint8_t *data,uint16_t datlen) -{ - ws2812_sendarray_mask(data,datlen,_BV(RGB_DI_PIN & 0xF)); -} - -/* - This routine writes an array of bytes with RGB values to the Dataout pin - using the fast 800kHz clockless WS2811/2812 protocol. -*/ - -// Timing in ns -#define w_zeropulse 350 -#define w_onepulse 900 -#define w_totalperiod 1250 - -// Fixed cycles used by the inner loop -#define w_fixedlow 2 -#define w_fixedhigh 4 -#define w_fixedtotal 8 - -// Insert NOPs to match the timing, if possible -#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000) -#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000) -#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000) - -// w1 - nops between rising edge and falling edge - low -#define w1 (w_zerocycles-w_fixedlow) -// w2 nops between fe low and fe high -#define w2 (w_onecycles-w_fixedhigh-w1) -// w3 nops to complete loop -#define w3 (w_totalcycles-w_fixedtotal-w1-w2) - -#if w1>0 - #define w1_nops w1 -#else - #define w1_nops 0 -#endif - -// The only critical timing parameter is the minimum pulse length of the "0" -// Warn or throw error if this timing can not be met with current F_CPU settings. -#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000) -#if w_lowtime>550 - #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?" -#elif w_lowtime>450 - #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)." - #warning "Please consider a higher clockspeed, if possible" -#endif - -#if w2>0 -#define w2_nops w2 -#else -#define w2_nops 0 -#endif - -#if w3>0 -#define w3_nops w3 -#else -#define w3_nops 0 -#endif - -#define w_nop1 "nop \n\t" -#define w_nop2 "rjmp .+0 \n\t" -#define w_nop4 w_nop2 w_nop2 -#define w_nop8 w_nop4 w_nop4 -#define w_nop16 w_nop8 w_nop8 - -void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi) -{ - uint8_t curbyte,ctr,masklo; - uint8_t sreg_prev; - - // masklo =~maskhi&ws2812_PORTREG; - // maskhi |= ws2812_PORTREG; - masklo =~maskhi&_SFR_IO8((RGB_DI_PIN >> 4) + 2); - maskhi |= _SFR_IO8((RGB_DI_PIN >> 4) + 2); - sreg_prev=SREG; - cli(); - - while (datlen--) { - curbyte=(*data++); - - asm volatile( - " ldi %0,8 \n\t" - "loop%=: \n\t" - " out %2,%3 \n\t" // '1' [01] '0' [01] - re -#if (w1_nops&1) -w_nop1 -#endif -#if (w1_nops&2) -w_nop2 -#endif -#if (w1_nops&4) -w_nop4 -#endif -#if (w1_nops&8) -w_nop8 -#endif -#if (w1_nops&16) -w_nop16 -#endif - " sbrs %1,7 \n\t" // '1' [03] '0' [02] - " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low - " lsl %1 \n\t" // '1' [04] '0' [04] -#if (w2_nops&1) - w_nop1 -#endif -#if (w2_nops&2) - w_nop2 -#endif -#if (w2_nops&4) - w_nop4 -#endif -#if (w2_nops&8) - w_nop8 -#endif -#if (w2_nops&16) - w_nop16 -#endif - " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high -#if (w3_nops&1) -w_nop1 -#endif -#if (w3_nops&2) -w_nop2 -#endif -#if (w3_nops&4) -w_nop4 -#endif -#if (w3_nops&8) -w_nop8 -#endif -#if (w3_nops&16) -w_nop16 -#endif - - " dec %0 \n\t" // '1' [+2] '0' [+2] - " brne loop%=\n\t" // '1' [+3] '0' [+4] - : "=&d" (ctr) - : "r" (curbyte), "I" (_SFR_IO_ADDR(_SFR_IO8((RGB_DI_PIN >> 4) + 2))), "r" (maskhi), "r" (masklo) - ); - } - - SREG=sreg_prev; -} diff --git a/quantum/light_ws2812.h b/quantum/light_ws2812.h deleted file mode 100755 index 60924a0fb6..0000000000 --- a/quantum/light_ws2812.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * light weight WS2812 lib include - * - * Version 2.3 - Nev 29th 2015 - * Author: Tim (cpldcpu@gmail.com) - * - * Please do not change this file! All configuration is handled in "ws2812_config.h" - * - * 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/>. - */ - -#ifndef LIGHT_WS2812_H_ -#define LIGHT_WS2812_H_ - -#include <avr/io.h> -#include <avr/interrupt.h> -//#include "ws2812_config.h" -//#include "i2cmaster.h" - -#ifdef RGBW - #define LED_TYPE struct cRGBW -#else - #define LED_TYPE struct cRGB -#endif - - -/* - * Structure of the LED array - * - * cRGB: RGB for WS2812S/B/C/D, SK6812, SK6812Mini, SK6812WWA, APA104, APA106 - * cRGBW: RGBW for SK6812RGBW - */ - -struct cRGB { uint8_t g; uint8_t r; uint8_t b; }; -struct cRGBW { uint8_t g; uint8_t r; uint8_t b; uint8_t w;}; - - - -/* User Interface - * - * Input: - * ledarray: An array of GRB data describing the LED colors - * number_of_leds: The number of LEDs to write - * pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0) - * - * The functions will perform the following actions: - * - Set the data-out pin as output - * - Send out the LED data - * - Wait 50�s to reset the LEDs - */ - -void ws2812_setleds (LED_TYPE *ledarray, uint16_t number_of_leds); -void ws2812_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask); -void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); - -/* - * Old interface / Internal functions - * - * The functions take a byte-array and send to the data output as WS2812 bitstream. - * The length is the number of bytes to send - three per LED. - */ - -void ws2812_sendarray (uint8_t *array,uint16_t length); -void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask); - - -/* - * Internal defines - */ -#ifndef CONCAT -#define CONCAT(a, b) a ## b -#endif -#ifndef CONCAT_EXP -#define CONCAT_EXP(a, b) CONCAT(a, b) -#endif - -// #define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port) -// #define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port) - -#endif /* LIGHT_WS2812_H_ */ diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index 0b6380ed39..32057ae8dc 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -1,10 +1,19 @@ #include "audio.h" #include "process_audio.h" +#ifndef VOICE_CHANGE_SONG + #define VOICE_CHANGE_SONG SONG(VOICE_CHANGE_SOUND) +#endif +float voice_change_song[][2] = VOICE_CHANGE_SONG; + +#ifndef PITCH_STANDARD_A + #define PITCH_STANDARD_A 440.0f +#endif + static float compute_freq_for_midi_note(uint8_t note) { // https://en.wikipedia.org/wiki/MIDI_tuning_standard - return pow(2.0, (note - 69) / 12.0) * 440.0f; + return pow(2.0, (note - 69) / 12.0) * PITCH_STANDARD_A; } bool process_audio(uint16_t keycode, keyrecord_t *record) { @@ -20,12 +29,9 @@ bool process_audio(uint16_t keycode, keyrecord_t *record) { } if (keycode == AU_TOG && record->event.pressed) { - if (is_audio_on()) - { + if (is_audio_on()) { audio_off(); - } - else - { + } else { audio_on(); } return false; @@ -33,13 +39,13 @@ bool process_audio(uint16_t keycode, keyrecord_t *record) { if (keycode == MUV_IN && record->event.pressed) { voice_iterate(); - music_scale_user(); + PLAY_SONG(voice_change_song); return false; } if (keycode == MUV_DE && record->event.pressed) { voice_deiterate(); - music_scale_user(); + PLAY_SONG(voice_change_song); return false; } diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 217dca2807..63841d1e87 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -27,6 +27,7 @@ bool music_activated = false; uint8_t music_starting_note = 0x0C; int music_offset = 7; +uint8_t music_mode = MUSIC_MODE_CHROMATIC; // music sequencer static bool music_sequence_recording = false; @@ -39,6 +40,39 @@ static uint8_t music_sequence_position = 0; static uint16_t music_sequence_timer = 0; static uint16_t music_sequence_interval = 100; +#ifdef AUDIO_ENABLE + #ifndef MUSIC_ON_SONG + #define MUSIC_ON_SONG SONG(MUSIC_ON_SOUND) + #endif + #ifndef MUSIC_OFF_SONG + #define MUSIC_OFF_SONG SONG(MUSIC_OFF_SOUND) + #endif + #ifndef CHROMATIC_SONG + #define CHROMATIC_SONG SONG(CHROMATIC_SOUND) + #endif + #ifndef GUITAR_SONG + #define GUITAR_SONG SONG(GUITAR_SOUND) + #endif + #ifndef VIOLIN_SONG + #define VIOLIN_SONG SONG(VIOLIN_SOUND) + #endif + #ifndef MAJOR_SONG + #define MAJOR_SONG SONG(MAJOR_SOUND) + #endif + float music_mode_songs[NUMBER_OF_MODES][5][2] = { + CHROMATIC_SONG, + GUITAR_SONG, + VIOLIN_SONG, + MAJOR_SONG + }; + float music_on_song[][2] = MUSIC_ON_SONG; + float music_off_song[][2] = MUSIC_OFF_SONG; +#endif + +#ifndef MUSIC_MASK + #define MUSIC_MASK keycode < 0xFF +#endif + static void music_noteon(uint8_t note) { #ifdef AUDIO_ENABLE process_audio_noteon(note); @@ -79,70 +113,71 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } if (keycode == MU_TOG && record->event.pressed) { - if (music_activated) - { + if (music_activated) { music_off(); - } - else - { + } else { music_on(); } return false; } - if (music_activated) { + if (keycode == MU_MOD && record->event.pressed) { + music_mode_cycle(); + return false; + } - if (keycode == KC_LCTL && record->event.pressed) { // Start recording - music_all_notes_off(); - music_sequence_recording = true; - music_sequence_recorded = false; - music_sequence_playing = false; - music_sequence_count = 0; - return false; - } + if (music_activated) { + if (record->event.pressed) { + if (keycode == KC_LCTL) { // Start recording + music_all_notes_off(); + music_sequence_recording = true; + music_sequence_recorded = false; + music_sequence_playing = false; + music_sequence_count = 0; + return false; + } - if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing - music_all_notes_off(); - if (music_sequence_recording) { // was recording - music_sequence_recorded = true; + if (keycode == KC_LALT) { // Stop recording/playing + music_all_notes_off(); + if (music_sequence_recording) { // was recording + music_sequence_recorded = true; + } + music_sequence_recording = false; + music_sequence_playing = false; + return false; } - music_sequence_recording = false; - music_sequence_playing = false; - return false; - } - if (keycode == KC_LGUI && record->event.pressed && music_sequence_recorded) { // Start playing - music_all_notes_off(); - music_sequence_recording = false; - music_sequence_playing = true; - music_sequence_position = 0; - music_sequence_timer = 0; - return false; - } + if (keycode == KC_LGUI && music_sequence_recorded) { // Start playing + music_all_notes_off(); + music_sequence_recording = false; + music_sequence_playing = true; + music_sequence_position = 0; + music_sequence_timer = 0; + return false; + } - if (keycode == KC_UP) { - if (record->event.pressed) - music_sequence_interval-=10; - return false; - } + if (keycode == KC_UP) { + music_sequence_interval-=10; + return false; + } - if (keycode == KC_DOWN) { - if (record->event.pressed) - music_sequence_interval+=10; - return false; + if (keycode == KC_DOWN) { + music_sequence_interval+=10; + return false; + } } - #define MUSIC_MODE_GUITAR - - #ifdef MUSIC_MODE_CHROMATIC - uint8_t note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row); - #elif defined(MUSIC_MODE_GUITAR) - uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row); - #elif defined(MUSIC_MODE_VIOLIN) - uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row); - #else - uint8_t note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row); - #endif + uint8_t note; + if (music_mode == MUSIC_MODE_CHROMATIC) + note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row); + else if (music_mode == MUSIC_MODE_GUITAR) + note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row); + else if (music_mode == MUSIC_MODE_VIOLIN) + note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row); + else if (music_mode == MUSIC_MODE_MAJOR) + note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row); + else + note = music_starting_note; if (record->event.pressed) { music_noteon(note); @@ -154,7 +189,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { music_noteoff(note); } - if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through + if (MUSIC_MASK) return false; } @@ -175,12 +210,26 @@ void music_toggle(void) { void music_on(void) { music_activated = 1; + #ifdef AUDIO_ENABLE + PLAY_SONG(music_on_song); + #endif music_on_user(); } void music_off(void) { - music_activated = 0; music_all_notes_off(); + music_activated = 0; + #ifdef AUDIO_ENABLE + PLAY_SONG(music_off_song); + #endif +} + +void music_mode_cycle(void) { + music_all_notes_off(); + music_mode = (music_mode + 1) % NUMBER_OF_MODES; + #ifdef AUDIO_ENABLE + PLAY_SONG(music_mode_songs[music_mode]); + #endif } void matrix_scan_music(void) { diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h index 8dfbf041f4..ee027197c2 100644 --- a/quantum/process_keycode/process_music.h +++ b/quantum/process_keycode/process_music.h @@ -21,6 +21,14 @@ #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) +enum music_modes { + MUSIC_MODE_CHROMATIC, + MUSIC_MODE_GUITAR, + MUSIC_MODE_VIOLIN, + MUSIC_MODE_MAJOR, + NUMBER_OF_MODES +}; + bool process_music(uint16_t keycode, keyrecord_t *record); bool is_music_on(void); @@ -31,6 +39,7 @@ void music_off(void); void music_on_user(void); void music_scale_user(void); void music_all_notes_off(void); +void music_mode_cycle(void); void matrix_scan_music(void); diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c new file mode 100644 index 0000000000..71e5e8ff1c --- /dev/null +++ b/quantum/process_keycode/process_steno.c @@ -0,0 +1,166 @@ +/* Copyright 2017 Joseph Wasson + * + * 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 "process_steno.h" +#include "quantum_keycodes.h" +#include "keymap_steno.h" +#include "virtser.h" + +// TxBolt Codes +#define TXB_NUL 0 +#define TXB_S_L 0b00000001 +#define TXB_T_L 0b00000010 +#define TXB_K_L 0b00000100 +#define TXB_P_L 0b00001000 +#define TXB_W_L 0b00010000 +#define TXB_H_L 0b00100000 +#define TXB_R_L 0b01000001 +#define TXB_A_L 0b01000010 +#define TXB_O_L 0b01000100 +#define TXB_STR 0b01001000 +#define TXB_E_R 0b01010000 +#define TXB_U_R 0b01100000 +#define TXB_F_R 0b10000001 +#define TXB_R_R 0b10000010 +#define TXB_P_R 0b10000100 +#define TXB_B_R 0b10001000 +#define TXB_L_R 0b10010000 +#define TXB_G_R 0b10100000 +#define TXB_T_R 0b11000001 +#define TXB_S_R 0b11000010 +#define TXB_D_R 0b11000100 +#define TXB_Z_R 0b11001000 +#define TXB_NUM 0b11010000 + +#define TXB_GRP0 0b00000000 +#define TXB_GRP1 0b01000000 +#define TXB_GRP2 0b10000000 +#define TXB_GRP3 0b11000000 +#define TXB_GRPMASK 0b11000000 + +#define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6) + +#define BOLT_STATE_SIZE 4 +#define GEMINI_STATE_SIZE 6 + +uint8_t state[MAX(BOLT_STATE_SIZE, GEMINI_STATE_SIZE)] = {0}; +uint8_t pressed = 0; +steno_mode_t mode; + +uint8_t boltmap[64] = { + TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, + TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, + TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, + TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, + TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, + TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R +}; + +#define BOLTMAP_MASK (sizeof(boltmap) - 1) + + +void steno_clear_state(void) { + memset(state, 0, sizeof(state)); +} + +void steno_init() { + if (!eeconfig_is_enabled()) { + eeconfig_init(); + } + mode = eeprom_read_byte(EECONFIG_STENOMODE); +} + +void steno_set_mode(steno_mode_t new_mode) { + steno_clear_state(); + mode = new_mode; + eeprom_update_byte(EECONFIG_STENOMODE, mode); +} + +void send_steno_state(uint8_t size, bool send_empty) { + for (uint8_t i = 0; i < size; ++i) { + if (state[i] || send_empty) { + virtser_send(state[i]); + } + } + steno_clear_state(); +} + +bool update_state_bolt(uint8_t key) { + uint8_t boltcode = boltmap[key]; + state[TXB_GET_GROUP(boltcode)] |= boltcode; + return false; +} + +bool send_state_bolt(void) { + send_steno_state(BOLT_STATE_SIZE, false); + virtser_send(0); // terminating byte + return false; +} + +bool update_state_gemini(uint8_t key) { + state[key / 7] |= 1 << (6 - (key % 7)); + return false; +} + +bool send_state_gemini(void) { + state[0] |= 0x80; // Indicate start of packet + send_steno_state(GEMINI_STATE_SIZE, true); + return false; +} + +bool process_steno(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case QK_STENO_BOLT: + if (IS_PRESSED(record->event)) { + steno_set_mode(STENO_MODE_BOLT); + } + return false; + + case QK_STENO_GEMINI: + if (IS_PRESSED(record->event)) { + steno_set_mode(STENO_MODE_GEMINI); + } + return false; + + case STN__MIN...STN__MAX: + if (IS_PRESSED(record->event)) { + uint8_t key = keycode - QK_STENO; + ++pressed; + switch(mode) { + case STENO_MODE_BOLT: + return update_state_bolt(key); + case STENO_MODE_GEMINI: + return update_state_gemini(key); + default: + return false; + } + } else { + --pressed; + if (pressed <= 0) { + pressed = 0; + switch(mode) { + case STENO_MODE_BOLT: + return send_state_bolt(); + case STENO_MODE_GEMINI: + return send_state_gemini(); + default: + return false; + } + } + } + + } + return true; +} diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h new file mode 100644 index 0000000000..3bbcbeaaf8 --- /dev/null +++ b/quantum/process_keycode/process_steno.h @@ -0,0 +1,31 @@ +/* Copyright 2017 Joseph Wasson + * + * 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/>. + */ +#ifndef PROCESS_STENO_H +#define PROCESS_STENO_H + +#include "quantum.h" + +#if defined(STENO_ENABLE) && !defined(VIRTSER_ENABLE) + #error "must have virtser enabled to use steno" +#endif + +typedef enum { STENO_MODE_BOLT, STENO_MODE_GEMINI } steno_mode_t; + +bool process_steno(uint16_t keycode, keyrecord_t *record); +void steno_init(void); +void steno_set_mode(steno_mode_t mode); + +#endif
\ No newline at end of file diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c index 4fd45810bb..00870c4e7f 100644 --- a/quantum/process_keycode/process_tap_dance.c +++ b/quantum/process_keycode/process_tap_dance.c @@ -41,6 +41,24 @@ void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) { } } +void qk_tap_dance_dual_role_finished (qk_tap_dance_state_t *state, void *user_data) { + qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data; + + if (state->count == 1) { + register_code16 (pair->kc); + } else if (state->count == 2) { + layer_invert (pair->layer); + } +} + +void qk_tap_dance_dual_role_reset (qk_tap_dance_state_t *state, void *user_data) { + qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data; + + if (state->count == 1) { + unregister_code16 (pair->kc); + } +} + static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, void *user_data, qk_tap_dance_user_fn_t fn) diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h index f42c154a05..37a27c5366 100644 --- a/quantum/process_keycode/process_tap_dance.h +++ b/quantum/process_keycode/process_tap_dance.h @@ -54,11 +54,22 @@ typedef struct uint16_t kc2; } qk_tap_dance_pair_t; +typedef struct +{ + uint16_t kc; + uint8_t layer; +} qk_tap_dance_dual_role_t; + #define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) { \ .fn = { NULL, qk_tap_dance_pair_finished, qk_tap_dance_pair_reset }, \ .user_data = (void *)&((qk_tap_dance_pair_t) { kc1, kc2 }), \ } +#define ACTION_TAP_DANCE_DUAL_ROLE(kc, layer) { \ + .fn = { NULL, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset }, \ + .user_data = (void *)&((qk_tap_dance_dual_role_t) { kc, layer }), \ + } + #define ACTION_TAP_DANCE_FN(user_fn) { \ .fn = { NULL, user_fn, NULL }, \ .user_data = NULL, \ @@ -86,6 +97,9 @@ void reset_tap_dance (qk_tap_dance_state_t *state); void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data); void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data); +void qk_tap_dance_dual_role_finished (qk_tap_dance_state_t *state, void *user_data); +void qk_tap_dance_dual_role_reset (qk_tap_dance_state_t *state, void *user_data); + #else #define TD(n) KC_NO diff --git a/quantum/quantum.c b/quantum/quantum.c index 5bb7b04d53..1f8ce6c46f 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -30,6 +30,25 @@ extern backlight_config_t backlight_config; #include "fauxclicky.h" #endif +#ifdef AUDIO_ENABLE + #ifndef GOODBYE_SONG + #define GOODBYE_SONG SONG(GOODBYE_SOUND) + #endif + #ifndef AG_NORM_SONG + #define AG_NORM_SONG SONG(AG_NORM_SOUND) + #endif + #ifndef AG_SWAP_SONG + #define AG_SWAP_SONG SONG(AG_SWAP_SOUND) + #endif + #ifndef DEFAULT_LAYER_SONGS + #define DEFAULT_LAYER_SONGS { } + #endif + float goodbye_song[][2] = GOODBYE_SONG; + float ag_norm_song[][2] = AG_NORM_SONG; + float ag_swap_song[][2] = AG_SWAP_SONG; + float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS; +#endif + static void do_code16 (uint16_t code, void (*f) (uint8_t)) { switch (code) { case QK_MODS ... QK_MODS_MAX: @@ -116,9 +135,15 @@ void reset_keyboard(void) { clear_keyboard(); #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_ENABLE_BASIC)) music_all_notes_off(); + uint16_t timer_start = timer_read(); + PLAY_SONG(goodbye_song); shutdown_user(); -#endif + while(timer_elapsed(timer_start) < 250) + wait_ms(1); + stop_all_notes(); +#else wait_ms(250); +#endif #ifdef CATERINA_BOOTLOADER *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific #endif @@ -175,6 +200,9 @@ bool process_record_quantum(keyrecord_t *record) { #ifdef AUDIO_ENABLE process_audio(keycode, record) && #endif + #ifdef STENO_ENABLE + process_steno(keycode, record) && + #endif #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) process_music(keycode, record) && #endif @@ -351,6 +379,9 @@ bool process_record_quantum(keyrecord_t *record) { case MAGIC_SWAP_ALT_GUI: keymap_config.swap_lalt_lgui = true; keymap_config.swap_ralt_rgui = true; + #ifdef AUDIO_ENABLE + PLAY_SONG(ag_swap_song); + #endif break; case MAGIC_UNSWAP_CONTROL_CAPSLOCK: keymap_config.swap_control_capslock = false; @@ -379,6 +410,9 @@ bool process_record_quantum(keyrecord_t *record) { case MAGIC_UNSWAP_ALT_GUI: keymap_config.swap_lalt_lgui = false; keymap_config.swap_ralt_rgui = false; + #ifdef AUDIO_ENABLE + PLAY_SONG(ag_norm_song); + #endif break; case MAGIC_TOGGLE_NKRO: keymap_config.nkro = !keymap_config.nkro; @@ -455,103 +489,8 @@ bool process_record_quantum(keyrecord_t *record) { return process_action_kb(record); } -#ifdef JIS_KEYCODE -static const uint16_t ascii_to_shift_lut[8] PROGMEM = { - 0x0000, /*0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,*/ - 0x0000, /*0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,*/ - 0x7ff0, /*0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 0, 0, 0,*/ - 0x000f, /*0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1,*/ - 0x7fff, /*0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1,*/ - 0xffe1, /*1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 0, 1,*/ - 0x8000, /*1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,*/ - 0x001e, /*0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 0*/ -}; - -static const struct { - uint8_t controls_0[16], - controls_1[16], - numerics[16], - alphabets_0[16], - alphabets_1[16]; -} lower_to_keycode PROGMEM = { - .controls_0 = { - 0, 0, 0, 0, 0, 0, 0, 0, - KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, - }, - .controls_1 = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, KC_ESC, 0, 0, 0, 0, - }, - .numerics = { - KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, - KC_8, KC_9, KC_QUOT, KC_SCLN, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, - }, - .alphabets_0 = { - KC_LBRC, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, - KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, - }, - .alphabets_1 = { - KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, - KC_X, KC_Y, KC_Z, KC_RBRC, KC_JYEN, KC_BSLS, KC_EQL, KC_RO, - }, -}; -static const uint8_t* ascii_to_keycode_lut[8] = { - lower_to_keycode.controls_0, - lower_to_keycode.controls_1, - lower_to_keycode.numerics, - lower_to_keycode.numerics, - lower_to_keycode.alphabets_0, - lower_to_keycode.alphabets_1, - lower_to_keycode.alphabets_0, - lower_to_keycode.alphabets_1 -}; - -void send_string(const char *str) { - while (1) { - uint8_t keycode; - bool shift; - uint8_t ascii_code = pgm_read_byte(str); - - if ( ascii_code == 0x00u ){ break; } - else if (ascii_code == 0x20u) { - keycode = KC_SPC; - shift = false; - } - else if (ascii_code == 0x7Fu) { - keycode = KC_DEL; - shift = false; - } - else { - int hi = ascii_code>>4 & 0x0f, - lo = ascii_code & 0x0f; - keycode = pgm_read_byte(&ascii_to_keycode_lut[hi][lo]); - shift = !!( pgm_read_word(&ascii_to_shift_lut[hi]) & (0x8000u>>lo) ); - } - - if (shift) { - register_code(KC_LSFT); - register_code(keycode); - unregister_code(keycode); - unregister_code(KC_LSFT); - } - else { - register_code(keycode); - unregister_code(keycode); - } - ++str; - } -} - -#else -static const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = { +__attribute__ ((weak)) +const bool ascii_to_shift_lut[0x80] PROGMEM = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -570,7 +509,8 @@ static const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = { 0, 0, 0, 1, 1, 1, 1, 0 }; -static const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = { +__attribute__ ((weak)) +const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = { 0, 0, 0, 0, 0, 0, 0, 0, KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -590,12 +530,16 @@ static const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = { }; void send_string(const char *str) { + send_string_with_delay(str, 0); +} + +void send_string_with_delay(const char *str, uint8_t interval) { while (1) { uint8_t keycode; uint8_t ascii_code = pgm_read_byte(str); if (!ascii_code) break; - keycode = pgm_read_byte(&ascii_to_qwerty_keycode_lut[ascii_code]); - if (pgm_read_byte(&ascii_to_qwerty_shift_lut[ascii_code])) { + keycode = pgm_read_byte(&ascii_to_keycode_lut[ascii_code]); + if (pgm_read_byte(&ascii_to_shift_lut[ascii_code])) { register_code(KC_LSFT); register_code(keycode); unregister_code(keycode); @@ -606,54 +550,18 @@ void send_string(const char *str) { unregister_code(keycode); } ++str; + // interval + { uint8_t ms = interval; while (ms--) wait_ms(1); } } } -#endif - -/* for users whose OSes are set to Colemak */ -#if 0 -#include "keymap_colemak.h" - -const bool ascii_to_colemak_shift_lut[0x80] PROGMEM = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 1, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 0 -}; - -const uint8_t ascii_to_colemak_keycode_lut[0x80] PROGMEM = { - 0, 0, 0, 0, 0, 0, 0, 0, - KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, KC_ESC, 0, 0, 0, 0, - KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT, - KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, - KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, - KC_8, KC_9, CM_SCLN, CM_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH, - KC_2, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G, - CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O, - CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W, - CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS, - KC_GRV, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G, - CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O, - CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W, - CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL -}; - -#endif +void set_single_persistent_default_layer(uint8_t default_layer) { + #ifdef AUDIO_ENABLE + PLAY_SONG(default_layer_songs[default_layer]); + #endif + eeconfig_update_default_layer(1U<<default_layer); + default_layer_set(1U<<default_layer); +} void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) { @@ -705,6 +613,9 @@ void matrix_init_quantum() { #ifdef BACKLIGHT_ENABLE backlight_init_ports(); #endif + #ifdef AUDIO_ENABLE + audio_init(); + #endif matrix_init_kb(); } @@ -814,14 +725,14 @@ void backlight_set(uint8_t level) // _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); // #endif #endif - } + } #ifndef NO_BACKLIGHT_CLOCK else if ( level == BACKLIGHT_LEVELS ) { // Turn on PWM control of backlight pin TCCR1A |= _BV(COM1x1); // Set the brightness OCR1x = 0xFFFF; - } + } else { // Turn on PWM control of backlight pin TCCR1A |= _BV(COM1x1); @@ -839,7 +750,7 @@ uint8_t backlight_tick = 0; void backlight_task(void) { #ifdef NO_BACKLIGHT_CLOCK - if ((0xFFFF >> ((BACKLIGHT_LEVELS - backlight_config.level) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) { + if ((0xFFFF >> ((BACKLIGHT_LEVELS - backlight_config.level) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) { #if BACKLIGHT_ON_STATE == 0 // PORTx &= ~n _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); diff --git a/quantum/quantum.h b/quantum/quantum.h index 2bf18d095e..453cb43f88 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -56,9 +56,14 @@ extern uint32_t default_layer_state; #endif // MIDI_ENABLE #ifdef AUDIO_ENABLE + #include "audio.h" #include "process_audio.h" #endif +#ifdef STENO_ENABLE + #include "process_steno.h" +#endif + #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) #include "process_music.h" #endif @@ -95,11 +100,16 @@ extern uint32_t default_layer_state; #endif #define SEND_STRING(str) send_string(PSTR(str)) +extern const bool ascii_to_shift_lut[0x80]; +extern const uint8_t ascii_to_keycode_lut[0x80]; void send_string(const char *str); +void send_string_with_delay(const char *str, uint8_t interval); // For tri-layer void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3); +void set_single_persistent_default_layer(uint8_t default_layer); + void tap_random_base64(void); #define IS_LAYER_ON(layer) (layer_state & (1UL << (layer))) diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 6038e31c46..acdb9248d6 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -26,6 +26,10 @@ #endif #endif +// Fillers to make layering more clear +#define _______ KC_TRNS +#define XXXXXXX KC_NO + enum quantum_keycodes { // Ranges used in shortucuts - not to be used directly QK_TMK = 0x0000, @@ -67,6 +71,12 @@ enum quantum_keycodes { QK_TAP_DANCE_MAX = 0x57FF, QK_LAYER_TAP_TOGGLE = 0x5800, QK_LAYER_TAP_TOGGLE_MAX = 0x58FF, +#ifdef STENO_ENABLE + QK_STENO = 0x5A00, + QK_STENO_BOLT = 0x5A30, + QK_STENO_GEMINI = 0x5A31, + QK_STENO_MAX = 0x5A3F, +#endif QK_MOD_TAP = 0x6000, QK_MOD_TAP_MAX = 0x7FFF, #if defined(UNICODEMAP_ENABLE) && defined(UNICODE_ENABLE) @@ -128,6 +138,9 @@ enum quantum_keycodes { MU_OFF, MU_TOG, + // Music mode cycle + MU_MOD, + // Music voice iterate MUV_IN, MUV_DE, diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 92130192ce..8fea96a9e8 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -61,7 +61,7 @@ #include <stdint.h> #include <stdbool.h> #include "eeconfig.h" -#include "light_ws2812.h" +#include "ws2812.h" extern LED_TYPE led[RGBLED_NUM]; diff --git a/quantum/visualizer/common_gfxconf.h b/quantum/visualizer/common_gfxconf.h new file mode 100644 index 0000000000..eb705b1881 --- /dev/null +++ b/quantum/visualizer/common_gfxconf.h @@ -0,0 +1,325 @@ +/** + * This file has a different license to the rest of the uGFX system. + * You can copy, modify and distribute this file as you see fit. + * You do not need to publish your source modifications to this file. + * The only thing you are not permitted to do is to relicense it + * under a different license. + */ + +/** + * Copy this file into your project directory and rename it as gfxconf.h + * Edit your copy to turn on the uGFX features you want to use. + * The values below are the defaults. + * + * Only remove the comments from lines where you want to change the + * default value. This allows definitions to be included from + * driver makefiles when required and provides the best future + * compatibility for your project. + * + * Please use spaces instead of tabs in this file. + */ + +#ifndef COMMON_GFXCONF_H +#define COMMON_GFXCONF_H + + +/////////////////////////////////////////////////////////////////////////// +// GOS - One of these must be defined, preferably in your Makefile // +/////////////////////////////////////////////////////////////////////////// +//#define GFX_USE_OS_CHIBIOS TRUE +//#define GFX_USE_OS_FREERTOS FALSE +// #define GFX_FREERTOS_USE_TRACE FALSE +//#define GFX_USE_OS_WIN32 FALSE +//#define GFX_USE_OS_LINUX FALSE +//#define GFX_USE_OS_OSX FALSE +//#define GFX_USE_OS_ECOS FALSE +//#define GFX_USE_OS_RAWRTOS FALSE +//#define GFX_USE_OS_ARDUINO FALSE +//#define GFX_USE_OS_KEIL FALSE +//#define GFX_USE_OS_CMSIS FALSE +//#define GFX_USE_OS_RAW32 FALSE +// #define INTERRUPTS_OFF() optional_code +// #define INTERRUPTS_ON() optional_code +// These are not defined by default for some reason +#define GOS_NEED_X_THREADS FALSE +#define GOS_NEED_X_HEAP FALSE + +// Options that (should where relevant) apply to all operating systems + #define GFX_NO_INLINE FALSE +// #define GFX_COMPILER GFX_COMPILER_UNKNOWN +// #define GFX_CPU GFX_CPU_UNKNOWN +// #define GFX_OS_HEAP_SIZE 0 +// #define GFX_OS_NO_INIT FALSE +// #define GFX_OS_INIT_NO_WARNING FALSE +// #define GFX_OS_PRE_INIT_FUNCTION myHardwareInitRoutine +// #define GFX_OS_EXTRA_INIT_FUNCTION myOSInitRoutine +// #define GFX_OS_EXTRA_DEINIT_FUNCTION myOSDeInitRoutine + + +/////////////////////////////////////////////////////////////////////////// +// GDISP // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GDISP TRUE + +//#define GDISP_NEED_AUTOFLUSH FALSE +//#define GDISP_NEED_TIMERFLUSH FALSE +//#define GDISP_NEED_VALIDATION TRUE +//#define GDISP_NEED_CLIP TRUE +#define GDISP_NEED_CIRCLE TRUE +#define GDISP_NEED_ELLIPSE TRUE +#define GDISP_NEED_ARC TRUE +#define GDISP_NEED_ARCSECTORS TRUE +#define GDISP_NEED_CONVEX_POLYGON TRUE +//#define GDISP_NEED_SCROLL FALSE +#define GDISP_NEED_PIXELREAD TRUE +#define GDISP_NEED_CONTROL TRUE +//#define GDISP_NEED_QUERY FALSE +//#define GDISP_NEED_MULTITHREAD FALSE +//#define GDISP_NEED_STREAMING FALSE +#define GDISP_NEED_TEXT TRUE +// #define GDISP_NEED_TEXT_WORDWRAP FALSE +// #define GDISP_NEED_ANTIALIAS FALSE +// #define GDISP_NEED_UTF8 FALSE + #define GDISP_NEED_TEXT_KERNING TRUE +// #define GDISP_INCLUDE_FONT_UI1 FALSE +// #define GDISP_INCLUDE_FONT_UI2 FALSE // The smallest preferred font. +// #define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS10 FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS12 FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS16 FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS20 FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS24 FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS32 FALSE + #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 TRUE +// #define GDISP_INCLUDE_FONT_FIXED_10X20 FALSE +// #define GDISP_INCLUDE_FONT_FIXED_7X14 FALSE + #define GDISP_INCLUDE_FONT_FIXED_5X8 TRUE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA FALSE +// #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA FALSE +// #define GDISP_INCLUDE_USER_FONTS FALSE + +//#define GDISP_NEED_IMAGE FALSE +// #define GDISP_NEED_IMAGE_NATIVE FALSE +// #define GDISP_NEED_IMAGE_GIF FALSE +// #define GDISP_NEED_IMAGE_BMP FALSE +// #define GDISP_NEED_IMAGE_BMP_1 FALSE +// #define GDISP_NEED_IMAGE_BMP_4 FALSE +// #define GDISP_NEED_IMAGE_BMP_4_RLE FALSE +// #define GDISP_NEED_IMAGE_BMP_8 FALSE +// #define GDISP_NEED_IMAGE_BMP_8_RLE FALSE +// #define GDISP_NEED_IMAGE_BMP_16 FALSE +// #define GDISP_NEED_IMAGE_BMP_24 FALSE +// #define GDISP_NEED_IMAGE_BMP_32 FALSE +// #define GDISP_NEED_IMAGE_JPG FALSE +// #define GDISP_NEED_IMAGE_PNG FALSE +// #define GDISP_NEED_IMAGE_ACCOUNTING FALSE +#ifdef EMULATOR +#define GDISP_NEED_PIXMAP TRUE +#endif +// #define GDISP_NEED_PIXMAP_IMAGE FALSE + +//#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE // If not defined the native hardware orientation is used. +//#define GDISP_LINEBUF_SIZE 128 +//#define GDISP_STARTUP_COLOR Black +#define GDISP_NEED_STARTUP_LOGO FALSE + +//#define GDISP_TOTAL_DISPLAYS 2 + + #ifdef GDISP_DRIVER_LIST + // For code and speed optimization define as TRUE or FALSE if all controllers have the same capability + #define GDISP_HARDWARE_STREAM_WRITE FALSE + #define GDISP_HARDWARE_STREAM_READ FALSE + #define GDISP_HARDWARE_STREAM_POS FALSE + #define GDISP_HARDWARE_DRAWPIXEL TRUE + #define GDISP_HARDWARE_CLEARS FALSE + #define GDISP_HARDWARE_FILLS FALSE + //#define GDISP_HARDWARE_BITFILLS FALSE + #define GDISP_HARDWARE_SCROLL FALSE + #define GDISP_HARDWARE_PIXELREAD TRUE + #define GDISP_HARDWARE_CONTROL TRUE + #define GDISP_HARDWARE_QUERY FALSE + #define GDISP_HARDWARE_CLIP FALSE + + #define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888 + #endif + +// The custom format is not defined for some reason, so define it as error +// so we don't get compiler warnings +#define GDISP_PIXELFORMAT_CUSTOM GDISP_PIXELFORMAT_ERROR + +#define GDISP_USE_GFXNET FALSE +// #define GDISP_GFXNET_PORT 13001 +// #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP FALSE +// #define GDISP_DONT_WAIT_FOR_NET_DISPLAY FALSE +// #define GDISP_GFXNET_UNSAFE_SOCKETS FALSE + + +/////////////////////////////////////////////////////////////////////////// +// GWIN // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GWIN FALSE + +//#define GWIN_NEED_WINDOWMANAGER FALSE +// #define GWIN_REDRAW_IMMEDIATE FALSE +// #define GWIN_REDRAW_SINGLEOP FALSE +// #define GWIN_NEED_FLASHING FALSE +// #define GWIN_FLASHING_PERIOD 250 + +//#define GWIN_NEED_CONSOLE FALSE +// #define GWIN_CONSOLE_USE_HISTORY FALSE +// #define GWIN_CONSOLE_HISTORY_AVERAGING FALSE +// #define GWIN_CONSOLE_HISTORY_ATCREATE FALSE +// #define GWIN_CONSOLE_ESCSEQ FALSE +// #define GWIN_CONSOLE_USE_BASESTREAM FALSE +// #define GWIN_CONSOLE_USE_FLOAT FALSE +//#define GWIN_NEED_GRAPH FALSE +//#define GWIN_NEED_GL3D FALSE + +//#define GWIN_NEED_WIDGET FALSE +//#define GWIN_FOCUS_HIGHLIGHT_WIDTH 1 +// #define GWIN_NEED_LABEL FALSE +// #define GWIN_LABEL_ATTRIBUTE FALSE +// #define GWIN_NEED_BUTTON FALSE +// #define GWIN_BUTTON_LAZY_RELEASE FALSE +// #define GWIN_NEED_SLIDER FALSE +// #define GWIN_SLIDER_NOSNAP FALSE +// #define GWIN_SLIDER_DEAD_BAND 5 +// #define GWIN_SLIDER_TOGGLE_INC 20 +// #define GWIN_NEED_CHECKBOX FALSE +// #define GWIN_NEED_IMAGE FALSE +// #define GWIN_NEED_IMAGE_ANIMATION FALSE +// #define GWIN_NEED_RADIO FALSE +// #define GWIN_NEED_LIST FALSE +// #define GWIN_NEED_LIST_IMAGES FALSE +// #define GWIN_NEED_PROGRESSBAR FALSE +// #define GWIN_PROGRESSBAR_AUTO FALSE +// #define GWIN_NEED_KEYBOARD FALSE +// #define GWIN_KEYBOARD_DEFAULT_LAYOUT VirtualKeyboard_English1 +// #define GWIN_NEED_KEYBOARD_ENGLISH1 TRUE +// #define GWIN_NEED_TEXTEDIT FALSE +// #define GWIN_FLAT_STYLING FALSE +// #define GWIN_WIDGET_TAGS FALSE + +//#define GWIN_NEED_CONTAINERS FALSE +// #define GWIN_NEED_CONTAINER FALSE +// #define GWIN_NEED_FRAME FALSE +// #define GWIN_NEED_TABSET FALSE +// #define GWIN_TABSET_TABHEIGHT 18 + + +/////////////////////////////////////////////////////////////////////////// +// GEVENT // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GEVENT TRUE + +//#define GEVENT_ASSERT_NO_RESOURCE FALSE +//#define GEVENT_MAXIMUM_SIZE 32 +//#define GEVENT_MAX_SOURCE_LISTENERS 32 + + +/////////////////////////////////////////////////////////////////////////// +// GTIMER // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GTIMER FALSE + +//#define GTIMER_THREAD_PRIORITY HIGH_PRIORITY +//#define GTIMER_THREAD_WORKAREA_SIZE 2048 + + +/////////////////////////////////////////////////////////////////////////// +// GQUEUE // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GQUEUE FALSE + +//#define GQUEUE_NEED_ASYNC FALSE +//#define GQUEUE_NEED_GSYNC FALSE +//#define GQUEUE_NEED_FSYNC FALSE +//#define GQUEUE_NEED_BUFFERS FALSE + +/////////////////////////////////////////////////////////////////////////// +// GINPUT // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GINPUT FALSE + +//#define GINPUT_NEED_MOUSE FALSE +// #define GINPUT_TOUCH_STARTRAW FALSE +// #define GINPUT_TOUCH_NOTOUCH FALSE +// #define GINPUT_TOUCH_NOCALIBRATE FALSE +// #define GINPUT_TOUCH_NOCALIBRATE_GUI FALSE +// #define GINPUT_MOUSE_POLL_PERIOD 25 +// #define GINPUT_MOUSE_CLICK_TIME 300 +// #define GINPUT_TOUCH_CXTCLICK_TIME 700 +// #define GINPUT_TOUCH_USER_CALIBRATION_LOAD FALSE +// #define GINPUT_TOUCH_USER_CALIBRATION_SAVE FALSE +// #define GMOUSE_DRIVER_LIST GMOUSEVMT_Win32, GMOUSEVMT_Win32 +//#define GINPUT_NEED_KEYBOARD FALSE +// #define GINPUT_KEYBOARD_POLL_PERIOD 200 +// #define GKEYBOARD_DRIVER_LIST GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32 +// #define GKEYBOARD_LAYOUT_OFF FALSE +// #define GKEYBOARD_LAYOUT_SCANCODE2_US FALSE +//#define GINPUT_NEED_TOGGLE FALSE +//#define GINPUT_NEED_DIAL FALSE + + +/////////////////////////////////////////////////////////////////////////// +// GFILE // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GFILE FALSE + +//#define GFILE_NEED_PRINTG FALSE +//#define GFILE_NEED_SCANG FALSE +//#define GFILE_NEED_STRINGS FALSE +//#define GFILE_NEED_FILELISTS FALSE +//#define GFILE_NEED_STDIO FALSE +//#define GFILE_NEED_NOAUTOMOUNT FALSE +//#define GFILE_NEED_NOAUTOSYNC FALSE + +//#define GFILE_NEED_MEMFS FALSE +//#define GFILE_NEED_ROMFS FALSE +//#define GFILE_NEED_RAMFS FALSE +//#define GFILE_NEED_FATFS FALSE +//#define GFILE_NEED_NATIVEFS FALSE +//#define GFILE_NEED_CHBIOSFS FALSE + +//#define GFILE_ALLOW_FLOATS FALSE +//#define GFILE_ALLOW_DEVICESPECIFIC FALSE +//#define GFILE_MAX_GFILES 3 + +/////////////////////////////////////////////////////////////////////////// +// GADC // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GADC FALSE + +//#define GADC_MAX_LOWSPEED_DEVICES 4 + + +/////////////////////////////////////////////////////////////////////////// +// GAUDIO // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GAUDIO FALSE +// There seems to be a bug in the ugfx code, the wrong define is used +// So define it in order to avoid warnings +#define GFX_USE_GAUDIN GFX_USE_GAUDIO +// #define GAUDIO_NEED_PLAY FALSE +// #define GAUDIO_NEED_RECORD FALSE + + +/////////////////////////////////////////////////////////////////////////// +// GMISC // +/////////////////////////////////////////////////////////////////////////// +#define GFX_USE_GMISC TRUE + +//#define GMISC_NEED_ARRAYOPS FALSE +//#define GMISC_NEED_FASTTRIG FALSE +//#define GMISC_NEED_FIXEDTRIG FALSE +//#define GMISC_NEED_INVSQRT FALSE +// #define GMISC_INVSQRT_MIXED_ENDIAN FALSE +// #define GMISC_INVSQRT_REAL_SLOW FALSE +#define GMISC_NEED_MATRIXFLOAT2D TRUE +#define GMISC_NEED_MATRIXFIXED2D FALSE + +#endif /* COMMON_GFXCONF_H */ diff --git a/quantum/visualizer/default_animations.c b/quantum/visualizer/default_animations.c new file mode 100644 index 0000000000..2d03273720 --- /dev/null +++ b/quantum/visualizer/default_animations.c @@ -0,0 +1,176 @@ +/* Copyright 2017 Fred Sundvik + * + * 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/>. + */ + +#if defined(VISUALIZER_ENABLE) + +#include "default_animations.h" +#include "visualizer.h" +#ifdef LCD_ENABLE +#include "lcd_keyframes.h" +#endif +#ifdef LCD_BACKLIGHT_ENABLE +#include "lcd_backlight_keyframes.h" +#endif + +#ifdef BACKLIGHT_ENABLE +#include "led_backlight_keyframes.h" +#endif + +#include "visualizer_keyframes.h" + + +#if defined(LCD_ENABLE) || defined(LCD_BACKLIGHT_ENABLE) || defined(BACKLIGHT_ENABLE) + +static bool keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { +#ifdef LCD_ENABLE + lcd_keyframe_enable(animation, state); +#endif +#ifdef LCD_BACKLIGHT_ENABLE + lcd_backlight_keyframe_enable(animation, state); +#endif +#ifdef BACKLIGHT_ENABLE + led_backlight_keyframe_enable(animation, state); +#endif + return false; +} + +static bool keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { +#ifdef LCD_ENABLE + lcd_keyframe_disable(animation, state); +#endif +#ifdef LCD_BACKLIGHT_ENABLE + lcd_backlight_keyframe_disable(animation, state); +#endif +#ifdef BACKLIGHT_ENABLE + led_backlight_keyframe_disable(animation, state); +#endif + return false; +} + +static bool keyframe_fade_in(keyframe_animation_t* animation, visualizer_state_t* state) { + bool ret = false; +#ifdef LCD_BACKLIGHT_ENABLE + ret |= lcd_backlight_keyframe_animate_color(animation, state); +#endif +#ifdef BACKLIGHT_ENABLE + ret |= led_backlight_keyframe_fade_in_all(animation, state); +#endif + return ret; +} + +static bool keyframe_fade_out(keyframe_animation_t* animation, visualizer_state_t* state) { + bool ret = false; +#ifdef LCD_BACKLIGHT_ENABLE + ret |= lcd_backlight_keyframe_animate_color(animation, state); +#endif +#ifdef BACKLIGHT_ENABLE + ret |= led_backlight_keyframe_fade_out_all(animation, state); +#endif + return ret; +} + + +// Don't worry, if the startup animation is long, you can use the keyboard like normal +// during that time +keyframe_animation_t default_startup_animation = { +#if LCD_ENABLE + .num_frames = 3, +#else + .num_frames = 2, +#endif + .loop = false, + .frame_lengths = { + 0, +#if LCD_ENABLE + 0, +#endif + gfxMillisecondsToTicks(5000)}, + .frame_functions = { + keyframe_enable, +#if LCD_ENABLE + lcd_keyframe_draw_logo, +#endif + keyframe_fade_in, + }, +}; + +keyframe_animation_t default_suspend_animation = { +#if LCD_ENABLE + .num_frames = 3, +#else + .num_frames = 2, +#endif + .loop = false, + .frame_lengths = { +#if LCD_ENABLE + 0, +#endif + gfxMillisecondsToTicks(1000), + 0}, + .frame_functions = { +#if LCD_ENABLE + lcd_keyframe_display_layer_text, +#endif + keyframe_fade_out, + keyframe_disable, + }, +}; +#endif + +#if defined(BACKLIGHT_ENABLE) +#define CROSSFADE_TIME 1000 +#define GRADIENT_TIME 3000 + +keyframe_animation_t led_test_animation = { + .num_frames = 14, + .loop = true, + .frame_lengths = { + gfxMillisecondsToTicks(1000), // fade in + gfxMillisecondsToTicks(1000), // no op (leds on) + gfxMillisecondsToTicks(1000), // fade out + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + gfxMillisecondsToTicks(GRADIENT_TIME), // left to rigt (outside in) + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom + 0, // mirror leds + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + gfxMillisecondsToTicks(GRADIENT_TIME), // left_to_right (mirrored, so inside out) + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom + 0, // normal leds + gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade + + }, + .frame_functions = { + led_backlight_keyframe_fade_in_all, + keyframe_no_operation, + led_backlight_keyframe_fade_out_all, + led_backlight_keyframe_crossfade, + led_backlight_keyframe_left_to_right_gradient, + led_backlight_keyframe_crossfade, + led_backlight_keyframe_top_to_bottom_gradient, + led_backlight_keyframe_mirror_orientation, + led_backlight_keyframe_crossfade, + led_backlight_keyframe_left_to_right_gradient, + led_backlight_keyframe_crossfade, + led_backlight_keyframe_top_to_bottom_gradient, + led_backlight_keyframe_normal_orientation, + led_backlight_keyframe_crossfade, + }, +}; +#endif + +#endif diff --git a/quantum/visualizer/lcd_backlight_keyframes.h b/quantum/visualizer/default_animations.h index e1c125cf91..51320b8b8a 100644 --- a/quantum/visualizer/lcd_backlight_keyframes.h +++ b/quantum/visualizer/default_animations.h @@ -14,17 +14,17 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef QUANTUM_VISUALIZER_LCD_BACKLIGHT_KEYFRAMES_H_ -#define QUANTUM_VISUALIZER_LCD_BACKLIGHT_KEYFRAMES_H_ +#ifndef DEFAULT_ANIMATIONS_H_ +#define DEFAULT_ANIMATIONS_H_ #include "visualizer.h" -// Animates the LCD backlight color between the current color and the target color (of the state) -bool backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state); -// Sets the backlight color to the target color -bool backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state); +// You can use these default animations, but of course you can also write your own custom ones instead +extern keyframe_animation_t default_startup_animation; +extern keyframe_animation_t default_suspend_animation; -bool backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); -bool backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); +// An animation for testing and demonstrating the led support, should probably not be used for real world +// cases +extern keyframe_animation_t led_test_animation; -#endif /* QUANTUM_VISUALIZER_LCD_BACKLIGHT_KEYFRAMES_H_ */ +#endif /* DEFAULT_ANIMATIONS_H_ */ diff --git a/quantum/visualizer/lcd_backlight_keyframes.c b/quantum/visualizer/lcd_backlight_keyframes.c index 8436d4e3dd..8c402baf6c 100644 --- a/quantum/visualizer/lcd_backlight_keyframes.c +++ b/quantum/visualizer/lcd_backlight_keyframes.c @@ -16,7 +16,7 @@ #include "lcd_backlight_keyframes.h" -bool backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state) { +bool lcd_backlight_keyframe_animate_color(keyframe_animation_t* animation, visualizer_state_t* state) { int frame_length = animation->frame_lengths[animation->current_frame]; int current_pos = frame_length - animation->time_left_in_frame; uint8_t t_h = LCD_HUE(state->target_lcd_color); @@ -49,7 +49,7 @@ bool backlight_keyframe_animate_color(keyframe_animation_t* animation, visualize return true; } -bool backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state) { +bool lcd_backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_state_t* state) { (void)animation; state->prev_lcd_color = state->target_lcd_color; state->current_lcd_color = state->target_lcd_color; @@ -60,14 +60,14 @@ bool backlight_keyframe_set_color(keyframe_animation_t* animation, visualizer_st return false; } -bool backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { +bool lcd_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { (void)animation; (void)state; lcd_backlight_hal_color(0, 0, 0); return false; } -bool backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { +bool lcd_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { (void)animation; (void)state; lcd_backlight_color(LCD_HUE(state->current_lcd_color), diff --git a/quantum/visualizer/lcd_keyframes.c b/quantum/visualizer/lcd_keyframes.c index 82e4184d2c..75eb457001 100644 --- a/quantum/visualizer/lcd_keyframes.c +++ b/quantum/visualizer/lcd_keyframes.c @@ -166,8 +166,8 @@ bool lcd_keyframe_draw_logo(keyframe_animation_t* animation, visualizer_state_t* // or state structs, here we use the image //gdispGBlitArea is a tricky function to use since it supports blitting part of the image - // if you have full screen image, then just use 128 and 32 for both source and target dimensions - gdispGBlitArea(GDISP, 0, 0, 128, 32, 0, 0, 128, (pixel_t*)resource_lcd_logo); + // if you have full screen image, then just use LCD_WIDTH and LCD_HEIGHT for both source and target dimensions + gdispGBlitArea(GDISP, 0, 0, LCD_WIDTH, LCD_HEIGHT, 0, 0, LCD_WIDTH, (pixel_t*)resource_lcd_logo); return false; } diff --git a/quantum/visualizer/led_keyframes.c b/quantum/visualizer/led_backlight_keyframes.c index 7e6e5d1ab9..eb3f5561d8 100644 --- a/quantum/visualizer/led_keyframes.c +++ b/quantum/visualizer/led_backlight_keyframes.c @@ -23,7 +23,7 @@ SOFTWARE. */ #include "gfx.h" #include "math.h" -#include "led_keyframes.h" +#include "led_backlight_keyframes.h" static uint8_t fade_led_color(keyframe_animation_t* animation, int from, int to) { int frame_length = animation->frame_lengths[animation->current_frame]; @@ -41,8 +41,8 @@ static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint } // TODO: Should be customizable per keyboard -#define NUM_ROWS LED_NUM_ROWS -#define NUM_COLS LED_NUM_COLS +#define NUM_ROWS LED_HEIGHT +#define NUM_COLS LED_WIDTH static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS]; static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS]; @@ -55,19 +55,19 @@ static uint8_t compute_gradient_color(float t, float index, float num) { return (uint8_t)(255.0f * v); } -bool led_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; keyframe_fade_all_leds_from_to(animation, 0, 255); return true; } -bool led_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; keyframe_fade_all_leds_from_to(animation, 255, 0); return true; } -bool led_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; float frame_length = animation->frame_lengths[animation->current_frame]; float current_pos = frame_length - animation->time_left_in_frame; @@ -79,7 +79,7 @@ bool led_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visual return true; } -bool led_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; float frame_length = animation->frame_lengths[animation->current_frame]; float current_pos = frame_length - animation->time_left_in_frame; @@ -98,7 +98,7 @@ static void copy_current_led_state(uint8_t* dest) { } } } -bool led_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; if (animation->first_update_of_frame) { copy_current_led_state(&crossfade_start_frame[0][0]); @@ -114,28 +114,28 @@ bool led_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* return true; } -bool led_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; (void)animation; gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180); return false; } -bool led_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; (void)animation; gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0); return false; } -bool led_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; (void)animation; gdispGSetPowerMode(LED_DISPLAY, powerOff); return false; } -bool led_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { +bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state) { (void)state; (void)animation; gdispGSetPowerMode(LED_DISPLAY, powerOn); diff --git a/quantum/visualizer/led_keyframes.h b/quantum/visualizer/led_backlight_keyframes.h index a59a4f37d1..487151013a 100644 --- a/quantum/visualizer/led_keyframes.h +++ b/quantum/visualizer/led_backlight_keyframes.h @@ -22,21 +22,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef LED_KEYFRAMES_H -#define LED_KEYFRAMES_H +#ifndef LED_BACKLIGHT_KEYFRAMES_H +#define LED_BACKLIGHT_KEYFRAMES_H #include "visualizer.h" -bool led_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_fade_in_all(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_fade_out_all(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_crossfade(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_mirror_orientation(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_normal_orientation(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); -bool led_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_disable(keyframe_animation_t* animation, visualizer_state_t* state); +bool led_backlight_keyframe_enable(keyframe_animation_t* animation, visualizer_state_t* state); extern keyframe_animation_t led_test_animation; diff --git a/quantum/visualizer/visualizer.c b/quantum/visualizer/visualizer.c index cc99d1e3b6..5b4d8d603e 100644 --- a/quantum/visualizer/visualizer.c +++ b/quantum/visualizer/visualizer.c @@ -52,7 +52,8 @@ SOFTWARE. // Define this in config.h #ifndef VISUALIZER_THREAD_PRIORITY -#define "Visualizer thread priority not defined" +// The visualizer needs gfx thread priorities +#define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2) #endif static visualizer_keyboard_status_t current_status = { @@ -255,6 +256,9 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { .mods = 0xFF, .leds = 0xFFFFFFFF, .suspended = false, + #ifdef BACKLIGHT_ENABLE + .backlight_level = 0, + #endif #ifdef VISUALIZER_USER_DATA_SIZE .user_data = {0}, #endif @@ -299,6 +303,7 @@ static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { else { gdispGSetPowerMode(LED_DISPLAY, powerOff); } + state.status.backlight_level = current_status.backlight_level; } #endif if (visualizer_enabled) { diff --git a/quantum/visualizer/visualizer.mk b/quantum/visualizer/visualizer.mk index 0f7d8636cf..102d23b7ef 100644 --- a/quantum/visualizer/visualizer.mk +++ b/quantum/visualizer/visualizer.mk @@ -20,6 +20,30 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +define ADD_DRIVER + $(1)_DRIVER:=$(strip $($(1)_DRIVER)) + $(1)_WIDTH:=$(strip $($(1)_WIDTH)) + $(1)_HEIGHT:=$(strip $($(1)_HEIGHT)) + ifeq ($($(1)_DRIVER),) + $$(error $(1)_DRIVER is not defined) + endif + ifeq ($($(1)_WIDTH),) + $$(error $(1)_WIDTH is not defined) + endif + ifeq ($($(1)_HEIGHT),) + $$(error $(1)_HEIGHT is not defined) + endif + OPT_DEFS+=-D$(1)_WIDTH=$($(1)_WIDTH) + OPT_DEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT) + GFXDEFS+=-D$(1)_WIDTH=$($(1)_WIDTH) + GFXDEFS+=-D$(1)_HEIGHT=$($(1)_HEIGHT) + $(1)_DISPLAY_NUMBER:=$$(words $$(GDISP_DRIVER_LIST)) + OPT_DEFS+=-D$(1)_DISPLAY_NUMBER=$$($(1)_DISPLAY_NUMBER) + include $(TOP_DIR)/drivers/ugfx/gdisp/$($(1)_DRIVER)/driver.mk +endef + +GDISP_DRIVER_LIST:= + SRC += $(VISUALIZER_DIR)/visualizer.c \ $(VISUALIZER_DIR)/visualizer_keyframes.c EXTRAINCDIRS += $(GFXINC) $(VISUALIZER_DIR) @@ -40,16 +64,32 @@ SRC += $(VISUALIZER_DIR)/lcd_backlight_keyframes.c # Note, that the linker will strip out any resources that are not actually in use SRC += $(VISUALIZER_DIR)/resources/lcd_logo.c OPT_DEFS += -DLCD_BACKLIGHT_ENABLE +$(eval $(call ADD_DRIVER,LCD)) endif ifeq ($(strip $(BACKLIGHT_ENABLE)), yes) -SRC += $(VISUALIZER_DIR)/led_keyframes.c +SRC += $(VISUALIZER_DIR)/led_backlight_keyframes.c +$(eval $(call ADD_DRIVER,LED)) endif +SRC += $(VISUALIZER_DIR)/default_animations.c + include $(GFXLIB)/gfx.mk +# For the common_gfxconf.h +GFXINC += quantum/visualizer + GFXSRC := $(patsubst $(TOP_DIR)/%,%,$(GFXSRC)) GFXDEFS := $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS))) +GDISP_LIST_COMMA=, +GDISP_LIST_EMPTY= +GDISP_LIST_SPACE=$(GDISP_LIST_EMPTY) $(GDISP_LIST_EMPTY) + +GDISP_DRIVER_LIST := $(strip $(GDISP_DRIVER_LIST)) +GDISP_DRIVER_LIST := $(subst $(GDISP_LIST_SPACE),$(GDISP_LIST_COMMA),$(GDISP_DRIVER_LIST)) + +GFXDEFS +=-DGDISP_DRIVER_LIST="$(GDISP_DRIVER_LIST)" + ifneq ("$(wildcard $(KEYMAP_PATH)/visualizer.c)","") SRC += keyboards/$(KEYBOARD)/keymaps/$(KEYMAP)/visualizer.c else |