diff options
Diffstat (limited to 'quantum')
168 files changed, 1096 insertions, 1401 deletions
| diff --git a/quantum/action.c b/quantum/action.c index a45e70c557..6368f7398c 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -528,6 +528,13 @@ void process_action(keyrecord_t *record, action_t action) {                              unregister_code(action.key.code);                          } else {                              ac_dprintf("MODS_TAP: No tap: add_mods\n"); +#    if defined(RETRO_TAPPING) && defined(DUMMY_MOD_NEUTRALIZER_KEYCODE) +                            // Send a dummy keycode to neutralize flashing modifiers +                            // if the key was held and then released with no interruptions. +                            if (retro_tapping_counter == 2) { +                                neutralize_flashing_modifiers(get_mods()); +                            } +#    endif                              unregister_mods(mods);                          }                      } @@ -882,7 +889,7 @@ __attribute__((weak)) void register_code(uint8_t code) {      } else if (KC_LOCKING_CAPS_LOCK == code) {  #    ifdef LOCKING_RESYNC_ENABLE          // Resync: ignore if caps lock already is on -        if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) return; +        if (host_keyboard_led_state().caps_lock) return;  #    endif          add_key(KC_CAPS_LOCK);          send_keyboard_report(); @@ -892,7 +899,7 @@ __attribute__((weak)) void register_code(uint8_t code) {      } else if (KC_LOCKING_NUM_LOCK == code) {  #    ifdef LOCKING_RESYNC_ENABLE -        if (host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)) return; +        if (host_keyboard_led_state().num_lock) return;  #    endif          add_key(KC_NUM_LOCK);          send_keyboard_report(); @@ -902,7 +909,7 @@ __attribute__((weak)) void register_code(uint8_t code) {      } else if (KC_LOCKING_SCROLL_LOCK == code) {  #    ifdef LOCKING_RESYNC_ENABLE -        if (host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK)) return; +        if (host_keyboard_led_state().scroll_lock) return;  #    endif          add_key(KC_SCROLL_LOCK);          send_keyboard_report(); @@ -952,7 +959,7 @@ __attribute__((weak)) void unregister_code(uint8_t code) {      } else if (KC_LOCKING_CAPS_LOCK == code) {  #    ifdef LOCKING_RESYNC_ENABLE          // Resync: ignore if caps lock already is off -        if (!(host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK))) return; +        if (!host_keyboard_led_state().caps_lock) return;  #    endif          add_key(KC_CAPS_LOCK);          send_keyboard_report(); @@ -961,7 +968,7 @@ __attribute__((weak)) void unregister_code(uint8_t code) {      } else if (KC_LOCKING_NUM_LOCK == code) {  #    ifdef LOCKING_RESYNC_ENABLE -        if (!(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK))) return; +        if (!host_keyboard_led_state().num_lock) return;  #    endif          add_key(KC_NUM_LOCK);          send_keyboard_report(); @@ -970,7 +977,7 @@ __attribute__((weak)) void unregister_code(uint8_t code) {      } else if (KC_LOCKING_SCROLL_LOCK == code) {  #    ifdef LOCKING_RESYNC_ENABLE -        if (!(host_keyboard_leds() & (1 << USB_LED_SCROLL_LOCK))) return; +        if (!host_keyboard_led_state().scroll_lock) return;  #    endif          add_key(KC_SCROLL_LOCK);          send_keyboard_report(); diff --git a/quantum/action_layer.h b/quantum/action_layer.h index ff783bb3e7..a2410d49a5 100644 --- a/quantum/action_layer.h +++ b/quantum/action_layer.h @@ -20,6 +20,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include <stdint.h>  #include "keyboard.h"  #include "action.h" +#include "bitwise.h"  #ifdef DYNAMIC_KEYMAP_ENABLE  #    ifndef DYNAMIC_KEYMAP_LAYER_COUNT diff --git a/quantum/action_util.c b/quantum/action_util.c index 361f410d2d..909dea0595 100644 --- a/quantum/action_util.c +++ b/quantum/action_util.c @@ -500,3 +500,28 @@ __attribute__((weak)) void oneshot_layer_changed_kb(uint8_t layer) {  uint8_t has_anymod(void) {      return bitpop(real_mods);  } + +#ifdef DUMMY_MOD_NEUTRALIZER_KEYCODE +/** \brief Send a dummy keycode in between the register and unregister event of a modifier key, to neutralize the "flashing modifiers" phenomenon. + * + * \param active_mods 8-bit packed bit-array describing the currently active modifiers (in the format GASCGASC). + * + * Certain QMK features like  key overrides or retro tap must unregister a previously + * registered modifier before sending another keycode but this can trigger undesired + * keyboard shortcuts if the clean tap of a single modifier key is bound to an action + * on the host OS, as is for example the case for the left GUI key on Windows, which + * opens the Start Menu when tapped. + */ +void neutralize_flashing_modifiers(uint8_t active_mods) { +    // In most scenarios, the flashing modifiers phenomenon is a problem +    // only for a subset of modifier masks. +    const static uint8_t mods_to_neutralize[] = MODS_TO_NEUTRALIZE; +    const static uint8_t n_mods               = ARRAY_SIZE(mods_to_neutralize); +    for (uint8_t i = 0; i < n_mods; ++i) { +        if (active_mods == mods_to_neutralize[i]) { +            tap_code(DUMMY_MOD_NEUTRALIZER_KEYCODE); +            break; +        } +    } +} +#endif diff --git a/quantum/action_util.h b/quantum/action_util.h index 02f6e9e6df..831caf3c0a 100644 --- a/quantum/action_util.h +++ b/quantum/action_util.h @@ -102,6 +102,19 @@ void use_oneshot_swaphands(void);  void clear_oneshot_swaphands(void);  #endif +#ifdef DUMMY_MOD_NEUTRALIZER_KEYCODE +// KC_A is used as the lowerbound instead of QK_BASIC because the range QK_BASIC...KC_A includes +// internal keycodes like KC_NO and KC_TRANSPARENT which are unsuitable for use with `tap_code(kc)`. +#    if !(KC_A <= DUMMY_MOD_NEUTRALIZER_KEYCODE && DUMMY_MOD_NEUTRALIZER_KEYCODE <= QK_BASIC_MAX) +#        error "DUMMY_MOD_NEUTRALIZER_KEYCODE must be a basic, unmodified, HID keycode!" +#    endif +void neutralize_flashing_modifiers(uint8_t active_mods); +#endif +#ifndef MODS_TO_NEUTRALIZE +#    define MODS_TO_NEUTRALIZE \ +        { MOD_BIT(KC_LEFT_ALT), MOD_BIT(KC_LEFT_GUI) } +#endif +  #ifdef __cplusplus  }  #endif diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index 2570ad9cd1..b9b21066cb 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -547,20 +547,42 @@ void audio_decrease_tempo(uint8_t tempo_change) {          note_tempo -= tempo_change;  } -// TODO in the int-math version are some bugs; songs sometimes abruptly end - maybe an issue with the timer/system-tick wrapping around? +/** + * Converts from units of 1/64ths of a beat to milliseconds. + * + * Round-off error is at most 1 millisecond. + * + * Conversion will never overflow for duration_bpm <= 699, provided that + * note_tempo is at least 10. This is quite a long duration, over ten beats. + * + * Beware that for duration_bpm > 699, the result may overflow uint16_t range + * when duration_bpm is large compared to note_tempo: + * + *    duration_bpm * 60 * 1000 / (64 * note_tempo) > UINT16_MAX + * + *    duration_bpm > (2 * 65535 / 1875) * note_tempo + *                 = 69.904 * note_tempo. + */  uint16_t audio_duration_to_ms(uint16_t duration_bpm) { -#if defined(__AVR__) -    // doing int-math saves us some bytes in the overall firmware size, but the intermediate result is less accurate before being cast to/returned as uint -    return ((uint32_t)duration_bpm * 60 * 1000) / (64 * note_tempo); -    // NOTE: beware of uint16_t overflows when note_tempo is low and/or the duration is long -#else -    return ((float)duration_bpm * 60) / (64 * note_tempo) * 1000; -#endif +    return ((uint32_t)duration_bpm * 1875) / ((uint_fast16_t)note_tempo * 2);  } + +/** + * Converts from units of milliseconds to 1/64ths of a beat. + * + * Round-off error is at most 1/64th of a beat. + * + * This conversion never overflows: since duration_ms <= UINT16_MAX = 65535 + * and note_tempo <= 255, the result is always in uint16_t range: + * + *     duration_ms * 64 * note_tempo / 60 / 1000 + *     <= 65535 * 2 * 255 / 1875 + *      = 17825.52 + *     <= UINT16_MAX. + */  uint16_t audio_ms_to_duration(uint16_t duration_ms) { -#if defined(__AVR__) -    return ((uint32_t)duration_ms * 64 * note_tempo) / 60 / 1000; -#else -    return ((float)duration_ms * 64 * note_tempo) / 60 / 1000; -#endif +    return ((uint32_t)duration_ms * 2 * note_tempo) / 1875;  } + +__attribute__((weak)) void audio_on_user(void) {} +__attribute__((weak)) void audio_off_user(void) {} diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index 75016a1100..a4a908b43c 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -21,12 +21,6 @@  #include "musical_notes.h"  #include "song_list.h"  #include "voices.h" -#include "quantum.h" -#include <math.h> - -#if defined(__AVR__) -#    include <avr/io.h> -#endif  #if defined(AUDIO_DRIVER_PWM)  #    include "audio_pwm.h" @@ -280,3 +274,6 @@ bool audio_update_state(void);  #define increase_tempo(t) audio_increase_tempo(t)  #define decrease_tempo(t) audio_decrease_tempo(t)  // vibrato functions are not used in any keyboards + +void audio_on_user(void); +void audio_off_user(void); diff --git a/quantum/audio/muse.c b/quantum/audio/muse.c index 01b95671fd..4c23cd7348 100644 --- a/quantum/audio/muse.c +++ b/quantum/audio/muse.c @@ -1,5 +1,7 @@  #include "muse.h" +#include <stdbool.h> +  enum { MUSE_OFF, MUSE_ON, MUSE_C_1_2, MUSE_C1, MUSE_C2, MUSE_C4, MUSE_C8, MUSE_C3, MUSE_C6, MUSE_B1, MUSE_B2, MUSE_B3, MUSE_B4, MUSE_B5, MUSE_B6, MUSE_B7, MUSE_B8, MUSE_B9, MUSE_B10, MUSE_B11, MUSE_B12, MUSE_B13, MUSE_B14, MUSE_B15, MUSE_B16, MUSE_B17, MUSE_B18, MUSE_B19, MUSE_B20, MUSE_B21, MUSE_B22, MUSE_B23, MUSE_B24, MUSE_B25, MUSE_B26, MUSE_B27, MUSE_B28, MUSE_B29, MUSE_B30, MUSE_B31 };  bool number_of_ones_to_bool[16] = {1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1}; diff --git a/quantum/audio/muse.h b/quantum/audio/muse.h index ad2f96e43a..7b289cac6c 100644 --- a/quantum/audio/muse.h +++ b/quantum/audio/muse.h @@ -1,6 +1,5 @@  #pragma once -#include "quantum.h" -#include "process_audio.h" +#include <stdint.h>  uint8_t muse_clock_pulse(void); diff --git a/quantum/audio/voices.c b/quantum/audio/voices.c index 01f257f4d4..4f511c93ba 100644 --- a/quantum/audio/voices.c +++ b/quantum/audio/voices.c @@ -16,7 +16,9 @@   */  #include "voices.h"  #include "audio.h" +#include "timer.h"  #include <stdlib.h> +#include <math.h>  uint8_t note_timbre      = TIMBRE_DEFAULT;  bool    glissando        = false; diff --git a/quantum/backlight/backlight.c b/quantum/backlight/backlight.c index 52ec086bb0..9d9f944f5d 100644 --- a/quantum/backlight/backlight.c +++ b/quantum/backlight/backlight.c @@ -15,7 +15,6 @@ 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 "quantum.h"  #include "backlight.h"  #include "eeprom.h"  #include "eeconfig.h" diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c deleted file mode 100644 index 474e0a86f5..0000000000 --- a/quantum/backlight/backlight_avr.c +++ /dev/null @@ -1,473 +0,0 @@ -#include "quantum.h" -#include "backlight.h" -#include "backlight_driver_common.h" -#include "debug.h" - -// Maximum duty cycle limit -#ifndef BACKLIGHT_LIMIT_VAL -#    define BACKLIGHT_LIMIT_VAL 255 -#endif - -// This logic is a bit complex, we support 3 setups: -// -//   1. Hardware PWM when backlight is wired to a PWM pin. -//      Depending on this pin, we use a different output compare unit. -//   2. Software PWM with hardware timers, but the used timer -//      depends on the Audio setup (Audio wins over Backlight). -//   3. Full software PWM, driven by the matrix scan, if both timers are used by Audio. - -#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) && (BACKLIGHT_PIN == B5 || BACKLIGHT_PIN == B6 || BACKLIGHT_PIN == B7) -#    define HARDWARE_PWM -#    define ICRx ICR1 -#    define TCCRxA TCCR1A -#    define TCCRxB TCCR1B -#    define TIMERx_OVF_vect TIMER1_OVF_vect -#    define TIMSKx TIMSK1 -#    define TOIEx TOIE1 - -#    if BACKLIGHT_PIN == B5 -#        define COMxx0 COM1A0 -#        define COMxx1 COM1A1 -#        define OCRxx OCR1A -#    elif BACKLIGHT_PIN == B6 -#        define COMxx0 COM1B0 -#        define COMxx1 COM1B1 -#        define OCRxx OCR1B -#    elif BACKLIGHT_PIN == B7 -#        define COMxx0 COM1C0 -#        define COMxx1 COM1C1 -#        define OCRxx OCR1C -#    endif -#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) && (BACKLIGHT_PIN == C4 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6) -#    define HARDWARE_PWM -#    define ICRx ICR3 -#    define TCCRxA TCCR3A -#    define TCCRxB TCCR3B -#    define TIMERx_OVF_vect TIMER3_OVF_vect -#    define TIMSKx TIMSK3 -#    define TOIEx TOIE3 - -#    if BACKLIGHT_PIN == C4 -#        if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) -#            error This MCU has no C4 pin! -#        else -#            define COMxx0 COM3C0 -#            define COMxx1 COM3C1 -#            define OCRxx OCR3C -#        endif -#    elif BACKLIGHT_PIN == C5 -#        if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) -#            error This MCU has no C5 pin! -#        else -#            define COMxx0 COM3B0 -#            define COMxx1 COM3B1 -#            define OCRxx OCR3B -#        endif -#    elif BACKLIGHT_PIN == C6 -#        define COMxx0 COM3A0 -#        define COMxx1 COM3A1 -#        define OCRxx OCR3A -#    endif -#elif (defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)) && (BACKLIGHT_PIN == B7 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6) -#    define HARDWARE_PWM -#    define ICRx ICR1 -#    define TCCRxA TCCR1A -#    define TCCRxB TCCR1B -#    define TIMERx_OVF_vect TIMER1_OVF_vect -#    define TIMSKx TIMSK1 -#    define TOIEx TOIE1 - -#    if BACKLIGHT_PIN == B7 -#        define COMxx0 COM1C0 -#        define COMxx1 COM1C1 -#        define OCRxx OCR1C -#    elif BACKLIGHT_PIN == C5 -#        define COMxx0 COM1B0 -#        define COMxx1 COM1B1 -#        define OCRxx OCR1B -#    elif BACKLIGHT_PIN == C6 -#        define COMxx0 COM1A0 -#        define COMxx1 COM1A1 -#        define OCRxx OCR1A -#    endif -#elif defined(__AVR_ATmega32A__) && (BACKLIGHT_PIN == D4 || BACKLIGHT_PIN == D5) -#    define HARDWARE_PWM -#    define ICRx ICR1 -#    define TCCRxA TCCR1A -#    define TCCRxB TCCR1B -#    define TIMERx_OVF_vect TIMER1_OVF_vect -#    define TIMSKx TIMSK -#    define TOIEx TOIE1 - -#    if BACKLIGHT_PIN == D4 -#        define COMxx0 COM1B0 -#        define COMxx1 COM1B1 -#        define OCRxx OCR1B -#    elif BACKLIGHT_PIN == D5 -#        define COMxx0 COM1A0 -#        define COMxx1 COM1A1 -#        define OCRxx OCR1A -#    endif -#elif (defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)) && (BACKLIGHT_PIN == B1 || BACKLIGHT_PIN == B2) -#    define HARDWARE_PWM -#    define ICRx ICR1 -#    define TCCRxA TCCR1A -#    define TCCRxB TCCR1B -#    define TIMERx_OVF_vect TIMER1_OVF_vect -#    define TIMSKx TIMSK1 -#    define TOIEx TOIE1 - -#    if BACKLIGHT_PIN == B1 -#        define COMxx0 COM1A0 -#        define COMxx1 COM1A1 -#        define OCRxx OCR1A -#    elif BACKLIGHT_PIN == B2 -#        define COMxx0 COM1B0 -#        define COMxx1 COM1B1 -#        define OCRxx OCR1B -#    endif -#elif (AUDIO_PIN != B5) && (AUDIO_PIN != B6) && (AUDIO_PIN != B7) && (AUDIO_PIN_ALT != B5) && (AUDIO_PIN_ALT != B6) && (AUDIO_PIN_ALT != B7) -// Timer 1 is not in use by Audio feature, Backlight can use it -#    pragma message "Using hardware timer 1 with software PWM" -#    define HARDWARE_PWM -#    define BACKLIGHT_PWM_TIMER -#    define ICRx ICR1 -#    define TCCRxA TCCR1A -#    define TCCRxB TCCR1B -#    define TIMERx_COMPA_vect TIMER1_COMPA_vect -#    define TIMERx_OVF_vect TIMER1_OVF_vect -#    if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register -#        define TIMSKx TIMSK -#    else -#        define TIMSKx TIMSK1 -#    endif -#    define TOIEx TOIE1 - -#    define OCIExA OCIE1A -#    define OCRxx OCR1A -#elif (AUDIO_PIN != C4) && (AUDIO_PIN != C5) && (AUDIO_PIN != C6) -#    pragma message "Using hardware timer 3 with software PWM" -// Timer 3 is not in use by Audio feature, Backlight can use it -#    define HARDWARE_PWM -#    define BACKLIGHT_PWM_TIMER -#    define ICRx ICR1 -#    define TCCRxA TCCR3A -#    define TCCRxB TCCR3B -#    define TIMERx_COMPA_vect TIMER3_COMPA_vect -#    define TIMERx_OVF_vect TIMER3_OVF_vect -#    define TIMSKx TIMSK3 -#    define TOIEx TOIE3 - -#    define OCIExA OCIE3A -#    define OCRxx OCR3A -#elif defined(BACKLIGHT_CUSTOM_DRIVER) -error("Please set 'BACKLIGHT_DRIVER = custom' within rules.mk") -#else -error("Please set 'BACKLIGHT_DRIVER = software' within rules.mk") -#endif - -#ifndef BACKLIGHT_PWM_TIMER // pwm through software - -static inline void enable_pwm(void) { -#    if BACKLIGHT_ON_STATE == 1 -    TCCRxA |= _BV(COMxx1); -#    else -    TCCRxA |= _BV(COMxx1) | _BV(COMxx0); -#    endif -} - -static inline void disable_pwm(void) { -#    if BACKLIGHT_ON_STATE == 1 -    TCCRxA &= ~(_BV(COMxx1)); -#    else -    TCCRxA &= ~(_BV(COMxx1) | _BV(COMxx0)); -#    endif -} - -#endif - -#ifdef BACKLIGHT_PWM_TIMER - -// The idea of software PWM assisted by hardware timers is the following -// we use the hardware timer in fast PWM mode like for hardware PWM, but -// instead of letting the Output Match Comparator control the led pin -// (which is not possible since the backlight is not wired to PWM pins on the -// CPU), we do the LED on/off by oursleves. -// The timer is setup to count up to 0xFFFF, and we set the Output Compare -// register to the current 16bits backlight level (after CIE correction). -// This means the CPU will trigger a compare match interrupt when the counter -// reaches the backlight level, where we turn off the LEDs, -// but also an overflow interrupt when the counter rolls back to 0, -// in which we're going to turn on the LEDs. -// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz, -// or F_CPU/BACKLIGHT_CUSTOM_RESOLUTION if used. - -// Triggered when the counter reaches the OCRx value -ISR(TIMERx_COMPA_vect) { -    backlight_pins_off(); -} - -// Triggered when the counter reaches the TOP value -// this one triggers at F_CPU/ICRx = 16MHz/65536 =~ 244 Hz -ISR(TIMERx_OVF_vect) { -#    ifdef BACKLIGHT_BREATHING -    if (is_breathing()) { -        breathing_task(); -    } -#    endif -    // for very small values of OCRxx (or backlight level) -    // we can't guarantee this whole code won't execute -    // at the same time as the compare match interrupt -    // which means that we might turn on the leds while -    // trying to turn them off, leading to flickering -    // artifacts (especially while breathing, because breathing_task -    // takes many computation cycles). -    // so better not turn them on while the counter TOP is very low. -    if (OCRxx > ICRx / 250 + 5) { -        backlight_pins_on(); -    } -} - -#endif - -#define TIMER_TOP 0xFFFFU - -// See http://jared.geek.nz/2013/feb/linear-led-pwm -static uint16_t cie_lightness(uint16_t v) { -    if (v <= (uint32_t)ICRx / 12) // If the value is less than or equal to ~8% of max -    { -        return v / 9; // Same as dividing by 900% -    } else { -        // In the next two lines values are bit-shifted. This is to avoid loosing decimals in integer math. -        uint32_t y   = (((uint32_t)v + (uint32_t)ICRx / 6) << 5) / ((uint32_t)ICRx / 6 + ICRx); // If above 8%, add ~16% of max, and normalize with (max + ~16% max) -        uint32_t out = (y * y * y * ICRx) >> 15;                                                // Cube it and undo the bit-shifting. (which is now three times as much due to the cubing) - -        if (out > ICRx) // Avoid overflows -        { -            out = ICRx; -        } -        return (uint16_t)out; -    } -} - -// rescale the supplied backlight value to be in terms of the value limit	// range for val is [0..ICRx]. PWM pin is high while the timer count is below val. -static uint32_t rescale_limit_val(uint32_t val) { -    return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256; -} - -// range for val is [0..ICRx]. PWM pin is high while the timer count is below val. -static inline void set_pwm(uint16_t val) { -    OCRxx = val; -} - -void backlight_set(uint8_t level) { -    if (level > BACKLIGHT_LEVELS) level = BACKLIGHT_LEVELS; - -    if (level == 0) { -#ifdef BACKLIGHT_PWM_TIMER -        if (OCRxx) { -            TIMSKx &= ~(_BV(OCIExA)); -            TIMSKx &= ~(_BV(TOIEx)); -        } -#else -        // Turn off PWM control on backlight pin -        disable_pwm(); -#endif -        backlight_pins_off(); -    } else { -#ifdef BACKLIGHT_PWM_TIMER -        if (!OCRxx) { -            TIMSKx |= _BV(OCIExA); -            TIMSKx |= _BV(TOIEx); -        } -#else -        // Turn on PWM control of backlight pin -        enable_pwm(); -#endif -    } -    // Set the brightness -    set_pwm(cie_lightness(rescale_limit_val(ICRx * (uint32_t)level / BACKLIGHT_LEVELS))); -} - -void backlight_task(void) {} - -#ifdef BACKLIGHT_BREATHING - -#    define BREATHING_NO_HALT 0 -#    define BREATHING_HALT_OFF 1 -#    define BREATHING_HALT_ON 2 -#    define BREATHING_STEPS 128 - -static uint8_t  breathing_halt    = BREATHING_NO_HALT; -static uint16_t breathing_counter = 0; - -static uint8_t breath_scale_counter = 1; -/* Run the breathing loop at ~120Hz*/ -const uint8_t   breathing_ISR_frequency     = 120; -static uint16_t breathing_freq_scale_factor = 2; - -#    ifdef BACKLIGHT_PWM_TIMER -static bool breathing = false; - -bool is_breathing(void) { -    return breathing; -} - -#        define breathing_interrupt_enable() \ -            do {                             \ -                breathing = true;            \ -            } while (0) -#        define breathing_interrupt_disable() \ -            do {                              \ -                breathing = false;            \ -            } while (0) -#    else - -bool is_breathing(void) { -    return !!(TIMSKx & _BV(TOIEx)); -} - -#        define breathing_interrupt_enable() \ -            do {                             \ -                TIMSKx |= _BV(TOIEx);        \ -            } while (0) -#        define breathing_interrupt_disable() \ -            do {                              \ -                TIMSKx &= ~_BV(TOIEx);        \ -            } while (0) -#    endif - -#    define breathing_min()        \ -        do {                       \ -            breathing_counter = 0; \ -        } while (0) -#    define breathing_max()                                                           \ -        do {                                                                          \ -            breathing_counter = get_breathing_period() * breathing_ISR_frequency / 2; \ -        } while (0) - -void breathing_enable(void) { -    breathing_counter = 0; -    breathing_halt    = BREATHING_NO_HALT; -    breathing_interrupt_enable(); -} - -void breathing_pulse(void) { -    if (get_backlight_level() == 0) -        breathing_min(); -    else -        breathing_max(); -    breathing_halt = BREATHING_HALT_ON; -    breathing_interrupt_enable(); -} - -void breathing_disable(void) { -    breathing_interrupt_disable(); -    // Restore backlight level -    backlight_set(get_backlight_level()); -} - -void breathing_self_disable(void) { -    if (get_backlight_level() == 0) -        breathing_halt = BREATHING_HALT_OFF; -    else -        breathing_halt = BREATHING_HALT_ON; -} - -/* To generate breathing curve in python: - * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)] - */ -static const uint8_t breathing_table[BREATHING_STEPS] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -// Use this before the cie_lightness function. -static inline uint16_t scale_backlight(uint16_t v) { -    return v / BACKLIGHT_LEVELS * get_backlight_level(); -} - -#    ifdef BACKLIGHT_PWM_TIMER -void breathing_task(void) -#    else -/* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run - * about 244 times per second. - * - * The following ISR runs at F_CPU/ISRx. With a 16MHz clock and default pwm resolution, that means 244Hz - */ -ISR(TIMERx_OVF_vect) -#    endif -{ - -    // Only run this ISR at ~120 Hz -    if (breath_scale_counter++ == breathing_freq_scale_factor) { -        breath_scale_counter = 1; -    } else { -        return; -    } -    uint16_t interval = (uint16_t)get_breathing_period() * breathing_ISR_frequency / BREATHING_STEPS; -    // resetting after one period to prevent ugly reset at overflow. -    breathing_counter = (breathing_counter + 1) % (get_breathing_period() * breathing_ISR_frequency); -    uint8_t index     = breathing_counter / interval; -    // limit index to max step value -    if (index >= BREATHING_STEPS) { -        index = BREATHING_STEPS - 1; -    } - -    if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) { -        breathing_interrupt_disable(); -    } - -    // Set PWM to a brightnessvalue scaled to the configured resolution -    set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint32_t)pgm_read_byte(&breathing_table[index]) * ICRx / 255)))); -} - -#endif // BACKLIGHT_BREATHING - -void backlight_init_ports(void) { -    // Setup backlight pin as output and output to on state. -    backlight_pins_init(); - -    // I could write a wall of text here to explain... but TL;DW -    // Go read the ATmega32u4 datasheet. -    // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on - -#ifdef BACKLIGHT_PWM_TIMER -    // TimerX setup, Fast PWM mode count to TOP set in ICRx -    TCCRxA = _BV(WGM11); // = 0b00000010; -    // clock select clk/1 -    TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; -#else                                             // hardware PWM -    // Pin PB7 = OCR1C (Timer 1, Channel C) -    // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0 -    // (i.e. start high, go low when counter matches.) -    // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0 -    // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1 - -    /* -    14.8.3: -    "In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]." -    "In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)." -    */ -    TCCRxA = _BV(COMxx1) | _BV(WGM11);            // = 0b00001010; -    TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; -#endif - -#ifdef BACKLIGHT_CUSTOM_RESOLUTION -#    if (BACKLIGHT_CUSTOM_RESOLUTION > 0xFFFF || BACKLIGHT_CUSTOM_RESOLUTION < 1) -#        error "This out of range of the timer capabilities" -#    elif (BACKLIGHT_CUSTOM_RESOLUTION < 0xFF) -#        warning "Resolution lower than 0xFF isn't recommended" -#    endif -#    ifdef BACKLIGHT_BREATHING -    breathing_freq_scale_factor = F_CPU / BACKLIGHT_CUSTOM_RESOLUTION / 120; -#    endif -    ICRx = BACKLIGHT_CUSTOM_RESOLUTION; -#else -    ICRx = TIMER_TOP; -#endif - -    backlight_init(); -#ifdef BACKLIGHT_BREATHING -    if (is_backlight_breathing()) { -        breathing_enable(); -    } -#endif -} diff --git a/quantum/backlight/backlight_chibios.c b/quantum/backlight/backlight_chibios.c deleted file mode 100644 index 30e95bd5c8..0000000000 --- a/quantum/backlight/backlight_chibios.c +++ /dev/null @@ -1,173 +0,0 @@ -#include "quantum.h" -#include "backlight.h" -#include <hal.h> -#include "debug.h" - -// Maximum duty cycle limit -#ifndef BACKLIGHT_LIMIT_VAL -#    define BACKLIGHT_LIMIT_VAL 255 -#endif - -#ifndef BACKLIGHT_PAL_MODE -#    if defined(USE_GPIOV1) -#        define BACKLIGHT_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL -#    else -// GPIOV2 && GPIOV3 -#        define BACKLIGHT_PAL_MODE 5 -#    endif -#endif - -// GENERIC -#ifndef BACKLIGHT_PWM_DRIVER -#    define BACKLIGHT_PWM_DRIVER PWMD4 -#endif -#ifndef BACKLIGHT_PWM_CHANNEL -#    define BACKLIGHT_PWM_CHANNEL 3 -#endif - -// Support for pins which are on TIM1_CH1N - requires STM32_PWM_USE_ADVANCED -#ifdef BACKLIGHT_PWM_COMPLEMENTARY_OUTPUT -#    if BACKLIGHT_ON_STATE == 1 -#        define PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_LOW; -#    else -#        define PWM_OUTPUT_MODE PWM_COMPLEMENTARY_OUTPUT_ACTIVE_HIGH; -#    endif -#else -#    if BACKLIGHT_ON_STATE == 1 -#        define PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_HIGH; -#    else -#        define PWM_OUTPUT_MODE PWM_OUTPUT_ACTIVE_LOW; -#    endif -#endif - -#ifndef BACKLIGHT_PWM_COUNTER_FREQUENCY -#    define BACKLIGHT_PWM_COUNTER_FREQUENCY 0xFFFF -#endif - -#ifndef BACKLIGHT_PWM_PERIOD -#    define BACKLIGHT_PWM_PERIOD 256 -#endif - -static PWMConfig pwmCFG = { -    .frequency = BACKLIGHT_PWM_COUNTER_FREQUENCY, /* PWM clock frequency  */ -    .period    = BACKLIGHT_PWM_PERIOD,            /* PWM period in counter ticks. e.g. clock frequency is 10KHz, period is 256 ticks then t_period is 25.6ms */ -}; - -#ifdef BACKLIGHT_BREATHING -static virtual_timer_t breathing_vt; -#endif - -// See http://jared.geek.nz/2013/feb/linear-led-pwm -static uint16_t cie_lightness(uint16_t v) { -    if (v <= 5243)    // if below 8% of max -        return v / 9; // same as dividing by 900% -    else { -        uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare -        // to get a useful result with integer division, we shift left in the expression above -        // and revert what we've done again after squaring. -        y = y * y * y >> 8; -        if (y > 0xFFFFUL) { // prevent overflow -            return 0xFFFFU; -        } else { -            return (uint16_t)y; -        } -    } -} - -static uint32_t rescale_limit_val(uint32_t val) { -    // rescale the supplied backlight value to be in terms of the value limit -    return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256; -} - -void backlight_init_ports(void) { -#ifdef USE_GPIOV1 -    palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), BACKLIGHT_PAL_MODE); -#else -    palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_ALTERNATE(BACKLIGHT_PAL_MODE)); -#endif - -    pwmCFG.channels[BACKLIGHT_PWM_CHANNEL - 1].mode = PWM_OUTPUT_MODE; -    pwmStart(&BACKLIGHT_PWM_DRIVER, &pwmCFG); - -    backlight_set(get_backlight_level()); - -#ifdef BACKLIGHT_BREATHING -    chVTObjectInit(&breathing_vt); -    if (is_backlight_breathing()) { -        breathing_enable(); -    } -#endif -} - -void backlight_set(uint8_t level) { -    if (level > BACKLIGHT_LEVELS) { -        level = BACKLIGHT_LEVELS; -    } - -    if (level == 0) { -        // Turn backlight off -        pwmDisableChannel(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1); -    } else { -        // Turn backlight on -        uint32_t duty = (uint32_t)(cie_lightness(rescale_limit_val(0xFFFF * (uint32_t)level / BACKLIGHT_LEVELS))); -        pwmEnableChannel(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, duty)); -    } -} - -void backlight_task(void) {} - -#ifdef BACKLIGHT_BREATHING - -#    define BREATHING_STEPS 128 - -/* To generate breathing curve in python: - * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)] - */ -static const uint8_t breathing_table[BREATHING_STEPS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -static void breathing_callback(virtual_timer_t *vtp, void *p); - -bool is_breathing(void) { -    return chVTIsArmed(&breathing_vt); -} - -void breathing_enable(void) { -    /* Update frequency is 256Hz -> 3906us intervals */ -    chVTSetContinuous(&breathing_vt, TIME_US2I(3906), breathing_callback, NULL); -} - -void breathing_disable(void) { -    chVTReset(&breathing_vt); - -    // Restore backlight level -    backlight_set(get_backlight_level()); -} - -// Use this before the cie_lightness function. -static inline uint16_t scale_backlight(uint16_t v) { -    return v / BACKLIGHT_LEVELS * get_backlight_level(); -} - -static void breathing_callback(virtual_timer_t *vtp, void *p) { -    uint8_t  breathing_period = get_breathing_period(); -    uint16_t interval         = (uint16_t)breathing_period * 256 / BREATHING_STEPS; - -    // resetting after one period to prevent ugly reset at overflow. -    static uint16_t breathing_counter = 0; -    breathing_counter                 = (breathing_counter + 1) % (breathing_period * 256); -    uint8_t  index                    = breathing_counter / interval % BREATHING_STEPS; -    uint32_t duty                     = cie_lightness(rescale_limit_val(scale_backlight(breathing_table[index] * 256))); - -    chSysLockFromISR(); -    pwmEnableChannelI(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, duty)); -    chSysUnlockFromISR(); -} - -// TODO: integrate generic pulse solution -void breathing_pulse(void) { -    backlight_set(is_backlight_enabled() ? 0 : BACKLIGHT_LEVELS); -    wait_ms(10); -    backlight_set(is_backlight_enabled() ? get_backlight_level() : 0); -} - -#endif diff --git a/quantum/backlight/backlight_driver_common.c b/quantum/backlight/backlight_driver_common.c index 1eb8969084..8c3fe461d7 100644 --- a/quantum/backlight/backlight_driver_common.c +++ b/quantum/backlight/backlight_driver_common.c @@ -1,6 +1,7 @@ -#include "quantum.h"  #include "backlight.h"  #include "backlight_driver_common.h" +#include "gpio.h" +#include "util.h"  #if !defined(BACKLIGHT_PIN) && !defined(BACKLIGHT_PINS)  #    error "Backlight pin/pins not defined. Please configure." diff --git a/quantum/backlight/backlight_software.c b/quantum/backlight/backlight_software.c deleted file mode 100644 index 27ccbd2c9f..0000000000 --- a/quantum/backlight/backlight_software.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "quantum.h" -#include "backlight.h" -#include "backlight_driver_common.h" - -#ifdef BACKLIGHT_BREATHING -#    error "Backlight breathing is not available for software PWM. Please disable." -#endif - -static uint16_t s_duty_pattern = 0; - -// clang-format off - -/** \brief PWM duty patterns - * - * We scale the current backlight level to an index within this array. This allows - * backlight_task to focus on just switching LEDs on/off, and we can predict the duty pattern - */ -static const uint16_t backlight_duty_table[] = { -    0b0000000000000000, -    0b1000000000000000, -    0b1000000010000000, -    0b1000001000010000, -    0b1000100010001000, -    0b1001001001001000, -    0b1010101010101010, -    0b1110111011101110, -    0b1111111111111111, -}; -#define backlight_duty_table_size ARRAY_SIZE(backlight_duty_table) - -// clang-format on - -static uint8_t scale_backlight(uint8_t v) { -    return v * (backlight_duty_table_size - 1) / BACKLIGHT_LEVELS; -} - -void backlight_init_ports(void) { -    backlight_pins_init(); -} - -void backlight_set(uint8_t level) { -    s_duty_pattern = backlight_duty_table[scale_backlight(level)]; -} - -void backlight_task(void) { -    static uint8_t backlight_tick = 0; - -    if (s_duty_pattern & ((uint16_t)1 << backlight_tick)) { -        backlight_pins_on(); -    } else { -        backlight_pins_off(); -    } -    backlight_tick = (backlight_tick + 1) % 16; -} diff --git a/quantum/backlight/backlight_timer.c b/quantum/backlight/backlight_timer.c deleted file mode 100644 index 82fb6a6a83..0000000000 --- a/quantum/backlight/backlight_timer.c +++ /dev/null @@ -1,179 +0,0 @@ -#include "quantum.h" -#include "backlight.h" -#include "backlight_driver_common.h" -#include "debug.h" - -#ifndef BACKLIGHT_GPT_DRIVER -#    define BACKLIGHT_GPT_DRIVER GPTD15 -#endif - -// Platform specific implementations -static void     backlight_timer_configure(bool enable); -static void     backlight_timer_set_duty(uint16_t duty); -static uint16_t backlight_timer_get_duty(void); - -// See http://jared.geek.nz/2013/feb/linear-led-pwm -static uint16_t cie_lightness(uint16_t v) { -    if (v <= 5243)    // if below 8% of max -        return v / 9; // same as dividing by 900% -    else { -        uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare -        // to get a useful result with integer division, we shift left in the expression above -        // and revert what we've done again after squaring. -        y = y * y * y >> 8; -        if (y > 0xFFFFUL) // prevent overflow -            return 0xFFFFU; -        else -            return (uint16_t)y; -    } -} - -void backlight_init_ports(void) { -    backlight_pins_init(); - -    backlight_set(get_backlight_level()); - -#ifdef BACKLIGHT_BREATHING -    if (is_backlight_breathing()) { -        breathing_enable(); -    } -#endif -} - -void backlight_set(uint8_t level) { -    if (level > BACKLIGHT_LEVELS) level = BACKLIGHT_LEVELS; - -    backlight_pins_off(); - -    backlight_timer_set_duty(cie_lightness(0xFFFFU / BACKLIGHT_LEVELS * level)); -    backlight_timer_configure(level != 0); -} - -static void backlight_timer_top(void) { -#ifdef BACKLIGHT_BREATHING -    if (is_breathing()) { -        breathing_task(); -    } -#endif - -    if (backlight_timer_get_duty() > 256) { -        backlight_pins_on(); -    } -} - -static void backlight_timer_cmp(void) { -    backlight_pins_off(); -} - -void backlight_task(void) {} - -#ifdef BACKLIGHT_BREATHING -#    define BREATHING_STEPS 128 - -static bool     breathing         = false; -static uint16_t breathing_counter = 0; - -/* To generate breathing curve in python: - * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)] - */ -static const uint8_t breathing_table[BREATHING_STEPS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -// Use this before the cie_lightness function. -static inline uint16_t scale_backlight(uint16_t v) { -    return v / BACKLIGHT_LEVELS * get_backlight_level(); -} - -void breathing_task(void) { -    uint8_t  breathing_period = get_breathing_period(); -    uint16_t interval         = (uint16_t)breathing_period * 256 / BREATHING_STEPS; -    // resetting after one period to prevent ugly reset at overflow. -    breathing_counter = (breathing_counter + 1) % (breathing_period * 256); -    uint8_t index     = breathing_counter / interval % BREATHING_STEPS; - -    // printf("index:%u\n", index); - -    backlight_timer_set_duty(cie_lightness(scale_backlight((uint16_t)breathing_table[index] * 256))); -} - -bool is_breathing(void) { -    return breathing; -} - -void breathing_enable(void) { -    breathing_counter = 0; -    breathing         = true; -} -void breathing_disable(void) { -    breathing = false; -} - -void breathing_pulse(void) { -    backlight_set(is_backlight_enabled() ? 0 : BACKLIGHT_LEVELS); -    wait_ms(10); -    backlight_set(is_backlight_enabled() ? get_backlight_level() : 0); -} -#endif - -#ifdef PROTOCOL_CHIBIOS -// On Platforms where timers fire every tick and have no capture/top events -//   - fake event in the normal timer callback -uint16_t s_duty = 0; - -static void timerCallback(void) { -    /* Software PWM -     * timer:1111 1111 1111 1111 -     *       \______/| \_______/____  count(0-255) -     *          \    \______________  unused(1) -     *           \__________________  index of step table(0-127) -     */ - -    // this works for cca 65536 irqs/sec -    static union { -        uint16_t raw; -        struct { -            uint16_t count : 8; -            uint8_t  dummy : 1; -            uint8_t  index : 7; -        } pwm; -    } timer = {.raw = 0}; - -    timer.raw++; - -    if (timer.pwm.count == 0) { -        // LED on -        backlight_timer_top(); -    } else if (timer.pwm.count == (s_duty / 256)) { -        // LED off -        backlight_timer_cmp(); -    } -} - -static void backlight_timer_set_duty(uint16_t duty) { -    s_duty = duty; -} -static uint16_t backlight_timer_get_duty(void) { -    return s_duty; -} - -// ChibiOS - Map GPT timer onto Software PWM -static void gptTimerCallback(GPTDriver *gptp) { -    (void)gptp; -    timerCallback(); -} - -static void backlight_timer_configure(bool enable) { -    static const GPTConfig gptcfg = {1000000, gptTimerCallback, 0, 0}; - -    static bool s_init = false; -    if (!s_init) { -        gptStart(&BACKLIGHT_GPT_DRIVER, &gptcfg); -        s_init = true; -    } - -    if (enable) { -        gptStartContinuous(&BACKLIGHT_GPT_DRIVER, gptcfg.frequency / 0xFFFF); -    } else { -        gptStopTimer(&BACKLIGHT_GPT_DRIVER); -    } -} -#endif diff --git a/quantum/bootmagic/bootmagic_lite.c b/quantum/bootmagic/bootmagic_lite.c index f63c71fc6b..efce6bfd12 100644 --- a/quantum/bootmagic/bootmagic_lite.c +++ b/quantum/bootmagic/bootmagic_lite.c @@ -13,7 +13,12 @@   * 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 "quantum.h" +#include "bootmagic.h" +#include "matrix.h" +#include "keyboard.h" +#include "wait.h" +#include "eeconfig.h" +#include "bootloader.h"  /** \brief Reset eeprom   * diff --git a/quantum/debounce.h b/quantum/debounce.h index a8629654c2..cea1f2b526 100644 --- a/quantum/debounce.h +++ b/quantum/debounce.h @@ -1,5 +1,9 @@  #pragma once +#include <stdint.h> +#include <stdbool.h> +#include "matrix.h" +  /**   * @brief Debounce raw matrix events according to the choosen debounce algorithm.   * diff --git a/quantum/debounce/asym_eager_defer_pk.c b/quantum/debounce/asym_eager_defer_pk.c index 4745c6f465..954d43536c 100644 --- a/quantum/debounce/asym_eager_defer_pk.c +++ b/quantum/debounce/asym_eager_defer_pk.c @@ -22,9 +22,8 @@ Basic symmetric per-key algorithm. Uses an 8-bit counter per key.  When no state changes have occured for DEBOUNCE milliseconds, we push the state.  */ -#include "matrix.h" +#include "debounce.h"  #include "timer.h" -#include "quantum.h"  #include <stdlib.h>  #ifdef PROTOCOL_CHIBIOS @@ -144,6 +143,8 @@ static void update_debounce_counters_and_transfer_if_expired(matrix_row_t raw[],  static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) {      debounce_counter_t *debounce_pointer = debounce_counters; +    matrix_need_update = false; +      for (uint8_t row = 0; row < num_rows; row++) {          matrix_row_t delta = raw[row] ^ cooked[row];          for (uint8_t col = 0; col < MATRIX_COLS; col++) { diff --git a/quantum/debounce/none.c b/quantum/debounce/none.c index 4cff5e05e2..1b8b1dc13a 100644 --- a/quantum/debounce/none.c +++ b/quantum/debounce/none.c @@ -14,9 +14,7 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "matrix.h" -#include "quantum.h" -#include <stdlib.h> +#include "debounce.h"  #include <string.h>  void debounce_init(uint8_t num_rows) {} diff --git a/quantum/debounce/sym_defer_g.c b/quantum/debounce/sym_defer_g.c index d04310a761..25e18890af 100644 --- a/quantum/debounce/sym_defer_g.c +++ b/quantum/debounce/sym_defer_g.c @@ -17,9 +17,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  Basic global debounce algorithm. Used in 99% of keyboards at time of implementation  When no state changes have occured for DEBOUNCE milliseconds, we push the state.  */ -#include "matrix.h" +#include "debounce.h"  #include "timer.h" -#include "quantum.h"  #include <string.h>  #ifndef DEBOUNCE  #    define DEBOUNCE 5 diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c index 7b59b5e100..156535a373 100644 --- a/quantum/debounce/sym_defer_pk.c +++ b/quantum/debounce/sym_defer_pk.c @@ -19,9 +19,8 @@ Basic symmetric per-key algorithm. Uses an 8-bit counter per key.  When no state changes have occured for DEBOUNCE milliseconds, we push the state.  */ -#include "matrix.h" +#include "debounce.h"  #include "timer.h" -#include "quantum.h"  #include <stdlib.h>  #ifdef PROTOCOL_CHIBIOS diff --git a/quantum/debounce/sym_defer_pr.c b/quantum/debounce/sym_defer_pr.c index 452c4599d0..d6222af5b2 100644 --- a/quantum/debounce/sym_defer_pr.c +++ b/quantum/debounce/sym_defer_pr.c @@ -17,9 +17,8 @@ Symmetric per-row debounce algorithm. Changes only apply when  DEBOUNCE milliseconds have elapsed since the last change.  */ -#include "matrix.h" +#include "debounce.h"  #include "timer.h" -#include "quantum.h"  #include <stdlib.h>  #ifndef DEBOUNCE diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c index f736d1645c..b359e79287 100644 --- a/quantum/debounce/sym_eager_pk.c +++ b/quantum/debounce/sym_eager_pk.c @@ -19,9 +19,8 @@ After pressing a key, it immediately changes state, and sets a counter.  No further inputs are accepted until DEBOUNCE milliseconds have occurred.  */ -#include "matrix.h" +#include "debounce.h"  #include "timer.h" -#include "quantum.h"  #include <stdlib.h>  #ifdef PROTOCOL_CHIBIOS @@ -125,6 +124,7 @@ static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {  // upload from raw_matrix to final matrix;  static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { +    matrix_need_update                   = false;      debounce_counter_t *debounce_pointer = debounce_counters;      for (uint8_t row = 0; row < num_rows; row++) {          matrix_row_t delta        = raw[row] ^ cooked[row]; diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c index aad5ca351b..ccc5d20fa2 100644 --- a/quantum/debounce/sym_eager_pr.c +++ b/quantum/debounce/sym_eager_pr.c @@ -19,9 +19,8 @@ After pressing a key, it immediately changes state, and sets a counter.  No further inputs are accepted until DEBOUNCE milliseconds have occurred.  */ -#include "matrix.h" +#include "debounce.h"  #include "timer.h" -#include "quantum.h"  #include <stdlib.h>  #ifdef PROTOCOL_CHIBIOS @@ -119,6 +118,7 @@ static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) {  // upload from raw_matrix to final matrix;  static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { +    matrix_need_update                   = false;      debounce_counter_t *debounce_pointer = debounce_counters;      for (uint8_t row = 0; row < num_rows; row++) {          matrix_row_t existing_row = cooked[row]; diff --git a/quantum/debounce/tests/debounce_test_common.cpp b/quantum/debounce/tests/debounce_test_common.cpp index bd98e32955..b11378b286 100644 --- a/quantum/debounce/tests/debounce_test_common.cpp +++ b/quantum/debounce/tests/debounce_test_common.cpp @@ -23,9 +23,8 @@  #include <sstream>  extern "C" { -#include "quantum.h" -#include "timer.h"  #include "debounce.h" +#include "timer.h"  void set_time(uint32_t t);  void advance_time(uint32_t ms); diff --git a/quantum/debounce/tests/debounce_test_common.h b/quantum/debounce/tests/debounce_test_common.h index b7becb3782..7319abfbf3 100644 --- a/quantum/debounce/tests/debounce_test_common.h +++ b/quantum/debounce/tests/debounce_test_common.h @@ -21,7 +21,7 @@  #include <string>  extern "C" { -#include "quantum.h" +#include "matrix.h"  #include "timer.h"  } diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index 90a0f20838..4c95128337 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -14,14 +14,16 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "keymap_introspection.h" // to get keymaps[][][] -#include "eeprom.h" -#include "progmem.h" // to read default from flash -#include "quantum.h" // for send_string()  #include "dynamic_keymap.h" +#include "keymap_introspection.h" +#include "action.h" +#include "eeprom.h" +#include "progmem.h" +#include "send_string.h" +#include "keycodes.h"  #ifdef VIA_ENABLE -#    include "via.h" // for VIA_EEPROM_CONFIG_END +#    include "via.h"  #    define DYNAMIC_KEYMAP_EEPROM_START (VIA_EEPROM_CONFIG_END)  #else  #    define DYNAMIC_KEYMAP_EEPROM_START (EECONFIG_SIZE) @@ -152,22 +154,13 @@ void dynamic_keymap_reset(void) {      for (int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++) {          for (int row = 0; row < MATRIX_ROWS; row++) {              for (int column = 0; column < MATRIX_COLS; column++) { -                if (layer < keymap_layer_count()) { -                    dynamic_keymap_set_keycode(layer, row, column, keycode_at_keymap_location_raw(layer, row, column)); -                } else { -                    dynamic_keymap_set_keycode(layer, row, column, KC_TRANSPARENT); -                } +                dynamic_keymap_set_keycode(layer, row, column, keycode_at_keymap_location_raw(layer, row, column));              }          }  #ifdef ENCODER_MAP_ENABLE          for (int encoder = 0; encoder < NUM_ENCODERS; encoder++) { -            if (layer < encodermap_layer_count()) { -                dynamic_keymap_set_encoder(layer, encoder, true, keycode_at_encodermap_location_raw(layer, encoder, true)); -                dynamic_keymap_set_encoder(layer, encoder, false, keycode_at_encodermap_location_raw(layer, encoder, false)); -            } else { -                dynamic_keymap_set_encoder(layer, encoder, true, KC_TRANSPARENT); -                dynamic_keymap_set_encoder(layer, encoder, false, KC_TRANSPARENT); -            } +            dynamic_keymap_set_encoder(layer, encoder, true, keycode_at_encodermap_location_raw(layer, encoder, true)); +            dynamic_keymap_set_encoder(layer, encoder, false, keycode_at_encodermap_location_raw(layer, encoder, false));          }  #endif // ENCODER_MAP_ENABLE      } diff --git a/quantum/encoder.c b/quantum/encoder.c index 1046fe6cc3..7ab194ed52 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -16,6 +16,11 @@   */  #include "encoder.h" +#include "keyboard.h" +#include "action.h" +#include "keycodes.h" +#include "wait.h" +  #ifdef SPLIT_KEYBOARD  #    include "split_util.h"  #endif diff --git a/quantum/encoder.h b/quantum/encoder.h index 7644853b30..1cbac98cb5 100644 --- a/quantum/encoder.h +++ b/quantum/encoder.h @@ -17,7 +17,9 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "gpio.h"  #include "util.h"  void encoder_init(void); diff --git a/quantum/encoder/tests/encoder_tests_split_role.cpp b/quantum/encoder/tests/encoder_tests_split_role.cpp index 02264067f4..0ab7bfc2a7 100644 --- a/quantum/encoder/tests/encoder_tests_split_role.cpp +++ b/quantum/encoder/tests/encoder_tests_split_role.cpp @@ -22,6 +22,7 @@  extern "C" {  #include "encoder.h" +#include "keyboard.h"  #include "encoder/tests/mock_split.h"  } diff --git a/quantum/haptic.c b/quantum/haptic.c index c151547fca..13b2258eb8 100644 --- a/quantum/haptic.c +++ b/quantum/haptic.c @@ -14,17 +14,20 @@   * 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 "haptic.h"  #include "eeconfig.h"  #include "debug.h"  #include "usb_device_state.h"  #include "gpio.h" -#ifdef DRV2605L -#    include "DRV2605L.h" + +#ifdef HAPTIC_DRV2605L +#    include "drv2605l.h"  #endif -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID  #    include "solenoid.h"  #endif +  #if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE)  extern uint8_t split_haptic_play;  #endif @@ -59,11 +62,11 @@ void haptic_init(void) {          eeconfig_init();      }      haptic_config.raw = eeconfig_read_haptic(); -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID      solenoid_set_dwell(haptic_config.dwell);  #endif      if ((haptic_config.raw == 0) -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID          || (haptic_config.dwell == 0)  #endif      ) { @@ -77,12 +80,12 @@ void haptic_init(void) {          // This is to execute any side effects of the configuration.          set_haptic_config_enable(haptic_config.enable);      } -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID      solenoid_setup();      dprintf("Solenoid driver initialized\n");  #endif -#ifdef DRV2605L -    DRV_init(); +#ifdef HAPTIC_DRV2605L +    drv2605l_init();      dprintf("DRV2605 driver initialized\n");  #endif      eeconfig_debug_haptic(); @@ -95,7 +98,7 @@ void haptic_init(void) {  }  void haptic_task(void) { -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID      solenoid_check();  #endif  } @@ -108,13 +111,13 @@ void eeconfig_debug_haptic(void) {  void haptic_enable(void) {      set_haptic_config_enable(true); -    xprintf("haptic_config.enable = %u\n", haptic_config.enable); +    dprintf("haptic_config.enable = %u\n", haptic_config.enable);      eeconfig_update_haptic(haptic_config.raw);  }  void haptic_disable(void) {      set_haptic_config_enable(false); -    xprintf("haptic_config.enable = %u\n", haptic_config.enable); +    dprintf("haptic_config.enable = %u\n", haptic_config.enable);      eeconfig_update_haptic(haptic_config.raw);  } @@ -130,7 +133,7 @@ void haptic_toggle(void) {  void haptic_feedback_toggle(void) {      haptic_config.feedback++;      if (haptic_config.feedback >= HAPTIC_FEEDBACK_MAX) haptic_config.feedback = KEY_PRESS; -    xprintf("haptic_config.feedback = %u\n", !haptic_config.feedback); +    dprintf("haptic_config.feedback = %u\n", !haptic_config.feedback);      eeconfig_update_haptic(haptic_config.raw);  } @@ -142,7 +145,7 @@ void haptic_buzz_toggle(void) {  void haptic_mode_increase(void) {      uint8_t mode = haptic_config.mode + 1; -#ifdef DRV2605L +#ifdef HAPTIC_DRV2605L      if (haptic_config.mode >= drv_effect_max) {          mode = 1;      } @@ -152,7 +155,7 @@ void haptic_mode_increase(void) {  void haptic_mode_decrease(void) {      uint8_t mode = haptic_config.mode - 1; -#ifdef DRV2605L +#ifdef HAPTIC_DRV2605L      if (haptic_config.mode < 1) {          mode = (drv_effect_max - 1);      } @@ -161,7 +164,7 @@ void haptic_mode_decrease(void) {  }  void haptic_dwell_increase(void) { -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID      int16_t next_dwell = ((int16_t)haptic_config.dwell) + SOLENOID_DWELL_STEP_SIZE;      if (haptic_config.dwell >= SOLENOID_MAX_DWELL) {          // if it's already at max, we wrap back to min @@ -178,7 +181,7 @@ void haptic_dwell_increase(void) {  }  void haptic_dwell_decrease(void) { -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID      int16_t next_dwell = ((int16_t)haptic_config.dwell) - SOLENOID_DWELL_STEP_SIZE;      if (haptic_config.dwell <= SOLENOID_MIN_DWELL) {          // if it's already at min, we wrap to max @@ -196,13 +199,13 @@ void haptic_dwell_decrease(void) {  void haptic_reset(void) {      set_haptic_config_enable(true); -    uint8_t feedback       = HAPTIC_FEEDBACK_DEFAULT; +    uint8_t feedback       = HAPTIC_DEFAULT_FEEDBACK;      haptic_config.feedback = feedback; -#ifdef DRV2605L -    uint8_t mode       = HAPTIC_MODE_DEFAULT; +#ifdef HAPTIC_DRV2605L +    uint8_t mode       = HAPTIC_DEFAULT_MODE;      haptic_config.mode = mode;  #endif -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID      uint8_t dwell       = SOLENOID_DEFAULT_DWELL;      haptic_config.dwell = dwell;      haptic_config.buzz  = SOLENOID_DEFAULT_BUZZ; @@ -213,41 +216,41 @@ void haptic_reset(void) {      haptic_config.buzz  = 0;  #endif      eeconfig_update_haptic(haptic_config.raw); -    xprintf("haptic_config.feedback = %u\n", haptic_config.feedback); -    xprintf("haptic_config.mode = %u\n", haptic_config.mode); +    dprintf("haptic_config.feedback = %u\n", haptic_config.feedback); +    dprintf("haptic_config.mode = %u\n", haptic_config.mode);  }  void haptic_set_feedback(uint8_t feedback) {      haptic_config.feedback = feedback;      eeconfig_update_haptic(haptic_config.raw); -    xprintf("haptic_config.feedback = %u\n", haptic_config.feedback); +    dprintf("haptic_config.feedback = %u\n", haptic_config.feedback);  }  void haptic_set_mode(uint8_t mode) {      haptic_config.mode = mode;      eeconfig_update_haptic(haptic_config.raw); -    xprintf("haptic_config.mode = %u\n", haptic_config.mode); +    dprintf("haptic_config.mode = %u\n", haptic_config.mode);  }  void haptic_set_amplitude(uint8_t amp) {      haptic_config.amplitude = amp;      eeconfig_update_haptic(haptic_config.raw); -    xprintf("haptic_config.amplitude = %u\n", haptic_config.amplitude); -#ifdef DRV2605L -    DRV_amplitude(amp); +    dprintf("haptic_config.amplitude = %u\n", haptic_config.amplitude); +#ifdef HAPTIC_DRV2605L +    drv2605l_amplitude(amp);  #endif  }  void haptic_set_buzz(uint8_t buzz) {      haptic_config.buzz = buzz;      eeconfig_update_haptic(haptic_config.raw); -    xprintf("haptic_config.buzz = %u\n", haptic_config.buzz); +    dprintf("haptic_config.buzz = %u\n", haptic_config.buzz);  }  void haptic_set_dwell(uint8_t dwell) {      haptic_config.dwell = dwell;      eeconfig_update_haptic(haptic_config.raw); -    xprintf("haptic_config.dwell = %u\n", haptic_config.dwell); +    dprintf("haptic_config.dwell = %u\n", haptic_config.dwell);  }  uint8_t haptic_get_enable(void) { @@ -277,19 +280,19 @@ uint8_t haptic_get_dwell(void) {  void haptic_enable_continuous(void) {      haptic_config.cont = 1; -    xprintf("haptic_config.cont = %u\n", haptic_config.cont); +    dprintf("haptic_config.cont = %u\n", haptic_config.cont);      eeconfig_update_haptic(haptic_config.raw); -#ifdef DRV2605L -    DRV_rtp_init(); +#ifdef HAPTIC_DRV2605L +    drv2605l_rtp_init();  #endif  }  void haptic_disable_continuous(void) {      haptic_config.cont = 0; -    xprintf("haptic_config.cont = %u\n", haptic_config.cont); +    dprintf("haptic_config.cont = %u\n", haptic_config.cont);      eeconfig_update_haptic(haptic_config.raw); -#ifdef DRV2605L -    DRV_write(DRV_MODE, 0x00); +#ifdef HAPTIC_DRV2605L +    drv2605l_write(DRV2605L_REG_MODE, 0x00);  #endif  } @@ -318,15 +321,15 @@ void haptic_cont_decrease(void) {  }  void haptic_play(void) { -#ifdef DRV2605L +#ifdef HAPTIC_DRV2605L      uint8_t play_eff = 0;      play_eff         = haptic_config.mode; -    DRV_pulse(play_eff); +    drv2605l_pulse(play_eff);  #    if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE)      split_haptic_play = haptic_config.mode;  #    endif  #endif -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID      solenoid_fire_handler();  #    if defined(SPLIT_KEYBOARD) && defined(SPLIT_HAPTIC_ENABLE)      split_haptic_play = 1; @@ -335,7 +338,7 @@ void haptic_play(void) {  }  void haptic_shutdown(void) { -#ifdef SOLENOID_ENABLE +#ifdef HAPTIC_SOLENOID      solenoid_shutdown();  #endif  } diff --git a/quantum/haptic.h b/quantum/haptic.h index 71d95cc61b..5bd1a71916 100644 --- a/quantum/haptic.h +++ b/quantum/haptic.h @@ -16,14 +16,15 @@   */  #pragma once +  #include <stdint.h>  #include <stdbool.h> -#ifndef HAPTIC_FEEDBACK_DEFAULT -#    define HAPTIC_FEEDBACK_DEFAULT 0 +#ifndef HAPTIC_DEFAULT_FEEDBACK +#    define HAPTIC_DEFAULT_FEEDBACK 0  #endif -#ifndef HAPTIC_MODE_DEFAULT -#    define HAPTIC_MODE_DEFAULT DRV_MODE_DEFAULT +#ifndef HAPTIC_DEFAULT_MODE +#    define HAPTIC_DEFAULT_MODE DRV2605L_DEFAULT_MODE  #endif  /* EEPROM config settings */ diff --git a/quantum/keyboard.c b/quantum/keyboard.c index 5115709748..c2ca15d52d 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -16,8 +16,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */  #include <stdint.h> -#include "quantum.h"  #include "keyboard.h" +#include "keycode_config.h"  #include "matrix.h"  #include "keymap_introspection.h"  #include "magic.h" @@ -33,6 +33,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "sendchar.h"  #include "eeconfig.h"  #include "action_layer.h" +#ifdef AUDIO_ENABLE +#    include "audio.h" +#endif +#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) +#    include "process_music.h" +#endif  #ifdef BACKLIGHT_ENABLE  #    include "backlight.h"  #endif @@ -54,9 +60,27 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #ifdef ENCODER_ENABLE  #    include "encoder.h"  #endif +#ifdef HAPTIC_ENABLE +#    include "haptic.h" +#endif +#ifdef AUTO_SHIFT_ENABLE +#    include "process_auto_shift.h" +#endif +#ifdef COMBO_ENABLE +#    include "process_combo.h" +#endif +#ifdef TAP_DANCE_ENABLE +#    include "process_tap_dance.h" +#endif  #ifdef STENO_ENABLE  #    include "process_steno.h"  #endif +#ifdef KEY_OVERRIDE_ENABLE +#    include "process_key_override.h" +#endif +#ifdef SECURE_ENABLE +#    include "secure.h" +#endif  #ifdef POINTING_DEVICE_ENABLE  #    include "pointing_device.h"  #endif @@ -64,7 +88,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    include "process_midi.h"  #endif  #ifdef JOYSTICK_ENABLE -#    include "process_joystick.h" +#    include "joystick.h"  #endif  #ifdef HD44780_ENABLE  #    include "hd44780.h" @@ -108,6 +132,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #ifdef LEADER_ENABLE  #    include "leader.h"  #endif +#ifdef UNICODE_COMMON_ENABLE +#    include "unicode.h" +#endif +#ifdef WPM_ENABLE +#    include "wpm.h" +#endif  static uint32_t last_input_modification_time = 0;  uint32_t        last_input_activity_time(void) { diff --git a/quantum/keyboard.h b/quantum/keyboard.h index bf1890d10b..5ea57815a7 100644 --- a/quantum/keyboard.h +++ b/quantum/keyboard.h @@ -20,6 +20,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include <stdbool.h>  #include <stdint.h> +#include "timer.h" +  #ifdef __cplusplus  extern "C" {  #endif diff --git a/quantum/keycode_config.c b/quantum/keycode_config.c index 9dd7097c86..864488a65c 100644 --- a/quantum/keycode_config.c +++ b/quantum/keycode_config.c @@ -122,40 +122,36 @@ __attribute__((weak)) uint16_t keycode_config(uint16_t keycode) {   */  __attribute__((weak)) uint8_t mod_config(uint8_t mod) { +    /** +     * Note: This function is for the 5-bit packed mods, NOT the full 8-bit mods. +     * More info about the mods can be seen in modifiers.h. +     */      if (keymap_config.swap_lalt_lgui) { -        if ((mod & MOD_RGUI) == MOD_LGUI) { -            mod &= ~MOD_LGUI; -            mod |= MOD_LALT; -        } else if ((mod & MOD_RALT) == MOD_LALT) { -            mod &= ~MOD_LALT; -            mod |= MOD_LGUI; +        /** If both modifiers pressed or neither pressed, do nothing +         * Otherwise swap the values +         * Note: The left mods are ANDed with the right-hand values to check +         * if they were pressed with the right hand bit set +         */ +        if (((mod & MOD_RALT) == MOD_LALT) ^ ((mod & MOD_RGUI) == MOD_LGUI)) { +            mod ^= (MOD_LALT | MOD_LGUI);          }      }      if (keymap_config.swap_ralt_rgui) { -        if ((mod & MOD_RGUI) == MOD_RGUI) { -            mod &= ~MOD_RGUI; -            mod |= MOD_RALT; -        } else if ((mod & MOD_RALT) == MOD_RALT) { -            mod &= ~MOD_RALT; -            mod |= MOD_RGUI; +        if (((mod & MOD_RALT) == MOD_RALT) ^ ((mod & MOD_RGUI) == MOD_RGUI)) { +            /* lefthand values to preserve the right hand bit */ +            mod ^= (MOD_LALT | MOD_LGUI);          }      }      if (keymap_config.swap_lctl_lgui) { -        if ((mod & MOD_RGUI) == MOD_LGUI) { -            mod &= ~MOD_LGUI; -            mod |= MOD_LCTL; -        } else if ((mod & MOD_RCTL) == MOD_LCTL) { -            mod &= ~MOD_LCTL; -            mod |= MOD_LGUI; +        /* left mods ANDed with right-hand values to check for right hand bit */ +        if (((mod & MOD_RCTL) == MOD_LCTL) ^ ((mod & MOD_RGUI) == MOD_LGUI)) { +            mod ^= (MOD_LCTL | MOD_LGUI);          }      }      if (keymap_config.swap_rctl_rgui) { -        if ((mod & MOD_RGUI) == MOD_RGUI) { -            mod &= ~MOD_RGUI; -            mod |= MOD_RCTL; -        } else if ((mod & MOD_RCTL) == MOD_RCTL) { -            mod &= ~MOD_RCTL; -            mod |= MOD_RGUI; +        if (((mod & MOD_RCTL) == MOD_RCTL) ^ ((mod & MOD_RGUI) == MOD_RGUI)) { +            /* lefthand values to preserve the right hand bit */ +            mod ^= (MOD_LCTL | MOD_LGUI);          }      }      if (keymap_config.no_gui) { diff --git a/quantum/keymap.h b/quantum/keymap.h deleted file mode 100644 index a067e1aa36..0000000000 --- a/quantum/keymap.h +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2012-2016 Jun Wako <[email protected]> - -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/>. -*/ - -#pragma once - -#pragma message("'keymap.h' should no longer be included!") diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 0492e6fd1c..9a67fad278 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -22,7 +22,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "action_layer.h"  #include "action.h"  #include "debug.h" -#include "quantum.h" +#include "keycode_config.h" +#include "quantum_keycodes.h" + +#ifdef ENCODER_MAP_ENABLE +#    include "encoder.h" +#endif  #ifdef BACKLIGHT_ENABLE  #    include "backlight.h" diff --git a/quantum/keymap_extras/sendstring_belgian.h b/quantum/keymap_extras/sendstring_belgian.h index 34ca9514c8..f33d6272e8 100644 --- a/quantum/keymap_extras/sendstring_belgian.h +++ b/quantum/keymap_extras/sendstring_belgian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_belgian.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_bepo.h b/quantum/keymap_extras/sendstring_bepo.h index 0f0d5a2111..1d24728ab6 100644 --- a/quantum/keymap_extras/sendstring_bepo.h +++ b/quantum/keymap_extras/sendstring_bepo.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_bepo.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_brazilian_abnt2.h b/quantum/keymap_extras/sendstring_brazilian_abnt2.h index b52ce4958a..ca908353ab 100644 --- a/quantum/keymap_extras/sendstring_brazilian_abnt2.h +++ b/quantum/keymap_extras/sendstring_brazilian_abnt2.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_brazilian_abnt2.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_canadian_multilingual.h b/quantum/keymap_extras/sendstring_canadian_multilingual.h index 92b588c82e..63bca96de9 100644 --- a/quantum/keymap_extras/sendstring_canadian_multilingual.h +++ b/quantum/keymap_extras/sendstring_canadian_multilingual.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_canadian_multilingual.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_colemak.h b/quantum/keymap_extras/sendstring_colemak.h index 3aef96b24a..1514620cb6 100644 --- a/quantum/keymap_extras/sendstring_colemak.h +++ b/quantum/keymap_extras/sendstring_colemak.h @@ -18,6 +18,7 @@  #pragma once +#include "send_string.h"  #include "keymap_colemak.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_croatian.h b/quantum/keymap_extras/sendstring_croatian.h index bf51c81a88..e43b54713d 100644 --- a/quantum/keymap_extras/sendstring_croatian.h +++ b/quantum/keymap_extras/sendstring_croatian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_croatian.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_czech.h b/quantum/keymap_extras/sendstring_czech.h index 54c3317418..083a723403 100644 --- a/quantum/keymap_extras/sendstring_czech.h +++ b/quantum/keymap_extras/sendstring_czech.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_czech.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_danish.h b/quantum/keymap_extras/sendstring_danish.h index 6923063ce2..573e4afae2 100644 --- a/quantum/keymap_extras/sendstring_danish.h +++ b/quantum/keymap_extras/sendstring_danish.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_danish.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_dvorak.h b/quantum/keymap_extras/sendstring_dvorak.h index 25e1d31423..d31a33ba51 100644 --- a/quantum/keymap_extras/sendstring_dvorak.h +++ b/quantum/keymap_extras/sendstring_dvorak.h @@ -18,6 +18,7 @@  #pragma once +#include "send_string.h"  #include "keymap_dvorak.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_dvorak_fr.h b/quantum/keymap_extras/sendstring_dvorak_fr.h index 2f4f281794..f1c3fa04cc 100644 --- a/quantum/keymap_extras/sendstring_dvorak_fr.h +++ b/quantum/keymap_extras/sendstring_dvorak_fr.h @@ -18,6 +18,7 @@  #pragma once +#include "send_string.h"  #include "keymap_dvorak_fr.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_dvorak_programmer.h b/quantum/keymap_extras/sendstring_dvorak_programmer.h index f19bb6f4b2..372ee5726b 100644 --- a/quantum/keymap_extras/sendstring_dvorak_programmer.h +++ b/quantum/keymap_extras/sendstring_dvorak_programmer.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_dvorak_programmer.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_estonian.h b/quantum/keymap_extras/sendstring_estonian.h index 9ea2ab3f8f..903ec3cab3 100644 --- a/quantum/keymap_extras/sendstring_estonian.h +++ b/quantum/keymap_extras/sendstring_estonian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_estonian.h" -#include "quantum"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_finnish.h b/quantum/keymap_extras/sendstring_finnish.h index 197836ba83..f797f34e0a 100644 --- a/quantum/keymap_extras/sendstring_finnish.h +++ b/quantum/keymap_extras/sendstring_finnish.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_finnish.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_french.h b/quantum/keymap_extras/sendstring_french.h index a37a5d314b..0e585ec093 100644 --- a/quantum/keymap_extras/sendstring_french.h +++ b/quantum/keymap_extras/sendstring_french.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_french.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_french_afnor.h b/quantum/keymap_extras/sendstring_french_afnor.h index 1408634a26..55b90b3204 100644 --- a/quantum/keymap_extras/sendstring_french_afnor.h +++ b/quantum/keymap_extras/sendstring_french_afnor.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_french_afnor.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_french_mac_iso.h b/quantum/keymap_extras/sendstring_french_mac_iso.h index 1033c3991f..9a17007898 100644 --- a/quantum/keymap_extras/sendstring_french_mac_iso.h +++ b/quantum/keymap_extras/sendstring_french_mac_iso.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_french_mac_iso.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_german.h b/quantum/keymap_extras/sendstring_german.h index 69c7dd996e..79357d71e4 100644 --- a/quantum/keymap_extras/sendstring_german.h +++ b/quantum/keymap_extras/sendstring_german.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_german.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_german_mac_iso.h b/quantum/keymap_extras/sendstring_german_mac_iso.h index 8345dbaaa1..711ba7d05b 100644 --- a/quantum/keymap_extras/sendstring_german_mac_iso.h +++ b/quantum/keymap_extras/sendstring_german_mac_iso.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_german_mac_iso.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_hungarian.h b/quantum/keymap_extras/sendstring_hungarian.h index 9169ba2557..d96a8fcd04 100644 --- a/quantum/keymap_extras/sendstring_hungarian.h +++ b/quantum/keymap_extras/sendstring_hungarian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_hungarian.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_icelandic.h b/quantum/keymap_extras/sendstring_icelandic.h index b25a4e76e7..8515c6cccf 100644 --- a/quantum/keymap_extras/sendstring_icelandic.h +++ b/quantum/keymap_extras/sendstring_icelandic.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_icelandic.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_italian.h b/quantum/keymap_extras/sendstring_italian.h index dad4902d34..322da2ac1b 100644 --- a/quantum/keymap_extras/sendstring_italian.h +++ b/quantum/keymap_extras/sendstring_italian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_italian.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_italian_mac_ansi.h b/quantum/keymap_extras/sendstring_italian_mac_ansi.h index 97b5164e23..2961316de6 100644 --- a/quantum/keymap_extras/sendstring_italian_mac_ansi.h +++ b/quantum/keymap_extras/sendstring_italian_mac_ansi.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_italian_mac_ansi.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_italian_mac_iso.h b/quantum/keymap_extras/sendstring_italian_mac_iso.h index d82e8bbddf..25eb2549bd 100644 --- a/quantum/keymap_extras/sendstring_italian_mac_iso.h +++ b/quantum/keymap_extras/sendstring_italian_mac_iso.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_italian_mac_iso.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_japanese.h b/quantum/keymap_extras/sendstring_japanese.h index 13628d7023..043446acbf 100644 --- a/quantum/keymap_extras/sendstring_japanese.h +++ b/quantum/keymap_extras/sendstring_japanese.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_japanese.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_latvian.h b/quantum/keymap_extras/sendstring_latvian.h index bd73a01e48..9323c603cc 100644 --- a/quantum/keymap_extras/sendstring_latvian.h +++ b/quantum/keymap_extras/sendstring_latvian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_latvian.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_lithuanian_azerty.h b/quantum/keymap_extras/sendstring_lithuanian_azerty.h index a886411143..92d2570022 100644 --- a/quantum/keymap_extras/sendstring_lithuanian_azerty.h +++ b/quantum/keymap_extras/sendstring_lithuanian_azerty.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_lithuanian_azerty.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_lithuanian_qwerty.h b/quantum/keymap_extras/sendstring_lithuanian_qwerty.h index 69cb94de71..676930e9d3 100644 --- a/quantum/keymap_extras/sendstring_lithuanian_qwerty.h +++ b/quantum/keymap_extras/sendstring_lithuanian_qwerty.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_lithuanian_qwerty.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_norman.h b/quantum/keymap_extras/sendstring_norman.h index 21dbbdd705..b9b175c822 100644 --- a/quantum/keymap_extras/sendstring_norman.h +++ b/quantum/keymap_extras/sendstring_norman.h @@ -18,6 +18,7 @@  #pragma once +#include "send_string.h"  #include "keymap_norman.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_norwegian.h b/quantum/keymap_extras/sendstring_norwegian.h index 28813da51f..ce362b76db 100644 --- a/quantum/keymap_extras/sendstring_norwegian.h +++ b/quantum/keymap_extras/sendstring_norwegian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_norwegian.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_portuguese.h b/quantum/keymap_extras/sendstring_portuguese.h index 37db5f97aa..951da2397c 100644 --- a/quantum/keymap_extras/sendstring_portuguese.h +++ b/quantum/keymap_extras/sendstring_portuguese.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_portuguese.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_portuguese_mac_iso.h b/quantum/keymap_extras/sendstring_portuguese_mac_iso.h index 5d43c66279..cda5541a50 100644 --- a/quantum/keymap_extras/sendstring_portuguese_mac_iso.h +++ b/quantum/keymap_extras/sendstring_portuguese_mac_iso.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_portuguese_mac_iso.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_romanian.h b/quantum/keymap_extras/sendstring_romanian.h index 9b5bee4a13..16d9137102 100644 --- a/quantum/keymap_extras/sendstring_romanian.h +++ b/quantum/keymap_extras/sendstring_romanian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_romanian.h" -#include "quantum"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_serbian_latin.h b/quantum/keymap_extras/sendstring_serbian_latin.h index 7e19a62595..5e3df75a95 100644 --- a/quantum/keymap_extras/sendstring_serbian_latin.h +++ b/quantum/keymap_extras/sendstring_serbian_latin.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_serbian_latin.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_slovak.h b/quantum/keymap_extras/sendstring_slovak.h index c94cca1379..a908773969 100644 --- a/quantum/keymap_extras/sendstring_slovak.h +++ b/quantum/keymap_extras/sendstring_slovak.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_slovak.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_slovenian.h b/quantum/keymap_extras/sendstring_slovenian.h index 117af7e76d..1b863aa6e9 100644 --- a/quantum/keymap_extras/sendstring_slovenian.h +++ b/quantum/keymap_extras/sendstring_slovenian.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_slovenian.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_spanish.h b/quantum/keymap_extras/sendstring_spanish.h index 680e99ef4e..374ceaddfe 100644 --- a/quantum/keymap_extras/sendstring_spanish.h +++ b/quantum/keymap_extras/sendstring_spanish.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_spanish.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_spanish_dvorak.h b/quantum/keymap_extras/sendstring_spanish_dvorak.h index ccf9458247..279b6f736a 100644 --- a/quantum/keymap_extras/sendstring_spanish_dvorak.h +++ b/quantum/keymap_extras/sendstring_spanish_dvorak.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_spanish_dvorak.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_swedish.h b/quantum/keymap_extras/sendstring_swedish.h index d451342992..6dd81ac95d 100644 --- a/quantum/keymap_extras/sendstring_swedish.h +++ b/quantum/keymap_extras/sendstring_swedish.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_swedish.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_swiss_de.h b/quantum/keymap_extras/sendstring_swiss_de.h index f6aa19210c..b352ab0b37 100644 --- a/quantum/keymap_extras/sendstring_swiss_de.h +++ b/quantum/keymap_extras/sendstring_swiss_de.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_swiss_de.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_swiss_fr.h b/quantum/keymap_extras/sendstring_swiss_fr.h index 7d04cc539a..1559b5efa4 100644 --- a/quantum/keymap_extras/sendstring_swiss_fr.h +++ b/quantum/keymap_extras/sendstring_swiss_fr.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_swiss_fr.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_turkish_f.h b/quantum/keymap_extras/sendstring_turkish_f.h index cabd5c5dc5..6d3e70bf81 100644 --- a/quantum/keymap_extras/sendstring_turkish_f.h +++ b/quantum/keymap_extras/sendstring_turkish_f.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_turkish_f.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_turkish_q.h b/quantum/keymap_extras/sendstring_turkish_q.h index 986f022333..077612737c 100644 --- a/quantum/keymap_extras/sendstring_turkish_q.h +++ b/quantum/keymap_extras/sendstring_turkish_q.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_turkish_q.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_uk.h b/quantum/keymap_extras/sendstring_uk.h index bbd30769b0..2a79507f20 100644 --- a/quantum/keymap_extras/sendstring_uk.h +++ b/quantum/keymap_extras/sendstring_uk.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_uk.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_us_international.h b/quantum/keymap_extras/sendstring_us_international.h index d1694ff0f0..9b13a2fcf7 100644 --- a/quantum/keymap_extras/sendstring_us_international.h +++ b/quantum/keymap_extras/sendstring_us_international.h @@ -18,8 +18,8 @@  #pragma once +#include "send_string.h"  #include "keymap_us_international.h" -#include "quantum.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_workman.h b/quantum/keymap_extras/sendstring_workman.h index 04f8e3908a..d22104fc5a 100644 --- a/quantum/keymap_extras/sendstring_workman.h +++ b/quantum/keymap_extras/sendstring_workman.h @@ -18,6 +18,7 @@  #pragma once +#include "send_string.h"  #include "keymap_workman.h"  // clang-format off diff --git a/quantum/keymap_extras/sendstring_workman_zxcvm.h b/quantum/keymap_extras/sendstring_workman_zxcvm.h index e7605d7cce..791268fdeb 100644 --- a/quantum/keymap_extras/sendstring_workman_zxcvm.h +++ b/quantum/keymap_extras/sendstring_workman_zxcvm.h @@ -18,6 +18,7 @@  #pragma once +#include "send_string.h"  #include "keymap_workman_zxcvm.h"  // clang-format off diff --git a/quantum/led.c b/quantum/led.c index 42144566fd..8d86374a6f 100644 --- a/quantum/led.c +++ b/quantum/led.c @@ -153,14 +153,14 @@ __attribute__((weak)) void led_set(uint8_t usb_led) {  /** \brief Trigger behaviour on transition to suspend   */  void led_suspend(void) { -    uint8_t leds_off = 0; +    led_t leds_off = {0};  #ifdef BACKLIGHT_CAPS_LOCK      if (is_backlight_enabled()) {          // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off -        leds_off |= (1 << USB_LED_CAPS_LOCK); +        leds_off.caps_lock = true;      }  #endif -    led_set(leds_off); +    led_set(leds_off.raw);  }  /** \brief Trigger behaviour on transition from suspend diff --git a/quantum/led.h b/quantum/led.h index b9ad7ed9ae..b9fad670ae 100644 --- a/quantum/led.h +++ b/quantum/led.h @@ -22,13 +22,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  /* FIXME: Add doxygen comments here. */ -/* keyboard LEDs */ -#define USB_LED_NUM_LOCK 0 -#define USB_LED_CAPS_LOCK 1 -#define USB_LED_SCROLL_LOCK 2 -#define USB_LED_COMPOSE 3 -#define USB_LED_KANA 4 -  #ifdef __cplusplus  extern "C" {  #endif diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c index 828d61641a..1676a60aa3 100644 --- a/quantum/led_matrix/led_matrix.c +++ b/quantum/led_matrix/led_matrix.c @@ -20,8 +20,13 @@  #include "led_matrix.h"  #include "progmem.h"  #include "eeprom.h" +#include "eeconfig.h" +#include "keyboard.h" +#include "sync_timer.h" +#include "debug.h"  #include <string.h>  #include <math.h> +#include <stdlib.h>  #include "led_tables.h"  #include <lib/lib8tion/lib8tion.h> @@ -366,7 +371,10 @@ void led_matrix_task(void) {          case RENDERING:              led_task_render(effect);              if (effect) { -                led_matrix_indicators(); +                // Only run the basic indicators in the last render iteration (default there are 5 iterations) +                if (led_effect_params.iter == LED_MATRIX_LED_PROCESS_MAX_ITERATIONS) { +                    led_matrix_indicators(); +                }                  led_matrix_indicators_advanced(&led_effect_params);              }              break; diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h index c7d360f366..c2533ca49c 100644 --- a/quantum/led_matrix/led_matrix.h +++ b/quantum/led_matrix/led_matrix.h @@ -23,7 +23,7 @@  #include <stdint.h>  #include <stdbool.h>  #include "led_matrix_types.h" -#include "quantum.h" +#include "keyboard.h"  #ifdef IS31FL3731  #    include "is31fl3731-simple.h" @@ -42,8 +42,9 @@  #endif  #ifndef LED_MATRIX_LED_PROCESS_LIMIT -#    define LED_MATRIX_LED_PROCESS_LIMIT (LED_MATRIX_LED_COUNT + 4) / 5 +#    define LED_MATRIX_LED_PROCESS_LIMIT ((LED_MATRIX_LED_COUNT + 4) / 5)  #endif +#define LED_MATRIX_LED_PROCESS_MAX_ITERATIONS ((LED_MATRIX_LED_COUNT + LED_MATRIX_LED_PROCESS_LIMIT - 1) / LED_MATRIX_LED_PROCESS_LIMIT)  #if defined(LED_MATRIX_LED_PROCESS_LIMIT) && LED_MATRIX_LED_PROCESS_LIMIT > 0 && LED_MATRIX_LED_PROCESS_LIMIT < LED_MATRIX_LED_COUNT  #    if defined(LED_MATRIX_SPLIT) diff --git a/quantum/matrix.c b/quantum/matrix.c index 97d41caedd..f087a215d4 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -20,7 +20,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "util.h"  #include "matrix.h"  #include "debounce.h" -#include "quantum.h" +#include "atomic_util.h" +  #ifdef SPLIT_KEYBOARD  #    include "split_common/split_util.h"  #    include "split_common/transactions.h" diff --git a/quantum/matrix_common.c b/quantum/matrix_common.c index 3173351888..d02c527caa 100644 --- a/quantum/matrix_common.c +++ b/quantum/matrix_common.c @@ -1,9 +1,9 @@ -#include "quantum.h"  #include "matrix.h"  #include "debounce.h"  #include "wait.h"  #include "print.h"  #include "debug.h" +  #ifdef SPLIT_KEYBOARD  #    include "split_common/split_util.h"  #    include "split_common/transactions.h" diff --git a/quantum/midi/qmk_midi.c b/quantum/midi/qmk_midi.c index f6a5d92281..43ebd72937 100644 --- a/quantum/midi/qmk_midi.c +++ b/quantum/midi/qmk_midi.c @@ -5,6 +5,11 @@  #include "usb_descriptor.h"  #include "process_midi.h" +#ifdef AUDIO_ENABLE +#    include "audio.h" +#    include <math.h> +#endif +  /*******************************************************************************   * MIDI   ******************************************************************************/ diff --git a/quantum/mousekey.c b/quantum/mousekey.c index df8aa613be..c982a2f40b 100644 --- a/quantum/mousekey.c +++ b/quantum/mousekey.c @@ -25,11 +25,16 @@  #include "mousekey.h"  static inline int8_t times_inv_sqrt2(int8_t x) { -    // 181/256 is pretty close to 1/sqrt(2) -    // 0.70703125                 0.707106781 -    // 1 too small for x=99 and x=198 -    // This ends up being a mult and discard lower 8 bits -    return (x * 181) >> 8; +    // 181/256 (0.70703125) is used as an approximation for 1/sqrt(2) +    // because it is close to the exact value which is 0.707106781 +    const int16_t  n = x * 181; +    const uint16_t d = 256; + +    // To ensure that the integer result is rounded accurately after +    // division, check the sign of the numerator: +    // If negative, subtract half of the denominator before dividing +    // Otherwise, add half of the denominator before dividing +    return n < 0 ? (n - d / 2) / d : (n + d / 2) / d;  }  static report_mouse_t mouse_report = {0}; @@ -74,7 +79,7 @@ uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;  uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10;  /* milliseconds between repeated motion events (0-255) */  #    ifdef MK_KINETIC_SPEED -float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; +uint16_t mk_wheel_interval = 1000U / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;  #    else  uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;  #    endif @@ -175,7 +180,7 @@ static uint8_t wheel_unit(void) {  /*   * Kinetic movement  acceleration algorithm   * - *  current speed = I + A * T/50 + A * 0.5 * T^2 | maximum B + *  current speed = I + A * T/50 + A * (T/50)^2 * 1/2 | maximum B   *   * T: time since the mouse movement started   * E: mouse events per second (set through MOUSEKEY_INTERVAL, UHK sends 250, the @@ -190,39 +195,48 @@ const uint16_t mk_decelerated_speed = MOUSEKEY_DECELERATED_SPEED;  const uint16_t mk_initial_speed     = MOUSEKEY_INITIAL_SPEED;  static uint8_t move_unit(void) { -    float speed = mk_initial_speed; +    uint16_t speed = mk_initial_speed; -    if (mousekey_accel & ((1 << 0) | (1 << 2))) { -        speed = mousekey_accel & (1 << 2) ? mk_accelerated_speed : mk_decelerated_speed; +    if (mousekey_accel & (1 << 0)) { +        speed = mk_decelerated_speed; +    } else if (mousekey_accel & (1 << 2)) { +        speed = mk_accelerated_speed;      } else if (mousekey_repeat && mouse_timer) { -        const float time_elapsed = timer_elapsed(mouse_timer) / 50; -        speed                    = mk_initial_speed + MOUSEKEY_MOVE_DELTA * time_elapsed + MOUSEKEY_MOVE_DELTA * 0.5 * time_elapsed * time_elapsed; - -        speed = speed > mk_base_speed ? mk_base_speed : speed; +        const uint16_t time_elapsed = timer_elapsed(mouse_timer) / 50; +        speed                       = mk_initial_speed + MOUSEKEY_MOVE_DELTA * time_elapsed + (MOUSEKEY_MOVE_DELTA * time_elapsed * time_elapsed) / 2; +        if (speed > mk_base_speed) { +            speed = mk_base_speed; +        }      } -      /* convert speed to USB mouse speed 1 to 127 */ -    speed = (uint8_t)(speed / (1000.0f / mk_interval)); -    speed = speed < 1 ? 1 : speed; +    speed = (uint8_t)(speed / (1000U / mk_interval)); -    return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed; +    if (speed > MOUSEKEY_MOVE_MAX) { +        speed = MOUSEKEY_MOVE_MAX; +    } else if (speed < 1) { +        speed = 1; +    } +    return speed;  }  static uint8_t wheel_unit(void) { -    float speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; +    uint16_t speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; -    if (mousekey_accel & ((1 << 0) | (1 << 2))) { -        speed = mousekey_accel & (1 << 2) ? MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS : MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS; +    if (mousekey_accel & (1 << 0)) { +        speed = MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS; +    } else if (mousekey_accel & (1 << 2)) { +        speed = MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS;      } else if (mousekey_wheel_repeat && mouse_timer) {          if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) { -            const float time_elapsed = timer_elapsed(mouse_timer) / 50; -            speed                    = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + 1 * 0.5 * time_elapsed * time_elapsed; +            const uint16_t time_elapsed = timer_elapsed(mouse_timer) / 50; +            speed                       = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + (1 * time_elapsed * time_elapsed) / 2; +        } +        if (speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS) { +            speed = MOUSEKEY_WHEEL_BASE_MOVEMENTS;          } -        speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed;      } -    mk_wheel_interval = 1000.0f / speed; - -    return (uint8_t)speed > MOUSEKEY_WHEEL_INITIAL_MOVEMENTS ? 2 : 1; +    mk_wheel_interval = 1000U / speed; +    return 1;  }  #        endif /* #ifndef MK_KINETIC_SPEED */ diff --git a/quantum/mousekey.h b/quantum/mousekey.h index e968e000c0..73380b743a 100644 --- a/quantum/mousekey.h +++ b/quantum/mousekey.h @@ -44,9 +44,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #            define MOUSEKEY_MOVE_DELTA 8  #        endif  #    endif -#    ifndef MOUSEKEY_WHEEL_DELTA -#        define MOUSEKEY_WHEEL_DELTA 1 -#    endif  #    ifndef MOUSEKEY_DELAY  #        if defined(MK_KINETIC_SPEED)  #            define MOUSEKEY_DELAY 5 @@ -85,6 +82,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #    ifndef MOUSEKEY_WHEEL_INTERVAL  #        define MOUSEKEY_WHEEL_INTERVAL 80  #    endif +#    ifndef MOUSEKEY_WHEEL_DELTA +#        define MOUSEKEY_WHEEL_DELTA 1 +#    endif  #    ifndef MOUSEKEY_WHEEL_MAX_SPEED  #        define MOUSEKEY_WHEEL_MAX_SPEED 8  #    endif diff --git a/quantum/painter/lvgl/qp_lvgl.c b/quantum/painter/lvgl/qp_lvgl.c index 6cc0061d73..280aeaf91f 100644 --- a/quantum/painter/lvgl/qp_lvgl.c +++ b/quantum/painter/lvgl/qp_lvgl.c @@ -61,7 +61,7 @@ bool qp_lvgl_attach(painter_device_t device) {      qp_lvgl_detach();      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_lvgl_attach: fail (validation_ok == false)\n");          qp_lvgl_detach();          return false; diff --git a/quantum/painter/qp.c b/quantum/painter/qp.c index aea9381b60..f27bb7892a 100644 --- a/quantum/painter/qp.c +++ b/quantum/painter/qp.c @@ -30,6 +30,11 @@ bool qp_init(painter_device_t device, painter_rotation_t rotation) {      qp_dprintf("qp_init: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; +    if (!driver) { +        qp_dprintf("qp_init: fail (pointer to NULL)\n"); +        return false; +    } +      driver->validate_ok = false;      if (!validate_driver_integrity(driver)) {          qp_dprintf("Failed to validate driver integrity in qp_init\n"); @@ -65,7 +70,7 @@ bool qp_init(painter_device_t device, painter_rotation_t rotation) {  bool qp_power(painter_device_t device, bool power_on) {      qp_dprintf("qp_power: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_power: fail (validation_ok == false)\n");          return false;      } @@ -87,7 +92,7 @@ bool qp_power(painter_device_t device, bool power_on) {  bool qp_clear(painter_device_t device) {      qp_dprintf("qp_clear: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_clear: fail (validation_ok == false)\n");          return false;      } @@ -109,7 +114,7 @@ bool qp_clear(painter_device_t device) {  bool qp_flush(painter_device_t device) {      qp_dprintf("qp_flush: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_flush: fail (validation_ok == false)\n");          return false;      } @@ -129,9 +134,14 @@ bool qp_flush(painter_device_t device) {  // Quantum Painter External API: qp_get_geometry  void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height, painter_rotation_t *rotation, uint16_t *offset_x, uint16_t *offset_y) { -    qp_dprintf("qp_geometry: entry\n"); +    qp_dprintf("qp_get_geometry: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; +    if (!driver) { +        qp_dprintf("qp_get_geometry: fail (pointer to NULL)\n"); +        return; +    } +      switch (driver->rotation) {          default:          case QP_ROTATION_0: @@ -166,7 +176,7 @@ void qp_get_geometry(painter_device_t device, uint16_t *width, uint16_t *height,          *offset_y = driver->offset_y;      } -    qp_dprintf("qp_geometry: ok\n"); +    qp_dprintf("qp_get_geometry: ok\n");  }  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -176,6 +186,11 @@ void qp_set_viewport_offsets(painter_device_t device, uint16_t offset_x, uint16_      qp_dprintf("qp_set_viewport_offsets: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; +    if (!driver) { +        qp_dprintf("qp_set_viewport_offsets: fail (pointer to NULL)\n"); +        return; +    } +      driver->offset_x = offset_x;      driver->offset_y = offset_y; @@ -188,7 +203,7 @@ void qp_set_viewport_offsets(painter_device_t device, uint16_t offset_x, uint16_  bool qp_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom) {      qp_dprintf("qp_viewport: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_viewport: fail (validation_ok == false)\n");          return false;      } @@ -211,7 +226,7 @@ bool qp_viewport(painter_device_t device, uint16_t left, uint16_t top, uint16_t  bool qp_pixdata(painter_device_t device, const void *pixel_data, uint32_t native_pixel_count) {      qp_dprintf("qp_pixdata: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_pixdata: fail (validation_ok == false)\n");          return false;      } diff --git a/quantum/painter/qp_comms.c b/quantum/painter/qp_comms.c index bcc6de8f2e..63667783e1 100644 --- a/quantum/painter/qp_comms.c +++ b/quantum/painter/qp_comms.c @@ -8,7 +8,7 @@  bool qp_comms_init(painter_device_t device) {      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_comms_init: fail (validation_ok == false)\n");          return false;      } @@ -18,7 +18,7 @@ bool qp_comms_init(painter_device_t device) {  bool qp_comms_start(painter_device_t device) {      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_comms_start: fail (validation_ok == false)\n");          return false;      } @@ -28,7 +28,7 @@ bool qp_comms_start(painter_device_t device) {  void qp_comms_stop(painter_device_t device) {      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_comms_stop: fail (validation_ok == false)\n");          return;      } @@ -38,7 +38,7 @@ void qp_comms_stop(painter_device_t device) {  uint32_t qp_comms_send(painter_device_t device, const void *data, uint32_t byte_count) {      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_comms_send: fail (validation_ok == false)\n");          return false;      } diff --git a/quantum/painter/qp_draw_circle.c b/quantum/painter/qp_draw_circle.c index 25517d91c5..7f5a7ddfcd 100644 --- a/quantum/painter/qp_draw_circle.c +++ b/quantum/painter/qp_draw_circle.c @@ -128,7 +128,7 @@ static bool qp_circle_helper_impl(painter_device_t device, uint16_t centerx, uin  bool qp_circle(painter_device_t device, uint16_t x, uint16_t y, uint16_t radius, uint8_t hue, uint8_t sat, uint8_t val, bool filled) {      qp_dprintf("qp_circle: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_circle: fail (validation_ok == false)\n");          return false;      } diff --git a/quantum/painter/qp_draw_core.c b/quantum/painter/qp_draw_core.c index 3988aaedf8..aa5fa4aa76 100644 --- a/quantum/painter/qp_draw_core.c +++ b/quantum/painter/qp_draw_core.c @@ -145,7 +145,7 @@ bool qp_internal_load_qgf_palette(qp_stream_t *stream, uint8_t bpp) {  bool qp_setpixel(painter_device_t device, uint16_t x, uint16_t y, uint8_t hue, uint8_t sat, uint8_t val) {      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_setpixel: fail (validation_ok == false)\n");          return false;      } @@ -175,7 +175,7 @@ bool qp_line(painter_device_t device, uint16_t x0, uint16_t y0, uint16_t x1, uin      qp_dprintf("qp_line(%d, %d, %d, %d): entry\n", (int)x0, (int)y0, (int)x1, (int)y1);      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_line: fail (validation_ok == false)\n");          return false;      } @@ -253,7 +253,7 @@ bool qp_internal_fillrect_helper_impl(painter_device_t device, uint16_t left, ui  bool qp_rect(painter_device_t device, uint16_t left, uint16_t top, uint16_t right, uint16_t bottom, uint8_t hue, uint8_t sat, uint8_t val, bool filled) {      qp_dprintf("qp_rect(%d, %d, %d, %d): entry\n", (int)left, (int)top, (int)right, (int)bottom);      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_rect: fail (validation_ok == false)\n");          return false;      } diff --git a/quantum/painter/qp_draw_ellipse.c b/quantum/painter/qp_draw_ellipse.c index 5c7abd7a7d..e912a3e91f 100644 --- a/quantum/painter/qp_draw_ellipse.c +++ b/quantum/painter/qp_draw_ellipse.c @@ -62,7 +62,7 @@ static bool qp_ellipse_helper_impl(painter_device_t device, uint16_t centerx, ui  bool qp_ellipse(painter_device_t device, uint16_t x, uint16_t y, uint16_t sizex, uint16_t sizey, uint8_t hue, uint8_t sat, uint8_t val, bool filled) {      qp_dprintf("qp_ellipse: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_ellipse: fail (validation_ok == false)\n");          return false;      } diff --git a/quantum/painter/qp_draw_image.c b/quantum/painter/qp_draw_image.c index 9f86b29f8b..fb17a05a1b 100644 --- a/quantum/painter/qp_draw_image.c +++ b/quantum/painter/qp_draw_image.c @@ -90,7 +90,7 @@ painter_image_handle_t qp_load_image_mem(const void *buffer) {  bool qp_close_image(painter_image_handle_t image) {      qgf_image_handle_t *qgf_image = (qgf_image_handle_t *)image; -    if (!qgf_image->validate_ok) { +    if (!qgf_image || !qgf_image->validate_ok) {          qp_dprintf("qp_close_image: fail (invalid image)\n");          return false;      } @@ -210,13 +210,13 @@ static bool qp_drawimage_prepare_frame_for_stream_read(painter_device_t device,  static bool qp_drawimage_recolor_impl(painter_device_t device, uint16_t x, uint16_t y, painter_image_handle_t image, int frame_number, qgf_frame_info_t *frame_info, qp_pixel_t fg_hsv888, qp_pixel_t bg_hsv888) {      qp_dprintf("qp_drawimage_recolor: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_drawimage_recolor: fail (validation_ok == false)\n");          return false;      }      qgf_image_handle_t *qgf_image = (qgf_image_handle_t *)image; -    if (!qgf_image->validate_ok) { +    if (!qgf_image || !qgf_image->validate_ok) {          qp_dprintf("qp_drawimage_recolor: fail (invalid image)\n");          return false;      } diff --git a/quantum/painter/qp_draw_text.c b/quantum/painter/qp_draw_text.c index a70caac6f4..ff6fc01d11 100644 --- a/quantum/painter/qp_draw_text.c +++ b/quantum/painter/qp_draw_text.c @@ -136,7 +136,7 @@ painter_font_handle_t qp_load_font_mem(const void *buffer) {  bool qp_close_font(painter_font_handle_t font) {      qff_font_handle_t *qff_font = (qff_font_handle_t *)font; -    if (!qff_font->validate_ok) { +    if (!qff_font || !qff_font->validate_ok) {          qp_dprintf("qp_close_font: fail (invalid font)\n");          return false;      } @@ -380,7 +380,7 @@ static inline bool qp_font_code_point_handler_drawglyph(qff_font_handle_t *qff_f  int16_t qp_textwidth(painter_font_handle_t font, const char *str) {      qff_font_handle_t *qff_font = (qff_font_handle_t *)font; -    if (!qff_font->validate_ok) { +    if (!qff_font || !qff_font->validate_ok) {          qp_dprintf("qp_textwidth: fail (invalid font)\n");          return false;      } @@ -406,13 +406,13 @@ int16_t qp_drawtext(painter_device_t device, uint16_t x, uint16_t y, painter_fon  int16_t qp_drawtext_recolor(painter_device_t device, uint16_t x, uint16_t y, painter_font_handle_t font, const char *str, uint8_t hue_fg, uint8_t sat_fg, uint8_t val_fg, uint8_t hue_bg, uint8_t sat_bg, uint8_t val_bg) {      qp_dprintf("qp_drawtext_recolor: entry\n");      painter_driver_t *driver = (painter_driver_t *)device; -    if (!driver->validate_ok) { +    if (!driver || !driver->validate_ok) {          qp_dprintf("qp_drawtext_recolor: fail (validation_ok == false)\n");          return 0;      }      qff_font_handle_t *qff_font = (qff_font_handle_t *)font; -    if (!qff_font->validate_ok) { +    if (!qff_font || !qff_font->validate_ok) {          qp_dprintf("qp_drawtext_recolor: fail (invalid font)\n");          return false;      } diff --git a/quantum/pointing_device/pointing_device_auto_mouse.c b/quantum/pointing_device/pointing_device_auto_mouse.c index b008d18db5..fc3106e37e 100644 --- a/quantum/pointing_device/pointing_device_auto_mouse.c +++ b/quantum/pointing_device/pointing_device_auto_mouse.c @@ -18,6 +18,9 @@  #ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE  #    include "pointing_device_auto_mouse.h" +#    include "debug.h" +#    include "action_util.h" +#    include "quantum_keycodes.h"  /* local data structure for tracking auto mouse */  static auto_mouse_context_t auto_mouse_context = { diff --git a/quantum/pointing_device/pointing_device_auto_mouse.h b/quantum/pointing_device/pointing_device_auto_mouse.h index 7db63bc6b8..1343855e00 100644 --- a/quantum/pointing_device/pointing_device_auto_mouse.h +++ b/quantum/pointing_device/pointing_device_auto_mouse.h @@ -16,11 +16,14 @@  #pragma once -#include <string.h> - -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h>  #include "pointing_device.h" -#include "print.h" +#include "keycodes.h" +#include "action.h" +#include "report.h" +#include "action_layer.h" +#include "action_tapping.h"  /* check settings and set defaults */  #ifndef POINTING_DEVICE_AUTO_MOUSE_ENABLE diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index c189dd02b7..ef2f52c9f1 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -1,5 +1,6 @@  #include "audio.h"  #include "process_audio.h" +#include <math.h>  #ifndef VOICE_CHANGE_SONG  #    define VOICE_CHANGE_SONG SONG(VOICE_CHANGE_SOUND) @@ -61,6 +62,3 @@ void process_audio_noteoff(uint8_t note) {  void process_audio_all_notes_off(void) {      stop_all_notes();  } - -__attribute__((weak)) void audio_on_user(void) {} -__attribute__((weak)) void audio_off_user(void) {} diff --git a/quantum/process_keycode/process_audio.h b/quantum/process_keycode/process_audio.h index 42cfab4af2..69e201e447 100644 --- a/quantum/process_keycode/process_audio.h +++ b/quantum/process_keycode/process_audio.h @@ -1,11 +1,12 @@  #pragma once +#include <stdint.h> +#include <stdbool.h> +#include "action.h" +  float compute_freq_for_midi_note(uint8_t note);  bool process_audio(uint16_t keycode, keyrecord_t *record);  void process_audio_noteon(uint8_t note);  void process_audio_noteoff(uint8_t note);  void process_audio_all_notes_off(void); - -void audio_on_user(void); -void audio_off_user(void); diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c index 62c347ae0c..9b78214e43 100644 --- a/quantum/process_keycode/process_auto_shift.c +++ b/quantum/process_keycode/process_auto_shift.c @@ -14,27 +14,28 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#ifdef AUTO_SHIFT_ENABLE - -#    include <stdbool.h> -#    include "process_auto_shift.h" - -#    ifndef AUTO_SHIFT_DISABLED_AT_STARTUP -#        define AUTO_SHIFT_STARTUP_STATE true /* enabled */ -#    else -#        define AUTO_SHIFT_STARTUP_STATE false /* disabled */ -#    endif +#include "process_auto_shift.h" +#include "quantum.h" +#include "action_util.h" +#include "timer.h" +#include "keycodes.h" + +#ifndef AUTO_SHIFT_DISABLED_AT_STARTUP +#    define AUTO_SHIFT_STARTUP_STATE true /* enabled */ +#else +#    define AUTO_SHIFT_STARTUP_STATE false /* disabled */ +#endif  // Stores the last Auto Shift key's up or down time, for evaluation or keyrepeat.  static uint16_t autoshift_time = 0; -#    if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)  // Stores the last key's up or down time, to replace autoshift_time so that Tap Hold times are accurate.  static uint16_t retroshift_time = 0;  // Stores a possibly Retro Shift key's up or down time, as retroshift_time needs  // to be set before the Retro Shift key is evaluated if it is interrupted by an  // Auto Shifted key.  static uint16_t last_retroshift_time; -#    endif +#endif  static uint16_t    autoshift_timeout = AUTO_SHIFT_TIMEOUT;  static uint16_t    autoshift_lastkey = KC_NO;  static keyrecord_t autoshift_lastrecord; @@ -68,15 +69,23 @@ __attribute__((weak)) bool get_custom_auto_shifted_key(uint16_t keycode, keyreco  /** \brief Called on physical press, returns whether is Auto Shift key */  __attribute__((weak)) bool get_auto_shifted_key(uint16_t keycode, keyrecord_t *record) {      switch (keycode) { -#    ifndef NO_AUTO_SHIFT_ALPHA +#ifndef NO_AUTO_SHIFT_ALPHA          case AUTO_SHIFT_ALPHA: -#    endif -#    ifndef NO_AUTO_SHIFT_NUMERIC +#endif +#ifndef NO_AUTO_SHIFT_NUMERIC          case AUTO_SHIFT_NUMERIC: +#endif +#ifndef NO_AUTO_SHIFT_SPECIAL +#    ifndef NO_AUTO_SHIFT_TAB +        case KC_TAB:  #    endif -#    ifndef NO_AUTO_SHIFT_SPECIAL -        case AUTO_SHIFT_SPECIAL: +#    ifndef NO_AUTO_SHIFT_SYMBOLS +        case AUTO_SHIFT_SYMBOLS:  #    endif +#endif +#ifdef AUTO_SHIFT_ENTER +        case KC_ENT: +#endif              return true;      }      return get_custom_auto_shifted_key(keycode, record); @@ -122,9 +131,9 @@ bool get_autoshift_shift_state(uint16_t keycode) {  /** \brief Restores the shift key if it was cancelled by Auto Shift */  static void autoshift_flush_shift(void) {      autoshift_flags.holding_shift = false; -#    ifdef CAPS_WORD_ENABLE +#ifdef CAPS_WORD_ENABLE      if (!is_caps_word_on()) -#    endif // CAPS_WORD_ENABLE +#endif // CAPS_WORD_ENABLE      {          del_weak_mods(MOD_BIT(KC_LSFT));      } @@ -146,26 +155,26 @@ static void autoshift_flush_shift(void) {  static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) {      // clang-format off      if ((get_mods() -#    if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)              | get_oneshot_mods() -#    endif +#endif          ) & (~MOD_BIT(KC_LSFT))      ) {          // clang-format on          // Prevents keyrepeating unshifted value of key after using it in a key combo.          autoshift_lastkey = KC_NO; -#    ifndef AUTO_SHIFT_MODIFIERS +#ifndef AUTO_SHIFT_MODIFIERS          // We can't return true here anymore because custom unshifted values are          // possible and there's no good way to tell whether the press returned          // true upon release.          set_autoshift_shift_state(keycode, false);          autoshift_press_user(keycode, false, record); -#        if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#    if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)          set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT)));          clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); -#        endif -        return false;  #    endif +        return false; +#endif      }      // Store record to be sent to user functions if there's no release record then. @@ -173,19 +182,19 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)      autoshift_lastrecord.event.pressed = false;      autoshift_lastrecord.event.time    = 0;      // clang-format off -#    if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY) +#if defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)      if (keycode == autoshift_lastkey && -#        ifdef AUTO_SHIFT_REPEAT_PER_KEY +#    ifdef AUTO_SHIFT_REPEAT_PER_KEY          get_auto_shift_repeat(autoshift_lastkey, record) && -#        endif -#        if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY) +#    endif +#    if !defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY)          (              !autoshift_flags.lastshifted -#            ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY +#        ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY              || get_auto_shift_no_auto_repeat(autoshift_lastkey, record) -#            endif -        ) &&  #        endif +        ) && +#    endif          TIMER_DIFF_16(now, autoshift_time) < GET_TAPPING_TERM(autoshift_lastkey, record)      ) {          // clang-format on @@ -202,23 +211,23 @@ static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record)          autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record);          return false;      } -#    endif +#endif      // Use physical shift state of press event to be more like normal typing. -#    if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)      autoshift_flags.lastshifted = (get_mods() | get_oneshot_mods()) & MOD_BIT(KC_LSFT);      set_oneshot_mods(get_oneshot_mods() & (~MOD_BIT(KC_LSFT))); -#    else +#else      autoshift_flags.lastshifted = get_mods() & MOD_BIT(KC_LSFT); -#    endif +#endif      // Record the keycode so we can simulate it later.      autoshift_lastkey           = keycode;      autoshift_time              = now;      autoshift_flags.in_progress = true; -#    if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING) +#if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)      clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); -#    endif +#endif      return false;  } @@ -239,11 +248,11 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, k          autoshift_flags.lastshifted =              autoshift_flags.lastshifted              || TIMER_DIFF_16(now, autoshift_time) >= -#    ifdef AUTO_SHIFT_TIMEOUT_PER_KEY +#ifdef AUTO_SHIFT_TIMEOUT_PER_KEY                  get_autoshift_timeout(autoshift_lastkey, record) -#    else +#else                  autoshift_timeout -#    endif +#endif          ;          // clang-format on          set_autoshift_shift_state(autoshift_lastkey, autoshift_flags.lastshifted); @@ -258,23 +267,23 @@ static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger, k          autoshift_press_user(autoshift_lastkey, autoshift_flags.lastshifted, record);          // clang-format off -#    if (defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)) && (!defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY)) +#if (defined(AUTO_SHIFT_REPEAT) || defined(AUTO_SHIFT_REPEAT_PER_KEY)) && (!defined(AUTO_SHIFT_NO_AUTO_REPEAT) || defined(AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY))          if (matrix_trigger -#        ifdef AUTO_SHIFT_REPEAT_PER_KEY +#    ifdef AUTO_SHIFT_REPEAT_PER_KEY              && get_auto_shift_repeat(autoshift_lastkey, record) -#        endif -#        ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY +#    endif +#    ifdef AUTO_SHIFT_NO_AUTO_REPEAT_PER_KEY              && !get_auto_shift_no_auto_repeat(autoshift_lastkey, record) -#        endif +#    endif          ) {              // Prevents release.              return;          } -#    endif +#endif          // clang-format on -#    if TAP_CODE_DELAY > 0 +#if TAP_CODE_DELAY > 0          wait_ms(TAP_CODE_DELAY); -#    endif +#endif          autoshift_release_user(autoshift_lastkey, autoshift_flags.lastshifted, record);          autoshift_flush_shift(); @@ -302,11 +311,11 @@ void autoshift_matrix_scan(void) {      if (autoshift_flags.in_progress) {          const uint16_t now = timer_read();          if (TIMER_DIFF_16(now, autoshift_time) >= -#    ifdef AUTO_SHIFT_TIMEOUT_PER_KEY +#ifdef AUTO_SHIFT_TIMEOUT_PER_KEY              get_autoshift_timeout(autoshift_lastkey, &autoshift_lastrecord) -#    else +#else              autoshift_timeout -#    endif +#endif          ) {              autoshift_end(autoshift_lastkey, now, true, &autoshift_lastrecord);          } @@ -327,18 +336,18 @@ void autoshift_disable(void) {      autoshift_flush_shift();  } -#    ifndef AUTO_SHIFT_NO_SETUP +#ifndef AUTO_SHIFT_NO_SETUP  void autoshift_timer_report(void) { -#        ifdef SEND_STRING_ENABLE +#    ifdef SEND_STRING_ENABLE      const char *autoshift_timeout_str = get_u16_str(autoshift_timeout, ' ');      // Skip padding spaces      while (*autoshift_timeout_str == ' ') {          autoshift_timeout_str++;      }      send_string(autoshift_timeout_str); -#        endif -}  #    endif +} +#endif  bool get_autoshift_state(void) {      return autoshift_flags.enabled; @@ -360,11 +369,11 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {      // https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550      // clang-format off      const uint16_t now = -#    if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING) +#if !defined(RETRO_SHIFT) || defined(NO_ACTION_TAPPING)          timer_read() -#    else +#else          (record->event.pressed) ? retroshift_time : timer_read() -#    endif +#endif      ;      // clang-format on @@ -385,7 +394,7 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {                  autoshift_disable();                  break; -#    ifndef AUTO_SHIFT_NO_SETUP +#ifndef AUTO_SHIFT_NO_SETUP              case AS_UP:                  autoshift_timeout += 5;                  break; @@ -395,27 +404,27 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {              case AS_RPT:                  autoshift_timer_report();                  break; -#    endif +#endif          }              // If Retro Shift is disabled, possible custom actions shouldn't happen.              // clang-format off -#   if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) -#       ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#    ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY              const bool is_hold_on_interrupt = get_hold_on_other_key_press(keycode, record); -#       else +#    else              const bool is_hold_on_interrupt = false; -#       endif -#   endif +#    endif +#endif          if (IS_RETRO(keycode) -#    if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)              // Not tapped or #defines mean that rolls should use hold action.              && (                  record->tap.count == 0 -#        ifdef RETRO_TAPPING_PER_KEY +#    ifdef RETRO_TAPPING_PER_KEY                  || !get_retro_tapping(keycode, record) -#        endif -                || (record->tap.interrupted && is_hold_on_interrupt))  #    endif +                || (record->tap.interrupted && is_hold_on_interrupt)) +#endif          ) {              // clang-format on              autoshift_lastkey = KC_NO; @@ -431,21 +440,21 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {          // tap.count gets set to 0 in process_action          // clang-format off          else if (IS_RETRO(keycode) -#    if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)              && (                  record->tap.count == 0 -#        ifdef RETRO_TAPPING_PER_KEY +#    ifdef RETRO_TAPPING_PER_KEY                  || !get_retro_tapping(keycode, record) -#        endif -            )  #    endif +            ) +#endif          ) {              // Fixes modifiers not being applied to rolls with AUTO_SHIFT_MODIFIERS set. -#    ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY +#ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY              if (autoshift_flags.in_progress && get_hold_on_other_key_press(keycode, record)) {                  autoshift_end(KC_NO, now, false, &autoshift_lastrecord);              } -#    endif +#endif              // clang-format on              return true;          } @@ -471,7 +480,7 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {      return true;  } -#    if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING) +#if defined(RETRO_SHIFT) && !defined(NO_ACTION_TAPPING)  // Called to record time before possible delays by action_tapping_process.  void retroshift_poll_time(keyevent_t *event) {      last_retroshift_time = retroshift_time; @@ -485,6 +494,4 @@ void retroshift_swap_times(void) {          last_retroshift_time = temp;      }  } -#    endif -  #endif diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h index 66a4b3138a..885a47b533 100644 --- a/quantum/process_keycode/process_auto_shift.h +++ b/quantum/process_keycode/process_auto_shift.h @@ -16,7 +16,11 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h" +#include "keyboard.h" +#include "keycodes.h"  #ifndef AUTO_SHIFT_TIMEOUT  #    define AUTO_SHIFT_TIMEOUT 175 @@ -28,10 +32,14 @@  // clang-format off  #define AUTO_SHIFT_ALPHA KC_A ... KC_Z  #define AUTO_SHIFT_NUMERIC KC_1 ... KC_0 +#define AUTO_SHIFT_SYMBOLS          \ +             KC_MINUS ... KC_SLASH: \ +        case KC_NONUS_BACKSLASH + +// Kept to avoid breaking existing keymaps.  #define AUTO_SHIFT_SPECIAL          \               KC_TAB:                \ -        case KC_MINUS ... KC_SLASH: \ -        case KC_NONUS_BACKSLASH +        case AUTO_SHIFT_SYMBOLS  // clang-format on  bool process_auto_shift(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_autocorrect.c b/quantum/process_keycode/process_autocorrect.c index 1376788266..edc47718f3 100644 --- a/quantum/process_keycode/process_autocorrect.c +++ b/quantum/process_keycode/process_autocorrect.c @@ -1,11 +1,16 @@  // Copyright 2021 Google LLC  // Copyright 2021 @filterpaper +// Copyright 2023 Pablo Martinez (@elpekenin) <[email protected]>  // SPDX-License-Identifier: Apache-2.0  // Original source: https://getreuer.info/posts/keyboards/autocorrection  #include "process_autocorrect.h"  #include <string.h> +#include "keycodes.h" +#include "quantum_keycodes.h"  #include "keycode_config.h" +#include "send_string.h" +#include "action_util.h"  #if __has_include("autocorrect_data.h")  #    include "autocorrect_data.h" @@ -57,7 +62,7 @@ void autocorrect_toggle(void) {  }  /** - * @brief handler for determining if autocorrect should process keypress + * @brief handler for user to override whether autocorrect should process this keypress   *   * @param keycode Keycode registered by matrix press, per keymap   * @param record keyrecord_t structure @@ -67,6 +72,23 @@ void autocorrect_toggle(void) {   * @return false Stop processing and escape from autocorrect.   */  __attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) { +    return process_autocorrect_default_handler(keycode, record, typo_buffer_size, mods); +} + +/** + * @brief fallback handler for determining if autocorrect should process this keypress + *        can be used by user callback to get the basic keycode being "wrapped" + * + * NOTE: These values may have been edited by user callback before getting here + * + * @param keycode Keycode registered by matrix press, per keymap + * @param record keyrecord_t structure + * @param typo_buffer_size passed along to allow resetting of autocorrect buffer + * @param mods allow processing of mod status + * @return true Allow autocorection + * @return false Stop processing and escape from autocorrect. + */ +bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) {      // See quantum_keycodes.h for reference on these matched ranges.      switch (*keycode) {          // Exclude these keycodes from processing. @@ -157,10 +179,12 @@ __attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord   *   * @param backspaces number of characters to remove   * @param str pointer to PROGMEM string to replace mistyped seletion with + * @param typo the wrong string that triggered a correction + * @param correct what it would become after the changes   * @return true apply correction   * @return false user handled replacement   */ -__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) { +__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct) {      return true;  } @@ -284,11 +308,57 @@ bool process_autocorrect(uint16_t keycode, keyrecord_t *record) {          if (code & 128) { // A typo was found! Apply autocorrect.              const uint8_t backspaces = (code & 63) + !record->event.pressed; -            if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) { +            const char *  changes    = (const char *)(autocorrect_data + state + 1); + +            /* Gather info about the typo'd word +             * +             * Since buffer may contain several words, delimited by spaces, we +             * iterate from the end to find the start and length of the typo +             */ +            char typo[AUTOCORRECT_MAX_LENGTH + 1] = {0}; // extra char for null terminator + +            uint8_t typo_len   = 0; +            uint8_t typo_start = 0; +            bool    space_last = typo_buffer[typo_buffer_size - 1] == KC_SPC; +            for (uint8_t i = typo_buffer_size; i > 0; --i) { +                // stop counting after finding space (unless it is the last thing) +                if (typo_buffer[i - 1] == KC_SPC && i != typo_buffer_size) { +                    typo_start = i; +                    break; +                } + +                ++typo_len; +            } + +            // when detecting 'typo:', reduce the length of the string by one +            if (space_last) { +                --typo_len; +            } + +            // convert buffer of keycodes into a string +            for (uint8_t i = 0; i < typo_len; ++i) { +                typo[i] = typo_buffer[typo_start + i] - KC_A + 'a'; +            } + +            /* Gather the corrected word +             * +             * A) Correction of 'typo:' -- Code takes into account +             * an extra backspace to delete the space (which we dont copy) +             * for this reason the offset is correct to "skip" the null terminator +             * +             * B) When correcting 'typo' -- Need extra offset for terminator +             */ +            char correct[AUTOCORRECT_MAX_LENGTH + 10] = {0}; // let's hope this is big enough + +            uint8_t offset = space_last ? backspaces : backspaces + 1; +            strcpy(correct, typo); +            strcpy_P(correct + typo_len - offset, changes); + +            if (apply_autocorrect(backspaces, changes, typo, correct)) {                  for (uint8_t i = 0; i < backspaces; ++i) {                      tap_code(KC_BSPC);                  } -                send_string_P((char const *)(autocorrect_data + state + 1)); +                send_string_P(changes);              }              if (keycode == KC_SPC) { diff --git a/quantum/process_keycode/process_autocorrect.h b/quantum/process_keycode/process_autocorrect.h index c7596107e5..ea77d6f56f 100644 --- a/quantum/process_keycode/process_autocorrect.h +++ b/quantum/process_keycode/process_autocorrect.h @@ -1,15 +1,19 @@  // Copyright 2021 Google LLC  // Copyright 2021 @filterpaper +// Copyright 2023 Pablo Martinez (@elpekenin) <[email protected]>  // SPDX-License-Identifier: Apache-2.0  // Original source: https://getreuer.info/posts/keyboards/autocorrection  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  bool process_autocorrect(uint16_t keycode, keyrecord_t *record);  bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); -bool apply_autocorrect(uint8_t backspaces, const char *str); +bool process_autocorrect_default_handler(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods); +bool apply_autocorrect(uint8_t backspaces, const char *str, char *typo, char *correct);  bool autocorrect_is_enabled(void);  void autocorrect_enable(void); diff --git a/quantum/process_keycode/process_backlight.h b/quantum/process_keycode/process_backlight.h index 7fe887ae67..e926833e79 100644 --- a/quantum/process_keycode/process_backlight.h +++ b/quantum/process_keycode/process_backlight.h @@ -16,6 +16,8 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  bool process_backlight(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_caps_word.c b/quantum/process_keycode/process_caps_word.c index d4382680bf..1088c8f76c 100644 --- a/quantum/process_keycode/process_caps_word.c +++ b/quantum/process_keycode/process_caps_word.c @@ -13,6 +13,14 @@  // limitations under the License.  #include "process_caps_word.h" +#include "process_auto_shift.h" +#include "caps_word.h" +#include "keycodes.h" +#include "quantum_keycodes.h" +#include "modifiers.h" +#include "timer.h" +#include "action_tapping.h" +#include "action_util.h"  #ifdef CAPS_WORD_INVERT_ON_SHIFT  static uint8_t held_mods = 0; diff --git a/quantum/process_keycode/process_caps_word.h b/quantum/process_keycode/process_caps_word.h index f215bbc3a3..f5eb140d32 100644 --- a/quantum/process_keycode/process_caps_word.h +++ b/quantum/process_keycode/process_caps_word.h @@ -14,8 +14,9 @@  #pragma once -#include "quantum.h" -#include "caps_word.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  /**   * @brief Process handler for Caps Word feature. diff --git a/quantum/process_keycode/process_clicky.c b/quantum/process_keycode/process_clicky.c index b662a3f2f4..0ee58282e6 100644 --- a/quantum/process_keycode/process_clicky.c +++ b/quantum/process_keycode/process_clicky.c @@ -1,5 +1,7 @@ -#include "audio.h"  #include "process_clicky.h" +#include "audio.h" +#include "eeconfig.h" +#include <stdlib.h>  #ifdef AUDIO_CLICKY diff --git a/quantum/process_keycode/process_clicky.h b/quantum/process_keycode/process_clicky.h index 67b6463c5d..dfdba14131 100644 --- a/quantum/process_keycode/process_clicky.h +++ b/quantum/process_keycode/process_clicky.h @@ -1,5 +1,9 @@  #pragma once +#include <stdint.h> +#include <stdbool.h> +#include "action.h" +  void clicky_play(void);  bool process_clicky(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index bbee560be9..64d30fc140 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -14,11 +14,17 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "keymap_common.h" -#include "print.h"  #include "process_combo.h" +#include <stddef.h> +#include "process_auto_shift.h" +#include "caps_word.h" +#include "timer.h" +#include "wait.h" +#include "keyboard.h" +#include "keymap_common.h" +#include "action_layer.h"  #include "action_tapping.h" -#include "action.h" +#include "action_util.h"  #include "keymap_introspection.h"  __attribute__((weak)) void process_combo_event(uint16_t combo_index, bool pressed) {} diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h index bba5d5ee63..f1d534236e 100644 --- a/quantum/process_keycode/process_combo.h +++ b/quantum/process_keycode/process_combo.h @@ -16,9 +16,11 @@  #pragma once -#include "progmem.h" -#include "quantum.h"  #include <stdint.h> +#include <stdbool.h> +#include "action.h" +#include "keycodes.h" +#include "quantum_keycodes.h"  #ifdef EXTRA_SHORT_COMBOS  #    define MAX_COMBO_LENGTH 6 diff --git a/quantum/process_keycode/process_dynamic_macro.c b/quantum/process_keycode/process_dynamic_macro.c index bf6af566e2..5e4a6fa308 100644 --- a/quantum/process_keycode/process_dynamic_macro.c +++ b/quantum/process_keycode/process_dynamic_macro.c @@ -17,6 +17,15 @@  /* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */  #include "process_dynamic_macro.h" +#include <stddef.h> +#include "action_layer.h" +#include "keycodes.h" +#include "debug.h" +#include "wait.h" + +#ifdef BACKLIGHT_ENABLE +#    include "backlight.h" +#endif  // default feedback method  void dynamic_macro_led_blink(void) { @@ -151,6 +160,67 @@ void dynamic_macro_record_end(keyrecord_t *macro_buffer, keyrecord_t *macro_poin      *macro_end = macro_pointer;  } +/* Both macros use the same buffer but read/write on different + * ends of it. + * + * Macro1 is written left-to-right starting from the beginning of + * the buffer. + * + * Macro2 is written right-to-left starting from the end of the + * buffer. + * + * ¯o_buffer   macro_end + *  v                   v + * +------------------------------------------------------------+ + * |>>>>>> MACRO1 >>>>>>      <<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| + * +------------------------------------------------------------+ + *                           ^                                 ^ + *                         r_macro_end                  r_macro_buffer + * + * During the recording when one macro encounters the end of the + * other macro, the recording is stopped. Apart from this, there + * are no arbitrary limits for the macros' length in relation to + * each other: for example one can either have two medium sized + * macros or one long macro and one short macro. Or even one empty + * and one using the whole buffer. + */ +static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE]; + +/* Pointer to the first buffer element after the first macro. + * Initially points to the very beginning of the buffer since the + * macro is empty. */ +static keyrecord_t *macro_end = macro_buffer; + +/* The other end of the macro buffer. Serves as the beginning of + * the second macro. */ +static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1; + +/* Like macro_end but for the second macro. */ +static keyrecord_t *r_macro_end = r_macro_buffer; + +/* A persistent pointer to the current macro position (iterator) + * used during the recording. */ +static keyrecord_t *macro_pointer = NULL; + +/* 0   - no macro is being recorded right now + * 1,2 - either macro 1 or 2 is being recorded */ +static uint8_t macro_id = 0; + +/** + * If a dynamic macro is currently being recorded, stop recording. + */ +void dynamic_macro_stop_recording(void) { +    switch (macro_id) { +        case 1: +            dynamic_macro_record_end(macro_buffer, macro_pointer, +1, ¯o_end); +            break; +        case 2: +            dynamic_macro_record_end(r_macro_buffer, macro_pointer, -1, &r_macro_end); +            break; +    } +    macro_id = 0; +} +  /* Handle the key events related to the dynamic macros. Should be   * called from process_record_user() like this:   * @@ -162,52 +232,6 @@ void dynamic_macro_record_end(keyrecord_t *macro_buffer, keyrecord_t *macro_poin   *   }   */  bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) { -    /* Both macros use the same buffer but read/write on different -     * ends of it. -     * -     * Macro1 is written left-to-right starting from the beginning of -     * the buffer. -     * -     * Macro2 is written right-to-left starting from the end of the -     * buffer. -     * -     * ¯o_buffer   macro_end -     *  v                   v -     * +------------------------------------------------------------+ -     * |>>>>>> MACRO1 >>>>>>      <<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| -     * +------------------------------------------------------------+ -     *                           ^                                 ^ -     *                         r_macro_end                  r_macro_buffer -     * -     * During the recording when one macro encounters the end of the -     * other macro, the recording is stopped. Apart from this, there -     * are no arbitrary limits for the macros' length in relation to -     * each other: for example one can either have two medium sized -     * macros or one long macro and one short macro. Or even one empty -     * and one using the whole buffer. -     */ -    static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE]; - -    /* Pointer to the first buffer element after the first macro. -     * Initially points to the very beginning of the buffer since the -     * macro is empty. */ -    static keyrecord_t *macro_end = macro_buffer; - -    /* The other end of the macro buffer. Serves as the beginning of -     * the second macro. */ -    static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1; - -    /* Like macro_end but for the second macro. */ -    static keyrecord_t *r_macro_end = r_macro_buffer; - -    /* A persistent pointer to the current macro position (iterator) -     * used during the recording. */ -    static keyrecord_t *macro_pointer = NULL; - -    /* 0   - no macro is being recorded right now -     * 1,2 - either macro 1 or 2 is being recorded */ -    static uint8_t macro_id = 0; -      if (macro_id == 0) {          /* No macro recording in progress. */          if (!record->event.pressed) { @@ -238,15 +262,7 @@ bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) {                  if (record->event.pressed ^ (keycode != QK_DYNAMIC_MACRO_RECORD_STOP)) { /* Ignore the initial release                                                                                            * just after the recording                                                                                            * starts for DM_RSTP. */ -                    switch (macro_id) { -                        case 1: -                            dynamic_macro_record_end(macro_buffer, macro_pointer, +1, ¯o_end); -                            break; -                        case 2: -                            dynamic_macro_record_end(r_macro_buffer, macro_pointer, -1, &r_macro_end); -                            break; -                    } -                    macro_id = 0; +                    dynamic_macro_stop_recording();                  }                  return false;  #ifdef DYNAMIC_MACRO_NO_NESTING diff --git a/quantum/process_keycode/process_dynamic_macro.h b/quantum/process_keycode/process_dynamic_macro.h index ab70726897..2f10733cae 100644 --- a/quantum/process_keycode/process_dynamic_macro.h +++ b/quantum/process_keycode/process_dynamic_macro.h @@ -18,7 +18,9 @@  /* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  /* May be overridden with a custom value. Be aware that the effective   * macro length is half of this value: each keypress is recorded twice @@ -39,3 +41,4 @@ void dynamic_macro_record_start_user(int8_t direction);  void dynamic_macro_play_user(int8_t direction);  void dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record);  void dynamic_macro_record_end_user(int8_t direction); +void dynamic_macro_stop_recording(void); diff --git a/quantum/process_keycode/process_dynamic_tapping_term.c b/quantum/process_keycode/process_dynamic_tapping_term.c index 146b9fccd7..cf52626e42 100644 --- a/quantum/process_keycode/process_dynamic_tapping_term.c +++ b/quantum/process_keycode/process_dynamic_tapping_term.c @@ -14,8 +14,10 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "quantum.h"  #include "process_dynamic_tapping_term.h" +#include "quantum.h" +#include "keycodes.h" +#include "send_string.h"  #ifndef DYNAMIC_TAPPING_TERM_INCREMENT  #    define DYNAMIC_TAPPING_TERM_INCREMENT 5 diff --git a/quantum/process_keycode/process_dynamic_tapping_term.h b/quantum/process_keycode/process_dynamic_tapping_term.h index 85e83ee73b..fee29e18df 100644 --- a/quantum/process_keycode/process_dynamic_tapping_term.h +++ b/quantum/process_keycode/process_dynamic_tapping_term.h @@ -16,6 +16,7 @@  #pragma once +#include <stdint.h>  #include <stdbool.h>  #include "action.h" diff --git a/quantum/process_keycode/process_grave_esc.c b/quantum/process_keycode/process_grave_esc.c index ddf027391d..d786f57a80 100644 --- a/quantum/process_keycode/process_grave_esc.c +++ b/quantum/process_keycode/process_grave_esc.c @@ -14,6 +14,9 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #include "process_grave_esc.h" +#include "keycodes.h" +#include "modifiers.h" +#include "action_util.h"  /* true if the last press of QK_GRAVE_ESCAPE was shifted (i.e. GUI or SHIFT were pressed), false otherwise.   * Used to ensure that the correct keycode is released if the key is released. diff --git a/quantum/process_keycode/process_grave_esc.h b/quantum/process_keycode/process_grave_esc.h index bbf4483763..358ff3c4e7 100644 --- a/quantum/process_keycode/process_grave_esc.h +++ b/quantum/process_keycode/process_grave_esc.h @@ -15,6 +15,8 @@   */  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  bool process_grave_esc(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_haptic.h b/quantum/process_keycode/process_haptic.h index 6dbb0f014d..7e61f6c0d6 100644 --- a/quantum/process_keycode/process_haptic.h +++ b/quantum/process_keycode/process_haptic.h @@ -15,6 +15,7 @@   */  #pragma once +#include <stdint.h>  #include <stdbool.h>  #include "action.h" diff --git a/quantum/process_keycode/process_joystick.h b/quantum/process_keycode/process_joystick.h index 1fb8757708..aa1a443271 100644 --- a/quantum/process_keycode/process_joystick.h +++ b/quantum/process_keycode/process_joystick.h @@ -17,6 +17,7 @@  #pragma once  #include <stdint.h> -#include "quantum.h" +#include <stdbool.h> +#include "action.h"  bool process_joystick(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_key_lock.h b/quantum/process_keycode/process_key_lock.h index 5159b0ba02..858945a8e4 100644 --- a/quantum/process_keycode/process_key_lock.h +++ b/quantum/process_keycode/process_key_lock.h @@ -16,7 +16,9 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  void cancel_key_lock(void);  bool process_key_lock(uint16_t *keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_key_override.c b/quantum/process_keycode/process_key_override.c index 17e490e67a..264e2562b8 100644 --- a/quantum/process_keycode/process_key_override.c +++ b/quantum/process_keycode/process_key_override.c @@ -15,12 +15,14 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "quantum.h" +#include "process_key_override.h"  #include "report.h"  #include "timer.h" -#include "process_key_override.h" - -#include <debug.h> +#include "debug.h" +#include "wait.h" +#include "action_util.h" +#include "quantum.h" +#include "quantum_keycodes.h"  #ifndef KEY_OVERRIDE_REPEAT_DELAY  #    define KEY_OVERRIDE_REPEAT_DELAY 500 @@ -322,6 +324,15 @@ static bool try_activating_override(const uint16_t keycode, const uint8_t layer,          clear_active_override(false); +#ifdef DUMMY_MOD_NEUTRALIZER_KEYCODE +        // Send a dummy keycode before unregistering the modifier(s) +        // so that suppressing the modifier(s) doesn't falsely get interpreted +        // by the host OS as a tap of a modifier key. +        // For example, unintended activations of the start menu on Windows when +        // using a GUI+<kc> key override with suppressed mods. +        neutralize_flashing_modifiers(active_mods); +#endif +          active_override                 = override;          active_override_trigger_is_down = true; diff --git a/quantum/process_keycode/process_key_override.h b/quantum/process_keycode/process_key_override.h index fd76f297a8..3e37c7e63a 100644 --- a/quantum/process_keycode/process_key_override.h +++ b/quantum/process_keycode/process_key_override.h @@ -18,9 +18,8 @@  #pragma once  #include <stdbool.h> -#include <stddef.h>  #include <stdint.h> - +#include "action.h"  #include "action_layer.h"  /** diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c index a9823b6285..ca017a577d 100644 --- a/quantum/process_keycode/process_leader.c +++ b/quantum/process_keycode/process_leader.c @@ -16,6 +16,7 @@  #include "process_leader.h"  #include "leader.h" +#include "quantum_keycodes.h"  bool process_leader(uint16_t keycode, keyrecord_t *record) {      if (record->event.pressed) { diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h index eb0f721f60..b78fbb94df 100644 --- a/quantum/process_keycode/process_leader.h +++ b/quantum/process_keycode/process_leader.h @@ -16,6 +16,8 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  bool process_leader(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_magic.c b/quantum/process_keycode/process_magic.c index 5fafe8550f..3b35884d68 100644 --- a/quantum/process_keycode/process_magic.c +++ b/quantum/process_keycode/process_magic.c @@ -14,8 +14,13 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #include "process_magic.h" +#include "keycode_config.h" +#include "keycodes.h" +#include "eeconfig.h"  #ifdef AUDIO_ENABLE +#    include "audio.h" +  #    ifndef AG_NORM_SONG  #        define AG_NORM_SONG SONG(AG_NORM_SOUND)  #    endif diff --git a/quantum/process_keycode/process_magic.h b/quantum/process_keycode/process_magic.h index 1eb39f1455..aa65a43bae 100644 --- a/quantum/process_keycode/process_magic.h +++ b/quantum/process_keycode/process_magic.h @@ -15,6 +15,8 @@   */  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  bool process_magic(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index ce62559849..377fcb69e2 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -15,12 +15,13 @@   */  #include "process_midi.h" -#ifdef MIDI_ENABLE -#    include <LUFA/Drivers/USB/USB.h> -#    include "midi.h" -#    include "qmk_midi.h" +#include <LUFA/Drivers/USB/USB.h> +#include "midi.h" +#include "qmk_midi.h" +#include "timer.h" +#include "debug.h" -#    ifdef MIDI_BASIC +#ifdef MIDI_BASIC  void process_midi_basic_noteon(uint8_t note) {      midi_send_noteon(&midi_device, 0, note, 127); @@ -34,12 +35,9 @@ void process_midi_all_notes_off(void) {      midi_send_cc(&midi_device, 0, 0x7B, 0);  } -#    endif // MIDI_BASIC - -#    ifdef MIDI_ADVANCED - -#        include "timer.h" +#endif // MIDI_BASIC +#ifdef MIDI_ADVANCED  static uint8_t tone_status[2][MIDI_TONE_COUNT];  static uint8_t  midi_modulation; @@ -248,11 +246,11 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {      return true;  } -#    endif // MIDI_ADVANCED +#endif // MIDI_ADVANCED  void midi_task(void) {      midi_device_process(&midi_device); -#    ifdef MIDI_ADVANCED +#ifdef MIDI_ADVANCED      if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval) return;      midi_modulation_timer = timer_read(); @@ -270,7 +268,5 @@ void midi_task(void) {          if (midi_modulation > 127) midi_modulation = 127;      } -#    endif +#endif  } - -#endif // MIDI_ENABLE diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h index e528c6ec0c..64ccc610f9 100644 --- a/quantum/process_keycode/process_midi.h +++ b/quantum/process_keycode/process_midi.h @@ -16,7 +16,10 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h" +#include "quantum_keycodes.h"  #ifdef MIDI_ENABLE diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 7c572079a7..f047668504 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -14,8 +14,10 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #include "process_music.h" +#include "timer.h"  #ifdef AUDIO_ENABLE +#    include "audio.h"  #    include "process_audio.h"  #endif  #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h index 83726a05ba..ed39d3cda5 100644 --- a/quantum/process_keycode/process_music.h +++ b/quantum/process_keycode/process_music.h @@ -16,7 +16,9 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) diff --git a/quantum/process_keycode/process_programmable_button.h b/quantum/process_keycode/process_programmable_button.h index 47c6ce5614..ef818af4ca 100644 --- a/quantum/process_keycode/process_programmable_button.h +++ b/quantum/process_keycode/process_programmable_button.h @@ -18,6 +18,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #pragma once  #include <stdint.h> -#include "quantum.h" +#include <stdbool.h> +#include "action.h"  bool process_programmable_button(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_repeat_key.c b/quantum/process_keycode/process_repeat_key.c index f819aa226e..73f4ddedcf 100644 --- a/quantum/process_keycode/process_repeat_key.c +++ b/quantum/process_keycode/process_repeat_key.c @@ -13,6 +13,10 @@  // limitations under the License.  #include "process_repeat_key.h" +#include "repeat_key.h" +#include "keycodes.h" +#include "quantum_keycodes.h" +#include "action_util.h"  // Default implementation of remember_last_key_user().  __attribute__((weak)) bool remember_last_key_user(uint16_t keycode, keyrecord_t* record, uint8_t* remembered_mods) { diff --git a/quantum/process_keycode/process_repeat_key.h b/quantum/process_keycode/process_repeat_key.h index eddc50f254..c3b200c632 100644 --- a/quantum/process_keycode/process_repeat_key.h +++ b/quantum/process_keycode/process_repeat_key.h @@ -14,7 +14,9 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  /**   * @brief Process handler for remembering the last key. diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c index dae129786e..4e63bf3ca8 100644 --- a/quantum/process_keycode/process_rgb.c +++ b/quantum/process_keycode/process_rgb.c @@ -14,6 +14,14 @@   * along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  #include "process_rgb.h" +#include "action_util.h" + +#ifdef RGB_MATRIX_ENABLE +#    include "rgb_matrix.h" +#endif +#ifdef RGBLIGHT_ENABLE +#    include "rgblight.h" +#endif  typedef void (*rgb_func_pointer)(void); diff --git a/quantum/process_keycode/process_rgb.h b/quantum/process_keycode/process_rgb.h index 26aca46896..b1069d4bb6 100644 --- a/quantum/process_keycode/process_rgb.h +++ b/quantum/process_keycode/process_rgb.h @@ -15,6 +15,8 @@   */  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  bool process_rgb(const uint16_t keycode, const keyrecord_t *record); diff --git a/quantum/process_keycode/process_secure.h b/quantum/process_keycode/process_secure.h index 2814264b92..78d793f0f6 100644 --- a/quantum/process_keycode/process_secure.h +++ b/quantum/process_keycode/process_secure.h @@ -3,6 +3,7 @@  #pragma once +#include <stdint.h>  #include <stdbool.h>  #include "action.h" diff --git a/quantum/process_keycode/process_sequencer.h b/quantum/process_keycode/process_sequencer.h index 2b85f24299..3a9bdc2b24 100644 --- a/quantum/process_keycode/process_sequencer.h +++ b/quantum/process_keycode/process_sequencer.h @@ -16,6 +16,8 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  bool process_sequencer(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_space_cadet.c b/quantum/process_keycode/process_space_cadet.c index 3109ea1711..f948ad6238 100644 --- a/quantum/process_keycode/process_space_cadet.c +++ b/quantum/process_keycode/process_space_cadet.c @@ -13,8 +13,13 @@   * 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_space_cadet.h" +#include "keycodes.h" +#include "timer.h" +#include "action.h"  #include "action_tapping.h" +#include "action_util.h"  // ********** OBSOLETE DEFINES, STOP USING! (pls?) **********  // Shift / paren setup diff --git a/quantum/process_keycode/process_space_cadet.h b/quantum/process_keycode/process_space_cadet.h index fcb70f3b43..6d10051532 100644 --- a/quantum/process_keycode/process_space_cadet.h +++ b/quantum/process_keycode/process_space_cadet.h @@ -15,7 +15,9 @@   */  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdMod, uint8_t tapMod, uint8_t keycode);  bool process_space_cadet(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c index d5ad61ba85..af26d4ca86 100644 --- a/quantum/process_keycode/process_steno.c +++ b/quantum/process_keycode/process_steno.c @@ -15,6 +15,7 @@   */  #include "process_steno.h"  #include "quantum_keycodes.h" +#include "eeconfig.h"  #include "keymap_steno.h"  #include <string.h>  #ifdef VIRTSER_ENABLE diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h index 68d6097b9b..0dd2103218 100644 --- a/quantum/process_keycode/process_steno.h +++ b/quantum/process_keycode/process_steno.h @@ -16,7 +16,9 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  #define BOLT_STROKE_SIZE 4  #define GEMINI_STROKE_SIZE 6 diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c index 706f5cddbb..b8a8d32f35 100644 --- a/quantum/process_keycode/process_tap_dance.c +++ b/quantum/process_keycode/process_tap_dance.c @@ -13,7 +13,14 @@   * 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_tap_dance.h"  #include "quantum.h" +#include "action_layer.h" +#include "action_tapping.h" +#include "action_util.h" +#include "timer.h" +#include "wait.h"  static uint16_t active_td;  static uint16_t last_tap_time; @@ -88,6 +95,10 @@ static inline void process_tap_dance_action_on_each_tap(tap_dance_action_t *acti      _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_tap);  } +static inline void process_tap_dance_action_on_each_release(tap_dance_action_t *action) { +    _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_release); +} +  static inline void process_tap_dance_action_on_reset(tap_dance_action_t *action) {      _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_reset);      del_weak_mods(action->state.weak_mods); @@ -151,8 +162,12 @@ bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {                  process_tap_dance_action_on_each_tap(action);                  active_td = action->state.finished ? 0 : keycode;              } else { +                process_tap_dance_action_on_each_release(action);                  if (action->state.finished) {                      process_tap_dance_action_on_reset(action); +                    if (active_td == keycode) { +                        active_td = 0; +                    }                  }              } diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h index 5cb6d9202c..2b114dabd3 100644 --- a/quantum/process_keycode/process_tap_dance.h +++ b/quantum/process_keycode/process_tap_dance.h @@ -16,18 +16,17 @@  #pragma once -#ifdef TAP_DANCE_ENABLE - -#    include <stdbool.h> -#    include <inttypes.h> +#include <stdint.h> +#include <stdbool.h> +#include "action.h"  typedef struct {      uint16_t interrupting_keycode;      uint8_t  count;      uint8_t  weak_mods; -#    ifndef NO_ACTION_ONESHOT +#ifndef NO_ACTION_ONESHOT      uint8_t oneshot_mods; -#    endif +#endif      bool pressed : 1;      bool finished : 1;      bool interrupted : 1; @@ -41,6 +40,7 @@ typedef struct {          tap_dance_user_fn_t on_each_tap;          tap_dance_user_fn_t on_dance_finished;          tap_dance_user_fn_t on_reset; +        tap_dance_user_fn_t on_each_release;      } fn;      void *user_data;  } tap_dance_action_t; @@ -56,24 +56,27 @@ typedef struct {      void (*layer_function)(uint8_t);  } tap_dance_dual_role_t; -#    define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \ -        { .fn = {tap_dance_pair_on_each_tap, tap_dance_pair_finished, tap_dance_pair_reset}, .user_data = (void *)&((tap_dance_pair_t){kc1, kc2}), } +#define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \ +    { .fn = {tap_dance_pair_on_each_tap, tap_dance_pair_finished, tap_dance_pair_reset, NULL}, .user_data = (void *)&((tap_dance_pair_t){kc1, kc2}), } -#    define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) \ -        { .fn = {tap_dance_dual_role_on_each_tap, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_move}), } +#define ACTION_TAP_DANCE_LAYER_MOVE(kc, layer) \ +    { .fn = {tap_dance_dual_role_on_each_tap, tap_dance_dual_role_finished, tap_dance_dual_role_reset, NULL}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_move}), } -#    define ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer) \ -        { .fn = {NULL, tap_dance_dual_role_finished, tap_dance_dual_role_reset}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_invert}), } +#define ACTION_TAP_DANCE_LAYER_TOGGLE(kc, layer) \ +    { .fn = {NULL, tap_dance_dual_role_finished, tap_dance_dual_role_reset, NULL}, .user_data = (void *)&((tap_dance_dual_role_t){kc, layer, layer_invert}), } -#    define ACTION_TAP_DANCE_FN(user_fn) \ -        { .fn = {NULL, user_fn, NULL}, .user_data = NULL, } +#define ACTION_TAP_DANCE_FN(user_fn) \ +    { .fn = {NULL, user_fn, NULL, NULL}, .user_data = NULL, } -#    define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) \ -        { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, } +#define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) \ +    { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, NULL}, .user_data = NULL, } -#    define TD(n) (QK_TAP_DANCE | TD_INDEX(n)) -#    define TD_INDEX(code) ((code)&0xFF) -#    define TAP_DANCE_KEYCODE(state) TD(((tap_dance_action_t *)state) - tap_dance_actions) +#define ACTION_TAP_DANCE_FN_ADVANCED_WITH_RELEASE(user_fn_on_each_tap, user_fn_on_each_release, user_fn_on_dance_finished, user_fn_on_dance_reset) \ +    { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, user_fn_on_each_release}, .user_data = NULL, } + +#define TD(n) (QK_TAP_DANCE | TD_INDEX(n)) +#define TD_INDEX(code) ((code)&0xFF) +#define TAP_DANCE_KEYCODE(state) TD(((tap_dance_action_t *)state) - tap_dance_actions)  extern tap_dance_action_t tap_dance_actions[]; @@ -92,9 +95,3 @@ void tap_dance_pair_reset(tap_dance_state_t *state, void *user_data);  void tap_dance_dual_role_on_each_tap(tap_dance_state_t *state, void *user_data);  void tap_dance_dual_role_finished(tap_dance_state_t *state, void *user_data);  void tap_dance_dual_role_reset(tap_dance_state_t *state, void *user_data); - -#else - -#    define TD(n) KC_NO - -#endif diff --git a/quantum/process_keycode/process_tri_layer.h b/quantum/process_keycode/process_tri_layer.h index 9c4e3df1c2..5e6e4ff94d 100644 --- a/quantum/process_keycode/process_tri_layer.h +++ b/quantum/process_keycode/process_tri_layer.h @@ -3,6 +3,8 @@  #pragma once +#include <stdint.h> +#include <stdbool.h>  #include "action.h"  /** diff --git a/quantum/quantum.c b/quantum/quantum.c index 091cf298f7..c6a40a4baa 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -310,15 +310,15 @@ bool process_record_quantum(keyrecord_t *record) {  #if (defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE)              process_music(keycode, record) &&  #endif +#ifdef CAPS_WORD_ENABLE +            process_caps_word(keycode, record) && +#endif  #ifdef KEY_OVERRIDE_ENABLE              process_key_override(keycode, record) &&  #endif  #ifdef TAP_DANCE_ENABLE              process_tap_dance(keycode, record) &&  #endif -#ifdef CAPS_WORD_ENABLE -            process_caps_word(keycode, record) && -#endif  #if defined(UNICODE_COMMON_ENABLE)              process_unicode_common(keycode, record) &&  #endif @@ -468,7 +468,7 @@ void suspend_power_down_quantum(void) {  #ifndef NO_SUSPEND_POWER_DOWN  // Turn off backlight  #    ifdef BACKLIGHT_ENABLE -    backlight_set(0); +    backlight_level_noeeprom(0);  #    endif  #    ifdef LED_MATRIX_ENABLE diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index f931b7e4c7..d3249bd455 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -179,10 +179,10 @@  #define QK_UNICODE_GET_CODE_POINT(kc) ((kc)&0x7FFF)  // UNICODEMAP_ENABLE - Allows Unicode input up to 0x10FFFF, requires unicode_map -#define X(i) (QK_UNICODEMAP | ((i)&0x3FFF)) +#define UM(i) (QK_UNICODEMAP | ((i)&0x3FFF))  #define QK_UNICODEMAP_GET_INDEX(kc) ((kc)&0x3FFF) -#define XP(i, j) (QK_UNICODEMAP_PAIR | ((i)&0x7F) | (((j)&0x7F) << 7)) // 127 max i and j +#define UP(i, j) (QK_UNICODEMAP_PAIR | ((i)&0x7F) | (((j)&0x7F) << 7)) // 127 max i and j  #define QK_UNICODEMAP_PAIR_GET_UNSHIFTED_INDEX(kc) ((kc)&0x7F)  #define QK_UNICODEMAP_PAIR_GET_SHIFTED_INDEX(kc) (((kc) >> 7) & 0x7F) diff --git a/quantum/quantum_keycodes_legacy.h b/quantum/quantum_keycodes_legacy.h index 120c98bc62..ad078cdad5 100644 --- a/quantum/quantum_keycodes_legacy.h +++ b/quantum/quantum_keycodes_legacy.h @@ -53,3 +53,6 @@  #define GUI_ON  QK_MAGIC_GUI_ON  #define GUI_OFF QK_MAGIC_GUI_OFF  #define GUI_TOG QK_MAGIC_TOGGLE_GUI + +#define X(i) UM(i) +#define XP(i, j) UM(i, j) diff --git a/quantum/raw_hid.h b/quantum/raw_hid.h index 6d60ab2bff..16830833cc 100644 --- a/quantum/raw_hid.h +++ b/quantum/raw_hid.h @@ -1,5 +1,31 @@ +// Copyright 2023 QMK +// SPDX-License-Identifier: GPL-2.0-or-later +  #pragma once +#include <stdint.h> + +/** + * \file + * + * \defgroup raw_hid Raw HID API + * \{ + */ + +/** + * \brief Callback, invoked when a raw HID report has been received from the host. + * + * \param data A pointer to the received data. Always 32 bytes in length. + * \param length The length of the buffer. Always 32. + */  void raw_hid_receive(uint8_t *data, uint8_t length); +/** + * \brief Send an HID report. + * + * \param data A pointer to the data to send. Must always be 32 bytes in length. + * \param length The length of the buffer. Must always be 32. + */  void raw_hid_send(uint8_t *data, uint8_t length); + +/** \} */ diff --git a/quantum/repeat_key.c b/quantum/repeat_key.c index 0689c6d454..4567428723 100644 --- a/quantum/repeat_key.c +++ b/quantum/repeat_key.c @@ -13,6 +13,7 @@  // limitations under the License.  #include "repeat_key.h" +#include "quantum_keycodes.h"  // Variables saving the state of the last key press.  static keyrecord_t last_record = {0}; diff --git a/quantum/repeat_key.h b/quantum/repeat_key.h index 06e8364529..8084be24ad 100644 --- a/quantum/repeat_key.h +++ b/quantum/repeat_key.h @@ -14,7 +14,10 @@  #pragma once -#include "quantum.h" +#include <stdint.h> +#include <stdbool.h> +#include "action.h" +#include "keyboard.h"  uint16_t get_last_keycode(void);             /**< Keycode of the last key. */  uint8_t  get_last_mods(void);                /**< Mods active with the last key. */ diff --git a/quantum/rgb_matrix/animations/pixel_fractal_anim.h b/quantum/rgb_matrix/animations/pixel_fractal_anim.h index 875b4ceb3d..4cd1d9b861 100644 --- a/quantum/rgb_matrix/animations/pixel_fractal_anim.h +++ b/quantum/rgb_matrix/animations/pixel_fractal_anim.h @@ -7,7 +7,11 @@ RGB_MATRIX_EFFECT(PIXEL_FRACTAL)  #    ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS  static bool PIXEL_FRACTAL(effect_params_t* params) { -#        define MID_COL MATRIX_COLS / 2 +#        if MATRIX_COLS < 2 +#            define MID_COL 1 +#        else +#            define MID_COL MATRIX_COLS / 2 +#        endif      static bool     led[MATRIX_ROWS][MID_COL];      static uint32_t wait_timer = 0; diff --git a/quantum/rgb_matrix/animations/pixel_rain_anim.h b/quantum/rgb_matrix/animations/pixel_rain_anim.h index 9d63f451e2..26cd73b578 100644 --- a/quantum/rgb_matrix/animations/pixel_rain_anim.h +++ b/quantum/rgb_matrix/animations/pixel_rain_anim.h @@ -16,13 +16,9 @@ static bool PIXEL_RAIN(effect_params_t* params) {          if (!HAS_ANY_FLAGS(g_led_config.flags[led_index], params->flags)) {              return;          } -        if (random8() & 2) { -            rgb_matrix_set_color(led_index, 0, 0, 0); -        } else { -            HSV hsv = {random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v}; -            RGB rgb = rgb_matrix_hsv_to_rgb(hsv); -            rgb_matrix_set_color(led_index, rgb.r, rgb.g, rgb.b); -        } +        HSV hsv = (random8() & 2) ? (HSV){0, 0, 0} : (HSV){random8(), random8_min_max(127, 255), rgb_matrix_config.hsv.v}; +        RGB rgb = rgb_matrix_hsv_to_rgb(hsv); +        rgb_matrix_set_color(led_index, rgb.r, rgb.g, rgb.b);          wait_timer = g_rgb_timer + interval();      } diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c index 1f3912cf7e..96be615162 100644 --- a/quantum/rgb_matrix/rgb_matrix.c +++ b/quantum/rgb_matrix/rgb_matrix.c @@ -19,8 +19,13 @@  #include "rgb_matrix.h"  #include "progmem.h"  #include "eeprom.h" +#include "eeconfig.h" +#include "keyboard.h" +#include "sync_timer.h" +#include "debug.h"  #include <string.h>  #include <math.h> +#include <stdlib.h>  #include <lib/lib8tion/lib8tion.h> @@ -428,7 +433,10 @@ void rgb_matrix_task(void) {          case RENDERING:              rgb_task_render(effect);              if (effect) { -                rgb_matrix_indicators(); +                // Only run the basic indicators in the last render iteration (default there are 5 iterations) +                if (rgb_effect_params.iter == RGB_MATRIX_LED_PROCESS_MAX_ITERATIONS) { +                    rgb_matrix_indicators(); +                }                  rgb_matrix_indicators_advanced(&rgb_effect_params);              }              break; diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h index 9ea248b66d..38040fb0cc 100644 --- a/quantum/rgb_matrix/rgb_matrix.h +++ b/quantum/rgb_matrix/rgb_matrix.h @@ -22,7 +22,7 @@  #include <stdbool.h>  #include "rgb_matrix_types.h"  #include "color.h" -#include "quantum.h" +#include "keyboard.h"  #ifdef IS31FL3731  #    include "is31fl3731.h" @@ -49,8 +49,9 @@  #endif  #ifndef RGB_MATRIX_LED_PROCESS_LIMIT -#    define RGB_MATRIX_LED_PROCESS_LIMIT (RGB_MATRIX_LED_COUNT + 4) / 5 +#    define RGB_MATRIX_LED_PROCESS_LIMIT ((RGB_MATRIX_LED_COUNT + 4) / 5)  #endif +#define RGB_MATRIX_LED_PROCESS_MAX_ITERATIONS ((RGB_MATRIX_LED_COUNT + RGB_MATRIX_LED_PROCESS_LIMIT - 1) / RGB_MATRIX_LED_PROCESS_LIMIT)  #if defined(RGB_MATRIX_LED_PROCESS_LIMIT) && RGB_MATRIX_LED_PROCESS_LIMIT > 0 && RGB_MATRIX_LED_PROCESS_LIMIT < RGB_MATRIX_LED_COUNT  #    if defined(RGB_MATRIX_SPLIT) diff --git a/quantum/rgb_matrix/rgb_matrix_drivers.c b/quantum/rgb_matrix/rgb_matrix_drivers.c index d66fc801dd..7bd274ee99 100644 --- a/quantum/rgb_matrix/rgb_matrix_drivers.c +++ b/quantum/rgb_matrix/rgb_matrix_drivers.c @@ -15,6 +15,7 @@   */  #include "rgb_matrix.h" +#include "util.h"  /* Each driver needs to define the struct   *    const rgb_matrix_driver_t rgb_matrix_driver; @@ -426,11 +427,17 @@ const rgb_matrix_driver_t rgb_matrix_driver = {  // LED color buffer  LED_TYPE rgb_matrix_ws2812_array[RGB_MATRIX_LED_COUNT]; +bool     ws2812_dirty = false; -static void init(void) {} +static void init(void) { +    ws2812_dirty = false; +}  static void flush(void) { -    ws2812_setleds(rgb_matrix_ws2812_array, RGB_MATRIX_LED_COUNT); +    if (ws2812_dirty) { +        ws2812_setleds(rgb_matrix_ws2812_array, RGB_MATRIX_LED_COUNT); +        ws2812_dirty = false; +    }  }  // Set an led in the buffer to a color @@ -448,6 +455,11 @@ static inline void setled(int i, uint8_t r, uint8_t g, uint8_t b) {      }  #    endif +    if (rgb_matrix_ws2812_array[i].r == r && rgb_matrix_ws2812_array[i].g == g && rgb_matrix_ws2812_array[i].b == b) { +        return; +    } + +    ws2812_dirty                 = true;      rgb_matrix_ws2812_array[i].r = r;      rgb_matrix_ws2812_array[i].g = g;      rgb_matrix_ws2812_array[i].b = b; diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c index a431383454..fca95e0847 100644 --- a/quantum/split_common/split_util.c +++ b/quantum/split_common/split_util.c @@ -18,9 +18,10 @@  #include "keyboard.h"  #include "timer.h"  #include "transport.h" -#include "quantum.h"  #include "wait.h" +#include "debug.h"  #include "usb_util.h" +#include "bootloader.h"  #ifdef EE_HANDS  #    include "eeconfig.h" diff --git a/quantum/split_common/split_util.h b/quantum/split_common/split_util.h index 5c9a260a14..ab42c85e9f 100644 --- a/quantum/split_common/split_util.h +++ b/quantum/split_common/split_util.h @@ -2,7 +2,6 @@  #include <stdbool.h>  #include <stdint.h> -#include <stdlib.h>  #include "matrix.h" diff --git a/quantum/split_common/transactions.c b/quantum/split_common/transactions.c index b3c80f1194..2b9423cd63 100644 --- a/quantum/split_common/transactions.c +++ b/quantum/split_common/transactions.c @@ -20,13 +20,50 @@  #include "crc.h"  #include "debug.h"  #include "matrix.h" -#include "quantum.h" +#include "host.h" +#include "action_util.h" +#include "sync_timer.h" +#include "wait.h"  #include "transactions.h"  #include "transport.h"  #include "transaction_id_define.h"  #include "split_util.h"  #include "synchronization_util.h" +#ifdef BACKLIGHT_ENABLE +#    include "backlight.h" +#endif +#ifdef RGBLIGHT_ENABLE +#    include "rgblight.h" +#endif +#ifdef LED_MATRIX_ENABLE +#    include "led_matrix.h" +#endif +#ifdef RGB_MATRIX_ENABLE +#    include "rgb_matrix.h" +#endif +#ifdef OLED_ENABLE +#    include "oled_driver.h" +#endif +#ifdef ST7565_ENABLE +#    include "st7565.h" +#endif +#ifdef ENCODER_ENABLE +#    include "encoder.h" +#endif +#ifdef HAPTIC_ENABLE +#    include "haptic.h" +#endif +#ifdef POINTING_DEVICE_ENABLE +#    include "pointing_device.h" +#endif +#ifdef OS_DETECTION_ENABLE +#    include "os_detection.h" +#endif +#ifdef WPM_ENABLE +#    include "wpm.h" +#endif +  #define SYNC_TIMER_OFFSET 2  #ifndef FORCED_SYNC_THROTTLE_MS @@ -412,7 +449,7 @@ static void backlight_handlers_slave(matrix_row_t master_matrix[], matrix_row_t      uint8_t backlight_level = split_shmem->backlight_level;      split_shared_memory_unlock(); -    backlight_set(backlight_level); +    backlight_level_noeeprom(backlight_level);  }  #    define TRANSACTIONS_BACKLIGHT_MASTER() TRANSACTION_HANDLER_MASTER(backlight) diff --git a/quantum/split_common/transactions.h b/quantum/split_common/transactions.h index e38ec79ce9..af3e68a15f 100644 --- a/quantum/split_common/transactions.h +++ b/quantum/split_common/transactions.h @@ -16,8 +16,8 @@  #pragma once -#include "stdint.h" -#include "stdbool.h" +#include <stdint.h> +#include <stdbool.h>  #include "matrix.h"  #include "transaction_id_define.h" diff --git a/quantum/split_common/transport.h b/quantum/split_common/transport.h index a3d6f1dfe9..2e2b918d45 100644 --- a/quantum/split_common/transport.h +++ b/quantum/split_common/transport.h @@ -16,8 +16,8 @@  #pragma once -#include "stdint.h" -#include "stdbool.h" +#include <stdint.h> +#include <stdbool.h>  #include "progmem.h"  #include "action_layer.h" diff --git a/quantum/unicode/unicode.c b/quantum/unicode/unicode.c index 35cb62e700..f92ba51984 100644 --- a/quantum/unicode/unicode.c +++ b/quantum/unicode/unicode.c @@ -25,6 +25,8 @@  #include "wait.h"  #include "send_string.h"  #include "utf8.h" +#include "debug.h" +#include "quantum.h"  #if defined(AUDIO_ENABLE)  #    include "audio.h" diff --git a/quantum/unicode/unicode.h b/quantum/unicode/unicode.h index 06505d87c0..ccf475d57c 100644 --- a/quantum/unicode/unicode.h +++ b/quantum/unicode/unicode.h @@ -17,8 +17,7 @@  #pragma once  #include <stdint.h> - -#include "quantum.h" +#include "quantum_keycodes.h"  typedef union {      uint8_t raw; diff --git a/quantum/via.c b/quantum/via.c index c54e37a175..2acd7aa90c 100644 --- a/quantum/via.c +++ b/quantum/via.c @@ -22,19 +22,41 @@  #    error "DYNAMIC_KEYMAP_ENABLE is not enabled"  #endif -#include "quantum.h" -  #include "via.h"  #include "raw_hid.h"  #include "dynamic_keymap.h"  #include "eeprom.h" +#include "eeconfig.h" +#include "matrix.h" +#include "timer.h" +#include "wait.h"  #include "version.h" // for QMK_BUILDDATE used in EEPROM magic -#if defined(RGB_MATRIX_ENABLE) +#if defined(AUDIO_ENABLE) +#    include "audio.h" +#endif + +#if defined(BACKLIGHT_ENABLE) +#    include "backlight.h" +#endif + +#if defined(RGBLIGHT_ENABLE) +#    include "rgblight.h" +#endif + +#if (defined(RGB_MATRIX_ENABLE) || defined(LED_MATRIX_ENABLE))  #    include <lib/lib8tion/lib8tion.h>  #endif +#if defined(RGB_MATRIX_ENABLE) +#    include "rgb_matrix.h" +#endif + +#if defined(LED_MATRIX_ENABLE) +#    include "led_matrix.h" +#endif +  // Can be called in an overriding via_init_kb() to test if keyboard level code usage of  // EEPROM is invalid and use/save defaults.  bool via_eeprom_is_valid(void) { @@ -141,6 +163,9 @@ __attribute__((weak)) void via_set_device_indication(uint8_t value) {  #if defined(RGB_MATRIX_ENABLE)      rgb_matrix_toggle_noeeprom();  #endif // RGB_MATRIX_ENABLE +#if defined(LED_MATRIX_ENABLE) +    led_matrix_toggle_noeeprom(); +#endif // LED_MATRIX_ENABLE  #if defined(AUDIO_ENABLE)      if (value == 0) {          wait_ms(10); @@ -194,6 +219,7 @@ __attribute__((weak)) void via_custom_value_command_kb(uint8_t *data, uint8_t le  //      id_qmk_backlight_channel    ->  via_qmk_backlight_command()  //      id_qmk_rgblight_channel     ->  via_qmk_rgblight_command()  //      id_qmk_rgb_matrix_channel   ->  via_qmk_rgb_matrix_command() +//      id_qmk_led_matrix_channel   ->  via_qmk_led_matrix_command()  //      id_qmk_audio_channel        ->  via_qmk_audio_command()  //  __attribute__((weak)) void via_custom_value_command(uint8_t *data, uint8_t length) { @@ -219,7 +245,14 @@ __attribute__((weak)) void via_custom_value_command(uint8_t *data, uint8_t lengt          via_qmk_rgb_matrix_command(data, length);          return;      } -#endif // RGBLIGHT_ENABLE +#endif // RGB_MATRIX_ENABLE + +#if defined(LED_MATRIX_ENABLE) +    if (*channel_id == id_qmk_led_matrix_channel) { +        via_qmk_led_matrix_command(data, length); +        return; +    } +#endif // LED_MATRIX_ENABLE  #if defined(AUDIO_ENABLE)      if (*channel_id == id_qmk_audio_channel) { @@ -692,6 +725,90 @@ void via_qmk_rgb_matrix_save(void) {  #endif // RGB_MATRIX_ENABLE +#if defined(LED_MATRIX_ENABLE) + +#    if !defined(LED_MATRIX_MAXIMUM_BRIGHTNESS) || LED_MATRIX_MAXIMUM_BRIGHTNESS > UINT8_MAX +#        undef LED_MATRIX_MAXIMUM_BRIGHTNESS +#        define LED_MATRIX_MAXIMUM_BRIGHTNESS UINT8_MAX +#    endif + +void via_qmk_led_matrix_command(uint8_t *data, uint8_t length) { +    // data = [ command_id, channel_id, value_id, value_data ] +    uint8_t *command_id        = &(data[0]); +    uint8_t *value_id_and_data = &(data[2]); + +    switch (*command_id) { +        case id_custom_set_value: { +            via_qmk_led_matrix_set_value(value_id_and_data); +            break; +        } +        case id_custom_get_value: { +            via_qmk_led_matrix_get_value(value_id_and_data); +            break; +        } +        case id_custom_save: { +            via_qmk_led_matrix_save(); +            break; +        } +        default: { +            *command_id = id_unhandled; +            break; +        } +    } +} + +void via_qmk_led_matrix_get_value(uint8_t *data) { +    // data = [ value_id, value_data ] +    uint8_t *value_id   = &(data[0]); +    uint8_t *value_data = &(data[1]); + +    switch (*value_id) { +        case id_qmk_led_matrix_brightness: { +            value_data[0] = ((uint16_t)led_matrix_get_val() * UINT8_MAX) / LED_MATRIX_MAXIMUM_BRIGHTNESS; +            break; +        } +        case id_qmk_led_matrix_effect: { +            value_data[0] = led_matrix_is_enabled() ? led_matrix_get_mode() : 0; +            break; +        } +        case id_qmk_led_matrix_effect_speed: { +            value_data[0] = led_matrix_get_speed(); +            break; +        } +    } +} + +void via_qmk_led_matrix_set_value(uint8_t *data) { +    // data = [ value_id, value_data ] +    uint8_t *value_id   = &(data[0]); +    uint8_t *value_data = &(data[1]); +    switch (*value_id) { +        case id_qmk_led_matrix_brightness: { +            led_matrix_set_val_noeeprom(scale8(value_data[0], LED_MATRIX_MAXIMUM_BRIGHTNESS)); +            break; +        } +        case id_qmk_led_matrix_effect: { +            if (value_data[0] == 0) { +                led_matrix_disable_noeeprom(); +            } else { +                led_matrix_enable_noeeprom(); +                led_matrix_mode_noeeprom(value_data[0]); +            } +            break; +        } +        case id_qmk_led_matrix_effect_speed: { +            led_matrix_set_speed_noeeprom(value_data[0]); +            break; +        } +    } +} + +void via_qmk_led_matrix_save(void) { +    eeconfig_update_led_matrix(); +} + +#endif // LED_MATRIX_ENABLE +  #if defined(AUDIO_ENABLE)  extern audio_config_t audio_config; diff --git a/quantum/via.h b/quantum/via.h index ab4eb05028..01d4c48b37 100644 --- a/quantum/via.h +++ b/quantum/via.h @@ -17,6 +17,7 @@  #pragma once  #include "eeconfig.h" // for EECONFIG_SIZE +#include "action.h"  // Keyboard level code can change where VIA stores the magic.  // The magic is the build date YYMMDD encoded as BCD in 3 bytes, @@ -109,6 +110,7 @@ enum via_channel_id {      id_qmk_rgblight_channel   = 2,      id_qmk_rgb_matrix_channel = 3,      id_qmk_audio_channel      = 4, +    id_qmk_led_matrix_channel = 5,  };  enum via_qmk_backlight_value { @@ -130,6 +132,12 @@ enum via_qmk_rgb_matrix_value {      id_qmk_rgb_matrix_color        = 4,  }; +enum via_qmk_led_matrix_value { +    id_qmk_led_matrix_brightness   = 1, +    id_qmk_led_matrix_effect       = 2, +    id_qmk_led_matrix_effect_speed = 3, +}; +  enum via_qmk_audio_value {      id_qmk_audio_enable        = 1,      id_qmk_audio_clicky_enable = 2, @@ -182,6 +190,13 @@ void via_qmk_rgb_matrix_get_value(uint8_t *data);  void via_qmk_rgb_matrix_save(void);  #endif +#if defined(LED_MATRIX_ENABLE) +void via_qmk_led_matrix_command(uint8_t *data, uint8_t length); +void via_qmk_led_matrix_set_value(uint8_t *data); +void via_qmk_led_matrix_get_value(uint8_t *data); +void via_qmk_led_matrix_save(void); +#endif +  #if defined(AUDIO_ENABLE)  void via_qmk_audio_command(uint8_t *data, uint8_t length);  void via_qmk_audio_set_value(uint8_t *data); | 
