aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/audio/audio.h1
-rw-r--r--quantum/audio/audio_avr.c2
-rw-r--r--quantum/audio/audio_chibios.c33
-rw-r--r--quantum/audio/audio_pwm.c11
-rw-r--r--quantum/audio/musical_notes.h9
-rw-r--r--quantum/backlight/backlight_avr.c2
-rw-r--r--quantum/command.c12
-rw-r--r--quantum/config_common.h2
-rw-r--r--quantum/debounce/sym_defer_pk.c6
-rw-r--r--quantum/debounce/sym_eager_pk.c6
-rw-r--r--quantum/debounce/sym_eager_pr.c6
-rw-r--r--quantum/dynamic_keymap.c2
-rw-r--r--quantum/encoder.c22
-rw-r--r--quantum/encoder.h2
-rw-r--r--quantum/keymap_extras/keymap_us_extended.h227
-rw-r--r--quantum/keymap_extras/keymap_us_international.h20
-rw-r--r--quantum/keymap_extras/keymap_us_international_linux.h224
-rw-r--r--quantum/keymap_extras/sendstring_us_international.h100
-rw-r--r--quantum/matrix.c14
-rw-r--r--quantum/matrix.h3
-rw-r--r--quantum/matrix_common.c7
-rw-r--r--quantum/mcu_selection.mk70
-rw-r--r--quantum/mousekey.c488
-rw-r--r--quantum/mousekey.h179
-rw-r--r--quantum/quantum.c47
-rw-r--r--quantum/quantum.h31
-rw-r--r--quantum/rgb_matrix.c6
-rw-r--r--quantum/rgblight.c100
-rw-r--r--quantum/rgblight.h2
-rw-r--r--quantum/split_common/matrix.c44
-rw-r--r--quantum/split_common/transport.c101
31 files changed, 1675 insertions, 104 deletions
diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h
index bc00cd19e..dccf03d5f 100644
--- a/quantum/audio/audio.h
+++ b/quantum/audio/audio.h
@@ -83,6 +83,7 @@ void increase_tempo(uint8_t tempo_change);
83void decrease_tempo(uint8_t tempo_change); 83void decrease_tempo(uint8_t tempo_change);
84 84
85void audio_init(void); 85void audio_init(void);
86void audio_startup(void);
86 87
87#ifdef PWM_AUDIO 88#ifdef PWM_AUDIO
88void play_sample(uint8_t* s, uint16_t l, bool r); 89void 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 5a96bf643..1bac43bb4 100644
--- a/quantum/audio/audio_avr.c
+++ b/quantum/audio/audio_avr.c
@@ -227,7 +227,9 @@ void audio_init() {
227 227
228 audio_initialized = true; 228 audio_initialized = true;
229 } 229 }
230}
230 231
232void audio_startup() {
231 if (audio_config.enable) { 233 if (audio_config.enable) {
232 PLAY_SONG(startup_song); 234 PLAY_SONG(startup_song);
233 } 235 }
diff --git a/quantum/audio/audio_chibios.c b/quantum/audio/audio_chibios.c
index 1f147f2c9..dddb8f135 100644
--- a/quantum/audio/audio_chibios.c
+++ b/quantum/audio/audio_chibios.c
@@ -86,13 +86,21 @@ static void gpt_cb8(GPTDriver *gptp);
86 86
87#define START_CHANNEL_1() \ 87#define START_CHANNEL_1() \
88 gptStart(&GPTD6, &gpt6cfg1); \ 88 gptStart(&GPTD6, &gpt6cfg1); \
89 gptStartContinuous(&GPTD6, 2U) 89 gptStartContinuous(&GPTD6, 2U); \
90 palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG)
90#define START_CHANNEL_2() \ 91#define START_CHANNEL_2() \
91 gptStart(&GPTD7, &gpt7cfg1); \ 92 gptStart(&GPTD7, &gpt7cfg1); \
92 gptStartContinuous(&GPTD7, 2U) 93 gptStartContinuous(&GPTD7, 2U); \
93#define STOP_CHANNEL_1() gptStopTimer(&GPTD6) 94 palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG)
94#define STOP_CHANNEL_2() gptStopTimer(&GPTD7) 95#define STOP_CHANNEL_1() \
95#define RESTART_CHANNEL_1() \ 96 gptStopTimer(&GPTD6); \
97 palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL); \
98 palSetPad(GPIOA, 4)
99#define STOP_CHANNEL_2() \
100 gptStopTimer(&GPTD7); \
101 palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); \
102 palSetPad(GPIOA, 5)
103 #define RESTART_CHANNEL_1() \
96 STOP_CHANNEL_1(); \ 104 STOP_CHANNEL_1(); \
97 START_CHANNEL_1() 105 START_CHANNEL_1()
98#define RESTART_CHANNEL_2() \ 106#define RESTART_CHANNEL_2() \
@@ -274,6 +282,12 @@ void audio_init() {
274 dacStart(&DACD2, &dac1cfg2); 282 dacStart(&DACD2, &dac1cfg2);
275 283
276 /* 284 /*
285 * Start the note timer
286 */
287 gptStart(&GPTD8, &gpt8cfg1);
288 gptStartContinuous(&GPTD8, 2U);
289
290 /*
277 * Starting GPT6/7 driver, it is used for triggering the DAC. 291 * Starting GPT6/7 driver, it is used for triggering the DAC.
278 */ 292 */
279 START_CHANNEL_1(); 293 START_CHANNEL_1();
@@ -287,10 +301,12 @@ void audio_init() {
287 301
288 audio_initialized = true; 302 audio_initialized = true;
289 303
304 stop_all_notes();
305}
306
307void audio_startup() {
290 if (audio_config.enable) { 308 if (audio_config.enable) {
291 PLAY_SONG(startup_song); 309 PLAY_SONG(startup_song);
292 } else {
293 stop_all_notes();
294 } 310 }
295} 311}
296 312
@@ -630,6 +646,9 @@ bool is_playing_notes(void) { return playing_notes; }
630bool is_audio_on(void) { return (audio_config.enable != 0); } 646bool is_audio_on(void) { return (audio_config.enable != 0); }
631 647
632void audio_toggle(void) { 648void audio_toggle(void) {
649 if (audio_config.enable) {
650 stop_all_notes();
651 }
633 audio_config.enable ^= 1; 652 audio_config.enable ^= 1;
634 eeconfig_update_audio(audio_config.raw); 653 eeconfig_update_audio(audio_config.raw);
635 if (audio_config.enable) { 654 if (audio_config.enable) {
diff --git a/quantum/audio/audio_pwm.c b/quantum/audio/audio_pwm.c
index 545aef6dd..d93ac4bb4 100644
--- a/quantum/audio/audio_pwm.c
+++ b/quantum/audio/audio_pwm.c
@@ -29,6 +29,11 @@
29 29
30#define CPU_PRESCALER 8 30#define CPU_PRESCALER 8
31 31
32#ifndef STARTUP_SONG
33# define STARTUP_SONG SONG(STARTUP_SOUND)
34#endif
35float startup_song[][2] = STARTUP_SONG;
36
32// Timer Abstractions 37// Timer Abstractions
33 38
34// TIMSK3 - Timer/Counter #3 Interrupt Mask Register 39// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
@@ -155,6 +160,12 @@ void audio_init() {
155 audio_initialized = true; 160 audio_initialized = true;
156} 161}
157 162
163void audio_startup() {
164 if (audio_config.enable) {
165 PLAY_SONG(startup_song);
166 }
167}
168
158void stop_all_notes() { 169void stop_all_notes() {
159 if (!audio_initialized) { 170 if (!audio_initialized) {
160 audio_init(); 171 audio_init();
diff --git a/quantum/audio/musical_notes.h b/quantum/audio/musical_notes.h
index 8ac6aafd3..0ba572c34 100644
--- a/quantum/audio/musical_notes.h
+++ b/quantum/audio/musical_notes.h
@@ -17,7 +17,9 @@
17#pragma once 17#pragma once
18 18
19// Tempo Placeholder 19// Tempo Placeholder
20#define TEMPO_DEFAULT 100 20#ifndef TEMPO_DEFAULT
21# define TEMPO_DEFAULT 100
22#endif
21 23
22#define SONG(notes...) \ 24#define SONG(notes...) \
23 { notes } 25 { notes }
@@ -60,8 +62,9 @@
60#define TIMBRE_25 0.250f 62#define TIMBRE_25 0.250f
61#define TIMBRE_50 0.500f 63#define TIMBRE_50 0.500f
62#define TIMBRE_75 0.750f 64#define TIMBRE_75 0.750f
63#define TIMBRE_DEFAULT TIMBRE_50 65#ifndef TIMBRE_DEFAULT
64 66# define TIMBRE_DEFAULT TIMBRE_50
67#endif
65// Notes - # = Octave 68// Notes - # = Octave
66 69
67#ifdef __arm__ 70#ifdef __arm__
diff --git a/quantum/backlight/backlight_avr.c b/quantum/backlight/backlight_avr.c
index 4d66da80b..2ecdd4f2c 100644
--- a/quantum/backlight/backlight_avr.c
+++ b/quantum/backlight/backlight_avr.c
@@ -68,7 +68,7 @@
68# define COMxx1 COM3A1 68# define COMxx1 COM3A1
69# define OCRxx OCR3A 69# define OCRxx OCR3A
70# endif 70# endif
71#elif (defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)) && (BACKLIGHT_PIN == B7 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6) 71#elif (defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)) && (BACKLIGHT_PIN == B7 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6)
72# define HARDWARE_PWM 72# define HARDWARE_PWM
73# define ICRx ICR1 73# define ICRx ICR1
74# define TCCRxA TCCR1A 74# define TCCRxA TCCR1A
diff --git a/quantum/command.c b/quantum/command.c
index 59aa4e4d3..34c4b36b1 100644
--- a/quantum/command.c
+++ b/quantum/command.c
@@ -550,22 +550,22 @@ static void mousekey_param_print(void) {
550# if !defined(NO_PRINT) && !defined(USER_PRINT) 550# if !defined(NO_PRINT) && !defined(USER_PRINT)
551 print("\n\t- Values -\n"); 551 print("\n\t- Values -\n");
552 print("1: delay(*10ms): "); 552 print("1: delay(*10ms): ");
553 pdec(mk_delay); 553 print_dec(mk_delay);
554 print("\n"); 554 print("\n");
555 print("2: interval(ms): "); 555 print("2: interval(ms): ");
556 pdec(mk_interval); 556 print_dec(mk_interval);
557 print("\n"); 557 print("\n");
558 print("3: max_speed: "); 558 print("3: max_speed: ");
559 pdec(mk_max_speed); 559 print_dec(mk_max_speed);
560 print("\n"); 560 print("\n");
561 print("4: time_to_max: "); 561 print("4: time_to_max: ");
562 pdec(mk_time_to_max); 562 print_dec(mk_time_to_max);
563 print("\n"); 563 print("\n");
564 print("5: wheel_max_speed: "); 564 print("5: wheel_max_speed: ");
565 pdec(mk_wheel_max_speed); 565 print_dec(mk_wheel_max_speed);
566 print("\n"); 566 print("\n");
567 print("6: wheel_time_to_max: "); 567 print("6: wheel_time_to_max: ");
568 pdec(mk_wheel_time_to_max); 568 print_dec(mk_wheel_time_to_max);
569 print("\n"); 569 print("\n");
570# endif /* !NO_PRINT */ 570# endif /* !NO_PRINT */
571} 571}
diff --git a/quantum/config_common.h b/quantum/config_common.h
index 5973232ef..bfaf7389e 100644
--- a/quantum/config_common.h
+++ b/quantum/config_common.h
@@ -39,7 +39,7 @@
39# define PIND_ADDRESS 0x9 39# define PIND_ADDRESS 0x9
40# define PINE_ADDRESS 0xC 40# define PINE_ADDRESS 0xC
41# define PINF_ADDRESS 0xF 41# define PINF_ADDRESS 0xF
42# elif defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) 42# elif defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
43# define ADDRESS_BASE 0x00 43# define ADDRESS_BASE 0x00
44# define PINB_ADDRESS 0x3 44# define PINB_ADDRESS 0x3
45# define PINC_ADDRESS 0x6 45# define PINC_ADDRESS 0x6
diff --git a/quantum/debounce/sym_defer_pk.c b/quantum/debounce/sym_defer_pk.c
index 6c0e3bb07..60513f98e 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.
23#include "quantum.h" 23#include "quantum.h"
24#include <stdlib.h> 24#include <stdlib.h>
25 25
26#ifdef PROTOCOL_CHIBIOS
27# if CH_CFG_USE_MEMCORE == FALSE
28# 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.
29# endif
30#endif
31
26#ifndef DEBOUNCE 32#ifndef DEBOUNCE
27# define DEBOUNCE 5 33# define DEBOUNCE 5
28#endif 34#endif
diff --git a/quantum/debounce/sym_eager_pk.c b/quantum/debounce/sym_eager_pk.c
index 93a40ad44..e66cf92d7 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.
23#include "quantum.h" 23#include "quantum.h"
24#include <stdlib.h> 24#include <stdlib.h>
25 25
26#ifdef PROTOCOL_CHIBIOS
27# if CH_CFG_USE_MEMCORE == FALSE
28# 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.
29# endif
30#endif
31
26#ifndef DEBOUNCE 32#ifndef DEBOUNCE
27# define DEBOUNCE 5 33# define DEBOUNCE 5
28#endif 34#endif
diff --git a/quantum/debounce/sym_eager_pr.c b/quantum/debounce/sym_eager_pr.c
index d12931fdd..20ccb46f1 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.
23#include "quantum.h" 23#include "quantum.h"
24#include <stdlib.h> 24#include <stdlib.h>
25 25
26#ifdef PROTOCOL_CHIBIOS
27# if CH_CFG_USE_MEMCORE == FALSE
28# 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.
29# endif
30#endif
31
26#ifndef DEBOUNCE 32#ifndef DEBOUNCE
27# define DEBOUNCE 5 33# define DEBOUNCE 5
28#endif 34#endif
diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c
index 0608b469c..a860b9497 100644
--- a/quantum/dynamic_keymap.c
+++ b/quantum/dynamic_keymap.c
@@ -37,6 +37,8 @@
37#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 37#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR
38# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) 38# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
39# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 2047 39# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 2047
40# elif defined(__AVR_AT90USB162__)
41# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 511
40# else 42# else
41# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023 43# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023
42# endif 44# endif
diff --git a/quantum/encoder.c b/quantum/encoder.c
index 7ca31afed..2ed64c1e3 100644
--- a/quantum/encoder.c
+++ b/quantum/encoder.c
@@ -94,8 +94,9 @@ void encoder_init(void) {
94#endif 94#endif
95} 95}
96 96
97static void encoder_update(int8_t index, uint8_t state) { 97static bool encoder_update(int8_t index, uint8_t state) {
98 uint8_t i = index; 98 bool changed = false;
99 uint8_t i = index;
99 100
100#ifdef ENCODER_RESOLUTIONS 101#ifdef ENCODER_RESOLUTIONS
101 int8_t resolution = encoder_resolutions[i]; 102 int8_t resolution = encoder_resolutions[i];
@@ -109,40 +110,53 @@ static void encoder_update(int8_t index, uint8_t state) {
109 encoder_pulses[i] += encoder_LUT[state & 0xF]; 110 encoder_pulses[i] += encoder_LUT[state & 0xF];
110 if (encoder_pulses[i] >= resolution) { 111 if (encoder_pulses[i] >= resolution) {
111 encoder_value[index]++; 112 encoder_value[index]++;
113 changed = true;
112 encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE); 114 encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE);
113 } 115 }
114 if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise 116 if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise
115 encoder_value[index]--; 117 encoder_value[index]--;
118 changed = true;
116 encoder_update_kb(index, ENCODER_CLOCKWISE); 119 encoder_update_kb(index, ENCODER_CLOCKWISE);
117 } 120 }
118 encoder_pulses[i] %= resolution; 121 encoder_pulses[i] %= resolution;
122 return changed;
119} 123}
120 124
121void encoder_read(void) { 125bool encoder_read(void) {
126 bool changed = false;
122 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { 127 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
123 encoder_state[i] <<= 2; 128 encoder_state[i] <<= 2;
124 encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1); 129 encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
125 encoder_update(i, encoder_state[i]); 130 changed |= encoder_update(i, encoder_state[i]);
126 } 131 }
132 return changed;
127} 133}
128 134
129#ifdef SPLIT_KEYBOARD 135#ifdef SPLIT_KEYBOARD
136void last_encoder_activity_trigger(void);
137
130void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); } 138void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); }
131 139
132void encoder_update_raw(uint8_t* slave_state) { 140void encoder_update_raw(uint8_t* slave_state) {
141 bool changed = false;
133 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) { 142 for (uint8_t i = 0; i < NUMBER_OF_ENCODERS; i++) {
134 uint8_t index = i + thatHand; 143 uint8_t index = i + thatHand;
135 int8_t delta = slave_state[i] - encoder_value[index]; 144 int8_t delta = slave_state[i] - encoder_value[index];
136 while (delta > 0) { 145 while (delta > 0) {
137 delta--; 146 delta--;
138 encoder_value[index]++; 147 encoder_value[index]++;
148 changed = true;
139 encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE); 149 encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE);
140 } 150 }
141 while (delta < 0) { 151 while (delta < 0) {
142 delta++; 152 delta++;
143 encoder_value[index]--; 153 encoder_value[index]--;
154 changed = true;
144 encoder_update_kb(index, ENCODER_CLOCKWISE); 155 encoder_update_kb(index, ENCODER_CLOCKWISE);
145 } 156 }
146 } 157 }
158
159 // Update the last encoder input time -- handled external to encoder_read() when we're running a split
160 if (changed) last_encoder_activity_trigger();
147} 161}
148#endif 162#endif
diff --git a/quantum/encoder.h b/quantum/encoder.h
index ec09a8cc4..db6f220da 100644
--- a/quantum/encoder.h
+++ b/quantum/encoder.h
@@ -20,7 +20,7 @@
20#include "quantum.h" 20#include "quantum.h"
21 21
22void encoder_init(void); 22void encoder_init(void);
23void encoder_read(void); 23bool encoder_read(void);
24 24
25void encoder_update_kb(int8_t index, bool clockwise); 25void encoder_update_kb(int8_t index, bool clockwise);
26void encoder_update_user(int8_t index, bool clockwise); 26void 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 000000000..b2b3a734c
--- /dev/null
+++ b/quantum/keymap_extras/keymap_us_extended.h
@@ -0,0 +1,227 @@
1/* Copyright 2020
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include "keymap.h"
20
21// clang-format off
22
23/*
24 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
25 * │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │       │
26 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
27 * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │  \  │
28 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
29 * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │        │
30 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
31 * │        │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │
32 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
33 * │    │    │    │                        │    │    │    │    │
34 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
35 */
36// Row 1
37#define US_GRV KC_GRV // `
38#define US_1 KC_1 // 1
39#define US_2 KC_2 // 2
40#define US_3 KC_3 // 3
41#define US_4 KC_4 // 4
42#define US_5 KC_5 // 5
43#define US_6 KC_6 // 6
44#define US_7 KC_7 // 7
45#define US_8 KC_8 // 8
46#define US_9 KC_9 // 9
47#define US_0 KC_0 // 0
48#define US_MINS KC_MINS // -
49#define US_EQL KC_EQL // =
50// Row 2
51#define US_Q KC_Q // Q
52#define US_W KC_W // W
53#define US_E KC_E // E
54#define US_R KC_R // R
55#define US_T KC_T // T
56#define US_Y KC_Y // Y
57#define US_U KC_U // U
58#define US_I KC_I // I
59#define US_O KC_O // O
60#define US_P KC_P // P
61#define US_LBRC KC_LBRC // [
62#define US_RBRC KC_RBRC // ]
63#define US_BSLS KC_BSLS // (backslash)
64// Row 3
65#define US_A KC_A // A
66#define US_S KC_S // S
67#define US_D KC_D // D
68#define US_F KC_F // F
69#define US_G KC_G // G
70#define US_H KC_H // H
71#define US_J KC_J // J
72#define US_K KC_K // K
73#define US_L KC_L // L
74#define US_SCLN KC_SCLN // ;
75#define US_QUOT KC_QUOT // '
76// Row 4
77#define US_Z KC_Z // Z
78#define US_X KC_X // X
79#define US_C KC_C // C
80#define US_V KC_V // V
81#define US_B KC_B // B
82#define US_N KC_N // N
83#define US_M KC_M // M
84#define US_COMM KC_COMM // ,
85#define US_DOT KC_DOT // .
86#define US_SLSH KC_SLSH // /
87
88/* Shifted symbols
89 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
90 * │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │       │
91 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
92 * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │
93 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
94 * │      │   │   │   │   │   │   │   │   │   │ : │ " │        │
95 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
96 * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │
97 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
98 * │    │    │    │                        │    │    │    │    │
99 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
100 */
101// Row 1
102#define US_TILD S(US_GRV) // ~
103#define US_EXLM S(US_1) // !
104#define US_AT S(US_2) // @
105#define US_HASH S(US_3) // #
106#define US_DLR S(US_4) // $
107#define US_PERC S(US_5) // %
108#define US_CIRC S(US_6) // ^
109#define US_AMPR S(US_7) // &
110#define US_ASTR S(US_8) // *
111#define US_LPRN S(US_9) // (
112#define US_RPRN S(US_0) // )
113#define US_UNDS S(US_MINS) // _
114#define US_PLUS S(US_EQL) // +
115// Row 2
116#define US_LCBR S(US_LBRC) // {
117#define US_RCBR S(US_RBRC) // }
118#define US_PIPE S(US_BSLS) // |
119// Row 3
120#define US_COLN S(US_SCLN) // :
121#define US_DQUO S(US_QUOT) // "
122// Row 4
123#define US_LABK S(US_COMM) // <
124#define US_RABK S(US_DOT) // >
125#define US_QUES S(US_SLSH) // ?
126
127/* AltGr symbols
128 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
129 * │ ` │ ¹ │ ² │ ³ │ ¤ │ € │ ^ │ ̛  │ ¾ │ ‘ │ ’ │ ¥ │ × │       │
130 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
131 * │     │ Ä │ Å │ É │ ® │ Þ │ Ü │ Ú │ Í │ Ó │ Ö │ « │ » │  ¬  │
132 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
133 * │      │ Á │ ß │ Ð │   │   │   │ Ï │ Œ │ Ø │ ¶ │ ' │        │
134 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
135 * │        │ Æ │   │ © │   │   │ Ñ │ µ │ Ç │ ˙ │ ¿ │          │
136 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
137 * │    │    │    │                        │    │    │    │    │
138 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
139 */
140// Row 1
141#define US_DGRV ALGR(US_GRV) // ` (dead)
142#define US_SUP1 ALGR(US_1) // ¹
143#define US_SUP2 ALGR(US_2) // ²
144#define US_SUP3 ALGR(US_3) // ³
145#define US_CURR ALGR(US_4) // ¤
146#define US_EURO ALGR(US_5) // €
147#define US_DCIR ALGR(US_6) // ^ (dead)
148#define US_HORN ALGR(US_7) // ̛̛ (dead)
149#define US_OGON ALGR(US_8) // ˛ (dead)
150#define US_LSQU ALGR(US_9) // ‘
151#define US_RSQU ALGR(US_0) // ’
152#define US_YEN ALGR(US_MINS) // ¥
153#define US_MUL ALGR(US_EQL) // ×
154// Row 2
155#define US_ADIA ALGR(US_Q) // Ä
156#define US_ARNG ALGR(US_W) // Å
157#define US_EACU ALGR(US_E) // É
158#define US_EDIA ALGR(US_R) // Ë
159#define US_THRN ALGR(US_T) // Þ
160#define US_UDIA ALGR(US_Y) // Ü
161#define US_UACU ALGR(US_U) // Ú
162#define US_IACU ALGR(US_I) // Í
163#define US_OACU ALGR(US_O) // Ó
164#define US_ODIA ALGR(US_P) // Ö
165#define US_LDAQ ALGR(US_LBRC) // «
166#define US_RDAQ ALGR(US_RBRC) // »
167#define US_NOT ALGR(US_BSLS) // ¬
168// Row 3
169#define US_AACU ALGR(US_A) // Á
170#define US_SS ALGR(US_S) // ß
171#define US_ETH ALGR(US_D) // Ð
172#define US_IDIA ALGR(US_J) // Ï
173#define US_OE ALGR(US_K) // Œ
174#define US_OSTR ALGR(US_L) // Ø
175#define US_PILC ALGR(US_SCLN) // ¶
176#define US_ACUT ALGR(US_QUOT) // ´ (dead)
177// Row 4
178#define US_AE ALGR(US_Z) // Æ
179#define US_OE_2 ALGR(US_X) // Œ
180#define US_COPY ALGR(US_C) // ©
181#define US_REGD ALGR(US_V) // ®
182#define US_NTIL ALGR(US_N) // Ñ
183#define US_MICR ALGR(US_M) // µ
184#define US_CCED ALGR(US_COMM) // Ç
185#define US_DOTA ALGR(US_DOT) // ˙ (dead)
186#define US_IQUE ALGR(US_SLSH) // ¿
187
188/* Shift+AltGr symbols
189 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
190 * │ ~ │ ¡ │ ˝ │ ¯ │ £ │ ¸ │ ¼ │ ½ │ ¾ │ ˘ │ ° │  ̣ │ ÷ │       │
191 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
192 * │     │   │   │   │   │   │   │   │   │   │   │ “ │ ” │  ¦  │
193 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
194 * │      │   │ § │   │   │   │   │   │   │   │ ° │ " │        │
195 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
196 * │        │   │   │ ¢ │   │   │   │   │   │ ˇ │  ̉ │          │
197 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
198 * │    │    │    │                        │    │    │    │    │
199 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
200 */
201// Row 1
202#define US_DTIL S(ALGR(US_GRV)) // ~ (dead)
203#define US_IEXL S(ALGR(US_1)) // ¡
204#define US_DACU S(ALGR(US_2)) // ˝ (dead)
205#define US_MACR S(ALGR(US_3)) // ¯ (dead)
206#define US_PND S(ALGR(US_4)) // £
207#define US_CEDL S(ALGR(US_5)) // ¸ (dead)
208#define US_QRTR S(ALGR(US_6)) // ¼
209#define US_HALF S(ALGR(US_7)) // ½
210#define US_TQTR S(ALGR(US_8)) // ¾
211#define US_BREV S(ALGR(US_9)) // ˘ (dead)
212#define US_RNGA S(ALGR(US_0)) // ° (dead)
213#define US_DOTB S(ALGR(US_MINS)) // ̣ (dead)
214#define US_DIV S(ALGR(US_EQL)) // ÷
215// Row 2
216#define US_LDQU S(ALGR(US_LBRC)) // “
217#define US_RDQU S(ALGR(US_LBRC)) // ”
218#define US_BRKP S(ALGR(US_BSLS)) // ¦
219// Row 3
220#define US_SECT S(ALGR(US_S)) // §
221#define US_DEG S(ALGR(US_SCLN)) // °
222#define US_DIAE S(ALGR(US_QUOT)) // ¨ (dead)
223// Row 4
224#define US_CENT S(ALGR(US_C)) // ¢
225#define US_CARN S(ALGR(US_DOT)) // ˇ (dead)
226#define US_HOKA S(ALGR(US_SLSH)) // ̉ (dead)
227
diff --git a/quantum/keymap_extras/keymap_us_international.h b/quantum/keymap_extras/keymap_us_international.h
index a3bc46597..49afcc4fb 100644
--- a/quantum/keymap_extras/keymap_us_international.h
+++ b/quantum/keymap_extras/keymap_us_international.h
@@ -26,7 +26,7 @@
26 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ 26 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
27 * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │  \  │ 27 * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │  \  │
28 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ 28 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
29 * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │        │ 29 * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ´ │        │
30 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ 30 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
31 * │        │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │ 31 * │        │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │
32 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ 32 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
@@ -34,7 +34,7 @@
34 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ 34 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
35 */ 35 */
36// Row 1 36// Row 1
37#define US_GRV KC_GRV // ` (dead) 37#define US_DGRV KC_GRV // ` (dead)
38#define US_1 KC_1 // 1 38#define US_1 KC_1 // 1
39#define US_2 KC_2 // 2 39#define US_2 KC_2 // 2
40#define US_3 KC_3 // 3 40#define US_3 KC_3 // 3
@@ -72,7 +72,7 @@
72#define US_K KC_K // K 72#define US_K KC_K // K
73#define US_L KC_L // L 73#define US_L KC_L // L
74#define US_SCLN KC_SCLN // ; 74#define US_SCLN KC_SCLN // ;
75#define US_QUOT KC_QUOT // ' (dead) 75#define US_ACUT KC_QUOT // ´ (dead)
76// Row 4 76// Row 4
77#define US_Z KC_Z // Z 77#define US_Z KC_Z // Z
78#define US_X KC_X // X 78#define US_X KC_X // X
@@ -91,7 +91,7 @@
91 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤ 91 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
92 * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │ 92 * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │
93 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤ 93 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
94 * │      │   │   │   │   │   │   │   │   │   │ : │ " │        │ 94 * │      │   │   │   │   │   │   │   │   │   │ : │ ¨ │        │
95 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤ 95 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
96 * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │ 96 * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │
97 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤ 97 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
@@ -99,13 +99,13 @@
99 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘ 99 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
100 */ 100 */
101// Row 1 101// Row 1
102#define US_TILD S(US_GRV) // ~ (dead) 102#define US_DTIL S(US_DGRV) // ~ (dead)
103#define US_EXLM S(US_1) // ! 103#define US_EXLM S(US_1) // !
104#define US_AT S(US_2) // " 104#define US_AT S(US_2) // @
105#define US_HASH S(US_3) // # 105#define US_HASH S(US_3) // #
106#define US_DLR S(US_4) // $ 106#define US_DLR S(US_4) // $
107#define US_PERC S(US_5) // % 107#define US_PERC S(US_5) // %
108#define US_CIRC S(US_6) // ^ 108#define US_DCIR S(US_6) // ^ (dead)
109#define US_AMPR S(US_7) // & 109#define US_AMPR S(US_7) // &
110#define US_ASTR S(US_8) // * 110#define US_ASTR S(US_8) // *
111#define US_LPRN S(US_9) // ( 111#define US_LPRN S(US_9) // (
@@ -118,7 +118,7 @@
118#define US_PIPE S(US_BSLS) // | 118#define US_PIPE S(US_BSLS) // |
119// Row 3 119// Row 3
120#define US_COLN S(US_SCLN) // : 120#define US_COLN S(US_SCLN) // :
121#define US_DQUO S(US_QUOT) // " (dead) 121#define US_DIAE S(US_ACUT) // ¨ (dead)
122// Row 4 122// Row 4
123#define US_LABK S(US_COMM) // < 123#define US_LABK S(US_COMM) // <
124#define US_RABK S(US_DOT) // > 124#define US_RABK S(US_DOT) // >
@@ -170,7 +170,7 @@
170#define US_ETH ALGR(US_D) // Ð 170#define US_ETH ALGR(US_D) // Ð
171#define US_OSTR ALGR(US_L) // Ø 171#define US_OSTR ALGR(US_L) // Ø
172#define US_PILC ALGR(US_SCLN) // ¶ 172#define US_PILC ALGR(US_SCLN) // ¶
173#define US_ACUT ALGR(US_QUOT) // ´ 173#define US_NDAC ALGR(US_ACUT) // ´
174// Row 4 174// Row 4
175#define US_AE ALGR(US_Z) // Æ 175#define US_AE ALGR(US_Z) // Æ
176#define US_COPY ALGR(US_C) // © 176#define US_COPY ALGR(US_C) // ©
@@ -201,6 +201,6 @@
201// Row 3 201// Row 3
202#define US_SECT S(ALGR(US_S)) // § 202#define US_SECT S(ALGR(US_S)) // §
203#define US_DEG S(ALGR(US_SCLN)) // ° 203#define US_DEG S(ALGR(US_SCLN)) // °
204#define US_DIAE S(ALGR(US_QUOT)) // ¨ 204#define US_NDDR S(ALGR(US_ACUT)) // ¨
205// Row 4 205// Row 4
206#define US_CENT S(ALGR(US_C)) // ¢ 206#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 000000000..2c3e23039
--- /dev/null
+++ b/quantum/keymap_extras/keymap_us_international_linux.h
@@ -0,0 +1,224 @@
1/* Copyright 2020
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19#include "keymap.h"
20
21// clang-format off
22
23/*
24 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
25 * │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │       │
26 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
27 * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │  \  │
28 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
29 * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ´ │        │
30 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
31 * │        │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │          │
32 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
33 * │    │    │    │                        │    │    │    │    │
34 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
35 */
36// Row 1
37#define US_DGRV KC_GRV // ` (dead)
38#define US_1 KC_1 // 1
39#define US_2 KC_2 // 2
40#define US_3 KC_3 // 3
41#define US_4 KC_4 // 4
42#define US_5 KC_5 // 5
43#define US_6 KC_6 // 6
44#define US_7 KC_7 // 7
45#define US_8 KC_8 // 8
46#define US_9 KC_9 // 9
47#define US_0 KC_0 // 0
48#define US_MINS KC_MINS // -
49#define US_EQL KC_EQL // =
50// Row 2
51#define US_Q KC_Q // Q
52#define US_W KC_W // W
53#define US_E KC_E // E
54#define US_R KC_R // R
55#define US_T KC_T // T
56#define US_Y KC_Y // Y
57#define US_U KC_U // U
58#define US_I KC_I // I
59#define US_O KC_O // O
60#define US_P KC_P // P
61#define US_LBRC KC_LBRC // [
62#define US_RBRC KC_RBRC // ]
63#define US_BSLS KC_BSLS // (backslash)
64// Row 3
65#define US_A KC_A // A
66#define US_S KC_S // S
67#define US_D KC_D // D
68#define US_F KC_F // F
69#define US_G KC_G // G
70#define US_H KC_H // H
71#define US_J KC_J // J
72#define US_K KC_K // K
73#define US_L KC_L // L
74#define US_SCLN KC_SCLN // ;
75#define US_ACUT KC_QUOT // ´ (dead)
76// Row 4
77#define US_Z KC_Z // Z
78#define US_X KC_X // X
79#define US_C KC_C // C
80#define US_V KC_V // V
81#define US_B KC_B // B
82#define US_N KC_N // N
83#define US_M KC_M // M
84#define US_COMM KC_COMM // ,
85#define US_DOT KC_DOT // .
86#define US_SLSH KC_SLSH // /
87
88/* Shifted symbols
89 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
90 * │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │       │
91 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
92 * │     │   │   │   │   │   │   │   │   │   │   │ { │ } │  |  │
93 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
94 * │      │   │   │   │   │   │   │   │   │   │ : │ ¨ │        │
95 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
96 * │        │   │   │   │   │   │   │   │ < │ > │ ? │          │
97 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
98 * │    │    │    │                        │    │    │    │    │
99 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
100 */
101// Row 1
102#define US_DTIL S(US_DGRV) // ~ (dead)
103#define US_EXLM S(US_1) // !
104#define US_AT S(US_2) // @
105#define US_HASH S(US_3) // #
106#define US_DLR S(US_4) // $
107#define US_PERC S(US_5) // %
108#define US_DCIR S(US_6) // ^ (dead)
109#define US_AMPR S(US_7) // &
110#define US_ASTR S(US_8) // *
111#define US_LPRN S(US_9) // (
112#define US_RPRN S(US_0) // )
113#define US_UNDS S(US_MINS) // _
114#define US_PLUS S(US_EQL) // +
115// Row 2
116#define US_LCBR S(US_LBRC) // {
117#define US_RCBR S(US_RBRC) // }
118#define US_PIPE S(US_BSLS) // |
119// Row 3
120#define US_COLN S(US_SCLN) // :
121#define US_DIAE S(US_ACUT) // ¨ (dead)
122// Row 4
123#define US_LABK S(US_COMM) // <
124#define US_RABK S(US_DOT) // >
125#define US_QUES S(US_SLSH) // ?
126
127/* AltGr symbols
128 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
129 * │ ` │ ¡ │ ² │ ³ │ ¤ │ € │ ¼ │ ½ │ ¾ │ ‘ │ ’ │ ¥ │ × │       │
130 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
131 * │     │ Ä │ Å │ É │ ® │ Þ │ Ü │ Ú │ Í │ Ó │ Ö │ « │ » │  ¬  │
132 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
133 * │      │ Á │ ß │ Ð │   │   │   │   │ Œ │ Ø │ ¶ │ ' │        │
134 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
135 * │        │ Æ │   │ © │   │   │ Ñ │ µ │ Ç │ ˙ │ ¿ │          │
136 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
137 * │    │    │    │                        │    │    │    │    │
138 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
139 */
140
141// Row 1
142#define US_GRV ALGR(US_DGRV) // `
143#define US_IEXL ALGR(US_1) // ¡
144#define US_SUP2 ALGR(US_2) // ²
145#define US_SUP3 ALGR(US_3) // ³
146#define US_CURR ALGR(US_4) // ¤
147#define US_EURO ALGR(US_5) // €
148#define US_QRTR ALGR(US_6) // ¼
149#define US_HALF ALGR(US_7) // ½
150#define US_TQTR ALGR(US_8) // ¾
151#define US_LSQU ALGR(US_9) // ‘
152#define US_RSQU ALGR(US_0) // ’
153#define US_YEN ALGR(US_MINS) // ¥
154#define US_MUL ALGR(US_EQL) // ×
155// Row 2
156#define US_ADIA ALGR(US_Q) // Ä
157#define US_ARNG ALGR(US_W) // Å
158#define US_EACU ALGR(US_E) // É
159#define US_REGD ALGR(US_R) // ®
160#define US_THRN ALGR(US_T) // Þ
161#define US_UDIA ALGR(US_Y) // Ü
162#define US_UACU ALGR(US_U) // Ú
163#define US_IACU ALGR(US_I) // Í
164#define US_OACU ALGR(US_O) // Ó
165#define US_ODIA ALGR(US_P) // Ö
166#define US_LDAQ ALGR(US_LBRC) // «
167#define US_RDAQ ALGR(US_RBRC) // »
168#define US_NOT ALGR(US_BSLS) // ¬
169// Row 3
170#define US_AACU ALGR(US_A) // Á
171#define US_SS ALGR(US_S) // ß
172#define US_ETH ALGR(US_D) // Ð
173#define US_OE ALGR(US_K) // Œ
174#define US_OSTR ALGR(US_L) // Ø
175#define US_PILC ALGR(US_SCLN) // ¶
176#define US_QUOT ALGR(US_ACUT) // '
177// Row 4
178#define US_AE ALGR(US_Z) // Æ
179#define US_COPY ALGR(US_C) // ©
180#define US_NTIL ALGR(US_N) // Ñ
181#define US_MICR ALGR(US_M) // µ
182#define US_CCED ALGR(US_COMM) // Ç
183#define US_DOTA ALGR(US_DOT) // ˙ (dead)
184#define US_IQUE ALGR(US_SLSH) // ¿
185
186/* Shift+AltGr symbols
187 * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
188 * │ ~ │ ¹ │ ˝ │ ¯ │ £ │ ¸ │ ^ │ ̛  │ ˛ │ ˘ │ ° │  ̣ │ ÷ │       │
189 * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
190 * │     │   │   │   │   │   │   │   │   │   │   │ “ │ ” │  ¦  │
191 * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
192 * │      │   │ § │   │   │   │   │   │   │   │ ° │ " │        │
193 * ├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────────┤
194 * │        │   │   │ ¢ │   │   │   │   │   │ ˇ │  ̉ │          │
195 * ├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
196 * │    │    │    │                        │    │    │    │    │
197 * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
198 */
199// Row 1
200#define US_TILD S(ALGR(US_DGRV)) // ~
201#define US_SUP1 S(ALGR(US_1)) // ¹
202#define US_DACU S(ALGR(US_2)) // ˝ (dead)
203#define US_MACR S(ALGR(US_3)) // ¯ (dead)
204#define US_PND S(ALGR(US_4)) // £
205#define US_CEDL S(ALGR(US_5)) // ¸ (dead)
206#define US_CIRC S(ALGR(US_6)) // ^
207#define US_HORN S(ALGR(US_7)) // ̛ (dead)
208#define US_OGON S(ALGR(US_8)) // ˛ (dead)
209#define US_BREV S(ALGR(US_9)) // ˘ (dead)
210#define US_RNGA S(ALGR(US_0)) // ° (dead)
211#define US_DOTB S(ALGR(US_MINS)) // ̣ (dead)
212#define US_DIV S(ALGR(US_EQL)) // ÷
213// Row 2
214#define US_LDQU S(ALGR(US_LBRC)) // “
215#define US_RDQU S(ALGR(US_LBRC)) // ”
216#define US_BRKP S(ALGR(US_BSLS)) // ¦
217// Row 3
218#define US_SECT S(ALGR(US_S)) // §
219#define US_DEG S(ALGR(US_SCLN)) // °
220#define US_DQUO S(ALGR(US_ACUT)) // "
221// Row 4
222#define US_CENT S(ALGR(US_C)) // ¢
223#define US_CARN S(ALGR(US_DOT)) // ˇ (dead)
224#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 000000000..53a5891fb
--- /dev/null
+++ b/quantum/keymap_extras/sendstring_us_international.h
@@ -0,0 +1,100 @@
1/* Copyright 2019 Rys Sommefeldt
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17// Sendstring lookup tables for UK layouts
18
19#pragma once
20
21#include "keymap_us_international.h"
22#include "quantum.h"
23
24// clang-format off
25
26const uint8_t ascii_to_shift_lut[16] PROGMEM = {
27 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
28 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
29 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
30 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
31
32 KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 0),
33 KCLUT_ENTRY(1, 1, 1, 1, 0, 0, 0, 0),
34 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
35 KCLUT_ENTRY(0, 0, 1, 0, 1, 0, 1, 1),
36 KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
37 KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
38 KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
39 KCLUT_ENTRY(1, 1, 1, 0, 0, 0, 1, 1),
40 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
41 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
42 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
43 KCLUT_ENTRY(0, 0, 0, 1, 1, 1, 1, 0),
44};
45
46__attribute__((weak)) const uint8_t ascii_to_dead_lut[16] PROGMEM = {
47 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
48 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
49 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
50 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
51
52 KCLUT_ENTRY(0, 0, 1, 0, 0, 0, 0, 1),
53 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
54 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
55 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
56 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
57 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
58 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
59 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 1, 0),
60 KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0),
61 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
62 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
63 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 1, 0),
64};
65
66const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
67 // NUL SOH STX ETX EOT ENQ ACK BEL
68 XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
69 // BS TAB LF VT FF CR SO SI
70 KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
71 // DLE DC1 DC2 DC3 DC4 NAK SYN ETB
72 XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
73 // CAN EM SUB ESC FS GS RS US
74 XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
75
76 // ! " # $ % & '
77 KC_SPC, US_1, US_ACUT, US_3, US_4, US_5, US_7, US_ACUT,
78 // ( ) * + , - . /
79 US_9, US_0, US_8, US_EQL, US_COMM, US_MINS, US_DOT, US_SLSH,
80 // 0 1 2 3 4 5 6 7
81 US_0, US_1, US_2, US_3, US_4, US_5, US_6, US_7,
82 // 8 9 : ; < = > ?
83 US_8, US_9, US_SCLN, US_SCLN, US_COMM, US_EQL, US_DOT, US_SLSH,
84 // @ A B C D E F G
85 US_2, US_A, US_B, US_C, US_D, US_E, US_F, US_G,
86 // H I J K L M N O
87 US_H, US_I, US_J, US_K, US_L, US_M, US_N, US_O,
88 // P Q R S T U V W
89 US_P, US_Q, US_R, US_S, US_T, US_U, US_V, US_W,
90 // X Y Z [ \ ] ^ _
91 US_X, US_Y, US_Z, US_LBRC, US_BSLS, US_RBRC, US_6, US_MINS,
92 // ` a b c d e f g
93 US_DGRV, US_A, US_B, US_C, US_D, US_E, US_F, US_G,
94 // h i j k l m n o
95 US_H, US_I, US_J, US_K, US_L, US_M, US_N, US_O,
96 // p q r s t u v w
97 US_P, US_Q, US_R, US_S, US_T, US_U, US_V, US_W,
98 // x y z { | } ~ DEL
99 US_X, US_Y, US_Z, US_LBRC, US_BSLS, US_RBRC, US_DGRV, KC_DEL
100};
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 9083ff386..c027b7bf2 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)
101 // Start with a clear matrix row 101 // Start with a clear matrix row
102 matrix_row_t current_row_value = 0; 102 matrix_row_t current_row_value = 0;
103 103
104 // Select row and wait for row selecton to stabilize 104 // Select row
105 select_row(current_row); 105 select_row(current_row);
106 matrix_io_delay(); 106 matrix_output_select_delay();
107 107
108 // For each col... 108 // For each col...
109 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 109 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)
116 116
117 // Unselect row 117 // Unselect row
118 unselect_row(current_row); 118 unselect_row(current_row);
119 if (current_row + 1 < MATRIX_ROWS) {
120 matrix_output_unselect_delay(); // wait for row signal to go HIGH
121 }
119 122
120 // If the row has changed, store the row and return the changed flag. 123 // If the row has changed, store the row and return the changed flag.
121 if (current_matrix[current_row] != current_row_value) { 124 if (current_matrix[current_row] != current_row_value) {
@@ -147,9 +150,9 @@ static void init_pins(void) {
147static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 150static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
148 bool matrix_changed = false; 151 bool matrix_changed = false;
149 152
150 // Select col and wait for col selecton to stabilize 153 // Select col
151 select_col(current_col); 154 select_col(current_col);
152 matrix_io_delay(); 155 matrix_output_select_delay();
153 156
154 // For each row... 157 // For each row...
155 for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { 158 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)
175 178
176 // Unselect col 179 // Unselect col
177 unselect_col(current_col); 180 unselect_col(current_col);
181 if (current_col + 1 < MATRIX_COLS) {
182 matrix_output_unselect_delay(); // wait for col signal to go HIGH
183 }
178 184
179 return matrix_changed; 185 return matrix_changed;
180} 186}
diff --git a/quantum/matrix.h b/quantum/matrix.h
index b570227a3..ce57010a4 100644
--- a/quantum/matrix.h
+++ b/quantum/matrix.h
@@ -55,6 +55,9 @@ matrix_row_t matrix_get_row(uint8_t row);
55/* print matrix for debug */ 55/* print matrix for debug */
56void matrix_print(void); 56void matrix_print(void);
57/* delay between changing matrix pin state and reading values */ 57/* delay between changing matrix pin state and reading values */
58void matrix_output_select_delay(void);
59void matrix_output_unselect_delay(void);
60/* only for backwards compatibility. delay between changing matrix pin state and reading values */
58void matrix_io_delay(void); 61void matrix_io_delay(void);
59 62
60/* power control */ 63/* power control */
diff --git a/quantum/matrix_common.c b/quantum/matrix_common.c
index 15f1e0e82..efbad6a5f 100644
--- a/quantum/matrix_common.c
+++ b/quantum/matrix_common.c
@@ -1,3 +1,4 @@
1#include "quantum.h"
1#include "matrix.h" 2#include "matrix.h"
2#include "debounce.h" 3#include "debounce.h"
3#include "wait.h" 4#include "wait.h"
@@ -68,7 +69,7 @@ void matrix_print(void) {
68 print_matrix_header(); 69 print_matrix_header();
69 70
70 for (uint8_t row = 0; row < MATRIX_ROWS; row++) { 71 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
71 phex(row); 72 print_hex8(row);
72 print(": "); 73 print(": ");
73 print_matrix_row(row); 74 print_matrix_row(row);
74 print("\n"); 75 print("\n");
@@ -83,8 +84,12 @@ uint8_t matrix_key_count(void) {
83 return count; 84 return count;
84} 85}
85 86
87/* `matrix_io_delay ()` exists for backwards compatibility. From now on, use matrix_output_unselect_delay(). */
86__attribute__((weak)) void matrix_io_delay(void) { wait_us(MATRIX_IO_DELAY); } 88__attribute__((weak)) void matrix_io_delay(void) { wait_us(MATRIX_IO_DELAY); }
87 89
90__attribute__((weak)) void matrix_output_select_delay(void) { waitInputPinDelay(); }
91__attribute__((weak)) void matrix_output_unselect_delay(void) { matrix_io_delay(); }
92
88// CUSTOM MATRIX 'LITE' 93// CUSTOM MATRIX 'LITE'
89__attribute__((weak)) void matrix_init_custom(void) {} 94__attribute__((weak)) void matrix_init_custom(void) {}
90 95
diff --git a/quantum/mcu_selection.mk b/quantum/mcu_selection.mk
index 6b11eb498..81c467c65 100644
--- a/quantum/mcu_selection.mk
+++ b/quantum/mcu_selection.mk
@@ -279,7 +279,73 @@ ifneq ($(findstring STM32F411, $(MCU)),)
279 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11 279 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
280endif 280endif
281 281
282ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287)) 282ifneq ($(findstring STM32G431, $(MCU)),)
283 # Cortex version
284 MCU = cortex-m4
285
286 # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
287 ARMV = 7
288
289 ## chip/board settings
290 # - the next two should match the directories in
291 # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
292 MCU_FAMILY = STM32
293 MCU_SERIES = STM32G4xx
294
295 # Linker script to use
296 # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
297 # or <keyboard_dir>/ld/
298 MCU_LDSCRIPT ?= STM32G431xB
299
300 # Startup code to use
301 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
302 MCU_STARTUP ?= stm32g4xx
303
304 # Board: it should exist either in <chibios>/os/hal/boards/,
305 # <keyboard_dir>/boards/, or drivers/boards/
306 BOARD ?= GENERIC_STM32_G431XB
307
308 USE_FPU ?= yes
309
310 # Options to pass to dfu-util when flashing
311 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
312 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
313endif
314
315ifneq ($(findstring STM32G474, $(MCU)),)
316 # Cortex version
317 MCU = cortex-m4
318
319 # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
320 ARMV = 7
321
322 ## chip/board settings
323 # - the next two should match the directories in
324 # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
325 MCU_FAMILY = STM32
326 MCU_SERIES = STM32G4xx
327
328 # Linker script to use
329 # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
330 # or <keyboard_dir>/ld/
331 MCU_LDSCRIPT ?= STM32G474xE
332
333 # Startup code to use
334 # - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
335 MCU_STARTUP ?= stm32g4xx
336
337 # Board: it should exist either in <chibios>/os/hal/boards/,
338 # <keyboard_dir>/boards/, or drivers/boards/
339 BOARD ?= GENERIC_STM32_G474XE
340
341 USE_FPU ?= yes
342
343 # Options to pass to dfu-util when flashing
344 DFU_ARGS ?= -d 0483:DF11 -a 0 -s 0x08000000:leave
345 DFU_SUFFIX_ARGS ?= -v 0483 -p DF11
346endif
347
348ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 at90usb647 at90usb1286 at90usb1287))
283 PROTOCOL = LUFA 349 PROTOCOL = LUFA
284 350
285 # Processor frequency. 351 # Processor frequency.
@@ -317,7 +383,7 @@ ifneq (,$(filter $(MCU),atmega16u2 atmega32u2 atmega16u4 atmega32u4 at90usb646 a
317 ifeq (,$(filter $(NO_INTERRUPT_CONTROL_ENDPOINT),yes)) 383 ifeq (,$(filter $(NO_INTERRUPT_CONTROL_ENDPOINT),yes))
318 OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT 384 OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
319 endif 385 endif
320 ifneq (,$(filter $(MCU),atmega16u2 atmega32u2)) 386 ifneq (,$(filter $(MCU),at90usb162 atmega16u2 atmega32u2))
321 NO_I2C = yes 387 NO_I2C = yes
322 endif 388 endif
323endif 389endif
diff --git a/quantum/mousekey.c b/quantum/mousekey.c
new file mode 100644
index 000000000..63e74baa9
--- /dev/null
+++ b/quantum/mousekey.c
@@ -0,0 +1,488 @@
1/*
2 * Copyright 2011 Jun Wako <wakojun@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <stdint.h>
19#include "keycode.h"
20#include "host.h"
21#include "timer.h"
22#include "print.h"
23#include "debug.h"
24#include "mousekey.h"
25
26inline int8_t times_inv_sqrt2(int8_t x) {
27 // 181/256 is pretty close to 1/sqrt(2)
28 // 0.70703125 0.707106781
29 // 1 too small for x=99 and x=198
30 // This ends up being a mult and discard lower 8 bits
31 return (x * 181) >> 8;
32}
33
34static report_mouse_t mouse_report = {0};
35static void mousekey_debug(void);
36static uint8_t mousekey_accel = 0;
37static uint8_t mousekey_repeat = 0;
38static uint8_t mousekey_wheel_repeat = 0;
39#ifdef MK_KINETIC_SPEED
40static uint16_t mouse_timer = 0;
41#endif
42
43#ifndef MK_3_SPEED
44
45static uint16_t last_timer_c = 0;
46static uint16_t last_timer_w = 0;
47
48/*
49 * Mouse keys acceleration algorithm
50 * http://en.wikipedia.org/wiki/Mouse_keys
51 *
52 * speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
53 */
54/* milliseconds between the initial key press and first repeated motion event (0-2550) */
55uint8_t mk_delay = MOUSEKEY_DELAY / 10;
56/* milliseconds between repeated motion events (0-255) */
57uint8_t mk_interval = MOUSEKEY_INTERVAL;
58/* steady speed (in action_delta units) applied each event (0-255) */
59uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED;
60/* number of events (count) accelerating to steady speed (0-255) */
61uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
62/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
63// int8_t mk_curve = 0;
64/* wheel params */
65/* milliseconds between the initial key press and first repeated motion event (0-2550) */
66uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10;
67/* milliseconds between repeated motion events (0-255) */
68uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;
69uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
70uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
71
72# ifndef MK_COMBINED
73
74static uint8_t move_unit(void) {
75 uint16_t unit;
76 if (mousekey_accel & (1 << 0)) {
77 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4;
78 } else if (mousekey_accel & (1 << 1)) {
79 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2;
80 } else if (mousekey_accel & (1 << 2)) {
81 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
82 } else if (mousekey_repeat == 0) {
83 unit = MOUSEKEY_MOVE_DELTA;
84 } else if (mousekey_repeat >= mk_time_to_max) {
85 unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
86 } else {
87 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
88 }
89 return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
90}
91
92static uint8_t wheel_unit(void) {
93 uint16_t unit;
94 if (mousekey_accel & (1 << 0)) {
95 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4;
96 } else if (mousekey_accel & (1 << 1)) {
97 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2;
98 } else if (mousekey_accel & (1 << 2)) {
99 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
100 } else if (mousekey_wheel_repeat == 0) {
101 unit = MOUSEKEY_WHEEL_DELTA;
102 } else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) {
103 unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
104 } else {
105 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_wheel_repeat) / mk_wheel_time_to_max;
106 }
107 return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
108}
109
110# else /* #ifndef MK_COMBINED */
111# ifndef MK_KINETIC_SPEED
112
113/*
114 * Kinetic movement acceleration algorithm
115 *
116 * current speed = I + A * T/50 + A * 0.5 * T^2 | maximum B
117 *
118 * T: time since the mouse movement started
119 * E: mouse events per second (set through MOUSEKEY_INTERVAL, UHK sends 250, the
120 * pro micro on my Signum 3.0 sends only 125!)
121 * I: initial speed at time 0
122 * A: acceleration
123 * B: base mouse travel speed
124 */
125const uint16_t mk_accelerated_speed = MOUSEKEY_ACCELERATED_SPEED;
126const uint16_t mk_base_speed = MOUSEKEY_BASE_SPEED;
127const uint16_t mk_decelerated_speed = MOUSEKEY_DECELERATED_SPEED;
128const uint16_t mk_initial_speed = MOUSEKEY_INITIAL_SPEED;
129
130static uint8_t move_unit(void) {
131 float speed = mk_initial_speed;
132
133 if (mousekey_accel & ((1 << 0) | (1 << 2))) {
134 speed = mousekey_accel & (1 << 2) ? mk_accelerated_speed : mk_decelerated_speed;
135 } else if (mousekey_repeat && mouse_timer) {
136 const float time_elapsed = timer_elapsed(mouse_timer) / 50;
137 speed = mk_initial_speed + MOUSEKEY_MOVE_DELTA * time_elapsed + MOUSEKEY_MOVE_DELTA * 0.5 * time_elapsed * time_elapsed;
138
139 speed = speed > mk_base_speed ? mk_base_speed : speed;
140 }
141
142 /* convert speed to USB mouse speed 1 to 127 */
143 speed = (uint8_t)(speed / (1000.0f / mk_interval));
144 speed = speed < 1 ? 1 : speed;
145
146 return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed;
147}
148
149float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
150
151static uint8_t wheel_unit(void) {
152 float speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
153
154 if (mousekey_accel & ((1 << 0) | (1 << 2))) {
155 speed = mousekey_accel & (1 << 2) ? MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS : MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS;
156 } else if (mousekey_repeat && mouse_timer) {
157 if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) {
158 const float time_elapsed = timer_elapsed(mouse_timer) / 50;
159 speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + 1 * 0.5 * time_elapsed * time_elapsed;
160 }
161 speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed;
162 }
163
164 mk_wheel_interval = 1000.0f / speed;
165
166 return 1;
167}
168
169# else /* #ifndef MK_KINETIC_SPEED */
170
171static uint8_t move_unit(void) {
172 uint16_t unit;
173 if (mousekey_accel & (1 << 0)) {
174 unit = 1;
175 } else if (mousekey_accel & (1 << 1)) {
176 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2;
177 } else if (mousekey_accel & (1 << 2)) {
178 unit = MOUSEKEY_MOVE_MAX;
179 } else if (mousekey_repeat == 0) {
180 unit = MOUSEKEY_MOVE_DELTA;
181 } else if (mousekey_repeat >= mk_time_to_max) {
182 unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
183 } else {
184 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
185 }
186 return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
187}
188
189static uint8_t wheel_unit(void) {
190 uint16_t unit;
191 if (mousekey_accel & (1 << 0)) {
192 unit = 1;
193 } else if (mousekey_accel & (1 << 1)) {
194 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2;
195 } else if (mousekey_accel & (1 << 2)) {
196 unit = MOUSEKEY_WHEEL_MAX;
197 } else if (mousekey_repeat == 0) {
198 unit = MOUSEKEY_WHEEL_DELTA;
199 } else if (mousekey_repeat >= mk_wheel_time_to_max) {
200 unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
201 } else {
202 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
203 }
204 return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
205}
206
207# endif /* #ifndef MK_KINETIC_SPEED */
208# endif /* #ifndef MK_COMBINED */
209
210void mousekey_task(void) {
211 // report cursor and scroll movement independently
212 report_mouse_t const tmpmr = mouse_report;
213
214 mouse_report.x = 0;
215 mouse_report.y = 0;
216 mouse_report.v = 0;
217 mouse_report.h = 0;
218
219 if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) {
220 if (mousekey_repeat != UINT8_MAX) mousekey_repeat++;
221 if (tmpmr.x != 0) mouse_report.x = move_unit() * ((tmpmr.x > 0) ? 1 : -1);
222 if (tmpmr.y != 0) mouse_report.y = move_unit() * ((tmpmr.y > 0) ? 1 : -1);
223
224 /* diagonal move [1/sqrt(2)] */
225 if (mouse_report.x && mouse_report.y) {
226 mouse_report.x = times_inv_sqrt2(mouse_report.x);
227 if (mouse_report.x == 0) {
228 mouse_report.x = 1;
229 }
230 mouse_report.y = times_inv_sqrt2(mouse_report.y);
231 if (mouse_report.y == 0) {
232 mouse_report.y = 1;
233 }
234 }
235 }
236 if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) {
237 if (mousekey_wheel_repeat != UINT8_MAX) mousekey_wheel_repeat++;
238 if (tmpmr.v != 0) mouse_report.v = wheel_unit() * ((tmpmr.v > 0) ? 1 : -1);
239 if (tmpmr.h != 0) mouse_report.h = wheel_unit() * ((tmpmr.h > 0) ? 1 : -1);
240
241 /* diagonal move [1/sqrt(2)] */
242 if (mouse_report.v && mouse_report.h) {
243 mouse_report.v = times_inv_sqrt2(mouse_report.v);
244 if (mouse_report.v == 0) {
245 mouse_report.v = 1;
246 }
247 mouse_report.h = times_inv_sqrt2(mouse_report.h);
248 if (mouse_report.h == 0) {
249 mouse_report.h = 1;
250 }
251 }
252 }
253
254 if (mouse_report.x || mouse_report.y || mouse_report.v || mouse_report.h) mousekey_send();
255 mouse_report = tmpmr;
256}
257
258void mousekey_on(uint8_t code) {
259# ifdef MK_KINETIC_SPEED
260 if (mouse_timer == 0) {
261 mouse_timer = timer_read();
262 }
263# endif /* #ifdef MK_KINETIC_SPEED */
264
265 if (code == KC_MS_UP)
266 mouse_report.y = move_unit() * -1;
267 else if (code == KC_MS_DOWN)
268 mouse_report.y = move_unit();
269 else if (code == KC_MS_LEFT)
270 mouse_report.x = move_unit() * -1;
271 else if (code == KC_MS_RIGHT)
272 mouse_report.x = move_unit();
273 else if (code == KC_MS_WH_UP)
274 mouse_report.v = wheel_unit();
275 else if (code == KC_MS_WH_DOWN)
276 mouse_report.v = wheel_unit() * -1;
277 else if (code == KC_MS_WH_LEFT)
278 mouse_report.h = wheel_unit() * -1;
279 else if (code == KC_MS_WH_RIGHT)
280 mouse_report.h = wheel_unit();
281 else if (IS_MOUSEKEY_BUTTON(code))
282 mouse_report.buttons |= 1 << (code - KC_MS_BTN1);
283 else if (code == KC_MS_ACCEL0)
284 mousekey_accel |= (1 << 0);
285 else if (code == KC_MS_ACCEL1)
286 mousekey_accel |= (1 << 1);
287 else if (code == KC_MS_ACCEL2)
288 mousekey_accel |= (1 << 2);
289}
290
291void mousekey_off(uint8_t code) {
292 if (code == KC_MS_UP && mouse_report.y < 0)
293 mouse_report.y = 0;
294 else if (code == KC_MS_DOWN && mouse_report.y > 0)
295 mouse_report.y = 0;
296 else if (code == KC_MS_LEFT && mouse_report.x < 0)
297 mouse_report.x = 0;
298 else if (code == KC_MS_RIGHT && mouse_report.x > 0)
299 mouse_report.x = 0;
300 else if (code == KC_MS_WH_UP && mouse_report.v > 0)
301 mouse_report.v = 0;
302 else if (code == KC_MS_WH_DOWN && mouse_report.v < 0)
303 mouse_report.v = 0;
304 else if (code == KC_MS_WH_LEFT && mouse_report.h < 0)
305 mouse_report.h = 0;
306 else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0)
307 mouse_report.h = 0;
308 else if (IS_MOUSEKEY_BUTTON(code))
309 mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1));
310 else if (code == KC_MS_ACCEL0)
311 mousekey_accel &= ~(1 << 0);
312 else if (code == KC_MS_ACCEL1)
313 mousekey_accel &= ~(1 << 1);
314 else if (code == KC_MS_ACCEL2)
315 mousekey_accel &= ~(1 << 2);
316 if (mouse_report.x == 0 && mouse_report.y == 0) {
317 mousekey_repeat = 0;
318# ifdef MK_KINETIC_SPEED
319 mouse_timer = 0;
320# endif /* #ifdef MK_KINETIC_SPEED */
321 }
322 if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0;
323}
324
325#else /* #ifndef MK_3_SPEED */
326
327enum { mkspd_unmod, mkspd_0, mkspd_1, mkspd_2, mkspd_COUNT };
328# ifndef MK_MOMENTARY_ACCEL
329static uint8_t mk_speed = mkspd_1;
330# else
331static uint8_t mk_speed = mkspd_unmod;
332static uint8_t mkspd_DEFAULT = mkspd_unmod;
333# endif
334static uint16_t last_timer_c = 0;
335static uint16_t last_timer_w = 0;
336uint16_t c_offsets[mkspd_COUNT] = {MK_C_OFFSET_UNMOD, MK_C_OFFSET_0, MK_C_OFFSET_1, MK_C_OFFSET_2};
337uint16_t c_intervals[mkspd_COUNT] = {MK_C_INTERVAL_UNMOD, MK_C_INTERVAL_0, MK_C_INTERVAL_1, MK_C_INTERVAL_2};
338uint16_t w_offsets[mkspd_COUNT] = {MK_W_OFFSET_UNMOD, MK_W_OFFSET_0, MK_W_OFFSET_1, MK_W_OFFSET_2};
339uint16_t w_intervals[mkspd_COUNT] = {MK_W_INTERVAL_UNMOD, MK_W_INTERVAL_0, MK_W_INTERVAL_1, MK_W_INTERVAL_2};
340
341void mousekey_task(void) {
342 // report cursor and scroll movement independently
343 report_mouse_t const tmpmr = mouse_report;
344 mouse_report.x = 0;
345 mouse_report.y = 0;
346 mouse_report.v = 0;
347 mouse_report.h = 0;
348
349 if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > c_intervals[mk_speed]) {
350 mouse_report.x = tmpmr.x;
351 mouse_report.y = tmpmr.y;
352 }
353 if ((tmpmr.h || tmpmr.v) && timer_elapsed(last_timer_w) > w_intervals[mk_speed]) {
354 mouse_report.v = tmpmr.v;
355 mouse_report.h = tmpmr.h;
356 }
357
358 if (mouse_report.x || mouse_report.y || mouse_report.v || mouse_report.h) mousekey_send();
359 mouse_report = tmpmr;
360}
361
362void adjust_speed(void) {
363 uint16_t const c_offset = c_offsets[mk_speed];
364 uint16_t const w_offset = w_offsets[mk_speed];
365 if (mouse_report.x > 0) mouse_report.x = c_offset;
366 if (mouse_report.x < 0) mouse_report.x = c_offset * -1;
367 if (mouse_report.y > 0) mouse_report.y = c_offset;
368 if (mouse_report.y < 0) mouse_report.y = c_offset * -1;
369 if (mouse_report.h > 0) mouse_report.h = w_offset;
370 if (mouse_report.h < 0) mouse_report.h = w_offset * -1;
371 if (mouse_report.v > 0) mouse_report.v = w_offset;
372 if (mouse_report.v < 0) mouse_report.v = w_offset * -1;
373 // adjust for diagonals
374 if (mouse_report.x && mouse_report.y) {
375 mouse_report.x = times_inv_sqrt2(mouse_report.x);
376 if (mouse_report.x == 0) {
377 mouse_report.x = 1;
378 }
379 mouse_report.y = times_inv_sqrt2(mouse_report.y);
380 if (mouse_report.y == 0) {
381 mouse_report.y = 1;
382 }
383 }
384 if (mouse_report.h && mouse_report.v) {
385 mouse_report.h = times_inv_sqrt2(mouse_report.h);
386 mouse_report.v = times_inv_sqrt2(mouse_report.v);
387 }
388}
389
390void mousekey_on(uint8_t code) {
391 uint16_t const c_offset = c_offsets[mk_speed];
392 uint16_t const w_offset = w_offsets[mk_speed];
393 uint8_t const old_speed = mk_speed;
394 if (code == KC_MS_UP)
395 mouse_report.y = c_offset * -1;
396 else if (code == KC_MS_DOWN)
397 mouse_report.y = c_offset;
398 else if (code == KC_MS_LEFT)
399 mouse_report.x = c_offset * -1;
400 else if (code == KC_MS_RIGHT)
401 mouse_report.x = c_offset;
402 else if (code == KC_MS_WH_UP)
403 mouse_report.v = w_offset;
404 else if (code == KC_MS_WH_DOWN)
405 mouse_report.v = w_offset * -1;
406 else if (code == KC_MS_WH_LEFT)
407 mouse_report.h = w_offset * -1;
408 else if (code == KC_MS_WH_RIGHT)
409 mouse_report.h = w_offset;
410 else if (IS_MOUSEKEY_BUTTON(code))
411 mouse_report.buttons |= 1 << (code - KC_MS_BTN1);
412 else if (code == KC_MS_ACCEL0)
413 mk_speed = mkspd_0;
414 else if (code == KC_MS_ACCEL1)
415 mk_speed = mkspd_1;
416 else if (code == KC_MS_ACCEL2)
417 mk_speed = mkspd_2;
418 if (mk_speed != old_speed) adjust_speed();
419}
420
421void mousekey_off(uint8_t code) {
422# ifdef MK_MOMENTARY_ACCEL
423 uint8_t const old_speed = mk_speed;
424# endif
425 if (code == KC_MS_UP && mouse_report.y < 0)
426 mouse_report.y = 0;
427 else if (code == KC_MS_DOWN && mouse_report.y > 0)
428 mouse_report.y = 0;
429 else if (code == KC_MS_LEFT && mouse_report.x < 0)
430 mouse_report.x = 0;
431 else if (code == KC_MS_RIGHT && mouse_report.x > 0)
432 mouse_report.x = 0;
433 else if (code == KC_MS_WH_UP && mouse_report.v > 0)
434 mouse_report.v = 0;
435 else if (code == KC_MS_WH_DOWN && mouse_report.v < 0)
436 mouse_report.v = 0;
437 else if (code == KC_MS_WH_LEFT && mouse_report.h < 0)
438 mouse_report.h = 0;
439 else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0)
440 mouse_report.h = 0;
441 else if (IS_MOUSEKEY_BUTTON(code))
442 mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1));
443# ifdef MK_MOMENTARY_ACCEL
444 else if (code == KC_MS_ACCEL0)
445 mk_speed = mkspd_DEFAULT;
446 else if (code == KC_MS_ACCEL1)
447 mk_speed = mkspd_DEFAULT;
448 else if (code == KC_MS_ACCEL2)
449 mk_speed = mkspd_DEFAULT;
450 if (mk_speed != old_speed) adjust_speed();
451# endif
452}
453
454#endif /* #ifndef MK_3_SPEED */
455
456void mousekey_send(void) {
457 mousekey_debug();
458 uint16_t time = timer_read();
459 if (mouse_report.x || mouse_report.y) last_timer_c = time;
460 if (mouse_report.v || mouse_report.h) last_timer_w = time;
461 host_mouse_send(&mouse_report);
462}
463
464void mousekey_clear(void) {
465 mouse_report = (report_mouse_t){};
466 mousekey_repeat = 0;
467 mousekey_wheel_repeat = 0;
468 mousekey_accel = 0;
469}
470
471static void mousekey_debug(void) {
472 if (!debug_mouse) return;
473 print("mousekey [btn|x y v h](rep/acl): [");
474 print_hex8(mouse_report.buttons);
475 print("|");
476 print_decs(mouse_report.x);
477 print(" ");
478 print_decs(mouse_report.y);
479 print(" ");
480 print_decs(mouse_report.v);
481 print(" ");
482 print_decs(mouse_report.h);
483 print("](");
484 print_dec(mousekey_repeat);
485 print("/");
486 print_dec(mousekey_accel);
487 print(")\n");
488}
diff --git a/quantum/mousekey.h b/quantum/mousekey.h
new file mode 100644
index 000000000..70dc4bb5c
--- /dev/null
+++ b/quantum/mousekey.h
@@ -0,0 +1,179 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#pragma once
19
20#include <stdint.h>
21#include "host.h"
22
23#ifndef MK_3_SPEED
24
25/* max value on report descriptor */
26# ifndef MOUSEKEY_MOVE_MAX
27# define MOUSEKEY_MOVE_MAX 127
28# elif MOUSEKEY_MOVE_MAX > 127
29# error MOUSEKEY_MOVE_MAX needs to be smaller than 127
30# endif
31
32# ifndef MOUSEKEY_WHEEL_MAX
33# define MOUSEKEY_WHEEL_MAX 127
34# elif MOUSEKEY_WHEEL_MAX > 127
35# error MOUSEKEY_WHEEL_MAX needs to be smaller than 127
36# endif
37
38# ifndef MOUSEKEY_MOVE_DELTA
39# ifndef MK_KINETIC_SPEED
40# define MOUSEKEY_MOVE_DELTA 5
41# else
42# define MOUSEKEY_MOVE_DELTA 25
43# endif
44# endif
45# ifndef MOUSEKEY_WHEEL_DELTA
46# define MOUSEKEY_WHEEL_DELTA 1
47# endif
48# ifndef MOUSEKEY_DELAY
49# ifndef MK_KINETIC_SPEED
50# define MOUSEKEY_DELAY 300
51# else
52# define MOUSEKEY_DELAY 8
53# endif
54# endif
55# ifndef MOUSEKEY_INTERVAL
56# ifndef MK_KINETIC_SPEED
57# define MOUSEKEY_INTERVAL 50
58# else
59# define MOUSEKEY_INTERVAL 8
60# endif
61# endif
62# ifndef MOUSEKEY_MAX_SPEED
63# define MOUSEKEY_MAX_SPEED 10
64# endif
65# ifndef MOUSEKEY_TIME_TO_MAX
66# define MOUSEKEY_TIME_TO_MAX 20
67# endif
68# ifndef MOUSEKEY_WHEEL_DELAY
69# define MOUSEKEY_WHEEL_DELAY 300
70# endif
71# ifndef MOUSEKEY_WHEEL_INTERVAL
72# define MOUSEKEY_WHEEL_INTERVAL 100
73# endif
74# ifndef MOUSEKEY_WHEEL_MAX_SPEED
75# define MOUSEKEY_WHEEL_MAX_SPEED 8
76# endif
77# ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
78# define MOUSEKEY_WHEEL_TIME_TO_MAX 40
79# endif
80
81# ifndef MOUSEKEY_INITIAL_SPEED
82# define MOUSEKEY_INITIAL_SPEED 100
83# endif
84# ifndef MOUSEKEY_BASE_SPEED
85# define MOUSEKEY_BASE_SPEED 1000
86# endif
87# ifndef MOUSEKEY_DECELERATED_SPEED
88# define MOUSEKEY_DECELERATED_SPEED 400
89# endif
90# ifndef MOUSEKEY_ACCELERATED_SPEED
91# define MOUSEKEY_ACCELERATED_SPEED 3000
92# endif
93# ifndef MOUSEKEY_WHEEL_INITIAL_MOVEMENTS
94# define MOUSEKEY_WHEEL_INITIAL_MOVEMENTS 16
95# endif
96# ifndef MOUSEKEY_WHEEL_BASE_MOVEMENTS
97# define MOUSEKEY_WHEEL_BASE_MOVEMENTS 32
98# endif
99# ifndef MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS
100# define MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS 48
101# endif
102# ifndef MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS
103# define MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS 8
104# endif
105
106#else /* #ifndef MK_3_SPEED */
107
108# ifndef MK_C_OFFSET_UNMOD
109# define MK_C_OFFSET_UNMOD 16
110# endif
111# ifndef MK_C_INTERVAL_UNMOD
112# define MK_C_INTERVAL_UNMOD 16
113# endif
114# ifndef MK_C_OFFSET_0
115# define MK_C_OFFSET_0 1
116# endif
117# ifndef MK_C_INTERVAL_0
118# define MK_C_INTERVAL_0 32
119# endif
120# ifndef MK_C_OFFSET_1
121# define MK_C_OFFSET_1 4
122# endif
123# ifndef MK_C_INTERVAL_1
124# define MK_C_INTERVAL_1 16
125# endif
126# ifndef MK_C_OFFSET_2
127# define MK_C_OFFSET_2 32
128# endif
129# ifndef MK_C_INTERVAL_2
130# define MK_C_INTERVAL_2 16
131# endif
132
133# ifndef MK_W_OFFSET_UNMOD
134# define MK_W_OFFSET_UNMOD 1
135# endif
136# ifndef MK_W_INTERVAL_UNMOD
137# define MK_W_INTERVAL_UNMOD 40
138# endif
139# ifndef MK_W_OFFSET_0
140# define MK_W_OFFSET_0 1
141# endif
142# ifndef MK_W_INTERVAL_0
143# define MK_W_INTERVAL_0 360
144# endif
145# ifndef MK_W_OFFSET_1
146# define MK_W_OFFSET_1 1
147# endif
148# ifndef MK_W_INTERVAL_1
149# define MK_W_INTERVAL_1 120
150# endif
151# ifndef MK_W_OFFSET_2
152# define MK_W_OFFSET_2 1
153# endif
154# ifndef MK_W_INTERVAL_2
155# define MK_W_INTERVAL_2 20
156# endif
157
158#endif /* #ifndef MK_3_SPEED */
159
160#ifdef __cplusplus
161extern "C" {
162#endif
163
164extern uint8_t mk_delay;
165extern uint8_t mk_interval;
166extern uint8_t mk_max_speed;
167extern uint8_t mk_time_to_max;
168extern uint8_t mk_wheel_max_speed;
169extern uint8_t mk_wheel_time_to_max;
170
171void mousekey_task(void);
172void mousekey_on(uint8_t code);
173void mousekey_off(uint8_t code);
174void mousekey_clear(void);
175void mousekey_send(void);
176
177#ifdef __cplusplus
178}
179#endif
diff --git a/quantum/quantum.c b/quantum/quantum.c
index cf16e953a..8ae487bec 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -391,6 +391,29 @@ __attribute__((weak)) const uint8_t ascii_to_altgr_lut[16] PROGMEM = {
391 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), 391 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
392}; 392};
393 393
394/* Bit-Packed look-up table to convert an ASCII character to whether
395 * [Space] needs to be sent after the keycode
396 */
397__attribute__((weak)) const uint8_t ascii_to_dead_lut[16] PROGMEM = {
398 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
399 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
400 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
401 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
402
403 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
404 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
405 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
406 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
407 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
408 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
409 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
410 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
411 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
412 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
413 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
414 KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
415};
416
394/* Look-up table to convert an ASCII character to a keycode. 417/* Look-up table to convert an ASCII character to a keycode.
395 */ 418 */
396__attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = { 419__attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
@@ -531,6 +554,7 @@ void send_char(char ascii_code) {
531 uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]); 554 uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]);
532 bool is_shifted = PGM_LOADBIT(ascii_to_shift_lut, (uint8_t)ascii_code); 555 bool is_shifted = PGM_LOADBIT(ascii_to_shift_lut, (uint8_t)ascii_code);
533 bool is_altgred = PGM_LOADBIT(ascii_to_altgr_lut, (uint8_t)ascii_code); 556 bool is_altgred = PGM_LOADBIT(ascii_to_altgr_lut, (uint8_t)ascii_code);
557 bool is_dead = PGM_LOADBIT(ascii_to_dead_lut, (uint8_t)ascii_code);
534 558
535 if (is_shifted) { 559 if (is_shifted) {
536 register_code(KC_LSFT); 560 register_code(KC_LSFT);
@@ -545,6 +569,9 @@ void send_char(char ascii_code) {
545 if (is_shifted) { 569 if (is_shifted) {
546 unregister_code(KC_LSFT); 570 unregister_code(KC_LSFT);
547 } 571 }
572 if (is_dead) {
573 tap_code(KC_SPACE);
574 }
548} 575}
549 576
550void set_single_persistent_default_layer(uint8_t default_layer) { 577void set_single_persistent_default_layer(uint8_t default_layer) {
@@ -629,6 +656,26 @@ void matrix_init_quantum() {
629} 656}
630 657
631void matrix_scan_quantum() { 658void matrix_scan_quantum() {
659#if defined(AUDIO_ENABLE)
660 // There are some tasks that need to be run a little bit
661 // after keyboard startup, or else they will not work correctly
662 // because of interaction with the USB device state, which
663 // may still be in flux...
664 //
665 // At the moment the only feature that needs this is the
666 // startup song.
667 static bool delayed_tasks_run = false;
668 static uint16_t delayed_task_timer = 0;
669 if (!delayed_tasks_run) {
670 if (!delayed_task_timer) {
671 delayed_task_timer = timer_read();
672 } else if (timer_elapsed(delayed_task_timer) > 300) {
673 audio_startup();
674 delayed_tasks_run = true;
675 }
676 }
677#endif
678
632#if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE) 679#if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE)
633 matrix_scan_music(); 680 matrix_scan_music();
634#endif 681#endif
diff --git a/quantum/quantum.h b/quantum/quantum.h
index f4df5bf15..370a65fe0 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -53,6 +53,7 @@
53#include "eeconfig.h" 53#include "eeconfig.h"
54#include "bootloader.h" 54#include "bootloader.h"
55#include "timer.h" 55#include "timer.h"
56#include "sync_timer.h"
56#include "config_common.h" 57#include "config_common.h"
57#include "led.h" 58#include "led.h"
58#include "action_util.h" 59#include "action_util.h"
@@ -209,6 +210,13 @@ typedef uint8_t pin_t;
209 210
210# define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF)) 211# define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF))
211 212
213/* The AVR series GPIOs have a one clock read delay for changes in the digital input signal.
214 * But here's more margin to make it two clocks. */
215# if !defined(GPIO_INPUT_PIN_DELAY)
216# define GPIO_INPUT_PIN_DELAY 2
217# endif
218# define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY)
219
212#elif defined(PROTOCOL_CHIBIOS) 220#elif defined(PROTOCOL_CHIBIOS)
213typedef ioline_t pin_t; 221typedef ioline_t pin_t;
214 222
@@ -224,6 +232,28 @@ typedef ioline_t pin_t;
224# define readPin(pin) palReadLine(pin) 232# define readPin(pin) palReadLine(pin)
225 233
226# define togglePin(pin) palToggleLine(pin) 234# define togglePin(pin) palToggleLine(pin)
235
236#endif
237
238#if defined(__ARMEL__) || defined(__ARMEB__)
239/* For GPIOs on ARM-based MCUs, the input pins are sampled by the clock of the bus
240 * to which the GPIO is connected.
241 * The connected buses differ depending on the various series of MCUs.
242 * And since the instruction execution clock of the CPU and the bus clock of GPIO are different,
243 * there is a delay of several clocks to read the change of the input signal.
244 *
245 * Define this delay with the GPIO_INPUT_PIN_DELAY macro.
246 * If the GPIO_INPUT_PIN_DELAY macro is not defined, the following default values will be used.
247 * (A fairly large value of 0.25 microseconds is set.)
248 */
249# if !defined(GPIO_INPUT_PIN_DELAY)
250# if defined(STM32_SYSCLK)
251# define GPIO_INPUT_PIN_DELAY (STM32_SYSCLK / 1000000L / 4)
252# elif defined(KINETIS_SYSCLK_FREQUENCY)
253# define GPIO_INPUT_PIN_DELAY (KINETIS_SYSCLK_FREQUENCY / 1000000L / 4)
254# endif
255# endif
256# define waitInputPinDelay() wait_cpuclock(GPIO_INPUT_PIN_DELAY)
227#endif 257#endif
228 258
229// Atomic macro to help make GPIO and other controls atomic. 259// Atomic macro to help make GPIO and other controls atomic.
@@ -288,6 +318,7 @@ static __inline__ void __interrupt_enable__(const uint8_t *__s) {
288extern const uint8_t ascii_to_keycode_lut[128]; 318extern const uint8_t ascii_to_keycode_lut[128];
289extern const uint8_t ascii_to_shift_lut[16]; 319extern const uint8_t ascii_to_shift_lut[16];
290extern const uint8_t ascii_to_altgr_lut[16]; 320extern const uint8_t ascii_to_altgr_lut[16];
321extern const uint8_t ascii_to_dead_lut[16];
291// clang-format off 322// clang-format off
292#define KCLUT_ENTRY(a, b, c, d, e, f, g, h) \ 323#define KCLUT_ENTRY(a, b, c, d, e, f, g, h) \
293 ( ((a) ? 1 : 0) << 0 \ 324 ( ((a) ? 1 : 0) << 0 \
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c
index 04af3ae9e..a945df68e 100644
--- a/quantum/rgb_matrix.c
+++ b/quantum/rgb_matrix.c
@@ -266,9 +266,9 @@ static bool rgb_matrix_none(effect_params_t *params) {
266 266
267static void rgb_task_timers(void) { 267static void rgb_task_timers(void) {
268#if defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_DISABLE_TIMEOUT > 0 268#if defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_DISABLE_TIMEOUT > 0
269 uint32_t deltaTime = timer_elapsed32(rgb_timer_buffer); 269 uint32_t deltaTime = sync_timer_elapsed32(rgb_timer_buffer);
270#endif // defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_DISABLE_TIMEOUT > 0 270#endif // defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_DISABLE_TIMEOUT > 0
271 rgb_timer_buffer = timer_read32(); 271 rgb_timer_buffer = sync_timer_read32();
272 272
273 // Update double buffer timers 273 // Update double buffer timers
274#if RGB_DISABLE_TIMEOUT > 0 274#if RGB_DISABLE_TIMEOUT > 0
@@ -296,7 +296,7 @@ static void rgb_task_timers(void) {
296 296
297static void rgb_task_sync(void) { 297static void rgb_task_sync(void) {
298 // next task 298 // next task
299 if (timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; 299 if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;
300} 300}
301 301
302static void rgb_task_start(void) { 302static void rgb_task_start(void) {
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index ac4ff9bfd..7d7d015ba 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -29,7 +29,7 @@
29#endif 29#endif
30#include "wait.h" 30#include "wait.h"
31#include "progmem.h" 31#include "progmem.h"
32#include "timer.h" 32#include "sync_timer.h"
33#include "rgblight.h" 33#include "rgblight.h"
34#include "color.h" 34#include "color.h"
35#include "debug.h" 35#include "debug.h"
@@ -42,6 +42,9 @@
42#ifndef MIN 42#ifndef MIN
43# define MIN(a, b) (((a) < (b)) ? (a) : (b)) 43# define MIN(a, b) (((a) < (b)) ? (a) : (b))
44#endif 44#endif
45#ifndef MAX
46# define MAX(a, b) (((a) > (b)) ? (a) : (b))
47#endif
45 48
46#ifdef RGBLIGHT_SPLIT 49#ifdef RGBLIGHT_SPLIT
47/* for split keyboard */ 50/* for split keyboard */
@@ -700,18 +703,16 @@ static void rgblight_layers_write(void) {
700 703
701# ifdef RGBLIGHT_LAYER_BLINK 704# ifdef RGBLIGHT_LAYER_BLINK
702rgblight_layer_mask_t _blinked_layer_mask = 0; 705rgblight_layer_mask_t _blinked_layer_mask = 0;
703uint16_t _blink_duration = 0;
704static uint16_t _blink_timer; 706static uint16_t _blink_timer;
705 707
706void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { 708void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {
707 rgblight_set_layer_state(layer, true); 709 rgblight_set_layer_state(layer, true);
708 _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; 710 _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer;
709 _blink_timer = timer_read(); 711 _blink_timer = sync_timer_read() + duration_ms;
710 _blink_duration = duration_ms;
711} 712}
712 713
713void rgblight_unblink_layers(void) { 714void rgblight_unblink_layers(void) {
714 if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) { 715 if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) {
715 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { 716 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
716 if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { 717 if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) {
717 rgblight_set_layer_state(layer, false); 718 rgblight_set_layer_state(layer, false);
@@ -886,7 +887,7 @@ void rgblight_timer_enable(void) {
886 if (!is_static_effect(rgblight_config.mode)) { 887 if (!is_static_effect(rgblight_config.mode)) {
887 rgblight_status.timer_enabled = true; 888 rgblight_status.timer_enabled = true;
888 } 889 }
889 animation_status.last_timer = timer_read(); 890 animation_status.last_timer = sync_timer_read();
890 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; 891 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
891 dprintf("rgblight timer enabled.\n"); 892 dprintf("rgblight timer enabled.\n");
892} 893}
@@ -989,24 +990,25 @@ void rgblight_task(void) {
989# endif 990# endif
990# ifdef RGBLIGHT_EFFECT_TWINKLE 991# ifdef RGBLIGHT_EFFECT_TWINKLE
991 else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) { 992 else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) {
992 interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50); 993 interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 30);
993 effect_func = (effect_func_t)rgblight_effect_twinkle; 994 effect_func = (effect_func_t)rgblight_effect_twinkle;
994 } 995 }
995# endif 996# endif
996 if (animation_status.restart) { 997 if (animation_status.restart) {
997 animation_status.restart = false; 998 animation_status.restart = false;
998 animation_status.last_timer = timer_read() - interval_time - 1; 999 animation_status.last_timer = sync_timer_read();
999 animation_status.pos16 = 0; // restart signal to local each effect 1000 animation_status.pos16 = 0; // restart signal to local each effect
1000 } 1001 }
1001 if (timer_elapsed(animation_status.last_timer) >= interval_time) { 1002 uint16_t now = sync_timer_read();
1003 if (timer_expired(now, animation_status.last_timer)) {
1002# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) 1004# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
1003 static uint16_t report_last_timer = 0; 1005 static uint16_t report_last_timer = 0;
1004 static bool tick_flag = false; 1006 static bool tick_flag = false;
1005 uint16_t oldpos16; 1007 uint16_t oldpos16;
1006 if (tick_flag) { 1008 if (tick_flag) {
1007 tick_flag = false; 1009 tick_flag = false;
1008 if (timer_elapsed(report_last_timer) >= 30000) { 1010 if (timer_expired(now, report_last_timer)) {
1009 report_last_timer = timer_read(); 1011 report_last_timer += 30000;
1010 dprintf("rgblight animation tick report to slave\n"); 1012 dprintf("rgblight animation tick report to slave\n");
1011 RGBLIGHT_SPLIT_ANIMATION_TICK; 1013 RGBLIGHT_SPLIT_ANIMATION_TICK;
1012 } 1014 }
@@ -1030,8 +1032,7 @@ void rgblight_task(void) {
1030 1032
1031#endif /* RGBLIGHT_USE_TIMER */ 1033#endif /* RGBLIGHT_USE_TIMER */
1032 1034
1033// Effects 1035#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_TWINKLE)
1034#ifdef RGBLIGHT_EFFECT_BREATHING
1035 1036
1036# ifndef RGBLIGHT_EFFECT_BREATHE_CENTER 1037# ifndef RGBLIGHT_EFFECT_BREATHE_CENTER
1037# ifndef RGBLIGHT_BREATHE_TABLE_SIZE 1038# ifndef RGBLIGHT_BREATHE_TABLE_SIZE
@@ -1040,17 +1041,24 @@ void rgblight_task(void) {
1040# include <rgblight_breathe_table.h> 1041# include <rgblight_breathe_table.h>
1041# endif 1042# endif
1042 1043
1043__attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; 1044static uint8_t breathe_calc(uint8_t pos) {
1044
1045void rgblight_effect_breathing(animation_status_t *anim) {
1046 float val;
1047
1048 // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ 1045 // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
1049# ifdef RGBLIGHT_EFFECT_BREATHE_TABLE 1046# ifdef RGBLIGHT_EFFECT_BREATHE_TABLE
1050 val = pgm_read_byte(&rgblight_effect_breathe_table[anim->pos / table_scale]); 1047 return pgm_read_byte(&rgblight_effect_breathe_table[pos / table_scale]);
1051# else 1048# else
1052 val = (exp(sin((anim->pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E)); 1049 return (exp(sin((pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E));
1053# endif 1050# endif
1051}
1052
1053#endif
1054
1055// Effects
1056#ifdef RGBLIGHT_EFFECT_BREATHING
1057
1058__attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
1059
1060void rgblight_effect_breathing(animation_status_t *anim) {
1061 uint8_t val = breathe_calc(anim->pos);
1054 rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); 1062 rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
1055 anim->pos = (anim->pos + 1); 1063 anim->pos = (anim->pos + 1);
1056} 1064}
@@ -1302,48 +1310,54 @@ void rgblight_effect_alternating(animation_status_t *anim) {
1302#endif 1310#endif
1303 1311
1304#ifdef RGBLIGHT_EFFECT_TWINKLE 1312#ifdef RGBLIGHT_EFFECT_TWINKLE
1305__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10}; 1313__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {30, 15, 5};
1306 1314
1307typedef struct PACKED { 1315typedef struct PACKED {
1308 HSV hsv; 1316 HSV hsv;
1309 uint8_t life; 1317 uint8_t life;
1310 bool up; 1318 uint8_t max_life;
1311} TwinkleState; 1319} TwinkleState;
1312 1320
1313static TwinkleState led_twinkle_state[RGBLED_NUM]; 1321static TwinkleState led_twinkle_state[RGBLED_NUM];
1314 1322
1315void rgblight_effect_twinkle(animation_status_t *anim) { 1323void rgblight_effect_twinkle(animation_status_t *anim) {
1316 bool random_color = anim->delta / 3; 1324 const bool random_color = anim->delta / 3;
1317 bool restart = anim->pos == 0; 1325 const bool restart = anim->pos == 0;
1318 anim->pos = 1; 1326 anim->pos = 1;
1327
1328 const uint8_t bottom = breathe_calc(0);
1329 const uint8_t top = breathe_calc(127);
1330
1331 uint8_t frac(uint8_t n, uint8_t d) { return (uint16_t)255 * n / d; }
1332 uint8_t scale(uint16_t v, uint8_t scale) { return (v * scale) >> 8; }
1319 1333
1320 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) { 1334 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1321 TwinkleState *t = &(led_twinkle_state[i]); 1335 TwinkleState *t = &(led_twinkle_state[i]);
1322 HSV * c = &(t->hsv); 1336 HSV * c = &(t->hsv);
1337
1338 if (!random_color) {
1339 c->h = rgblight_config.hue;
1340 c->s = rgblight_config.sat;
1341 }
1342
1323 if (restart) { 1343 if (restart) {
1324 // Restart 1344 // Restart
1325 t->life = 0; 1345 t->life = 0;
1326 t->hsv.v = 0; 1346 c->v = 0;
1327 } else if (t->life) { 1347 } else if (t->life) {
1328 // This LED is already on, either brightening or dimming 1348 // This LED is already on, either brightening or dimming
1329 t->life--; 1349 t->life--;
1330 uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life; 1350 uint8_t unscaled = frac(breathe_calc(frac(t->life, t->max_life)) - bottom, top - bottom);
1331 c->v = (uint16_t)rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE; 1351 c->v = scale(rgblight_config.val, unscaled);
1332 if (t->life == 0 && t->up) { 1352 } else if (rand() < scale((uint16_t)RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY, 127 + rgblight_config.val / 2)) {
1333 t->up = false;
1334 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
1335 }
1336 if (!random_color) {
1337 c->h = rgblight_config.hue;
1338 c->s = rgblight_config.sat;
1339 }
1340 } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) {
1341 // This LED is off, but was randomly selected to start brightening 1353 // This LED is off, but was randomly selected to start brightening
1342 c->h = random_color ? rand() % 0xFF : rgblight_config.hue; 1354 if (random_color) {
1343 c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat; 1355 c->h = rand() % 0xFF;
1344 c->v = 0; 1356 c->s = (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2);
1345 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE; 1357 }
1346 t->up = true; 1358 c->v = 0;
1359 t->max_life = MAX(20, MIN(RGBLIGHT_EFFECT_TWINKLE_LIFE, rgblight_config.val));
1360 t->life = t->max_life;
1347 } else { 1361 } else {
1348 // This LED is off, and was NOT selected to start brightening 1362 // This LED is off, and was NOT selected to start brightening
1349 } 1363 }
diff --git a/quantum/rgblight.h b/quantum/rgblight.h
index 1854fee99..028b3ea41 100644
--- a/quantum/rgblight.h
+++ b/quantum/rgblight.h
@@ -150,7 +150,7 @@ enum RGBLIGHT_EFFECT_MODE {
150# endif 150# endif
151 151
152# ifndef RGBLIGHT_EFFECT_TWINKLE_LIFE 152# ifndef RGBLIGHT_EFFECT_TWINKLE_LIFE
153# define RGBLIGHT_EFFECT_TWINKLE_LIFE 75 153# define RGBLIGHT_EFFECT_TWINKLE_LIFE 200
154# endif 154# endif
155 155
156# ifndef RGBLIGHT_EFFECT_TWINKLE_PROBABILITY 156# ifndef RGBLIGHT_EFFECT_TWINKLE_PROBABILITY
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index 51bf8b109..bad762b49 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)
114 // Start with a clear matrix row 114 // Start with a clear matrix row
115 matrix_row_t current_row_value = 0; 115 matrix_row_t current_row_value = 0;
116 116
117 // Select row and wait for row selecton to stabilize 117 // Select row
118 select_row(current_row); 118 select_row(current_row);
119 matrix_io_delay(); 119 matrix_output_select_delay();
120 120
121 // For each col... 121 // For each col...
122 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) { 122 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)
129 129
130 // Unselect row 130 // Unselect row
131 unselect_row(current_row); 131 unselect_row(current_row);
132 if (current_row + 1 < MATRIX_ROWS) {
133 matrix_output_unselect_delay(); // wait for row signal to go HIGH
134 }
132 135
133 // If the row has changed, store the row and return the changed flag. 136 // If the row has changed, store the row and return the changed flag.
134 if (current_matrix[current_row] != current_row_value) { 137 if (current_matrix[current_row] != current_row_value) {
@@ -160,9 +163,9 @@ static void init_pins(void) {
160static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { 163static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
161 bool matrix_changed = false; 164 bool matrix_changed = false;
162 165
163 // Select col and wait for col selecton to stabilize 166 // Select col
164 select_col(current_col); 167 select_col(current_col);
165 matrix_io_delay(); 168 matrix_output_select_delay();
166 169
167 // For each row... 170 // For each row...
168 for (uint8_t row_index = 0; row_index < ROWS_PER_HAND; row_index++) { 171 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)
188 191
189 // Unselect col 192 // Unselect col
190 unselect_col(current_col); 193 unselect_col(current_col);
194 if (current_col + 1 < MATRIX_COLS) {
195 matrix_output_unselect_delay(); // wait for col signal to go HIGH
196 }
191 197
192 return matrix_changed; 198 return matrix_changed;
193} 199}
@@ -245,21 +251,33 @@ void matrix_init(void) {
245 split_post_init(); 251 split_post_init();
246} 252}
247 253
248void matrix_post_scan(void) { 254bool matrix_post_scan(void) {
255 bool changed = false;
249 if (is_keyboard_master()) { 256 if (is_keyboard_master()) {
250 static uint8_t error_count; 257 static uint8_t error_count;
251 258
252 if (!transport_master(matrix + thatHand)) { 259 matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
260 if (!transport_master(slave_matrix)) {
253 error_count++; 261 error_count++;
254 262
255 if (error_count > ERROR_DISCONNECT_COUNT) { 263 if (error_count > ERROR_DISCONNECT_COUNT) {
256 // reset other half if disconnected 264 // reset other half if disconnected
257 for (int i = 0; i < ROWS_PER_HAND; ++i) { 265 for (int i = 0; i < ROWS_PER_HAND; ++i) {
258 matrix[thatHand + i] = 0; 266 matrix[thatHand + i] = 0;
267 slave_matrix[i] = 0;
259 } 268 }
269
270 changed = true;
260 } 271 }
261 } else { 272 } else {
262 error_count = 0; 273 error_count = 0;
274
275 for (int i = 0; i < ROWS_PER_HAND; ++i) {
276 if (matrix[thatHand + i] != slave_matrix[i]) {
277 matrix[thatHand + i] = slave_matrix[i];
278 changed = true;
279 }
280 }
263 } 281 }
264 282
265 matrix_scan_quantum(); 283 matrix_scan_quantum();
@@ -268,25 +286,27 @@ void matrix_post_scan(void) {
268 286
269 matrix_slave_scan_user(); 287 matrix_slave_scan_user();
270 } 288 }
289
290 return changed;
271} 291}
272 292
273uint8_t matrix_scan(void) { 293uint8_t matrix_scan(void) {
274 bool changed = false; 294 bool local_changed = false;
275 295
276#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 296#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
277 // Set row, read cols 297 // Set row, read cols
278 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { 298 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
279 changed |= read_cols_on_row(raw_matrix, current_row); 299 local_changed |= read_cols_on_row(raw_matrix, current_row);
280 } 300 }
281#elif (DIODE_DIRECTION == ROW2COL) 301#elif (DIODE_DIRECTION == ROW2COL)
282 // Set col, read rows 302 // Set col, read rows
283 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 303 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
284 changed |= read_rows_on_col(raw_matrix, current_col); 304 local_changed |= read_rows_on_col(raw_matrix, current_col);
285 } 305 }
286#endif 306#endif
287 307
288 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); 308 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed);
289 309
290 matrix_post_scan(); 310 bool remote_changed = matrix_post_scan();
291 return (uint8_t)changed; 311 return (uint8_t)(local_changed || remote_changed);
292} 312}
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
index 467ff81a9..b45ba92c3 100644
--- a/quantum/split_common/transport.c
+++ b/quantum/split_common/transport.c
@@ -6,6 +6,7 @@
6#include "quantum.h" 6#include "quantum.h"
7 7
8#define ROWS_PER_HAND (MATRIX_ROWS / 2) 8#define ROWS_PER_HAND (MATRIX_ROWS / 2)
9#define SYNC_TIMER_OFFSET 2
9 10
10#ifdef RGBLIGHT_ENABLE 11#ifdef RGBLIGHT_ENABLE
11# include "rgblight.h" 12# include "rgblight.h"
@@ -27,8 +28,20 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A;
27# include "i2c_slave.h" 28# include "i2c_slave.h"
28 29
29typedef struct _I2C_slave_buffer_t { 30typedef struct _I2C_slave_buffer_t {
31# ifndef DISABLE_SYNC_TIMER
32 uint32_t sync_timer;
33# endif
30 matrix_row_t smatrix[ROWS_PER_HAND]; 34 matrix_row_t smatrix[ROWS_PER_HAND];
31 uint8_t backlight_level; 35# ifdef SPLIT_MODS_ENABLE
36 uint8_t real_mods;
37 uint8_t weak_mods;
38# ifndef NO_ACTION_ONESHOT
39 uint8_t oneshot_mods;
40# endif
41# endif
42# ifdef BACKLIGHT_ENABLE
43 uint8_t backlight_level;
44# endif
32# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT) 45# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
33 rgblight_syncinfo_t rgblight_sync; 46 rgblight_syncinfo_t rgblight_sync;
34# endif 47# endif
@@ -42,9 +55,13 @@ typedef struct _I2C_slave_buffer_t {
42 55
43static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg; 56static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg;
44 57
58# define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer)
59# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix)
60# define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods)
61# define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods)
62# define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods)
45# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level) 63# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level)
46# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync) 64# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)
47# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix)
48# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state) 65# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)
49# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm) 66# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm)
50 67
@@ -91,10 +108,43 @@ bool transport_master(matrix_row_t matrix[]) {
91 } 108 }
92 } 109 }
93# endif 110# endif
111
112# ifdef SPLIT_MODS_ENABLE
113 uint8_t real_mods = get_mods();
114 if (real_mods != i2c_buffer->real_mods) {
115 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) {
116 i2c_buffer->real_mods = real_mods;
117 }
118 }
119
120 uint8_t weak_mods = get_weak_mods();
121 if (weak_mods != i2c_buffer->weak_mods) {
122 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) {
123 i2c_buffer->weak_mods = weak_mods;
124 }
125 }
126
127# ifndef NO_ACTION_ONESHOT
128 uint8_t oneshot_mods = get_oneshot_mods();
129 if (oneshot_mods != i2c_buffer->oneshot_mods) {
130 if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) {
131 i2c_buffer->oneshot_mods = oneshot_mods;
132 }
133 }
134# endif
135# endif
136
137# ifndef DISABLE_SYNC_TIMER
138 i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
139 i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT);
140# endif
94 return true; 141 return true;
95} 142}
96 143
97void transport_slave(matrix_row_t matrix[]) { 144void transport_slave(matrix_row_t matrix[]) {
145# ifndef DISABLE_SYNC_TIMER
146 sync_timer_update(i2c_buffer->sync_timer);
147# endif
98 // Copy matrix to I2C buffer 148 // Copy matrix to I2C buffer
99 memcpy((void *)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix)); 149 memcpy((void *)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix));
100 150
@@ -118,6 +168,14 @@ void transport_slave(matrix_row_t matrix[]) {
118# ifdef WPM_ENABLE 168# ifdef WPM_ENABLE
119 set_current_wpm(i2c_buffer->current_wpm); 169 set_current_wpm(i2c_buffer->current_wpm);
120# endif 170# endif
171
172# ifdef SPLIT_MODS_ENABLE
173 set_mods(i2c_buffer->real_mods);
174 set_weak_mods(i2c_buffer->weak_mods);
175# ifndef NO_ACTION_ONESHOT
176 set_oneshot_mods(i2c_buffer->oneshot_mods);
177# endif
178# endif
121} 179}
122 180
123void transport_master_init(void) { i2c_init(); } 181void transport_master_init(void) { i2c_init(); }
@@ -139,11 +197,21 @@ typedef struct _Serial_s2m_buffer_t {
139} Serial_s2m_buffer_t; 197} Serial_s2m_buffer_t;
140 198
141typedef struct _Serial_m2s_buffer_t { 199typedef struct _Serial_m2s_buffer_t {
200# ifdef SPLIT_MODS_ENABLE
201 uint8_t real_mods;
202 uint8_t weak_mods;
203# ifndef NO_ACTION_ONESHOT
204 uint8_t oneshot_mods;
205# endif
206# endif
207# ifndef DISABLE_SYNC_TIMER
208 uint32_t sync_timer;
209# endif
142# ifdef BACKLIGHT_ENABLE 210# ifdef BACKLIGHT_ENABLE
143 uint8_t backlight_level; 211 uint8_t backlight_level;
144# endif 212# endif
145# ifdef WPM_ENABLE 213# ifdef WPM_ENABLE
146 uint8_t current_wpm; 214 uint8_t current_wpm;
147# endif 215# endif
148} Serial_m2s_buffer_t; 216} Serial_m2s_buffer_t;
149 217
@@ -249,13 +317,28 @@ bool transport_master(matrix_row_t matrix[]) {
249 317
250# ifdef WPM_ENABLE 318# ifdef WPM_ENABLE
251 // Write wpm to slave 319 // Write wpm to slave
252 serial_m2s_buffer.current_wpm = get_current_wpm(); 320 serial_m2s_buffer.current_wpm = get_current_wpm();
321# endif
322
323# ifdef SPLIT_MODS_ENABLE
324 serial_m2s_buffer.real_mods = get_mods();
325 serial_m2s_buffer.weak_mods = get_weak_mods();
326# ifndef NO_ACTION_ONESHOT
327 serial_m2s_buffer.oneshot_mods = get_oneshot_mods();
328# endif
329# endif
330# ifndef DISABLE_SYNC_TIMER
331 serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
253# endif 332# endif
254 return true; 333 return true;
255} 334}
256 335
257void transport_slave(matrix_row_t matrix[]) { 336void transport_slave(matrix_row_t matrix[]) {
258 transport_rgblight_slave(); 337 transport_rgblight_slave();
338# ifndef DISABLE_SYNC_TIMER
339 sync_timer_update(serial_m2s_buffer.sync_timer);
340# endif
341
259 // TODO: if MATRIX_COLS > 8 change to pack() 342 // TODO: if MATRIX_COLS > 8 change to pack()
260 for (int i = 0; i < ROWS_PER_HAND; ++i) { 343 for (int i = 0; i < ROWS_PER_HAND; ++i) {
261 serial_s2m_buffer.smatrix[i] = matrix[i]; 344 serial_s2m_buffer.smatrix[i] = matrix[i];
@@ -271,6 +354,14 @@ void transport_slave(matrix_row_t matrix[]) {
271# ifdef WPM_ENABLE 354# ifdef WPM_ENABLE
272 set_current_wpm(serial_m2s_buffer.current_wpm); 355 set_current_wpm(serial_m2s_buffer.current_wpm);
273# endif 356# endif
357
358# ifdef SPLIT_MODS_ENABLE
359 set_mods(serial_m2s_buffer.real_mods);
360 set_weak_mods(serial_m2s_buffer.weak_mods);
361# ifndef NO_ACTION_ONESHOT
362 set_oneshot_mods(serial_m2s_buffer.oneshot_mods);
363# endif
364# endif
274} 365}
275 366
276#endif 367#endif