diff options
Diffstat (limited to 'quantum')
29 files changed, 1666 insertions, 98 deletions
| diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index bc00cd19e6..dccf03d5f6 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -83,6 +83,7 @@ void increase_tempo(uint8_t tempo_change);  void decrease_tempo(uint8_t tempo_change);  void audio_init(void); +void audio_startup(void);  #ifdef PWM_AUDIO  void play_sample(uint8_t* s, uint16_t l, bool r); diff --git a/quantum/audio/audio_avr.c b/quantum/audio/audio_avr.c index 5a96bf6439..1bac43bb43 100644 --- a/quantum/audio/audio_avr.c +++ b/quantum/audio/audio_avr.c @@ -227,7 +227,9 @@ void audio_init() {          audio_initialized = true;      } +} +void audio_startup() {      if (audio_config.enable) {          PLAY_SONG(startup_song);      } diff --git a/quantum/audio/audio_chibios.c b/quantum/audio/audio_chibios.c index 1f147f2c92..dddb8f1357 100644 --- a/quantum/audio/audio_chibios.c +++ b/quantum/audio/audio_chibios.c @@ -86,13 +86,21 @@ static void gpt_cb8(GPTDriver *gptp);  #define START_CHANNEL_1()        \      gptStart(&GPTD6, &gpt6cfg1); \ -    gptStartContinuous(&GPTD6, 2U) +    gptStartContinuous(&GPTD6, 2U); \ +    palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG)  #define START_CHANNEL_2()        \      gptStart(&GPTD7, &gpt7cfg1); \ -    gptStartContinuous(&GPTD7, 2U) -#define STOP_CHANNEL_1() gptStopTimer(&GPTD6) -#define STOP_CHANNEL_2() gptStopTimer(&GPTD7) -#define RESTART_CHANNEL_1() \ +    gptStartContinuous(&GPTD7, 2U); \ +    palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG) +#define STOP_CHANNEL_1()          \ +    gptStopTimer(&GPTD6);         \ +    palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL); \ +    palSetPad(GPIOA, 4) +#define STOP_CHANNEL_2()         \ +    gptStopTimer(&GPTD7);        \ +    palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); \ +    palSetPad(GPIOA, 5) +    #define RESTART_CHANNEL_1() \      STOP_CHANNEL_1();       \      START_CHANNEL_1()  #define RESTART_CHANNEL_2() \ @@ -274,6 +282,12 @@ void audio_init() {      dacStart(&DACD2, &dac1cfg2);      /* +     * Start the note timer +     */ +    gptStart(&GPTD8, &gpt8cfg1); +    gptStartContinuous(&GPTD8, 2U); + +    /*       * Starting GPT6/7 driver, it is used for triggering the DAC.       */      START_CHANNEL_1(); @@ -287,10 +301,12 @@ void audio_init() {      audio_initialized = true; +    stop_all_notes(); +} + +void audio_startup() {      if (audio_config.enable) {          PLAY_SONG(startup_song); -    } else { -        stop_all_notes();      }  } @@ -630,6 +646,9 @@ bool is_playing_notes(void) { return playing_notes; }  bool is_audio_on(void) { return (audio_config.enable != 0); }  void audio_toggle(void) { +    if (audio_config.enable) { +        stop_all_notes(); +    }      audio_config.enable ^= 1;      eeconfig_update_audio(audio_config.raw);      if (audio_config.enable) { diff --git a/quantum/audio/audio_pwm.c b/quantum/audio/audio_pwm.c index 545aef6dd7..d93ac4bb40 100644 --- a/quantum/audio/audio_pwm.c +++ b/quantum/audio/audio_pwm.c @@ -29,6 +29,11 @@  #define CPU_PRESCALER 8 +#ifndef STARTUP_SONG +#    define STARTUP_SONG SONG(STARTUP_SOUND) +#endif +float startup_song[][2] = STARTUP_SONG; +  // Timer Abstractions  // TIMSK3 - Timer/Counter #3 Interrupt Mask Register @@ -155,6 +160,12 @@ void audio_init() {      audio_initialized = true;  } +void audio_startup() { +    if (audio_config.enable) { +        PLAY_SONG(startup_song); +    } +} +  void stop_all_notes() {      if (!audio_initialized) {          audio_init(); diff --git a/quantum/audio/musical_notes.h b/quantum/audio/musical_notes.h index 8ac6aafd38..0ba572c346 100644 --- a/quantum/audio/musical_notes.h +++ b/quantum/audio/musical_notes.h @@ -17,7 +17,9 @@  #pragma once  // Tempo Placeholder -#define TEMPO_DEFAULT 100 +#ifndef TEMPO_DEFAULT +#    define TEMPO_DEFAULT 100 +#endif  #define SONG(notes...) \      { notes } @@ -60,8 +62,9 @@  #define TIMBRE_25 0.250f  #define TIMBRE_50 0.500f  #define TIMBRE_75 0.750f -#define TIMBRE_DEFAULT TIMBRE_50 - +#ifndef TIMBRE_DEFAULT +#    define TIMBRE_DEFAULT TIMBRE_50 +#endif  // Notes - # = Octave  #ifdef __arm__ diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c index 4d66da80ba..2ecdd4f2c4 100644 --- a/quantum/backlight/backlight_avr.c +++ b/quantum/backlight/backlight_avr.c @@ -68,7 +68,7 @@  #        define COMxx1 COM3A1  #        define OCRxx OCR3A  #    endif -#elif (defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)) && (BACKLIGHT_PIN == B7 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6) +#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 diff --git a/quantum/config_common.h b/quantum/config_common.h index 5973232ef6..bfaf7389e2 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -39,7 +39,7 @@  #        define PIND_ADDRESS 0x9  #        define PINE_ADDRESS 0xC  #        define PINF_ADDRESS 0xF -#    elif defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) +#    elif defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)  #        define ADDRESS_BASE 0x00  #        define PINB_ADDRESS 0x3  #        define PINC_ADDRESS 0x6 diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c index 6c0e3bb071..60513f98e1 100644 --- a/quantum/debounce/sym_defer_pk.c +++ b/quantum/debounce/sym_defer_pk.c @@ -23,6 +23,12 @@ When no state changes have occured for DEBOUNCE milliseconds, we push the state.  #include "quantum.h"  #include <stdlib.h> +#ifdef PROTOCOL_CHIBIOS +#    if CH_CFG_USE_MEMCORE == FALSE +#        error ChibiOS is configured without a memory allocator. Your keyboard may have set `#define CH_CFG_USE_MEMCORE FALSE`, which is incompatible with this debounce algorithm. +#    endif +#endif +  #ifndef DEBOUNCE  #    define DEBOUNCE 5  #endif diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c index 93a40ad441..e66cf92d79 100644 --- a/quantum/debounce/sym_eager_pk.c +++ b/quantum/debounce/sym_eager_pk.c @@ -23,6 +23,12 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.  #include "quantum.h"  #include <stdlib.h> +#ifdef PROTOCOL_CHIBIOS +#    if CH_CFG_USE_MEMCORE == FALSE +#        error ChibiOS is configured without a memory allocator. Your keyboard may have set `#define CH_CFG_USE_MEMCORE FALSE`, which is incompatible with this debounce algorithm. +#    endif +#endif +  #ifndef DEBOUNCE  #    define DEBOUNCE 5  #endif diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c index d12931fddb..20ccb46f1d 100644 --- a/quantum/debounce/sym_eager_pr.c +++ b/quantum/debounce/sym_eager_pr.c @@ -23,6 +23,12 @@ No further inputs are accepted until DEBOUNCE milliseconds have occurred.  #include "quantum.h"  #include <stdlib.h> +#ifdef PROTOCOL_CHIBIOS +#    if CH_CFG_USE_MEMCORE == FALSE +#        error ChibiOS is configured without a memory allocator. Your keyboard may have set `#define CH_CFG_USE_MEMCORE FALSE`, which is incompatible with this debounce algorithm. +#    endif +#endif +  #ifndef DEBOUNCE  #    define DEBOUNCE 5  #endif diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index 0608b469c0..a860b94979 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -37,6 +37,8 @@  #ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR  #    if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)  #        define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 2047 +#    elif defined(__AVR_AT90USB162__) +#        define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 511  #    else  #        define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023  #    endif diff --git a/quantum/encoder.c b/quantum/encoder.c index 7ca31afedc..2ed64c1e30 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -94,8 +94,9 @@ void encoder_init(void) {  #endif  } -static void encoder_update(int8_t index, uint8_t state) { -    uint8_t i = index; +static bool encoder_update(int8_t index, uint8_t state) { +    bool    changed = false; +    uint8_t i       = index;  #ifdef ENCODER_RESOLUTIONS      int8_t resolution = encoder_resolutions[i]; @@ -109,40 +110,53 @@ static void encoder_update(int8_t index, uint8_t state) {      encoder_pulses[i] += encoder_LUT[state & 0xF];      if (encoder_pulses[i] >= resolution) {          encoder_value[index]++; +        changed = true;          encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE);      }      if (encoder_pulses[i] <= -resolution) {  // direction is arbitrary here, but this clockwise          encoder_value[index]--; +        changed = true;          encoder_update_kb(index, ENCODER_CLOCKWISE);      }      encoder_pulses[i] %= resolution; +    return changed;  } -void encoder_read(void) { +bool encoder_read(void) { +    bool changed = false;      for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {          encoder_state[i] <<= 2;          encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); -        encoder_update(i, encoder_state[i]); +        changed |= encoder_update(i, encoder_state[i]);      } +    return changed;  }  #ifdef SPLIT_KEYBOARD +void last_encoder_activity_trigger(void); +  void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); }  void encoder_update_raw(uint8_t* slave_state) { +    bool changed = false;      for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {          uint8_t index = i + thatHand;          int8_t  delta = slave_state[i] - encoder_value[index];          while (delta > 0) {              delta--;              encoder_value[index]++; +            changed = true;              encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE);          }          while (delta < 0) {              delta++;              encoder_value[index]--; +            changed = true;              encoder_update_kb(index, ENCODER_CLOCKWISE);          }      } + +    // Update the last encoder input time -- handled external to encoder_read() when we're running a split +    if (changed) last_encoder_activity_trigger();  }  #endif diff --git a/quantum/encoder.h b/quantum/encoder.h index ec09a8cc47..db6f220da4 100644 --- a/quantum/encoder.h +++ b/quantum/encoder.h @@ -20,7 +20,7 @@  #include "quantum.h"  void encoder_init(void); -void encoder_read(void); +bool encoder_read(void);  void encoder_update_kb(int8_t index, bool clockwise);  void encoder_update_user(int8_t index, bool clockwise); diff --git a/quantum/keymap_extras/keymap_us_extended.h b/quantum/keymap_extras/keymap_us_extended.h new file mode 100644 index 0000000000..b2b3a734c9 --- /dev/null +++ b/quantum/keymap_extras/keymap_us_extended.h @@ -0,0 +1,227 @@ +/* Copyright 2020 + * + * 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 + +#include "keymap.h" + +// clang-format off + +/* + * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ + * │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │       │ + * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ + * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │  \  │ + * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ + * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │        │ + * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ + * │        │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │ + * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ + * │    │    │    │                        │    │    │    │    │ + * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ + */ +// Row 1 +#define US_GRV  KC_GRV  // ` +#define US_1    KC_1    // 1 +#define US_2    KC_2    // 2 +#define US_3    KC_3    // 3 +#define US_4    KC_4    // 4 +#define US_5    KC_5    // 5 +#define US_6    KC_6    // 6 +#define US_7    KC_7    // 7 +#define US_8    KC_8    // 8 +#define US_9    KC_9    // 9 +#define US_0    KC_0    // 0 +#define US_MINS KC_MINS // - +#define US_EQL  KC_EQL  // = +// Row 2 +#define US_Q    KC_Q    // Q +#define US_W    KC_W    // W +#define US_E    KC_E    // E +#define US_R    KC_R    // R +#define US_T    KC_T    // T +#define US_Y    KC_Y    // Y +#define US_U    KC_U    // U +#define US_I    KC_I    // I +#define US_O    KC_O    // O +#define US_P    KC_P    // P +#define US_LBRC KC_LBRC // [ +#define US_RBRC KC_RBRC // ] +#define US_BSLS KC_BSLS // (backslash) +// Row 3 +#define US_A    KC_A    // A +#define US_S    KC_S    // S +#define US_D    KC_D    // D +#define US_F    KC_F    // F +#define US_G    KC_G    // G +#define US_H    KC_H    // H +#define US_J    KC_J    // J +#define US_K    KC_K    // K +#define US_L    KC_L    // L +#define US_SCLN KC_SCLN // ; +#define US_QUOT KC_QUOT // ' +// Row 4 +#define US_Z    KC_Z    // Z +#define US_X    KC_X    // X +#define US_C    KC_C    // C +#define US_V    KC_V    // V +#define US_B    KC_B    // B +#define US_N    KC_N    // N +#define US_M    KC_M    // M +#define US_COMM KC_COMM // , +#define US_DOT  KC_DOT  // . +#define US_SLSH KC_SLSH // / + +/* Shifted symbols + * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ + * │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │       │ + * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ + * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │ + * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ + * │      │   │   │   │   │   │   │   │   │   │ : │ " │        │ + * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ + * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │ + * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ + * │    │    │    │                        │    │    │    │    │ + * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ + */ +// Row 1 +#define US_TILD S(US_GRV)  // ~ +#define US_EXLM S(US_1)    // ! +#define US_AT   S(US_2)    // @ +#define US_HASH S(US_3)    // # +#define US_DLR  S(US_4)    // $ +#define US_PERC S(US_5)    // % +#define US_CIRC S(US_6)    // ^ +#define US_AMPR S(US_7)    // & +#define US_ASTR S(US_8)    // * +#define US_LPRN S(US_9)    // ( +#define US_RPRN S(US_0)    // ) +#define US_UNDS S(US_MINS) // _ +#define US_PLUS S(US_EQL)  // + +// Row 2 +#define US_LCBR S(US_LBRC) // { +#define US_RCBR S(US_RBRC) // } +#define US_PIPE S(US_BSLS) // | +// Row 3 +#define US_COLN S(US_SCLN) // : +#define US_DQUO S(US_QUOT) // " +// Row 4 +#define US_LABK S(US_COMM) // < +#define US_RABK S(US_DOT)  // > +#define US_QUES S(US_SLSH) // ? + +/* AltGr symbols + * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ + * │ ` │ ¹ │ ² │ ³ │ ¤ │ € │ ^ │ ̛  │ ¾ │ ‘ │ ’ │ ¥ │ × │       │ + * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ + * │     │ Ä │ Å │ É │ ® │ Þ │ Ü │ Ú │ Í │ Ó │ Ö │ « │ » │  ¬  │ + * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ + * │      │ Á │ ß │ Ð │   │   │   │ Ï │ Œ │ Ø │ ¶ │ ' │        │ + * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ + * │        │ Æ │   │ © │   │   │ Ñ │ µ │ Ç │ ˙ │ ¿ │          │ + * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ + * │    │    │    │                        │    │    │    │    │ + * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ + */ +// Row 1 +#define US_DGRV ALGR(US_GRV)  // ` (dead) +#define US_SUP1 ALGR(US_1)    // ¹ +#define US_SUP2 ALGR(US_2)    // ² +#define US_SUP3 ALGR(US_3)    // ³ +#define US_CURR ALGR(US_4)    // ¤ +#define US_EURO ALGR(US_5)    // € +#define US_DCIR ALGR(US_6)    // ^ (dead) +#define US_HORN ALGR(US_7)    // ̛̛  (dead) +#define US_OGON ALGR(US_8)    // ˛ (dead) +#define US_LSQU ALGR(US_9)    // ‘ +#define US_RSQU ALGR(US_0)    // ’ +#define US_YEN  ALGR(US_MINS) // ¥ +#define US_MUL  ALGR(US_EQL)  // × +// Row 2 +#define US_ADIA ALGR(US_Q)    // Ä +#define US_ARNG ALGR(US_W)    // Å +#define US_EACU ALGR(US_E)    // É +#define US_EDIA ALGR(US_R)    // Ë +#define US_THRN ALGR(US_T)    // Þ +#define US_UDIA ALGR(US_Y)    // Ü +#define US_UACU ALGR(US_U)    // Ú +#define US_IACU ALGR(US_I)    // Í +#define US_OACU ALGR(US_O)    // Ó +#define US_ODIA ALGR(US_P)    // Ö +#define US_LDAQ ALGR(US_LBRC) // « +#define US_RDAQ ALGR(US_RBRC) // » +#define US_NOT  ALGR(US_BSLS) // ¬ +// Row 3 +#define US_AACU ALGR(US_A)    // Á +#define US_SS   ALGR(US_S)    // ß +#define US_ETH  ALGR(US_D)    // Ð +#define US_IDIA ALGR(US_J)    // Ï +#define US_OE   ALGR(US_K)    // Œ +#define US_OSTR ALGR(US_L)    // Ø +#define US_PILC ALGR(US_SCLN) // ¶ +#define US_ACUT ALGR(US_QUOT) // ´ (dead) +// Row 4 +#define US_AE   ALGR(US_Z)    // Æ +#define US_OE_2 ALGR(US_X)    // Œ +#define US_COPY ALGR(US_C)    // © +#define US_REGD ALGR(US_V)    // ® +#define US_NTIL ALGR(US_N)    // Ñ +#define US_MICR ALGR(US_M)    // µ +#define US_CCED ALGR(US_COMM) // Ç +#define US_DOTA ALGR(US_DOT)  // ˙ (dead) +#define US_IQUE ALGR(US_SLSH) // ¿ + +/* Shift+AltGr symbols + * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ + * │ ~ │ ¡ │ ˝ │ ¯ │ £ │ ¸ │ ¼ │ ½ │ ¾ │ ˘ │ ° │  ̣ │ ÷ │       │ + * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ + * │     │   │   │   │   │   │   │   │   │   │   │ “ │ ” │  ¦  │ + * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ + * │      │   │ § │   │   │   │   │   │   │   │ ° │ " │        │ + * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ + * │        │   │   │ ¢ │   │   │   │   │   │ ˇ │  ̉ │          │ + * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ + * │    │    │    │                        │    │    │    │    │ + * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ + */ +// Row 1 +#define US_DTIL S(ALGR(US_GRV))  // ~ (dead) +#define US_IEXL S(ALGR(US_1))    // ¡ +#define US_DACU S(ALGR(US_2))    // ˝ (dead) +#define US_MACR S(ALGR(US_3))    // ¯ (dead) +#define US_PND  S(ALGR(US_4))    // £ +#define US_CEDL S(ALGR(US_5))    // ¸ (dead) +#define US_QRTR S(ALGR(US_6))    // ¼ +#define US_HALF S(ALGR(US_7))    // ½ +#define US_TQTR S(ALGR(US_8))    // ¾ +#define US_BREV S(ALGR(US_9))    // ˘ (dead) +#define US_RNGA S(ALGR(US_0))    // ° (dead) +#define US_DOTB S(ALGR(US_MINS)) // ̣  (dead) +#define US_DIV  S(ALGR(US_EQL))  // ÷ +// Row 2 +#define US_LDQU S(ALGR(US_LBRC)) // “ +#define US_RDQU S(ALGR(US_LBRC)) // ” +#define US_BRKP S(ALGR(US_BSLS)) // ¦ +// Row 3 +#define US_SECT S(ALGR(US_S))    // § +#define US_DEG  S(ALGR(US_SCLN)) // ° +#define US_DIAE S(ALGR(US_QUOT)) // ¨ (dead) +// Row 4 +#define US_CENT S(ALGR(US_C))    // ¢ +#define US_CARN S(ALGR(US_DOT))  // ˇ (dead) +#define US_HOKA S(ALGR(US_SLSH)) //  ̉ (dead) + diff --git a/quantum/keymap_extras/keymap_us_international.h b/quantum/keymap_extras/keymap_us_international.h index a3bc465971..49afcc4fb2 100644 --- a/quantum/keymap_extras/keymap_us_international.h +++ b/quantum/keymap_extras/keymap_us_international.h @@ -26,7 +26,7 @@   * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤   * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │  \  │   * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ - * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │        │ + * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ´ │        │   * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤   * │        │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │   * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ @@ -34,7 +34,7 @@   * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘   */  // Row 1 -#define US_GRV  KC_GRV  // ` (dead) +#define US_DGRV KC_GRV  // ` (dead)  #define US_1    KC_1    // 1  #define US_2    KC_2    // 2  #define US_3    KC_3    // 3 @@ -72,7 +72,7 @@  #define US_K    KC_K    // K  #define US_L    KC_L    // L  #define US_SCLN KC_SCLN // ; -#define US_QUOT KC_QUOT // ' (dead) +#define US_ACUT KC_QUOT // ´ (dead)  // Row 4  #define US_Z    KC_Z    // Z  #define US_X    KC_X    // X @@ -91,7 +91,7 @@   * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤   * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │   * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ - * │      │   │   │   │   │   │   │   │   │   │ : │ " │        │ + * │      │   │   │   │   │   │   │   │   │   │ : │ ¨ │        │   * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤   * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │   * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ @@ -99,13 +99,13 @@   * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘   */  // Row 1 -#define US_TILD S(US_GRV)  // ~ (dead) +#define US_DTIL S(US_DGRV) // ~ (dead)  #define US_EXLM S(US_1)    // ! -#define US_AT   S(US_2)    // " +#define US_AT   S(US_2)    // @  #define US_HASH S(US_3)    // #  #define US_DLR  S(US_4)    // $  #define US_PERC S(US_5)    // % -#define US_CIRC S(US_6)    // ^ +#define US_DCIR S(US_6)    // ^ (dead)  #define US_AMPR S(US_7)    // &  #define US_ASTR S(US_8)    // *  #define US_LPRN S(US_9)    // ( @@ -118,7 +118,7 @@  #define US_PIPE S(US_BSLS) // |  // Row 3  #define US_COLN S(US_SCLN) // : -#define US_DQUO S(US_QUOT) // " (dead) +#define US_DIAE S(US_ACUT) // ¨ (dead)  // Row 4  #define US_LABK S(US_COMM) // <  #define US_RABK S(US_DOT)  // > @@ -170,7 +170,7 @@  #define US_ETH  ALGR(US_D)    // Ð  #define US_OSTR ALGR(US_L)    // Ø  #define US_PILC ALGR(US_SCLN) // ¶ -#define US_ACUT ALGR(US_QUOT) // ´ +#define US_NDAC ALGR(US_ACUT) // ´  // Row 4  #define US_AE   ALGR(US_Z)    // Æ  #define US_COPY ALGR(US_C)    // © @@ -201,6 +201,6 @@  // Row 3  #define US_SECT S(ALGR(US_S))    // §  #define US_DEG  S(ALGR(US_SCLN)) // ° -#define US_DIAE S(ALGR(US_QUOT)) // ¨ +#define US_NDDR S(ALGR(US_ACUT)) // ¨  // Row 4  #define US_CENT S(ALGR(US_C))    // ¢ diff --git a/quantum/keymap_extras/keymap_us_international_linux.h b/quantum/keymap_extras/keymap_us_international_linux.h new file mode 100644 index 0000000000..2c3e230393 --- /dev/null +++ b/quantum/keymap_extras/keymap_us_international_linux.h @@ -0,0 +1,224 @@ +/* Copyright 2020 + * + * 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 + +#include "keymap.h" + +// clang-format off + +/* + * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ + * │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │       │ + * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ + * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │  \  │ + * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ + * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ´ │        │ + * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ + * │        │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │ + * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ + * │    │    │    │                        │    │    │    │    │ + * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ + */ +// Row 1 +#define US_DGRV KC_GRV  // ` (dead) +#define US_1    KC_1    // 1 +#define US_2    KC_2    // 2 +#define US_3    KC_3    // 3 +#define US_4    KC_4    // 4 +#define US_5    KC_5    // 5 +#define US_6    KC_6    // 6 +#define US_7    KC_7    // 7 +#define US_8    KC_8    // 8 +#define US_9    KC_9    // 9 +#define US_0    KC_0    // 0 +#define US_MINS KC_MINS // - +#define US_EQL  KC_EQL  // = +// Row 2 +#define US_Q    KC_Q    // Q +#define US_W    KC_W    // W +#define US_E    KC_E    // E +#define US_R    KC_R    // R +#define US_T    KC_T    // T +#define US_Y    KC_Y    // Y +#define US_U    KC_U    // U +#define US_I    KC_I    // I +#define US_O    KC_O    // O +#define US_P    KC_P    // P +#define US_LBRC KC_LBRC // [ +#define US_RBRC KC_RBRC // ] +#define US_BSLS KC_BSLS // (backslash) +// Row 3 +#define US_A    KC_A    // A +#define US_S    KC_S    // S +#define US_D    KC_D    // D +#define US_F    KC_F    // F +#define US_G    KC_G    // G +#define US_H    KC_H    // H +#define US_J    KC_J    // J +#define US_K    KC_K    // K +#define US_L    KC_L    // L +#define US_SCLN KC_SCLN // ; +#define US_ACUT KC_QUOT // ´ (dead) +// Row 4 +#define US_Z    KC_Z    // Z +#define US_X    KC_X    // X +#define US_C    KC_C    // C +#define US_V    KC_V    // V +#define US_B    KC_B    // B +#define US_N    KC_N    // N +#define US_M    KC_M    // M +#define US_COMM KC_COMM // , +#define US_DOT  KC_DOT  // . +#define US_SLSH KC_SLSH // / + +/* Shifted symbols + * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ + * │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │       │ + * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ + * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │ + * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ + * │      │   │   │   │   │   │   │   │   │   │ : │ ¨ │        │ + * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ + * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │ + * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ + * │    │    │    │                        │    │    │    │    │ + * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ + */ +// Row 1 +#define US_DTIL S(US_DGRV) // ~ (dead) +#define US_EXLM S(US_1)    // ! +#define US_AT   S(US_2)    // @ +#define US_HASH S(US_3)    // # +#define US_DLR  S(US_4)    // $ +#define US_PERC S(US_5)    // % +#define US_DCIR S(US_6)    // ^ (dead) +#define US_AMPR S(US_7)    // & +#define US_ASTR S(US_8)    // * +#define US_LPRN S(US_9)    // ( +#define US_RPRN S(US_0)    // ) +#define US_UNDS S(US_MINS) // _ +#define US_PLUS S(US_EQL)  // + +// Row 2 +#define US_LCBR S(US_LBRC) // { +#define US_RCBR S(US_RBRC) // } +#define US_PIPE S(US_BSLS) // | +// Row 3 +#define US_COLN S(US_SCLN) // : +#define US_DIAE S(US_ACUT) // ¨ (dead) +// Row 4 +#define US_LABK S(US_COMM) // < +#define US_RABK S(US_DOT)  // > +#define US_QUES S(US_SLSH) // ? + +/* AltGr symbols + * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ + * │ ` │ ¡ │ ² │ ³ │ ¤ │ € │ ¼ │ ½ │ ¾ │ ‘ │ ’ │ ¥ │ × │       │ + * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ + * │     │ Ä │ Å │ É │ ® │ Þ │ Ü │ Ú │ Í │ Ó │ Ö │ « │ » │  ¬  │ + * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ + * │      │ Á │ ß │ Ð │   │   │   │   │ Œ │ Ø │ ¶ │ ' │        │ + * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ + * │        │ Æ │   │ © │   │   │ Ñ │ µ │ Ç │ ˙ │ ¿ │          │ + * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ + * │    │    │    │                        │    │    │    │    │ + * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ + */ + +// Row 1 +#define US_GRV  ALGR(US_DGRV) // ` +#define US_IEXL ALGR(US_1)    // ¡ +#define US_SUP2 ALGR(US_2)    // ² +#define US_SUP3 ALGR(US_3)    // ³ +#define US_CURR ALGR(US_4)    // ¤ +#define US_EURO ALGR(US_5)    // € +#define US_QRTR ALGR(US_6)    // ¼ +#define US_HALF ALGR(US_7)    // ½ +#define US_TQTR ALGR(US_8)    // ¾ +#define US_LSQU ALGR(US_9)    // ‘ +#define US_RSQU ALGR(US_0)    // ’ +#define US_YEN  ALGR(US_MINS) // ¥ +#define US_MUL  ALGR(US_EQL)  // × +// Row 2 +#define US_ADIA ALGR(US_Q)    // Ä +#define US_ARNG ALGR(US_W)    // Å +#define US_EACU ALGR(US_E)    // É +#define US_REGD ALGR(US_R)    // ® +#define US_THRN ALGR(US_T)    // Þ +#define US_UDIA ALGR(US_Y)    // Ü +#define US_UACU ALGR(US_U)    // Ú +#define US_IACU ALGR(US_I)    // Í +#define US_OACU ALGR(US_O)    // Ó +#define US_ODIA ALGR(US_P)    // Ö +#define US_LDAQ ALGR(US_LBRC) // « +#define US_RDAQ ALGR(US_RBRC) // » +#define US_NOT  ALGR(US_BSLS) // ¬ +// Row 3 +#define US_AACU ALGR(US_A)    // Á +#define US_SS   ALGR(US_S)    // ß +#define US_ETH  ALGR(US_D)    // Ð +#define US_OE   ALGR(US_K)    // Œ +#define US_OSTR ALGR(US_L)    // Ø +#define US_PILC ALGR(US_SCLN) // ¶ +#define US_QUOT ALGR(US_ACUT) // ' +// Row 4 +#define US_AE   ALGR(US_Z)    // Æ +#define US_COPY ALGR(US_C)    // © +#define US_NTIL ALGR(US_N)    // Ñ +#define US_MICR ALGR(US_M)    // µ +#define US_CCED ALGR(US_COMM) // Ç +#define US_DOTA ALGR(US_DOT)  // ˙ (dead) +#define US_IQUE ALGR(US_SLSH) // ¿ + +/* Shift+AltGr symbols + * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐ + * │ ~ │ ¹ │ ˝ │ ¯ │ £ │ ¸ │ ^ │ ̛  │ ˛ │ ˘ │ ° │  ̣ │ ÷ │       │ + * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ + * │     │   │   │   │   │   │   │   │   │   │   │ “ │ ” │  ¦  │ + * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ + * │      │   │ § │   │   │   │   │   │   │   │ ° │ " │        │ + * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ + * │        │   │   │ ¢ │   │   │   │   │   │ ˇ │  ̉ │          │ + * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ + * │    │    │    │                        │    │    │    │    │ + * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ + */ +// Row 1 +#define US_TILD S(ALGR(US_DGRV)) // ~ +#define US_SUP1 S(ALGR(US_1))    // ¹ +#define US_DACU S(ALGR(US_2))    // ˝ (dead) +#define US_MACR S(ALGR(US_3))    // ¯ (dead) +#define US_PND  S(ALGR(US_4))    // £ +#define US_CEDL S(ALGR(US_5))    // ¸ (dead) +#define US_CIRC S(ALGR(US_6))    // ^ +#define US_HORN S(ALGR(US_7))    //  ̛  (dead) +#define US_OGON S(ALGR(US_8))    // ˛ (dead) +#define US_BREV S(ALGR(US_9))    // ˘ (dead) +#define US_RNGA S(ALGR(US_0))    // ° (dead) +#define US_DOTB S(ALGR(US_MINS)) //  ̣ (dead) +#define US_DIV  S(ALGR(US_EQL))  // ÷ +// Row 2 +#define US_LDQU S(ALGR(US_LBRC)) // “ +#define US_RDQU S(ALGR(US_LBRC)) // ” +#define US_BRKP S(ALGR(US_BSLS)) // ¦ +// Row 3 +#define US_SECT S(ALGR(US_S))    // § +#define US_DEG  S(ALGR(US_SCLN)) // ° +#define US_DQUO S(ALGR(US_ACUT)) // " +// Row 4 +#define US_CENT S(ALGR(US_C))    // ¢ +#define US_CARN S(ALGR(US_DOT))  // ˇ (dead) +#define US_HOKA S(ALGR(US_SLSH)) //  ̉ (dead) diff --git a/quantum/keymap_extras/sendstring_us_international.h b/quantum/keymap_extras/sendstring_us_international.h new file mode 100644 index 0000000000..53a5891fb1 --- /dev/null +++ b/quantum/keymap_extras/sendstring_us_international.h @@ -0,0 +1,100 @@ +/* Copyright 2019 Rys Sommefeldt + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +// Sendstring lookup tables for UK layouts + +#pragma once + +#include "keymap_us_international.h" +#include "quantum.h" + +// clang-format off + +const uint8_t ascii_to_shift_lut[16] PROGMEM = { +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + +    KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 0), +    KCLUT_ENTRY(1, 1, 1, 1, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 1, 0, 1, 0, 1, 1), +    KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), +    KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), +    KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), +    KCLUT_ENTRY(1, 1, 1, 0, 0, 0, 1, 1), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 1, 1, 1, 1, 0), +}; + +__attribute__((weak)) const uint8_t ascii_to_dead_lut[16] PROGMEM = { +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + +    KCLUT_ENTRY(0, 0, 1, 0, 0, 0, 0, 1), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 1, 0), +    KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 1, 0), +}; + +const uint8_t ascii_to_keycode_lut[128] PROGMEM = { +    // NUL   SOH      STX      ETX      EOT      ENQ      ACK      BEL +    XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, +    // BS    TAB      LF       VT       FF       CR       SO       SI +    KC_BSPC, KC_TAB,  KC_ENT,  XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, +    // DLE   DC1      DC2      DC3      DC4      NAK      SYN      ETB +    XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, +    // CAN   EM       SUB      ESC      FS       GS       RS       US +    XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC,  XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + +    //       !        "        #        $        %        &        ' +    KC_SPC,  US_1,    US_ACUT, US_3,    US_4,    US_5,    US_7,    US_ACUT, +    // (     )        *        +        ,        -        .        / +    US_9,    US_0,    US_8,    US_EQL,  US_COMM, US_MINS, US_DOT,  US_SLSH, +    // 0     1        2        3        4        5        6        7 +    US_0,    US_1,    US_2,    US_3,    US_4,    US_5,    US_6,    US_7, +    // 8     9        :        ;        <        =        >        ? +    US_8,    US_9,    US_SCLN, US_SCLN, US_COMM, US_EQL,  US_DOT,  US_SLSH, +    // @     A        B        C        D        E        F        G +    US_2,    US_A,    US_B,    US_C,    US_D,    US_E,    US_F,    US_G, +    // H     I        J        K        L        M        N        O +    US_H,    US_I,    US_J,    US_K,    US_L,    US_M,    US_N,    US_O, +    // P     Q        R        S        T        U        V        W +    US_P,    US_Q,    US_R,    US_S,    US_T,    US_U,    US_V,    US_W, +    // X     Y        Z        [        \        ]        ^        _ +    US_X,    US_Y,    US_Z,    US_LBRC, US_BSLS, US_RBRC, US_6,    US_MINS, +    // `     a        b        c        d        e        f        g +    US_DGRV, US_A,    US_B,    US_C,    US_D,    US_E,    US_F,    US_G, +    // h     i        j        k        l        m        n        o +    US_H,    US_I,    US_J,    US_K,    US_L,    US_M,    US_N,    US_O, +    // p     q        r        s        t        u        v        w +    US_P,    US_Q,    US_R,    US_S,    US_T,    US_U,    US_V,    US_W, +    // x     y        z        {        |        }        ~        DEL +    US_X,    US_Y,    US_Z,    US_LBRC, US_BSLS, US_RBRC, US_DGRV, KC_DEL +}; diff --git a/quantum/matrix.c b/quantum/matrix.c index 9083ff3861..c027b7bf27 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -101,9 +101,9 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)      // Start with a clear matrix row      matrix_row_t current_row_value = 0; -    // Select row and wait for row selecton to stabilize +    // Select row      select_row(current_row); -    matrix_io_delay(); +    matrix_output_select_delay();      // For each col...      for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { @@ -116,6 +116,9 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)      // Unselect row      unselect_row(current_row); +    if (current_row + 1 < MATRIX_ROWS) { +        matrix_output_unselect_delay();  // wait for row signal to go HIGH +    }      // If the row has changed, store the row and return the changed flag.      if (current_matrix[current_row] != current_row_value) { @@ -147,9 +150,9 @@ static void init_pins(void) {  static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {      bool matrix_changed = false; -    // Select col and wait for col selecton to stabilize +    // Select col      select_col(current_col); -    matrix_io_delay(); +    matrix_output_select_delay();      // For each row...      for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { @@ -175,6 +178,9 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)      // Unselect col      unselect_col(current_col); +    if (current_col + 1 < MATRIX_COLS) { +        matrix_output_unselect_delay();  // wait for col signal to go HIGH +    }      return matrix_changed;  } diff --git a/quantum/matrix_common.c b/quantum/matrix_common.c index 15f1e0e82e..efbad6a5fd 100644 --- a/quantum/matrix_common.c +++ b/quantum/matrix_common.c @@ -1,3 +1,4 @@ +#include "quantum.h"  #include "matrix.h"  #include "debounce.h"  #include "wait.h" @@ -68,7 +69,7 @@ void matrix_print(void) {      print_matrix_header();      for (uint8_t row = 0; row < MATRIX_ROWS; row++) { -        phex(row); +        print_hex8(row);          print(": ");          print_matrix_row(row);          print("\n"); @@ -83,8 +84,12 @@ uint8_t matrix_key_count(void) {      return count;  } +/* `matrix_io_delay ()` exists for backwards compatibility. From now on, use matrix_output_unselect_delay(). */  __attribute__((weak)) void matrix_io_delay(void) { wait_us(MATRIX_IO_DELAY); } +__attribute__((weak)) void matrix_output_select_delay(void) { waitInputPinDelay(); } +__attribute__((weak)) void matrix_output_unselect_delay(void) { matrix_io_delay(); } +  // CUSTOM MATRIX 'LITE'  __attribute__((weak)) void matrix_init_custom(void) {} diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk index 6b11eb4987..81c467c656 100644 --- a/quantum/mcu_selection.mk +++ b/quantum/mcu_selection.mk @@ -279,7 +279,73 @@ ifneq ($(findstring STM32F411, $(MCU)),)    DFU_SUFFIX_ARGS ?= -v 0483 -p DF11  endif -ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287)) +ifneq ($(findstring STM32G431, $(MCU)),) +  # Cortex version +  MCU = cortex-m4 + +  # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +  ARMV = 7 + +  ## chip/board settings +  # - the next two should match the directories in +  #   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +  MCU_FAMILY = STM32 +  MCU_SERIES = STM32G4xx + +  # Linker script to use +  # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ +  #   or <keyboard_dir>/ld/ +  MCU_LDSCRIPT ?= STM32G431xB + +  # Startup code to use +  #  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ +  MCU_STARTUP ?= stm32g4xx + +  # Board: it should exist either in <chibios>/os/hal/boards/, +  # <keyboard_dir>/boards/, or drivers/boards/ +  BOARD ?= GENERIC_STM32_G431XB + +  USE_FPU ?= yes + +  # Options to pass to dfu-util when flashing +  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave +  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 +endif + +ifneq ($(findstring STM32G474, $(MCU)),) +  # Cortex version +  MCU = cortex-m4 + +  # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +  ARMV = 7 + +  ## chip/board settings +  # - the next two should match the directories in +  #   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +  MCU_FAMILY = STM32 +  MCU_SERIES = STM32G4xx + +  # Linker script to use +  # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/ +  #   or <keyboard_dir>/ld/ +  MCU_LDSCRIPT ?= STM32G474xE + +  # Startup code to use +  #  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/ +  MCU_STARTUP ?= stm32g4xx + +  # Board: it should exist either in <chibios>/os/hal/boards/, +  # <keyboard_dir>/boards/, or drivers/boards/ +  BOARD ?= GENERIC_STM32_G474XE + +  USE_FPU ?= yes + +  # Options to pass to dfu-util when flashing +  DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave +  DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 +endif + +ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287))    PROTOCOL = LUFA    # Processor frequency. @@ -317,7 +383,7 @@ ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 a    ifeq (,$(filter $(NO_INTERRUPT_CONTROL_ENDPOINT),yes))      OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT    endif -  ifneq (,$(filter $(MCU),atmega16u2 atmega32u2)) +  ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2))      NO_I2C = yes    endif  endif diff --git a/quantum/mousekey.c b/quantum/mousekey.c new file mode 100644 index 0000000000..63e74baa93 --- /dev/null +++ b/quantum/mousekey.c @@ -0,0 +1,488 @@ +/* + * Copyright 2011 Jun Wako <wakojun@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include "keycode.h" +#include "host.h" +#include "timer.h" +#include "print.h" +#include "debug.h" +#include "mousekey.h" + +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; +} + +static report_mouse_t mouse_report = {0}; +static void           mousekey_debug(void); +static uint8_t        mousekey_accel        = 0; +static uint8_t        mousekey_repeat       = 0; +static uint8_t        mousekey_wheel_repeat = 0; +#ifdef MK_KINETIC_SPEED +static uint16_t mouse_timer = 0; +#endif + +#ifndef MK_3_SPEED + +static uint16_t last_timer_c = 0; +static uint16_t last_timer_w = 0; + +/* + * Mouse keys acceleration algorithm + *  http://en.wikipedia.org/wiki/Mouse_keys + * + *  speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000) + */ +/* milliseconds between the initial key press and first repeated motion event (0-2550) */ +uint8_t mk_delay = MOUSEKEY_DELAY / 10; +/* milliseconds between repeated motion events (0-255) */ +uint8_t mk_interval = MOUSEKEY_INTERVAL; +/* steady speed (in action_delta units) applied each event (0-255) */ +uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED; +/* number of events (count) accelerating to steady speed (0-255) */ +uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX; +/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */ +// int8_t mk_curve = 0; +/* wheel params */ +/* milliseconds between the initial key press and first repeated motion event (0-2550) */ +uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10; +/* milliseconds between repeated motion events (0-255) */ +uint8_t mk_wheel_interval    = MOUSEKEY_WHEEL_INTERVAL; +uint8_t mk_wheel_max_speed   = MOUSEKEY_WHEEL_MAX_SPEED; +uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; + +#    ifndef MK_COMBINED + +static uint8_t move_unit(void) { +    uint16_t unit; +    if (mousekey_accel & (1 << 0)) { +        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4; +    } else if (mousekey_accel & (1 << 1)) { +        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2; +    } else if (mousekey_accel & (1 << 2)) { +        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed); +    } else if (mousekey_repeat == 0) { +        unit = MOUSEKEY_MOVE_DELTA; +    } else if (mousekey_repeat >= mk_time_to_max) { +        unit = MOUSEKEY_MOVE_DELTA * mk_max_speed; +    } else { +        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max; +    } +    return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); +} + +static uint8_t wheel_unit(void) { +    uint16_t unit; +    if (mousekey_accel & (1 << 0)) { +        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4; +    } else if (mousekey_accel & (1 << 1)) { +        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2; +    } else if (mousekey_accel & (1 << 2)) { +        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed); +    } else if (mousekey_wheel_repeat == 0) { +        unit = MOUSEKEY_WHEEL_DELTA; +    } else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) { +        unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed; +    } else { +        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_wheel_repeat) / mk_wheel_time_to_max; +    } +    return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); +} + +#    else /* #ifndef MK_COMBINED */ +#        ifndef MK_KINETIC_SPEED + +/* + * Kinetic movement  acceleration algorithm + * + *  current speed = I + A * T/50 + A * 0.5 * T^2 | maximum B + * + * T: time since the mouse movement started + * E: mouse events per second (set through MOUSEKEY_INTERVAL, UHK sends 250, the + *    pro micro on my Signum 3.0 sends only 125!) + * I: initial speed at time 0 + * A: acceleration + * B: base mouse travel speed + */ +const uint16_t mk_accelerated_speed = MOUSEKEY_ACCELERATED_SPEED; +const uint16_t mk_base_speed        = MOUSEKEY_BASE_SPEED; +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; + +    if (mousekey_accel & ((1 << 0) | (1 << 2))) { +        speed = mousekey_accel & (1 << 2) ? mk_accelerated_speed : mk_decelerated_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; +    } + +    /* convert speed to USB mouse speed 1 to 127 */ +    speed = (uint8_t)(speed / (1000.0f / mk_interval)); +    speed = speed < 1 ? 1 : speed; + +    return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed; +} + +float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; + +static uint8_t wheel_unit(void) { +    float 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; +    } else if (mousekey_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; +        } +        speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed; +    } + +    mk_wheel_interval = 1000.0f / speed; + +    return 1; +} + +#        else /* #ifndef MK_KINETIC_SPEED */ + +static uint8_t move_unit(void) { +    uint16_t unit; +    if (mousekey_accel & (1 << 0)) { +        unit = 1; +    } else if (mousekey_accel & (1 << 1)) { +        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2; +    } else if (mousekey_accel & (1 << 2)) { +        unit = MOUSEKEY_MOVE_MAX; +    } else if (mousekey_repeat == 0) { +        unit = MOUSEKEY_MOVE_DELTA; +    } else if (mousekey_repeat >= mk_time_to_max) { +        unit = MOUSEKEY_MOVE_DELTA * mk_max_speed; +    } else { +        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max; +    } +    return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); +} + +static uint8_t wheel_unit(void) { +    uint16_t unit; +    if (mousekey_accel & (1 << 0)) { +        unit = 1; +    } else if (mousekey_accel & (1 << 1)) { +        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2; +    } else if (mousekey_accel & (1 << 2)) { +        unit = MOUSEKEY_WHEEL_MAX; +    } else if (mousekey_repeat == 0) { +        unit = MOUSEKEY_WHEEL_DELTA; +    } else if (mousekey_repeat >= mk_wheel_time_to_max) { +        unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed; +    } else { +        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max; +    } +    return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); +} + +#        endif /* #ifndef MK_KINETIC_SPEED */ +#    endif     /* #ifndef MK_COMBINED */ + +void mousekey_task(void) { +    // report cursor and scroll movement independently +    report_mouse_t const tmpmr = mouse_report; + +    mouse_report.x = 0; +    mouse_report.y = 0; +    mouse_report.v = 0; +    mouse_report.h = 0; + +    if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) { +        if (mousekey_repeat != UINT8_MAX) mousekey_repeat++; +        if (tmpmr.x != 0) mouse_report.x = move_unit() * ((tmpmr.x > 0) ? 1 : -1); +        if (tmpmr.y != 0) mouse_report.y = move_unit() * ((tmpmr.y > 0) ? 1 : -1); + +        /* diagonal move [1/sqrt(2)] */ +        if (mouse_report.x && mouse_report.y) { +            mouse_report.x = times_inv_sqrt2(mouse_report.x); +            if (mouse_report.x == 0) { +                mouse_report.x = 1; +            } +            mouse_report.y = times_inv_sqrt2(mouse_report.y); +            if (mouse_report.y == 0) { +                mouse_report.y = 1; +            } +        } +    } +    if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) { +        if (mousekey_wheel_repeat != UINT8_MAX) mousekey_wheel_repeat++; +        if (tmpmr.v != 0) mouse_report.v = wheel_unit() * ((tmpmr.v > 0) ? 1 : -1); +        if (tmpmr.h != 0) mouse_report.h = wheel_unit() * ((tmpmr.h > 0) ? 1 : -1); + +        /* diagonal move [1/sqrt(2)] */ +        if (mouse_report.v && mouse_report.h) { +            mouse_report.v = times_inv_sqrt2(mouse_report.v); +            if (mouse_report.v == 0) { +                mouse_report.v = 1; +            } +            mouse_report.h = times_inv_sqrt2(mouse_report.h); +            if (mouse_report.h == 0) { +                mouse_report.h = 1; +            } +        } +    } + +    if (mouse_report.x || mouse_report.y || mouse_report.v || mouse_report.h) mousekey_send(); +    mouse_report = tmpmr; +} + +void mousekey_on(uint8_t code) { +#    ifdef MK_KINETIC_SPEED +    if (mouse_timer == 0) { +        mouse_timer = timer_read(); +    } +#    endif /* #ifdef MK_KINETIC_SPEED */ + +    if (code == KC_MS_UP) +        mouse_report.y = move_unit() * -1; +    else if (code == KC_MS_DOWN) +        mouse_report.y = move_unit(); +    else if (code == KC_MS_LEFT) +        mouse_report.x = move_unit() * -1; +    else if (code == KC_MS_RIGHT) +        mouse_report.x = move_unit(); +    else if (code == KC_MS_WH_UP) +        mouse_report.v = wheel_unit(); +    else if (code == KC_MS_WH_DOWN) +        mouse_report.v = wheel_unit() * -1; +    else if (code == KC_MS_WH_LEFT) +        mouse_report.h = wheel_unit() * -1; +    else if (code == KC_MS_WH_RIGHT) +        mouse_report.h = wheel_unit(); +    else if (IS_MOUSEKEY_BUTTON(code)) +        mouse_report.buttons |= 1 << (code - KC_MS_BTN1); +    else if (code == KC_MS_ACCEL0) +        mousekey_accel |= (1 << 0); +    else if (code == KC_MS_ACCEL1) +        mousekey_accel |= (1 << 1); +    else if (code == KC_MS_ACCEL2) +        mousekey_accel |= (1 << 2); +} + +void mousekey_off(uint8_t code) { +    if (code == KC_MS_UP && mouse_report.y < 0) +        mouse_report.y = 0; +    else if (code == KC_MS_DOWN && mouse_report.y > 0) +        mouse_report.y = 0; +    else if (code == KC_MS_LEFT && mouse_report.x < 0) +        mouse_report.x = 0; +    else if (code == KC_MS_RIGHT && mouse_report.x > 0) +        mouse_report.x = 0; +    else if (code == KC_MS_WH_UP && mouse_report.v > 0) +        mouse_report.v = 0; +    else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) +        mouse_report.v = 0; +    else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) +        mouse_report.h = 0; +    else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) +        mouse_report.h = 0; +    else if (IS_MOUSEKEY_BUTTON(code)) +        mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1)); +    else if (code == KC_MS_ACCEL0) +        mousekey_accel &= ~(1 << 0); +    else if (code == KC_MS_ACCEL1) +        mousekey_accel &= ~(1 << 1); +    else if (code == KC_MS_ACCEL2) +        mousekey_accel &= ~(1 << 2); +    if (mouse_report.x == 0 && mouse_report.y == 0) { +        mousekey_repeat = 0; +#    ifdef MK_KINETIC_SPEED +        mouse_timer = 0; +#    endif /* #ifdef MK_KINETIC_SPEED */ +    } +    if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0; +} + +#else /* #ifndef MK_3_SPEED */ + +enum { mkspd_unmod, mkspd_0, mkspd_1, mkspd_2, mkspd_COUNT }; +#    ifndef MK_MOMENTARY_ACCEL +static uint8_t  mk_speed                 = mkspd_1; +#    else +static uint8_t mk_speed      = mkspd_unmod; +static uint8_t mkspd_DEFAULT = mkspd_unmod; +#    endif +static uint16_t last_timer_c             = 0; +static uint16_t last_timer_w             = 0; +uint16_t        c_offsets[mkspd_COUNT]   = {MK_C_OFFSET_UNMOD, MK_C_OFFSET_0, MK_C_OFFSET_1, MK_C_OFFSET_2}; +uint16_t        c_intervals[mkspd_COUNT] = {MK_C_INTERVAL_UNMOD, MK_C_INTERVAL_0, MK_C_INTERVAL_1, MK_C_INTERVAL_2}; +uint16_t        w_offsets[mkspd_COUNT]   = {MK_W_OFFSET_UNMOD, MK_W_OFFSET_0, MK_W_OFFSET_1, MK_W_OFFSET_2}; +uint16_t        w_intervals[mkspd_COUNT] = {MK_W_INTERVAL_UNMOD, MK_W_INTERVAL_0, MK_W_INTERVAL_1, MK_W_INTERVAL_2}; + +void mousekey_task(void) { +    // report cursor and scroll movement independently +    report_mouse_t const tmpmr = mouse_report; +    mouse_report.x             = 0; +    mouse_report.y             = 0; +    mouse_report.v             = 0; +    mouse_report.h             = 0; + +    if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > c_intervals[mk_speed]) { +        mouse_report.x = tmpmr.x; +        mouse_report.y = tmpmr.y; +    } +    if ((tmpmr.h || tmpmr.v) && timer_elapsed(last_timer_w) > w_intervals[mk_speed]) { +        mouse_report.v = tmpmr.v; +        mouse_report.h = tmpmr.h; +    } + +    if (mouse_report.x || mouse_report.y || mouse_report.v || mouse_report.h) mousekey_send(); +    mouse_report = tmpmr; +} + +void adjust_speed(void) { +    uint16_t const c_offset = c_offsets[mk_speed]; +    uint16_t const w_offset = w_offsets[mk_speed]; +    if (mouse_report.x > 0) mouse_report.x = c_offset; +    if (mouse_report.x < 0) mouse_report.x = c_offset * -1; +    if (mouse_report.y > 0) mouse_report.y = c_offset; +    if (mouse_report.y < 0) mouse_report.y = c_offset * -1; +    if (mouse_report.h > 0) mouse_report.h = w_offset; +    if (mouse_report.h < 0) mouse_report.h = w_offset * -1; +    if (mouse_report.v > 0) mouse_report.v = w_offset; +    if (mouse_report.v < 0) mouse_report.v = w_offset * -1; +    // adjust for diagonals +    if (mouse_report.x && mouse_report.y) { +        mouse_report.x = times_inv_sqrt2(mouse_report.x); +        if (mouse_report.x == 0) { +            mouse_report.x = 1; +        } +        mouse_report.y = times_inv_sqrt2(mouse_report.y); +        if (mouse_report.y == 0) { +            mouse_report.y = 1; +        } +    } +    if (mouse_report.h && mouse_report.v) { +        mouse_report.h = times_inv_sqrt2(mouse_report.h); +        mouse_report.v = times_inv_sqrt2(mouse_report.v); +    } +} + +void mousekey_on(uint8_t code) { +    uint16_t const c_offset  = c_offsets[mk_speed]; +    uint16_t const w_offset  = w_offsets[mk_speed]; +    uint8_t const  old_speed = mk_speed; +    if (code == KC_MS_UP) +        mouse_report.y = c_offset * -1; +    else if (code == KC_MS_DOWN) +        mouse_report.y = c_offset; +    else if (code == KC_MS_LEFT) +        mouse_report.x = c_offset * -1; +    else if (code == KC_MS_RIGHT) +        mouse_report.x = c_offset; +    else if (code == KC_MS_WH_UP) +        mouse_report.v = w_offset; +    else if (code == KC_MS_WH_DOWN) +        mouse_report.v = w_offset * -1; +    else if (code == KC_MS_WH_LEFT) +        mouse_report.h = w_offset * -1; +    else if (code == KC_MS_WH_RIGHT) +        mouse_report.h = w_offset; +    else if (IS_MOUSEKEY_BUTTON(code)) +        mouse_report.buttons |= 1 << (code - KC_MS_BTN1); +    else if (code == KC_MS_ACCEL0) +        mk_speed = mkspd_0; +    else if (code == KC_MS_ACCEL1) +        mk_speed = mkspd_1; +    else if (code == KC_MS_ACCEL2) +        mk_speed = mkspd_2; +    if (mk_speed != old_speed) adjust_speed(); +} + +void mousekey_off(uint8_t code) { +#    ifdef MK_MOMENTARY_ACCEL +    uint8_t const old_speed = mk_speed; +#    endif +    if (code == KC_MS_UP && mouse_report.y < 0) +        mouse_report.y = 0; +    else if (code == KC_MS_DOWN && mouse_report.y > 0) +        mouse_report.y = 0; +    else if (code == KC_MS_LEFT && mouse_report.x < 0) +        mouse_report.x = 0; +    else if (code == KC_MS_RIGHT && mouse_report.x > 0) +        mouse_report.x = 0; +    else if (code == KC_MS_WH_UP && mouse_report.v > 0) +        mouse_report.v = 0; +    else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) +        mouse_report.v = 0; +    else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) +        mouse_report.h = 0; +    else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) +        mouse_report.h = 0; +    else if (IS_MOUSEKEY_BUTTON(code)) +        mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1)); +#    ifdef MK_MOMENTARY_ACCEL +    else if (code == KC_MS_ACCEL0) +        mk_speed = mkspd_DEFAULT; +    else if (code == KC_MS_ACCEL1) +        mk_speed = mkspd_DEFAULT; +    else if (code == KC_MS_ACCEL2) +        mk_speed = mkspd_DEFAULT; +    if (mk_speed != old_speed) adjust_speed(); +#    endif +} + +#endif /* #ifndef MK_3_SPEED */ + +void mousekey_send(void) { +    mousekey_debug(); +    uint16_t time = timer_read(); +    if (mouse_report.x || mouse_report.y) last_timer_c = time; +    if (mouse_report.v || mouse_report.h) last_timer_w = time; +    host_mouse_send(&mouse_report); +} + +void mousekey_clear(void) { +    mouse_report          = (report_mouse_t){}; +    mousekey_repeat       = 0; +    mousekey_wheel_repeat = 0; +    mousekey_accel        = 0; +} + +static void mousekey_debug(void) { +    if (!debug_mouse) return; +    print("mousekey [btn|x y v h](rep/acl): ["); +    print_hex8(mouse_report.buttons); +    print("|"); +    print_decs(mouse_report.x); +    print(" "); +    print_decs(mouse_report.y); +    print(" "); +    print_decs(mouse_report.v); +    print(" "); +    print_decs(mouse_report.h); +    print("]("); +    print_dec(mousekey_repeat); +    print("/"); +    print_dec(mousekey_accel); +    print(")\n"); +} diff --git a/quantum/mousekey.h b/quantum/mousekey.h new file mode 100644 index 0000000000..70dc4bb5c5 --- /dev/null +++ b/quantum/mousekey.h @@ -0,0 +1,179 @@ +/* +Copyright 2011 Jun Wako <wakojun@gmail.com> + +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 + +#include <stdint.h> +#include "host.h" + +#ifndef MK_3_SPEED + +/* max value on report descriptor */ +#    ifndef MOUSEKEY_MOVE_MAX +#        define MOUSEKEY_MOVE_MAX 127 +#    elif MOUSEKEY_MOVE_MAX > 127 +#        error MOUSEKEY_MOVE_MAX needs to be smaller than 127 +#    endif + +#    ifndef MOUSEKEY_WHEEL_MAX +#        define MOUSEKEY_WHEEL_MAX 127 +#    elif MOUSEKEY_WHEEL_MAX > 127 +#        error MOUSEKEY_WHEEL_MAX needs to be smaller than 127 +#    endif + +#    ifndef MOUSEKEY_MOVE_DELTA +#        ifndef MK_KINETIC_SPEED +#            define MOUSEKEY_MOVE_DELTA 5 +#        else +#            define MOUSEKEY_MOVE_DELTA 25 +#        endif +#    endif +#    ifndef MOUSEKEY_WHEEL_DELTA +#        define MOUSEKEY_WHEEL_DELTA 1 +#    endif +#    ifndef MOUSEKEY_DELAY +#        ifndef MK_KINETIC_SPEED +#            define MOUSEKEY_DELAY 300 +#        else +#            define MOUSEKEY_DELAY 8 +#        endif +#    endif +#    ifndef MOUSEKEY_INTERVAL +#        ifndef MK_KINETIC_SPEED +#            define MOUSEKEY_INTERVAL 50 +#        else +#            define MOUSEKEY_INTERVAL 8 +#        endif +#    endif +#    ifndef MOUSEKEY_MAX_SPEED +#        define MOUSEKEY_MAX_SPEED 10 +#    endif +#    ifndef MOUSEKEY_TIME_TO_MAX +#        define MOUSEKEY_TIME_TO_MAX 20 +#    endif +#    ifndef MOUSEKEY_WHEEL_DELAY +#        define MOUSEKEY_WHEEL_DELAY 300 +#    endif +#    ifndef MOUSEKEY_WHEEL_INTERVAL +#        define MOUSEKEY_WHEEL_INTERVAL 100 +#    endif +#    ifndef MOUSEKEY_WHEEL_MAX_SPEED +#        define MOUSEKEY_WHEEL_MAX_SPEED 8 +#    endif +#    ifndef MOUSEKEY_WHEEL_TIME_TO_MAX +#        define MOUSEKEY_WHEEL_TIME_TO_MAX 40 +#    endif + +#    ifndef MOUSEKEY_INITIAL_SPEED +#        define MOUSEKEY_INITIAL_SPEED 100 +#    endif +#    ifndef MOUSEKEY_BASE_SPEED +#        define MOUSEKEY_BASE_SPEED 1000 +#    endif +#    ifndef MOUSEKEY_DECELERATED_SPEED +#        define MOUSEKEY_DECELERATED_SPEED 400 +#    endif +#    ifndef MOUSEKEY_ACCELERATED_SPEED +#        define MOUSEKEY_ACCELERATED_SPEED 3000 +#    endif +#    ifndef MOUSEKEY_WHEEL_INITIAL_MOVEMENTS +#        define MOUSEKEY_WHEEL_INITIAL_MOVEMENTS 16 +#    endif +#    ifndef MOUSEKEY_WHEEL_BASE_MOVEMENTS +#        define MOUSEKEY_WHEEL_BASE_MOVEMENTS 32 +#    endif +#    ifndef MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS +#        define MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS 48 +#    endif +#    ifndef MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS +#        define MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS 8 +#    endif + +#else /* #ifndef MK_3_SPEED */ + +#    ifndef MK_C_OFFSET_UNMOD +#        define MK_C_OFFSET_UNMOD 16 +#    endif +#    ifndef MK_C_INTERVAL_UNMOD +#        define MK_C_INTERVAL_UNMOD 16 +#    endif +#    ifndef MK_C_OFFSET_0 +#        define MK_C_OFFSET_0 1 +#    endif +#    ifndef MK_C_INTERVAL_0 +#        define MK_C_INTERVAL_0 32 +#    endif +#    ifndef MK_C_OFFSET_1 +#        define MK_C_OFFSET_1 4 +#    endif +#    ifndef MK_C_INTERVAL_1 +#        define MK_C_INTERVAL_1 16 +#    endif +#    ifndef MK_C_OFFSET_2 +#        define MK_C_OFFSET_2 32 +#    endif +#    ifndef MK_C_INTERVAL_2 +#        define MK_C_INTERVAL_2 16 +#    endif + +#    ifndef MK_W_OFFSET_UNMOD +#        define MK_W_OFFSET_UNMOD 1 +#    endif +#    ifndef MK_W_INTERVAL_UNMOD +#        define MK_W_INTERVAL_UNMOD 40 +#    endif +#    ifndef MK_W_OFFSET_0 +#        define MK_W_OFFSET_0 1 +#    endif +#    ifndef MK_W_INTERVAL_0 +#        define MK_W_INTERVAL_0 360 +#    endif +#    ifndef MK_W_OFFSET_1 +#        define MK_W_OFFSET_1 1 +#    endif +#    ifndef MK_W_INTERVAL_1 +#        define MK_W_INTERVAL_1 120 +#    endif +#    ifndef MK_W_OFFSET_2 +#        define MK_W_OFFSET_2 1 +#    endif +#    ifndef MK_W_INTERVAL_2 +#        define MK_W_INTERVAL_2 20 +#    endif + +#endif /* #ifndef MK_3_SPEED */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint8_t mk_delay; +extern uint8_t mk_interval; +extern uint8_t mk_max_speed; +extern uint8_t mk_time_to_max; +extern uint8_t mk_wheel_max_speed; +extern uint8_t mk_wheel_time_to_max; + +void mousekey_task(void); +void mousekey_on(uint8_t code); +void mousekey_off(uint8_t code); +void mousekey_clear(void); +void mousekey_send(void); + +#ifdef __cplusplus +} +#endif diff --git a/quantum/quantum.c b/quantum/quantum.c index cf16e953a2..8ae487bec2 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -391,6 +391,29 @@ __attribute__((weak)) const uint8_t ascii_to_altgr_lut[16] PROGMEM = {      KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),  }; +/* Bit-Packed look-up table to convert an ASCII character to whether + * [Space] needs to be sent after the keycode + */ +__attribute__((weak)) const uint8_t ascii_to_dead_lut[16] PROGMEM = { +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +}; +  /* Look-up table to convert an ASCII character to a keycode.   */  __attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = { @@ -531,6 +554,7 @@ void send_char(char ascii_code) {      uint8_t keycode    = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]);      bool    is_shifted = PGM_LOADBIT(ascii_to_shift_lut, (uint8_t)ascii_code);      bool    is_altgred = PGM_LOADBIT(ascii_to_altgr_lut, (uint8_t)ascii_code); +    bool    is_dead    = PGM_LOADBIT(ascii_to_dead_lut, (uint8_t)ascii_code);      if (is_shifted) {          register_code(KC_LSFT); @@ -545,6 +569,9 @@ void send_char(char ascii_code) {      if (is_shifted) {          unregister_code(KC_LSFT);      } +    if (is_dead) { +        tap_code(KC_SPACE); +    }  }  void set_single_persistent_default_layer(uint8_t default_layer) { @@ -629,6 +656,26 @@ void matrix_init_quantum() {  }  void matrix_scan_quantum() { +#if defined(AUDIO_ENABLE) +    // There are some tasks that need to be run a little bit +    // after keyboard startup, or else they will not work correctly +    // because of interaction with the USB device state, which +    // may still be in flux... +    // +    // At the moment the only feature that needs this is the +    // startup song. +    static bool     delayed_tasks_run  = false; +    static uint16_t delayed_task_timer = 0; +    if (!delayed_tasks_run) { +        if (!delayed_task_timer) { +            delayed_task_timer = timer_read(); +        } else if (timer_elapsed(delayed_task_timer) > 300) { +            audio_startup(); +            delayed_tasks_run = true; +        } +    } +#endif +  #if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE)      matrix_scan_music();  #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index f4df5bf155..370a65fe04 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -53,6 +53,7 @@  #include "eeconfig.h"  #include "bootloader.h"  #include "timer.h" +#include "sync_timer.h"  #include "config_common.h"  #include "led.h"  #include "action_util.h" @@ -209,6 +210,13 @@ typedef uint8_t pin_t;  #    define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF)) +/*   The AVR series GPIOs have a one clock read delay for changes in the digital input signal. + *   But here's more margin to make it two clocks. */ +#    if !defined(GPIO_INPUT_PIN_DELAY) +#        define GPIO_INPUT_PIN_DELAY 2 +#    endif +#    define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY) +  #elif defined(PROTOCOL_CHIBIOS)  typedef ioline_t pin_t; @@ -224,6 +232,28 @@ typedef ioline_t pin_t;  #    define readPin(pin) palReadLine(pin)  #    define togglePin(pin) palToggleLine(pin) + +#endif + +#if defined(__ARMEL__) || defined(__ARMEB__) +/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus + * to which the GPIO is connected. + * The connected buses differ depending on the various series of MCUs. + * And since the instruction execution clock of the CPU and the bus clock of GPIO are different, + * there is a delay of several clocks to read the change of the input signal. + * + * Define this delay with the GPIO_INPUT_PIN_DELAY macro. + * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used. + * (A fairly large value of 0.25 microseconds is set.) + */ +#    if !defined(GPIO_INPUT_PIN_DELAY) +#        if defined(STM32_SYSCLK) +#            define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4) +#        elif defined(KINETIS_SYSCLK_FREQUENCY) +#            define GPIO_INPUT_PIN_DELAY (KINETIS_SYSCLK_FREQUENCY / 1000000L / 4) +#        endif +#    endif +#    define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY)  #endif  // Atomic macro to help make GPIO and other controls atomic. @@ -288,6 +318,7 @@ static __inline__ void __interrupt_enable__(const uint8_t *__s) {  extern const uint8_t ascii_to_keycode_lut[128];  extern const uint8_t ascii_to_shift_lut[16];  extern const uint8_t ascii_to_altgr_lut[16]; +extern const uint8_t ascii_to_dead_lut[16];  // clang-format off  #define KCLUT_ENTRY(a, b, c, d, e, f, g, h) \      ( ((a) ? 1 : 0) << 0 \ diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index 04af3ae9ec..a945df68e0 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -266,9 +266,9 @@ static bool rgb_matrix_none(effect_params_t *params) {  static void rgb_task_timers(void) {  #if defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_DISABLE_TIMEOUT > 0 -    uint32_t deltaTime = timer_elapsed32(rgb_timer_buffer); +    uint32_t deltaTime = sync_timer_elapsed32(rgb_timer_buffer);  #endif  // defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_DISABLE_TIMEOUT > 0 -    rgb_timer_buffer = timer_read32(); +    rgb_timer_buffer = sync_timer_read32();      // Update double buffer timers  #if RGB_DISABLE_TIMEOUT > 0 @@ -296,7 +296,7 @@ static void rgb_task_timers(void) {  static void rgb_task_sync(void) {      // next task -    if (timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; +    if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;  }  static void rgb_task_start(void) { diff --git a/quantum/rgblight.c b/quantum/rgblight.c index ac4ff9bfda..7d7d015ba0 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -29,7 +29,7 @@  #endif  #include "wait.h"  #include "progmem.h" -#include "timer.h" +#include "sync_timer.h"  #include "rgblight.h"  #include "color.h"  #include "debug.h" @@ -42,6 +42,9 @@  #ifndef MIN  #    define MIN(a, b) (((a) < (b)) ? (a) : (b))  #endif +#ifndef MAX +#    define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif  #ifdef RGBLIGHT_SPLIT  /* for split keyboard */ @@ -700,18 +703,16 @@ static void rgblight_layers_write(void) {  #    ifdef RGBLIGHT_LAYER_BLINK  rgblight_layer_mask_t _blinked_layer_mask = 0; -uint16_t              _blink_duration     = 0;  static uint16_t       _blink_timer;  void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {      rgblight_set_layer_state(layer, true);      _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; -    _blink_timer    = timer_read(); -    _blink_duration = duration_ms; +    _blink_timer = sync_timer_read() + duration_ms;  }  void rgblight_unblink_layers(void) { -    if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) { +    if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) {          for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {              if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) {                  rgblight_set_layer_state(layer, false); @@ -886,7 +887,7 @@ void rgblight_timer_enable(void) {      if (!is_static_effect(rgblight_config.mode)) {          rgblight_status.timer_enabled = true;      } -    animation_status.last_timer = timer_read(); +    animation_status.last_timer = sync_timer_read();      RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;      dprintf("rgblight timer enabled.\n");  } @@ -989,24 +990,25 @@ void rgblight_task(void) {  #    endif  #    ifdef RGBLIGHT_EFFECT_TWINKLE          else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) { -            interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50); +            interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 30);              effect_func   = (effect_func_t)rgblight_effect_twinkle;          }  #    endif          if (animation_status.restart) {              animation_status.restart    = false; -            animation_status.last_timer = timer_read() - interval_time - 1; +            animation_status.last_timer = sync_timer_read();              animation_status.pos16      = 0;  // restart signal to local each effect          } -        if (timer_elapsed(animation_status.last_timer) >= interval_time) { +        uint16_t now = sync_timer_read(); +        if (timer_expired(now, animation_status.last_timer)) {  #    if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)              static uint16_t report_last_timer = 0;              static bool     tick_flag         = false;              uint16_t        oldpos16;              if (tick_flag) {                  tick_flag = false; -                if (timer_elapsed(report_last_timer) >= 30000) { -                    report_last_timer = timer_read(); +                if (timer_expired(now, report_last_timer)) { +                    report_last_timer += 30000;                      dprintf("rgblight animation tick report to slave\n");                      RGBLIGHT_SPLIT_ANIMATION_TICK;                  } @@ -1030,8 +1032,7 @@ void rgblight_task(void) {  #endif /* RGBLIGHT_USE_TIMER */ -// Effects -#ifdef RGBLIGHT_EFFECT_BREATHING +#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_TWINKLE)  #    ifndef RGBLIGHT_EFFECT_BREATHE_CENTER  #        ifndef RGBLIGHT_BREATHE_TABLE_SIZE @@ -1040,17 +1041,24 @@ void rgblight_task(void) {  #        include <rgblight_breathe_table.h>  #    endif -__attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; - -void rgblight_effect_breathing(animation_status_t *anim) { -    float val; - +static uint8_t breathe_calc(uint8_t pos) {      // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/  #    ifdef RGBLIGHT_EFFECT_BREATHE_TABLE -    val = pgm_read_byte(&rgblight_effect_breathe_table[anim->pos / table_scale]); +    return pgm_read_byte(&rgblight_effect_breathe_table[pos / table_scale]);  #    else -    val = (exp(sin((anim->pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E)); +    return (exp(sin((pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E));  #    endif +} + +#endif + +// Effects +#ifdef RGBLIGHT_EFFECT_BREATHING + +__attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; + +void rgblight_effect_breathing(animation_status_t *anim) { +    uint8_t val = breathe_calc(anim->pos);      rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);      anim->pos = (anim->pos + 1);  } @@ -1302,48 +1310,54 @@ void rgblight_effect_alternating(animation_status_t *anim) {  #endif  #ifdef RGBLIGHT_EFFECT_TWINKLE -__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10}; +__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {30, 15, 5};  typedef struct PACKED {      HSV     hsv;      uint8_t life; -    bool    up; +    uint8_t max_life;  } TwinkleState;  static TwinkleState led_twinkle_state[RGBLED_NUM];  void rgblight_effect_twinkle(animation_status_t *anim) { -    bool random_color = anim->delta / 3; -    bool restart      = anim->pos == 0; -    anim->pos         = 1; +    const bool random_color = anim->delta / 3; +    const bool restart      = anim->pos == 0; +    anim->pos               = 1; + +    const uint8_t bottom = breathe_calc(0); +    const uint8_t top    = breathe_calc(127); + +    uint8_t frac(uint8_t n, uint8_t d) { return (uint16_t)255 * n / d; } +    uint8_t scale(uint16_t v, uint8_t scale) { return (v * scale) >> 8; }      for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {          TwinkleState *t = &(led_twinkle_state[i]);          HSV *         c = &(t->hsv); + +        if (!random_color) { +            c->h = rgblight_config.hue; +            c->s = rgblight_config.sat; +        } +          if (restart) {              // Restart -            t->life  = 0; -            t->hsv.v = 0; +            t->life = 0; +            c->v    = 0;          } else if (t->life) {              // This LED is already on, either brightening or dimming              t->life--; -            uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life; -            c->v       = (uint16_t)rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE; -            if (t->life == 0 && t->up) { -                t->up   = false; -                t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE; -            } -            if (!random_color) { -                c->h = rgblight_config.hue; -                c->s = rgblight_config.sat; -            } -        } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) { +            uint8_t unscaled = frac(breathe_calc(frac(t->life, t->max_life)) - bottom, top - bottom); +            c->v             = scale(rgblight_config.val, unscaled); +        } else if (rand() < scale((uint16_t)RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY, 127 + rgblight_config.val / 2)) {              // This LED is off, but was randomly selected to start brightening -            c->h    = random_color ? rand() % 0xFF : rgblight_config.hue; -            c->s    = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat; -            c->v    = 0; -            t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE; -            t->up   = true; +            if (random_color) { +                c->h = rand() % 0xFF; +                c->s = (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2); +            } +            c->v        = 0; +            t->max_life = MAX(20, MIN(RGBLIGHT_EFFECT_TWINKLE_LIFE, rgblight_config.val)); +            t->life     = t->max_life;          } else {              // This LED is off, and was NOT selected to start brightening          } diff --git a/quantum/rgblight.h b/quantum/rgblight.h index 1854fee999..028b3ea416 100644 --- a/quantum/rgblight.h +++ b/quantum/rgblight.h @@ -150,7 +150,7 @@ enum RGBLIGHT_EFFECT_MODE {  #    endif  #    ifndef RGBLIGHT_EFFECT_TWINKLE_LIFE -#        define RGBLIGHT_EFFECT_TWINKLE_LIFE 75 +#        define RGBLIGHT_EFFECT_TWINKLE_LIFE 200  #    endif  #    ifndef RGBLIGHT_EFFECT_TWINKLE_PROBABILITY diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c index 51bf8b1095..bad762b493 100644 --- a/quantum/split_common/matrix.c +++ b/quantum/split_common/matrix.c @@ -114,9 +114,9 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)      // Start with a clear matrix row      matrix_row_t current_row_value = 0; -    // Select row and wait for row selecton to stabilize +    // Select row      select_row(current_row); -    matrix_io_delay(); +    matrix_output_select_delay();      // For each col...      for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { @@ -129,6 +129,9 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)      // Unselect row      unselect_row(current_row); +    if (current_row + 1 < MATRIX_ROWS) { +        matrix_output_unselect_delay();  // wait for row signal to go HIGH +    }      // If the row has changed, store the row and return the changed flag.      if (current_matrix[current_row] != current_row_value) { @@ -160,9 +163,9 @@ static void init_pins(void) {  static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {      bool matrix_changed = false; -    // Select col and wait for col selecton to stabilize +    // Select col      select_col(current_col); -    matrix_io_delay(); +    matrix_output_select_delay();      // For each row...      for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { @@ -188,6 +191,9 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)      // Unselect col      unselect_col(current_col); +    if (current_col + 1 < MATRIX_COLS) { +        matrix_output_unselect_delay();  // wait for col signal to go HIGH +    }      return matrix_changed;  } @@ -245,21 +251,33 @@ void matrix_init(void) {      split_post_init();  } -void matrix_post_scan(void) { +bool matrix_post_scan(void) { +    bool changed = false;      if (is_keyboard_master()) {          static uint8_t error_count; -        if (!transport_master(matrix + thatHand)) { +        matrix_row_t slave_matrix[ROWS_PER_HAND] = {0}; +        if (!transport_master(slave_matrix)) {              error_count++;              if (error_count > ERROR_DISCONNECT_COUNT) {                  // reset other half if disconnected                  for (int i = 0; i < ROWS_PER_HAND; ++i) {                      matrix[thatHand + i] = 0; +                    slave_matrix[i]      = 0;                  } + +                changed = true;              }          } else {              error_count = 0; + +            for (int i = 0; i < ROWS_PER_HAND; ++i) { +                if (matrix[thatHand + i] != slave_matrix[i]) { +                    matrix[thatHand + i] = slave_matrix[i]; +                    changed              = true; +                } +            }          }          matrix_scan_quantum(); @@ -268,25 +286,27 @@ void matrix_post_scan(void) {          matrix_slave_scan_user();      } + +    return changed;  }  uint8_t matrix_scan(void) { -    bool changed = false; +    bool local_changed = false;  #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)      // Set row, read cols      for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { -        changed |= read_cols_on_row(raw_matrix, current_row); +        local_changed |= read_cols_on_row(raw_matrix, current_row);      }  #elif (DIODE_DIRECTION == ROW2COL)      // Set col, read rows      for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { -        changed |= read_rows_on_col(raw_matrix, current_col); +        local_changed |= read_rows_on_col(raw_matrix, current_col);      }  #endif -    debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); +    debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed); -    matrix_post_scan(); -    return (uint8_t)changed; +    bool remote_changed = matrix_post_scan(); +    return (uint8_t)(local_changed || remote_changed);  } diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c index 467ff81a97..b45ba92c3b 100644 --- a/quantum/split_common/transport.c +++ b/quantum/split_common/transport.c @@ -6,6 +6,7 @@  #include "quantum.h"  #define ROWS_PER_HAND (MATRIX_ROWS / 2) +#define SYNC_TIMER_OFFSET 2  #ifdef RGBLIGHT_ENABLE  #    include "rgblight.h" @@ -27,8 +28,20 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A;  #    include "i2c_slave.h"  typedef struct _I2C_slave_buffer_t { +#    ifndef DISABLE_SYNC_TIMER +    uint32_t sync_timer; +#    endif      matrix_row_t smatrix[ROWS_PER_HAND]; -    uint8_t      backlight_level; +#    ifdef SPLIT_MODS_ENABLE +    uint8_t real_mods; +    uint8_t weak_mods; +#        ifndef NO_ACTION_ONESHOT +    uint8_t oneshot_mods; +#        endif +#    endif +#    ifdef BACKLIGHT_ENABLE +    uint8_t backlight_level; +#    endif  #    if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)      rgblight_syncinfo_t rgblight_sync;  #    endif @@ -42,9 +55,13 @@ typedef struct _I2C_slave_buffer_t {  static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; +#    define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer) +#    define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix) +#    define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods) +#    define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods) +#    define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods)  #    define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level)  #    define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) -#    define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix)  #    define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)  #    define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) @@ -91,10 +108,43 @@ bool transport_master(matrix_row_t matrix[]) {          }      }  #    endif + +#    ifdef SPLIT_MODS_ENABLE +    uint8_t real_mods = get_mods(); +    if (real_mods != i2c_buffer->real_mods) { +        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) { +            i2c_buffer->real_mods = real_mods; +        } +    } + +    uint8_t weak_mods = get_weak_mods(); +    if (weak_mods != i2c_buffer->weak_mods) { +        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) { +            i2c_buffer->weak_mods = weak_mods; +        } +    } + +#        ifndef NO_ACTION_ONESHOT +    uint8_t oneshot_mods = get_oneshot_mods(); +    if (oneshot_mods != i2c_buffer->oneshot_mods) { +        if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) { +            i2c_buffer->oneshot_mods = oneshot_mods; +        } +    } +#        endif +#    endif + +#    ifndef DISABLE_SYNC_TIMER +    i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET; +    i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT); +#    endif      return true;  }  void transport_slave(matrix_row_t matrix[]) { +#    ifndef DISABLE_SYNC_TIMER +    sync_timer_update(i2c_buffer->sync_timer); +#    endif      // Copy matrix to I2C buffer      memcpy((void *)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix)); @@ -118,6 +168,14 @@ void transport_slave(matrix_row_t matrix[]) {  #    ifdef WPM_ENABLE      set_current_wpm(i2c_buffer->current_wpm);  #    endif + +#    ifdef SPLIT_MODS_ENABLE +    set_mods(i2c_buffer->real_mods); +    set_weak_mods(i2c_buffer->weak_mods); +#        ifndef NO_ACTION_ONESHOT +    set_oneshot_mods(i2c_buffer->oneshot_mods); +#        endif +#    endif  }  void transport_master_init(void) { i2c_init(); } @@ -139,11 +197,21 @@ typedef struct _Serial_s2m_buffer_t {  } Serial_s2m_buffer_t;  typedef struct _Serial_m2s_buffer_t { +#    ifdef SPLIT_MODS_ENABLE +    uint8_t  real_mods; +    uint8_t  weak_mods; +#        ifndef NO_ACTION_ONESHOT +    uint8_t  oneshot_mods; +#        endif +#    endif +#    ifndef DISABLE_SYNC_TIMER +    uint32_t sync_timer; +#    endif  #    ifdef BACKLIGHT_ENABLE -    uint8_t backlight_level; +    uint8_t  backlight_level;  #    endif  #    ifdef WPM_ENABLE -    uint8_t current_wpm; +    uint8_t  current_wpm;  #    endif  } Serial_m2s_buffer_t; @@ -249,13 +317,28 @@ bool transport_master(matrix_row_t matrix[]) {  #    ifdef WPM_ENABLE      // Write wpm to slave -    serial_m2s_buffer.current_wpm = get_current_wpm(); +    serial_m2s_buffer.current_wpm  = get_current_wpm(); +#    endif + +#    ifdef SPLIT_MODS_ENABLE +    serial_m2s_buffer.real_mods    = get_mods(); +    serial_m2s_buffer.weak_mods    = get_weak_mods(); +#        ifndef NO_ACTION_ONESHOT +    serial_m2s_buffer.oneshot_mods = get_oneshot_mods(); +#        endif +#    endif +#    ifndef DISABLE_SYNC_TIMER +    serial_m2s_buffer.sync_timer   = sync_timer_read32() + SYNC_TIMER_OFFSET;  #    endif      return true;  }  void transport_slave(matrix_row_t matrix[]) {      transport_rgblight_slave(); +#    ifndef DISABLE_SYNC_TIMER +    sync_timer_update(serial_m2s_buffer.sync_timer); +#    endif +      // TODO: if MATRIX_COLS > 8 change to pack()      for (int i = 0; i < ROWS_PER_HAND; ++i) {          serial_s2m_buffer.smatrix[i] = matrix[i]; @@ -271,6 +354,14 @@ void transport_slave(matrix_row_t matrix[]) {  #    ifdef WPM_ENABLE      set_current_wpm(serial_m2s_buffer.current_wpm);  #    endif + +#    ifdef SPLIT_MODS_ENABLE +    set_mods(serial_m2s_buffer.real_mods); +    set_weak_mods(serial_m2s_buffer.weak_mods); +#        ifndef NO_ACTION_ONESHOT +    set_oneshot_mods(serial_m2s_buffer.oneshot_mods); +#        endif +#    endif  }  #endif | 
