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/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_common.c5
-rw-r--r--quantum/mcu_selection.mk70
-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
27 files changed, 998 insertions, 97 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/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_common.c b/quantum/matrix_common.c
index 15f1e0e82..01d2b38e5 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"
@@ -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/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