aboutsummaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-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/quantum.c33
-rw-r--r--quantum/quantum.h31
-rw-r--r--quantum/rgb_matrix.c6
-rw-r--r--quantum/rgblight.c102
-rw-r--r--quantum/rgblight.h2
-rw-r--r--quantum/split_common/matrix.c43
-rw-r--r--quantum/split_common/transport.c95
13 files changed, 822 insertions, 80 deletions
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/quantum.c b/quantum/quantum.c
index 3ac0ed871..ece0388d3 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 = {
@@ -528,9 +551,10 @@ void send_char(char ascii_code) {
528 } 551 }
529#endif 552#endif
530 553
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) {
diff --git a/quantum/quantum.h b/quantum/quantum.h
index f4df5bf15..d234e6ea0 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 d856f6d6c..b16c3e7c2 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 */
@@ -689,18 +692,16 @@ static void rgblight_layers_write(void) {
689 692
690# ifdef RGBLIGHT_LAYER_BLINK 693# ifdef RGBLIGHT_LAYER_BLINK
691rgblight_layer_mask_t _blinked_layer_mask = 0; 694rgblight_layer_mask_t _blinked_layer_mask = 0;
692uint16_t _blink_duration = 0;
693static uint16_t _blink_timer; 695static uint16_t _blink_timer;
694 696
695void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) { 697void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {
696 rgblight_set_layer_state(layer, true); 698 rgblight_set_layer_state(layer, true);
697 _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer; 699 _blinked_layer_mask |= (rgblight_layer_mask_t)1 << layer;
698 _blink_timer = timer_read(); 700 _blink_timer = sync_timer_read() + duration_ms;
699 _blink_duration = duration_ms;
700} 701}
701 702
702void rgblight_unblink_layers(void) { 703void rgblight_unblink_layers(void) {
703 if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) { 704 if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) {
704 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) { 705 for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
705 if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) { 706 if ((_blinked_layer_mask & (rgblight_layer_mask_t)1 << layer) != 0) {
706 rgblight_set_layer_state(layer, false); 707 rgblight_set_layer_state(layer, false);
@@ -842,7 +843,7 @@ void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
842 animation_status.restart = true; 843 animation_status.restart = true;
843 } 844 }
844# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ 845# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */
845# endif /* RGBLIGHT_USE_TIMER */ 846# endif /* RGBLIGHT_USE_TIMER */
846} 847}
847#endif /* RGBLIGHT_SPLIT */ 848#endif /* RGBLIGHT_SPLIT */
848 849
@@ -875,7 +876,7 @@ void rgblight_timer_enable(void) {
875 if (!is_static_effect(rgblight_config.mode)) { 876 if (!is_static_effect(rgblight_config.mode)) {
876 rgblight_status.timer_enabled = true; 877 rgblight_status.timer_enabled = true;
877 } 878 }
878 animation_status.last_timer = timer_read(); 879 animation_status.last_timer = sync_timer_read();
879 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; 880 RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
880 dprintf("rgblight timer enabled.\n"); 881 dprintf("rgblight timer enabled.\n");
881} 882}
@@ -978,24 +979,25 @@ void rgblight_task(void) {
978# endif 979# endif
979# ifdef RGBLIGHT_EFFECT_TWINKLE 980# ifdef RGBLIGHT_EFFECT_TWINKLE
980 else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) { 981 else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) {
981 interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50); 982 interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 30);
982 effect_func = (effect_func_t)rgblight_effect_twinkle; 983 effect_func = (effect_func_t)rgblight_effect_twinkle;
983 } 984 }
984# endif 985# endif
985 if (animation_status.restart) { 986 if (animation_status.restart) {
986 animation_status.restart = false; 987 animation_status.restart = false;
987 animation_status.last_timer = timer_read() - interval_time - 1; 988 animation_status.last_timer = sync_timer_read();
988 animation_status.pos16 = 0; // restart signal to local each effect 989 animation_status.pos16 = 0; // restart signal to local each effect
989 } 990 }
990 if (timer_elapsed(animation_status.last_timer) >= interval_time) { 991 uint16_t now = sync_timer_read();
992 if (timer_expired(now, animation_status.last_timer)) {
991# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) 993# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
992 static uint16_t report_last_timer = 0; 994 static uint16_t report_last_timer = 0;
993 static bool tick_flag = false; 995 static bool tick_flag = false;
994 uint16_t oldpos16; 996 uint16_t oldpos16;
995 if (tick_flag) { 997 if (tick_flag) {
996 tick_flag = false; 998 tick_flag = false;
997 if (timer_elapsed(report_last_timer) >= 30000) { 999 if (timer_expired(now, report_last_timer)) {
998 report_last_timer = timer_read(); 1000 report_last_timer += 30000;
999 dprintf("rgblight animation tick report to slave\n"); 1001 dprintf("rgblight animation tick report to slave\n");
1000 RGBLIGHT_SPLIT_ANIMATION_TICK; 1002 RGBLIGHT_SPLIT_ANIMATION_TICK;
1001 } 1003 }
@@ -1019,8 +1021,7 @@ void rgblight_task(void) {
1019 1021
1020#endif /* RGBLIGHT_USE_TIMER */ 1022#endif /* RGBLIGHT_USE_TIMER */
1021 1023
1022// Effects 1024#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_TWINKLE)
1023#ifdef RGBLIGHT_EFFECT_BREATHING
1024 1025
1025# ifndef RGBLIGHT_EFFECT_BREATHE_CENTER 1026# ifndef RGBLIGHT_EFFECT_BREATHE_CENTER
1026# ifndef RGBLIGHT_BREATHE_TABLE_SIZE 1027# ifndef RGBLIGHT_BREATHE_TABLE_SIZE
@@ -1029,17 +1030,24 @@ void rgblight_task(void) {
1029# include <rgblight_breathe_table.h> 1030# include <rgblight_breathe_table.h>
1030# endif 1031# endif
1031 1032
1032__attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; 1033static uint8_t breathe_calc(uint8_t pos) {
1033
1034void rgblight_effect_breathing(animation_status_t *anim) {
1035 float val;
1036
1037 // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ 1034 // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
1038# ifdef RGBLIGHT_EFFECT_BREATHE_TABLE 1035# ifdef RGBLIGHT_EFFECT_BREATHE_TABLE
1039 val = pgm_read_byte(&rgblight_effect_breathe_table[anim->pos / table_scale]); 1036 return pgm_read_byte(&rgblight_effect_breathe_table[pos / table_scale]);
1040# else 1037# else
1041 val = (exp(sin((anim->pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E)); 1038 return (exp(sin((pos / 255.0) * M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER / M_E) * (RGBLIGHT_EFFECT_BREATHE_MAX / (M_E - 1 / M_E));
1042# endif 1039# endif
1040}
1041
1042#endif
1043
1044// Effects
1045#ifdef RGBLIGHT_EFFECT_BREATHING
1046
1047__attribute__((weak)) const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
1048
1049void rgblight_effect_breathing(animation_status_t *anim) {
1050 uint8_t val = breathe_calc(anim->pos);
1043 rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); 1051 rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
1044 anim->pos = (anim->pos + 1); 1052 anim->pos = (anim->pos + 1);
1045} 1053}
@@ -1291,48 +1299,54 @@ void rgblight_effect_alternating(animation_status_t *anim) {
1291#endif 1299#endif
1292 1300
1293#ifdef RGBLIGHT_EFFECT_TWINKLE 1301#ifdef RGBLIGHT_EFFECT_TWINKLE
1294__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10}; 1302__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {30, 15, 5};
1295 1303
1296typedef struct PACKED { 1304typedef struct PACKED {
1297 HSV hsv; 1305 HSV hsv;
1298 uint8_t life; 1306 uint8_t life;
1299 bool up; 1307 uint8_t max_life;
1300} TwinkleState; 1308} TwinkleState;
1301 1309
1302static TwinkleState led_twinkle_state[RGBLED_NUM]; 1310static TwinkleState led_twinkle_state[RGBLED_NUM];
1303 1311
1304void rgblight_effect_twinkle(animation_status_t *anim) { 1312void rgblight_effect_twinkle(animation_status_t *anim) {
1305 bool random_color = anim->delta / 3; 1313 const bool random_color = anim->delta / 3;
1306 bool restart = anim->pos == 0; 1314 const bool restart = anim->pos == 0;
1307 anim->pos = 1; 1315 anim->pos = 1;
1316
1317 const uint8_t bottom = breathe_calc(0);
1318 const uint8_t top = breathe_calc(127);
1319
1320 uint8_t frac(uint8_t n, uint8_t d) { return (uint16_t)255 * n / d; }
1321 uint8_t scale(uint16_t v, uint8_t scale) { return (v * scale) >> 8; }
1308 1322
1309 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) { 1323 for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
1310 TwinkleState *t = &(led_twinkle_state[i]); 1324 TwinkleState *t = &(led_twinkle_state[i]);
1311 HSV * c = &(t->hsv); 1325 HSV * c = &(t->hsv);
1326
1327 if (!random_color) {
1328 c->h = rgblight_config.hue;
1329 c->s = rgblight_config.sat;
1330 }
1331
1312 if (restart) { 1332 if (restart) {
1313 // Restart 1333 // Restart
1314 t->life = 0; 1334 t->life = 0;
1315 t->hsv.v = 0; 1335 c->v = 0;
1316 } else if (t->life) { 1336 } else if (t->life) {
1317 // This LED is already on, either brightening or dimming 1337 // This LED is already on, either brightening or dimming
1318 t->life--; 1338 t->life--;
1319 uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life; 1339 uint8_t unscaled = frac(breathe_calc(frac(t->life, t->max_life)) - bottom, top - bottom);
1320 c->v = (uint16_t)rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE; 1340 c->v = scale(rgblight_config.val, unscaled);
1321 if (t->life == 0 && t->up) { 1341 } else if (rand() < scale((uint16_t)RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY, 127 + rgblight_config.val / 2)) {
1322 t->up = false;
1323 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
1324 }
1325 if (!random_color) {
1326 c->h = rgblight_config.hue;
1327 c->s = rgblight_config.sat;
1328 }
1329 } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) {
1330 // This LED is off, but was randomly selected to start brightening 1342 // This LED is off, but was randomly selected to start brightening
1331 c->h = random_color ? rand() % 0xFF : rgblight_config.hue; 1343 if (random_color) {
1332 c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat; 1344 c->h = rand() % 0xFF;
1333 c->v = 0; 1345 c->s = (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2);
1334 t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE; 1346 }
1335 t->up = true; 1347 c->v = 0;
1348 t->max_life = MAX(20, MIN(RGBLIGHT_EFFECT_TWINKLE_LIFE, rgblight_config.val));
1349 t->life = t->max_life;
1336 } else { 1350 } else {
1337 // This LED is off, and was NOT selected to start brightening 1351 // This LED is off, and was NOT selected to start brightening
1338 } 1352 }
diff --git a/quantum/rgblight.h b/quantum/rgblight.h
index efbffa7fd..b9306e4d2 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..067815c99 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,48 +251,59 @@ 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 slave_matrix[i] = 0;
259 } 267 }
260 } 268 }
261 } else { 269 } else {
262 error_count = 0; 270 error_count = 0;
263 } 271 }
264 272
273 for (int i = 0; i < ROWS_PER_HAND; ++i) {
274 if (matrix[thatHand + i] != slave_matrix[i]) {
275 matrix[thatHand + i] = slave_matrix[i];
276 changed = true;
277 }
278 }
279
265 matrix_scan_quantum(); 280 matrix_scan_quantum();
266 } else { 281 } else {
267 transport_slave(matrix + thisHand); 282 transport_slave(matrix + thisHand);
268 283
269 matrix_slave_scan_user(); 284 matrix_slave_scan_user();
270 } 285 }
286
287 return changed;
271} 288}
272 289
273uint8_t matrix_scan(void) { 290uint8_t matrix_scan(void) {
274 bool changed = false; 291 bool local_changed = false;
275 292
276#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) 293#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
277 // Set row, read cols 294 // Set row, read cols
278 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { 295 for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) {
279 changed |= read_cols_on_row(raw_matrix, current_row); 296 local_changed |= read_cols_on_row(raw_matrix, current_row);
280 } 297 }
281#elif (DIODE_DIRECTION == ROW2COL) 298#elif (DIODE_DIRECTION == ROW2COL)
282 // Set col, read rows 299 // Set col, read rows
283 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { 300 for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
284 changed |= read_rows_on_col(raw_matrix, current_col); 301 local_changed |= read_rows_on_col(raw_matrix, current_col);
285 } 302 }
286#endif 303#endif
287 304
288 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed); 305 debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, local_changed);
289 306
290 matrix_post_scan(); 307 bool remote_changed = matrix_post_scan();
291 return (uint8_t)changed; 308 return (uint8_t)(local_changed || remote_changed);
292} 309}
diff --git a/quantum/split_common/transport.c b/quantum/split_common/transport.c
index 467ff81a9..e601fb4df 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];
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
31 uint8_t backlight_level; 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(); }
@@ -133,12 +191,22 @@ typedef struct _Serial_s2m_buffer_t {
133 matrix_row_t smatrix[ROWS_PER_HAND]; 191 matrix_row_t smatrix[ROWS_PER_HAND];
134 192
135# ifdef ENCODER_ENABLE 193# ifdef ENCODER_ENABLE
136 uint8_t encoder_state[NUMBER_OF_ENCODERS]; 194 uint8_t encoder_state[NUMBER_OF_ENCODERS];
137# endif 195# endif
138 196
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
@@ -251,11 +319,26 @@ bool transport_master(matrix_row_t matrix[]) {
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();
253# endif 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;
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