summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
Diffstat (limited to 'quantum')
-rw-r--r--quantum/keymap_extras/keymap_canadian_multilingual.h646
-rw-r--r--quantum/keymap_extras/keymap_neo2.h180
-rw-r--r--quantum/keymap_extras/sendstring_canadian_multilingual.h100
-rw-r--r--quantum/pincontrol.h50
-rw-r--r--quantum/process_keycode/process_rgb.c2
-rw-r--r--quantum/process_keycode/process_unicode_common.c118
-rw-r--r--quantum/process_keycode/process_unicode_common.h2
-rw-r--r--quantum/process_keycode/process_unicodemap.c3
-rw-r--r--quantum/quantum.h4
-rw-r--r--quantum/quantum_keycodes.h1
-rw-r--r--quantum/rgb_matrix.c11
-rw-r--r--quantum/rgb_matrix.h13
-rw-r--r--quantum/rgblight.c173
-rw-r--r--quantum/rgblight.h64
-rw-r--r--quantum/rgblight_modes.h8
-rw-r--r--quantum/stm32/halconf.h2
-rw-r--r--quantum/stm32/mcuconf.h2
-rw-r--r--quantum/template/avr/rules.mk2
-rw-r--r--quantum/template/ps2avrgb/rules.mk2
19 files changed, 937 insertions, 446 deletions
diff --git a/quantum/keymap_extras/keymap_canadian_multilingual.h b/quantum/keymap_extras/keymap_canadian_multilingual.h
index 4fc174e735..d980dc2e41 100644
--- a/quantum/keymap_extras/keymap_canadian_multilingual.h
+++ b/quantum/keymap_extras/keymap_canadian_multilingual.h
@@ -1,4 +1,4 @@
-/* Copyright 2016 Didier Loiseau
+/* Copyright 2020
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,247 +13,421 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef KEYMAP_CANADIAN_MULTILINGUAL_H
-#define KEYMAP_CANADIAN_MULTILINGUAL_H
-#include "keymap.h"
-
-#ifndef GR2A
-# define GR2A(kc) RCTL(kc)
-#endif
-
-// Normal characters
-// First row
-#define CSA_SLASH KC_GRV // /
-#define CSA_SLSH CSA_SLASH
-
-// Second row
-#define CSA_DEAD_CIRCUMFLEX KC_LBRACKET // dead ^
-#define CSA_DCRC CSA_DEAD_CIRCUMFLEX
-#define CSA_C_CEDILLA KC_RBRACKET // Ç
-#define CSA_CCED CSA_C_CEDILLA
-
-// Third row
-#define CSA_E_GRAVE KC_QUOT // è
-#define CSA_EGRV CSA_E_GRAVE
-#define CSA_A_GRAVE KC_BSLASH // à
-#define CSA_AGRV CSA_A_GRAVE
-
-// Fourth row
-#define CSA_U_GRAVE KC_NONUS_BSLASH // ù
-#define CSA_UGRV CSA_U_GRAVE
-#define CSA_E_ACUTE KC_SLSH // é
-#define CSA_ECUT CSA_E_ACUTE
-
-// Shifted characters
-// First row
-#define CSA_BACKSLASH LSFT(CSA_SLASH) /* \ */
-#define CSA_BSLS CSA_BACKSLASH
-#define CSA_QUESTION LSFT(KC_6) // ?
-#define CSA_QEST CSA_QUESTION
-
-// Second row
-#define CSA_DEAD_TREMA LSFT(CSA_DEAD_CIRCUMFLEX) // dead trema/umlaut/diaresis for ä ë ï ö ü
-#define CSA_DTRM CSA_DEAD_TREMA
-
-// Third row
-// all same as US-QWERTY, or capitalised character of the non-shifted key
-
-// Fourth row
-#define CSA_APOSTROPHE LSFT(KC_COMMA) // '
-#define CSA_APOS CSA_APOSTROPHE
-#define CSA_DOUBLE_QUOTE LSFT(KC_DOT) // "
-#define CSA_DQOT CSA_DOUBLE_QUOTE
-
-// Alt Gr-ed characters
-// First row
-#define CSA_PIPE ALGR(CSA_SLASH) // |
-#define CSA_CURRENCY ALGR(KC_4) // ¤
-#define CSA_CURR CSA_CURRENCY
-#define CSA_LEFT_CURLY_BRACE ALGR(KC_7) // {
-#define CSA_LCBR CSA_LEFT_CURLY_BRACE
-#define CSA_RIGHT_CURLY_BRACE ALGR(KC_8) // }
-#define CSA_RCBR CSA_RIGHT_CURLY_BRACE
-#define CSA_LBRACKET ALGR(KC_9) // [
-#define CSA_LBRC CSA_LBRACKET
-#define CSA_RBRACKET ALGR(KC_0) // ]
-#define CSA_RBRC CSA_RBRACKET
-#define CSA_NEGATION ALGR(KC_EQUAL) // ¬
-#define CSA_NEGT CSA_NEGATION
+#pragma once
-// Second row
-// euro symbol not available on Linux? (X.org)
-#define CSA_EURO ALGR(KC_E) // €
-#define CSA_DEAD_GRAVE ALGR(CSA_DEAD_CIRCUMFLEX)
-#define CSA_DGRV CSA_DEAD_GRAVE // dead `
-#define CSA_DEAD_TILDE ALGR(CSA_C_CEDILLA) // ~
-#define CSA_DTLD CSA_DEAD_TILDE
-
-// Third row
-#define CSA_DEGREE ALGR(KC_SCOLON) // °
-#define CSA_DEGR CSA_DEGREE
-
-// Fourth row
-#define CSA_LEFT_GUILLEMET ALGR(KC_Z) // «
-#define CSA_LGIL CSA_LEFT_GUILLEMET
-#define CSA_RIGHT_GUILLEMET ALGR(KC_X) // »
-#define CSA_RGIL CSA_RIGHT_GUILLEMET
-#define CSA_LESS ALGR(KC_COMMA) // <
-#define CSA_GREATER ALGR(KC_DOT) // >
-#define CSA_GRTR CSA_GREATER
-
-// Space bar
-#define CSA_NON_BREAKING_SPACE ALGR(KC_SPACE)
-#define CSA_NBSP CSA_NON_BREAKING_SPACE
-
-// GR2A-ed characters
-// First row
-#define CSA_SUPERSCRIPT_ONE GR2A(KC_1) // ¹
-#define CSA_SUP1 CSA_SUPERSCRIPT_ONE
-#define CSA_SUPERSCRIPT_TWO GR2A(KC_2) // ²
-#define CSA_SUP2 CSA_SUPERSCRIPT_TWO
-#define CSA_SUPERSCRIPT_THREE GR2A(KC_3) // ³
-#define CSA_SUP3 CSA_SUPERSCRIPT_THREE
-#define CSA_ONE_QUARTER GR2A(KC_4) // ¼
-#define CSA_1QRT CSA_ONE_QUARTER
-#define CSA_ONE_HALF GR2A(KC_5) // ½
-#define CSA_1HLF CSA_ONE_HALF
-#define CSA_THREE_QUARTERS GR2A(KC_6) // ¾
-#define CSA_3QRT CSA_THREE_QUARTERS
-// nothing on 7-0 and -
-#define CSA_DEAD_CEDILLA GR2A(KC_EQUAL) // dead ¸
-#define CSA_DCED CSA_DEAD_CEDILLA
-
-// Second row
-#define CSA_OMEGA GR2A(KC_Q) // ω
-#define CSA_OMEG CSA_OMEGA
-#define CSA_L_STROKE GR2A(KC_W) // ł
-#define CSA_LSTK CSA_L_STROKE
-#define CSA_OE_LIGATURE GR2A(KC_E) // œ
-#define CSA_OE CSA_OE_LIGATURE
-#define CSA_PARAGRAPH GR2A(KC_R) // ¶
-#define CSA_PARG CSA_PARAGRAPH
-#define CSA_T_STROKE GR2A(KC_T) // ŧ
-#define CSA_LEFT_ARROW GR2A(KC_Y) // ←
-#define CSA_LARW CSA_LEFT_ARROW
-#define CSA_DOWN_ARROW GR2A(KC_U) // ↓
-#define CSA_DARW CSA_DOWN_ARROW
-#define CSA_RIGHT_ARROW GR2A(KC_I) // →
-#define CSA_RARW CSA_RIGHT_ARROW
-#define CSA_O_STROKE GR2A(KC_O) // ø
-#define CSA_OSTK CSA_O_STROKE
-#define CSA_THORN GR2A(KC_P) // þ
-#define CSA_THRN CSA_THORN
-// nothing on ^
-#define CSA_TILDE GR2A(CSA_C_CEDILLA) // dead ~
-#define CSA_TILD CSA_TILDE
+#include "keymap.h"
-// Third row
-#define CSA_AE_LIGATURE GR2A(KC_A) // æ
-#define CSA_AE CSA_AE_LIGATURE
-#define CSA_SHARP_S GR2A(KC_S) // ß
-#define CSA_SRPS CSA_SHARP_S
-#define CSA_ETH GR2A(KC_D) // ð
-// nothing on F
-#define CSA_ENG GR2A(KC_G) // ŋ
-#define CSA_H_SRTOKE GR2A(KC_H) // ħ
-#define CSA_HSTK CSA_H_SRTOKE
-#define CSA_IJ_LIGATURE GR2A(KC_J) // ij
-#define CSA_IJ CSA_IJ_LIGATURE
-#define CSA_KRA GR2A(KC_K) // ĸ
-#define CSA_L_FLOWN_DOT GR2A(KC_L) // ŀ
-#define CSA_LFLD CSA_L_FLOWN_DOT
-#define CSA_DEAD_ACUTE GR2A(KC_SCLN) // dead acute accent
-#define CSA_DACT CSA_DEAD_ACUTE
-// nothing on È & À
+// clang-format off
-// Fourth row
-#define CSA_CENT GR2A(KC_C) // ¢
-#define CSA_LEFT_DOUBLE_QUOTE GR2A(KC_V) // “
-#define CSA_LDQT CSA_LEFT_DOUBLE_QUOTE
-#define CSA_RIGHT_DOUBLE_QUOTE GR2A(KC_B) // ”
-#define CSA_RDQT CSA_RIGHT_DOUBLE_QUOTE
-#define CSA_N_APOSTROPHE GR2A(KC_N) // ʼn (deprecated unicode codepoint)
-#define CSA_NAPO CSA_N_APOSTROPHE
-#define CSA_MU GR2A(KC_M) // μ
-#define CSA_HORIZONTAL_BAR GR2A(KC_COMMA) // ―
-#define CSA_HZBR CSA_HORIZONTAL_BAR
-#define CSA_DEAD_DOT_ABOVE GR2A(KC_DOT) // dead ˙
-#define CSA_DDTA CSA_DEAD_DOT_ABOVE
+/*
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ / │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ ^ │ Ç │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │      │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ È │ À │    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │ Ù │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ É │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+// Row 1
+#define CA_SLSH KC_GRV // /
+#define CA_1 KC_1 // 1
+#define CA_2 KC_2 // 2
+#define CA_3 KC_3 // 3
+#define CA_4 KC_4 // 4
+#define CA_5 KC_5 // 5
+#define CA_6 KC_6 // 6
+#define CA_7 KC_7 // 7
+#define CA_8 KC_8 // 8
+#define CA_9 KC_9 // 9
+#define CA_0 KC_0 // 0
+#define CA_MINS KC_MINS // -
+#define CA_EQL KC_EQL // =
+// Row 2
+#define CA_Q KC_Q // Q
+#define CA_W KC_W // W
+#define CA_E KC_E // E
+#define CA_R KC_R // R
+#define CA_T KC_T // T
+#define CA_Y KC_Y // Y
+#define CA_U KC_U // U
+#define CA_I KC_I // I
+#define CA_O KC_O // O
+#define CA_P KC_P // P
+#define CA_CIRC KC_LBRC // ^ (dead)
+#define CA_CCED KC_RBRC // Ç
+// Row 3
+#define CA_A KC_A // A
+#define CA_S KC_S // S
+#define CA_D KC_D // D
+#define CA_F KC_F // F
+#define CA_G KC_G // G
+#define CA_H KC_H // H
+#define CA_J KC_J // J
+#define CA_K KC_K // K
+#define CA_L KC_L // L
+#define CA_SCLN KC_SCLN // ;
+#define CA_EGRV KC_QUOT // É
+#define CA_AGRV KC_NUHS // À
+// Row 4
+#define CA_UGRV KC_NUBS // Ù
+#define CA_Z KC_Z // Z
+#define CA_X KC_X // X
+#define CA_C KC_C // C
+#define CA_V KC_V // V
+#define CA_B KC_B // B
+#define CA_N KC_N // N
+#define CA_M KC_M // M
+#define CA_COMM KC_COMM // ,
+#define CA_DOT KC_DOT // .
+#define CA_EACU KC_SLSH // É
-// GR2A-shifted characters (different from capitalised GR2A-ed characters)
-// First row
-#define CSA_SOFT_HYPHEN GR2A(LSFT(CSA_SLASH)) // soft-hyphen, appears as a hyphen in wrapped word
-#define CSA_SHYP CSA_SOFT_HYPHEN
-#define CSA_INVERTED_EXCLAIM GR2A(KC_EXCLAIM) // ¡
-#define CSA_IXLM CSA_INVERTED_EXCLAIM
-// nothing on 2
-#define CSA_POUND GR2A(LSFT(KC_3)) // £
-#define CSA_GBP CSA_POUND_SIGN
-// already on ALGR(KC_E)
-#define CSA_EURO_BIS GR2A(LSFT(KC_4)) // €
-#define CSA_EURB CSA_EURO_BIS
-#define CSA_THREE_EIGHTHS GR2A(LSFT(KC_5)) // ⅜
-#define CSA_3ON8 CSA_THREE_EIGHTHS
-#define CSA_FIVE_EIGHTHS GR2A(LSFT(KC_6)) // ⅝
-#define CSA_5ON8 CSA_FIVE_EIGHTHS
-#define CSA_SEVEN_EIGHTHS GR2A(LSFT(KC_7)) // ⅞
-#define CSA_7ON8 CSA_SEVEN_EIGHTHS
-#define CSA_TRADEMARK GR2A(LSFT(KC_8)) // ™
-#define CSA_TM CSA_TRADEMARK
-#define CSA_PLUS_MINUS GR2A(LSFT(KC_9)) // ±
-#define CSA_PSMS CSA_PLUS_MINUS
-// nothing on 0
-#define CSA_INVERTED_QUESTION GR2A(LSFT(KC_MINUS)) // ¿
-#define CSA_IQST CSA_INVERTED_QUESTION
-#define CSA_DEAD_OGONEK GR2A(LSFT(KC_EQUAL)) // dead ˛
-#define CSA_DOGO CSA_DEAD_OGONEK
+/* Shifted symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ \ │ ! │ @ │ # │ $ │ % │ ? │ & │ * │ ( │ ) │ _ │ + │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │   │   │   │   │   │   │   │   │   │   │ ¨ │   │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │      │   │   │   │   │   │   │   │   │   │ : │   │   │    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │   │   │   │   │   │   │   │   │ ' │ " │   │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+// Row 1
+#define CA_BSLS S(CA_SLSH) // (backslash)
+#define CA_EXLM S(CA_1) // !
+#define CA_AT S(CA_2) // @
+#define CA_HASH S(CA_3) // #
+#define CA_DLR S(CA_4) // $
+#define CA_PERC S(CA_5) // %
+#define CA_QUES S(CA_6) // ?
+#define CA_AMPR S(CA_7) // &
+#define CA_ASTR S(CA_8) // *
+#define CA_LPRN S(CA_9) // (
+#define CA_RPRN S(CA_0) // )
+#define CA_UNDS S(CA_MINS) // _
+#define CA_PLUS S(CA_EQL) // +
+// Row 2
+#define CA_DIAE S(CA_CIRC) // ¨ (dead)
+// Row 3
+#define CA_COLN S(CA_SCLN) // :
+// Row 4
+#define CA_QUOT S(CA_COMM) // '
+#define CA_DQUO S(CA_DOT) // "
-// Second row
-#define CSA_REGISTERED_TRADEMARK GR2A(LSFT(KC_R)) // ®
-#define CSA_RTM CSA_REGISTERED_TRADEMARK
-#define CSA_YEN GR2A(LSFT(KC_Y)) // ¥
-#define CSA_YUAN CSA_YEN
-#define CSA_UP_ARROW LSFT(CSA_DOWN_ARROW) // ↑
-#define CSA_DOTLESS_I GR2A(LSFT(KC_I)) // ı
-#define CSA_DLSI CSA_DOTLESS_I
-#define CSA_DEAD_RING GR2A(LSFT(CSA_DCRC)) // dead °
-#define CSA_DRNG CSA_DEAD_RING
-#define CSA_DEAD_MACRON GR2A(LSFT(CSA_C_CEDILLA)) // dead ¯
-#define CSA_DMCR CSA_DEAD_MACRON
+/* AltGr symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ | │   │   │   │ ¤ │   │   │ { │ } │ [ │ ] │   │ ¬ │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │   │   │ € │   │   │   │   │   │   │   │ ` │ ~ │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │      │   │   │   │   │   │   │   │   │   │ ° │   │   │    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │   │ « │ » │   │   │   │   │   │ < │ > │   │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+// Row 1
+#define CA_PIPE ALGR(CA_SLSH) // |
+#define CA_CURR ALGR(CA_4) // ¤
+#define CA_LCBR ALGR(CA_7) // {
+#define CA_RCBR ALGR(CA_8) // }
+#define CA_LBRC ALGR(CA_9) // [
+#define CA_RBRC ALGR(CA_0) // ]
+#define CA_NOT ALGR(CA_EQL) // ¬
+// Row 2
+#define CA_EURO ALGR(CA_E) // €
+#define CA_GRV ALGR(CA_CIRC) // ` (dead)
+#define CA_DTIL ALGR(CA_CCED) // ~ (dead)
+// Row 3
+#define CA_DEG ALGR(CA_SCLN) // °
+// Row 4
+#define CA_LDAQ ALGR(CA_X) // «
+#define CA_RDAQ ALGR(CA_C) // »
+#define CA_LABK ALGR(CA_DOT) // <
+#define CA_RABK ALGR(CA_COMM) // >
-// Third row
-#define CSA_SECTION GR2A(LSFT(KC_S)) // §
-#define CSA_SECT CSA_SECTION
-#define CSA_ORDINAL_INDICATOR_A GR2A(LSFT(KC_F)) // ª
-#define CSA_ORDA CSA_ORDINAL_INDICATOR_A
-#define CSA_DEAD_DOUBLE_ACUTE LSFT(CSA_DEAD_ACUTE) // ˝
-#define CSA_DDCT CSA_DEAD_DOUBLE_ACUTE
-#define CSA_DEAD_CARON GR2A(LSFT(CSA_E_GRAVE)) // dead ˇ
-#define CSA_DCAR CSA_DEAD_CARON
-#define CSA_DEAD_BREVE GR2A(LSFT(CSA_A_GRAVE)) // dead ˘
-#define CSA_DBRV CSA_DEAD_BREVE
+/* Right Ctrl symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │   │ ¹ │ ² │ ³ │ ¼ │ ½ │ ¾ │   │   │   │   │   │ ¸ │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │ Ω │ Ł │ Œ │ ¶ │ Ŧ │ ← │ ↓ │ → │ Ø │ Þ │   │ ~ │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │      │ Æ │ ß │ Ð │   │ Ŋ │ Ħ │ IJ │ ĸ │ Ŀ │ ´ │   │   │    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │   │   │   │ ¢ │ “ │ ” │ ʼn │ μ │ ― │ ˙ │   │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+// Row 1
+#define CA_SUP1 RCTL(CA_1) // ¹
+#define CA_SUP2 RCTL(CA_2) // ²
+#define CA_SUP3 RCTL(CA_3) // ³
+#define CA_QRTR RCTL(CA_4) // ¼
+#define CA_HALF RCTL(CA_5) // ½
+#define CA_TQTR RCTL(CA_6) // ¾
+#define CA_CEDL RCTL(CA_EQL) // ¸ (dead)
+// Row 2
+#define CA_OMEG RCTL(CA_Q) // Ω
+#define CA_LSTR RCTL(CA_W) // Ł
+#define CA_OE RCTL(CA_E) // Œ
+#define CA_PARA RCTL(CA_R) // ¶
+#define CA_TSTR RCTL(CA_T) // Ŧ
+#define CA_LARR RCTL(CA_Y) // ←
+#define CA_DARR RCTL(CA_U) // ↓
+#define CA_RARR RCTL(CA_I) // →
+#define CA_OSTR RCTL(CA_O) // Ø
+#define CA_THRN RCTL(CA_P) // Þ
+#define CA_TILD RCTL(CA_CCED) // ~
+// Row 3
+#define CA_AE RCTL(CA_A) // Æ
+#define CA_SS RCTL(CA_S) // ß
+#define CA_ETH RCTL(CA_D) // Ð
+#define CA_ENG RCTL(CA_G) // Ŋ
+#define CA_HSTR RCTL(CA_H) // Ħ
+#define CA_IJ RCTL(CA_J) // IJ
+#define CA_KRA RCTL(CA_K) // ĸ
+#define CA_LMDT RCTL(CA_L) // Ŀ
+#define CA_ACUT RCTL(CA_SCLN) // ´ (dead)
+// Row 4
+#define CA_CENT RCTL(CA_C) // ¢
+#define CA_LDQU RCTL(CA_V) // “
+#define CA_RDQU RCTL(CA_B) // ”
+#define CA_APSN RCTL(CA_N) // ʼn
+#define CA_MICR RCTL(CA_M) // μ
+#define CA_HRZB RCTL(CA_COMM) // ―
+#define CA_DOTA ALGR(CA_DOT) // ˙ (dead)
-// Fourth row
-#define CSA_BROKEN_PIPE GR2A(LSFT(CSA_U_GRAVE)) // ¦
-#define CSA_BPIP CSA_BROKEN_PIPE
-#define CSA_COPYRIGHT GR2A(LSFT(KC_C)) // ©
-#define CSA_CPRT CSA_COPYRIGHT
-#define CSA_LEFT_QUOTE GR2A(LSFT(KC_V)) // ‘
-#define CSA_LQOT CSA_LEFT_QUOTE
-#define CSA_RIGHT_QUOTE GR2A(LSFT(KC_B)) // ’
-#define CSA_RQOT CSA_RIGHT_QUOTE
-#define CSA_EIGHTH_NOTE GR2A(LSFT(KC_N)) // ♪
-#define CSA_8NOT CSA_EIGHTH_NOTE
-#define CSA_ORDINAL_INDICATOR_O GR2A(LSFT(KC_M)) // º
-#define CSA_ORDO CSA_ORDINAL_INDICATOR_O
-#define CSA_TIMES GR2A(LSFT(KC_COMMA)) // ×
-#define CSA_TIMS CSA_TIMES
-#define CSA_OBELUS GR2A(LSFT(KC_DOT)) // ÷
-#define CSA_OBEL CSA_OBELUS
-// more conventional name of the symbol
-#define CSA_DIVISION_SIGN CSA_OBELUS
-#define CSA_DVSN CSA_DIVISION_SIGN
-// TODO GR2A(LSFT(CSA_E_ACUTE))
+/* Shift+Right Ctrl symbols
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ - │ ¡ │   │ £ │   │ ⅜ │ ⅝ │ ⅞ │ ™ │ ± │   │ ¿ │ ˛ │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │   │   │   │ ® │   │ ¥ │ ↑ │ ı │   │   │ ° │ ¯ │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │      │   │ § │   │ ª │   │   │   │   │   │ ˝ │ ˇ │ ˘ │    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │ ¦ │   │   │ © │ ‘ │ ’ │ ♪ │ º │ × │ ÷ │   │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │    │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+// Row 1
+#define CA_SHYP RCTL(S(CA_SLSH)) // (soft hyphen)
+#define CA_IEXL RCTL(S(CA_1)) // ¡
+#define CA_PND RCTL(S(CA_3)) // £
+#define CA_TEIG RCTL(S(CA_5)) // ⅜
+#define CA_FEIG RCTL(S(CA_6)) // ⅝
+#define CA_SEIG RCTL(S(CA_7)) // ⅞
+#define CA_TM RCTL(S(CA_8)) // ™
+#define CA_PLMN RCTL(S(CA_9)) // ±
+#define CA_IQUE RCTL(S(CA_MINS)) // ¿
+#define CA_OGON RCTL(S(CA_EQL)) // ˛ (dead)
+// Row 2
+#define CA_REGD RCTL(S(CA_R)) // ®
+#define CA_YEN RCTL(S(CA_Y)) // ¥
+#define CA_UARR RCTL(S(CA_U)) // ↑
+#define CA_DLSI RCTL(S(CA_I)) // ı
+#define CA_RNGA RCTL(S(CA_CIRC)) // ° (dead)
+#define CA_MACR RCTL(S(CA_CCED)) // ¯ (dead)
+// Row 3
+#define CA_SECT RCTL(S(CA_S)) // §
+#define CA_FORD RCTL(S(CA_F)) // ª
+#define CA_DACU RCTL(S(CA_SCLN)) // ˝ (dead)
+#define CA_CARN RCTL(S(CA_EGRV)) // ˇ (dead)
+#define CA_BREV RCTL(S(CA_AGRV)) // ˘ (dead)
+// Row 4
+#define CA_BRKP RCTL(S(CA_UGRV)) // ¦
+#define CA_COPY RCTL(S(CA_C)) // ©
+#define CA_LSQU RCTL(S(CA_V)) // ‘
+#define CA_RSQU RCTL(S(CA_B)) // ’
+#define CA_ENOT RCTL(S(CA_N)) // ♪
+#define CA_MORD RCTL(S(CA_M)) // º
+#define CA_MUL RCTL(S(CA_COMM)) // ×
+#define CA_DIV RCTL(S(CA_DOT)) // ÷
-#endif
+// DEPRECATED
+#define GR2A(kc) RCTL(kc)
+#define CSA_SLASH CA_SLSH
+#define CSA_SLSH CA_SLSH
+#define CSA_DEAD_CIRCUMFLEX CA_CIRC
+#define CSA_DCRC CA_CIRC
+#define CSA_C_CEDILLA CA_CCED
+#define CSA_CCED CA_CCED
+#define CSA_E_GRAVE CA_EGRV
+#define CSA_EGRV CA_EGRV
+#define CSA_A_GRAVE CA_AGRV
+#define CSA_AGRV CA_AGRV
+#define CSA_U_GRAVE CA_UGRV
+#define CSA_UGRV CA_UGRV
+#define CSA_E_ACUTE CA_EACU
+#define CSA_ECUT CA_EACU
+#define CSA_BACKSLASH CA_BSLS
+#define CSA_BSLS CA_BSLS
+#define CSA_QUESTION CA_QUES
+#define CSA_QEST CA_QUES
+#define CSA_DEAD_TREMA CA_DIAE
+#define CSA_DTRM CA_DIAE
+#define CSA_APOSTROPHE CA_QUOT
+#define CSA_APOS CA_QUOT
+#define CSA_DOUBLE_QUOTE CA_DQUO
+#define CSA_DQOT CA_DQUO
+#define CSA_PIPE CA_PIPE
+#define CSA_CURRENCY CA_CURR
+#define CSA_CURR CA_CURR
+#define CSA_LEFT_CURLY_BRACE CA_LCBR
+#define CSA_LCBR CA_LCBR
+#define CSA_RIGHT_CURLY_BRACE CA_RCBR
+#define CSA_RCBR CA_RCBR
+#define CSA_LBRACKET CA_LBRC
+#define CSA_LBRC CA_LBRC
+#define CSA_RBRACKET CA_RBRC
+#define CSA_RBRC CA_RBRC
+#define CSA_NEGATION CA_NOT
+#define CSA_NEGT CA_NOT
+#define CSA_EURO CA_EURO
+#define CSA_DEAD_GRAVE CA_GRV
+#define CSA_DGRV CA_GRV
+#define CSA_DEAD_TILDE CA_DTIL
+#define CSA_DTLD CA_DTIL
+#define CSA_DEGREE CA_DEG
+#define CSA_DEGR CA_DEG
+#define CSA_LEFT_GUILLEMET CA_LDAQ
+#define CSA_LGIL CA_LDAQ
+#define CSA_RIGHT_GUILLEMET CA_RDAQ
+#define CSA_RGIL CA_RDAQ
+#define CSA_LESS CA_LABK
+#define CSA_GREATER CA_RABK
+#define CSA_GRTR CA_RABK
+#define CSA_NON_BREAKING_SPACE ALGR(KC_SPC)
+#define CSA_NBSP ALGR(KC_SPC)
+#define CSA_SUPERSCRIPT_ONE CA_SUP1
+#define CSA_SUP1 CA_SUP1
+#define CSA_SUPERSCRIPT_TWO CA_SUP2
+#define CSA_SUP2 CA_SUP2
+#define CSA_SUPERSCRIPT_THREE CA_SUP3
+#define CSA_SUP3 CA_SUP3
+#define CSA_ONE_QUARTER CA_QRTR
+#define CSA_1QRT CA_QRTR
+#define CSA_ONE_HALF CA_HALF
+#define CSA_1HLF CA_HALF
+#define CSA_THREE_QUARTERS CA_TQTR
+#define CSA_3QRT CA_TQTR
+#define CSA_DEAD_CEDILLA CA_CEDL
+#define CSA_DCED CA_CEDL
+#define CSA_OMEGA CA_OMEG
+#define CSA_OMEG CA_OMEG
+#define CSA_L_STROKE CA_LSTR
+#define CSA_LSTK CA_LSTR
+#define CSA_OE_LIGATURE CA_OE
+#define CSA_OE CA_OE
+#define CSA_PARAGRAPH CA_PARA
+#define CSA_PARG CA_PARA
+#define CSA_T_STROKE CA_TSTR
+#define CSA_LEFT_ARROW CA_LARR
+#define CSA_LARW CA_LARR
+#define CSA_DOWN_ARROW CA_DARR
+#define CSA_DARW CA_DARR
+#define CSA_RIGHT_ARROW CA_RARR
+#define CSA_RARW CA_RARR
+#define CSA_O_STROKE CA_OSTR
+#define CSA_OSTK CA_OSTR
+#define CSA_THORN CA_THRN
+#define CSA_THRN CA_THRN
+#define CSA_TILDE CA_TILD
+#define CSA_TILD CA_TILD
+#define CSA_AE_LIGATURE CA_AE
+#define CSA_AE CA_AE
+#define CSA_SHARP_S CA_SS
+#define CSA_SRPS CA_SS
+#define CSA_ETH CA_ETH
+#define CSA_ENG CA_ENG
+#define CSA_H_SRTOKE CA_HSTR
+#define CSA_HSTK CA_HSTR
+#define CSA_IJ_LIGATURE CA_IJ
+#define CSA_IJ CA_IJ
+#define CSA_KRA CA_KRA
+#define CSA_L_FLOWN_DOT CA_LMDT
+#define CSA_LFLD CA_LMDT
+#define CSA_DEAD_ACUTE CA_ACUT
+#define CSA_DACT CA_ACUT
+#define CSA_CENT CA_CENT
+#define CSA_LEFT_DOUBLE_QUOTE CA_LDQU
+#define CSA_LDQT CA_LDQU
+#define CSA_RIGHT_DOUBLE_QUOTE CA_RDQU
+#define CSA_RDQT CA_RDQU
+#define CSA_N_APOSTROPHE CA_APSN
+#define CSA_NAPO CA_APSN
+#define CSA_MU CA_MICR
+#define CSA_HORIZONTAL_BAR CA_HRZB
+#define CSA_HZBR CA_HRZB
+#define CSA_DEAD_DOT_ABOVE CA_DOTA
+#define CSA_DDTA CA_DOTA
+#define CSA_SOFT_HYPHEN CA_SHYP
+#define CSA_SHYP CA_SHYP
+#define CSA_INVERTED_EXCLAIM CA_IEXL
+#define CSA_IXLM CA_IEXL
+#define CSA_POUND CA_PND
+#define CSA_GBP CA_PND
+#define CSA_EURO_BIS CA_EURO
+#define CSA_EURB CA_EURO
+#define CSA_THREE_EIGHTHS CA_TEIG
+#define CSA_3ON8 CA_TEIG
+#define CSA_FIVE_EIGHTHS CA_FEIG
+#define CSA_5ON8 CA_FEIG
+#define CSA_SEVEN_EIGHTHS CA_SEIG
+#define CSA_7ON8 CA_SEIG
+#define CSA_TRADEMARK CA_TM
+#define CSA_TM CA_TM
+#define CSA_PLUS_MINUS CA_PLMN
+#define CSA_PSMS CA_PLMN
+#define CSA_INVERTED_QUESTION CA_IQUE
+#define CSA_IQST CA_IQUE
+#define CSA_DEAD_OGONEK CA_OGON
+#define CSA_DOGO CA_OGON
+#define CSA_REGISTERED_TRADEMARK CA_REGD
+#define CSA_RTM CA_REGD
+#define CSA_YEN CA_YEN
+#define CSA_YUAN CA_YEN
+#define CSA_UP_ARROW CA_UARR
+#define CSA_DOTLESS_I CA_DLSI
+#define CSA_DLSI CA_DLSI
+#define CSA_DEAD_RING CA_RNGA
+#define CSA_DRNG CA_RNGA
+#define CSA_DEAD_MACRON CA_MACR
+#define CSA_DMCR CA_MACR
+#define CSA_SECTION CA_SECT
+#define CSA_SECT CA_SECT
+#define CSA_ORDINAL_INDICATOR_A CA_FORD
+#define CSA_ORDA CA_FORD
+#define CSA_DEAD_DOUBLE_ACUTE CA_DACU
+#define CSA_DDCT CA_DACU
+#define CSA_DEAD_CARON CA_CARN
+#define CSA_DCAR CA_CARN
+#define CSA_DEAD_BREVE CA_BREV
+#define CSA_DBRV CA_BREV
+#define CSA_BROKEN_PIPE CA_BRKP
+#define CSA_BPIP CA_BRKP
+#define CSA_COPYRIGHT CA_COPY
+#define CSA_CPRT CA_COPY
+#define CSA_LEFT_QUOTE CA_LSQU
+#define CSA_LQOT CA_LSQU
+#define CSA_RIGHT_QUOTE CA_RSQU
+#define CSA_RQOT CA_RSQU
+#define CSA_EIGHTH_NOTE CA_ENOT
+#define CSA_8NOT CA_ENOT
+#define CSA_ORDINAL_INDICATOR_O CA_MORD
+#define CSA_ORDO CA_MORD
+#define CSA_TIMES CA_MUL
+#define CSA_TIMS CA_MUL
+#define CSA_OBELUS CA_DIV
+#define CSA_OBEL CA_DIV
+#define CSA_DIVISION_SIGN CA_DIV
+#define CSA_DVSN CA_DIV
diff --git a/quantum/keymap_extras/keymap_neo2.h b/quantum/keymap_extras/keymap_neo2.h
index 818a739c76..8e6e2b77a2 100644
--- a/quantum/keymap_extras/keymap_neo2.h
+++ b/quantum/keymap_extras/keymap_neo2.h
@@ -13,66 +13,130 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef KEYMAP_NEO2
-#define KEYMAP_NEO2
-#include "keymap.h"
-#include "keymap_german.h"
-
-#define NEO_A KC_D
-#define NEO_B KC_N
-#define NEO_C KC_R
-#define NEO_D DE_OE
-#define NEO_E KC_F
-#define NEO_F KC_O
-#define NEO_G KC_I
-#define NEO_H KC_U
-#define NEO_I KC_S
-#define NEO_J DE_MINS
-#define NEO_K DE_Z
-#define NEO_L KC_E
-#define NEO_M KC_M
-#define NEO_N KC_J
-#define NEO_O KC_G
-#define NEO_P KC_V
-#define NEO_Q KC_P
-#define NEO_R KC_K
-#define NEO_S KC_H
-#define NEO_T KC_L
-#define NEO_U KC_A
-#define NEO_V KC_W
-#define NEO_W KC_T
-#define NEO_X KC_Q
-#define NEO_Y DE_AE
-#define NEO_Z KC_B
-#define NEO_AE KC_C
-#define NEO_OE KC_X
-#define NEO_UE DE_Y
-#define NEO_SS DE_UE
-
-#define NEO_DOT DE_DOT
-#define NEO_COMM DE_COMM
+#pragma once
-#define NEO_1 DE_1
-#define NEO_2 DE_2
-#define NEO_3 DE_3
-#define NEO_4 DE_4
-#define NEO_5 DE_5
-#define NEO_6 DE_6
-#define NEO_7 DE_7
-#define NEO_8 DE_8
-#define NEO_9 DE_9
-#define NEO_0 DE_0
-#define NEO_MINS DE_SS
-
-#define NEO_ACUT DE_PLUS
-#define NEO_GRV DE_ACUT
-#define NEO_CIRC DE_CIRC
+#include "keymap.h"
-#define NEO_L1_L KC_CAPS
-#define NEO_L1_R DE_HASH
+// clang-format off
-#define NEO_L2_L DE_LESS
-#define NEO_L2_R KC_ALGR
+/*
+ * ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐
+ * │ ^ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ ` │       │
+ * ├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤
+ * │     │ X │ V │ L │ C │ W │ K │ H │ G │ F │ Q │ ß │ ´ │     │
+ * ├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┐    │
+ * │  L3  │ U │ I │ A │ E │ O │ S │ N │ R │ T │ D │ Y │ L3│    │
+ * ├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┴────┤
+ * │    │L4 │ Ü │ Ö │ Ä │ P │ Z │ B │ M │ , │ . │ J │          │
+ * ├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬────┤
+ * │    │    │    │                        │    │ L4 │    │    │
+ * └────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
+ */
+// Row 1
+#define NE_CIRC KC_GRV // ^ (dead)
+#define NE_1 KC_1 // 1
+#define NE_2 KC_2 // 2
+#define NE_3 KC_3 // 3
+#define NE_4 KC_4 // 4
+#define NE_5 KC_5 // 5
+#define NE_6 KC_6 // 6
+#define NE_7 KC_7 // 7
+#define NE_8 KC_8 // 8
+#define NE_9 KC_9 // 9
+#define NE_0 KC_0 // 0
+#define NE_MINS KC_MINS // -
+#define NE_GRV KC_EQL // ` (dead)
+// Row 2
+#define NE_X KC_Q // X
+#define NE_V KC_W // V
+#define NE_L KC_E // L
+#define NE_C KC_R // C
+#define NE_W KC_T // W
+#define NE_K KC_Y // K
+#define NE_H KC_U // H
+#define NE_H KC_I // G
+#define NE_F KC_O // F
+#define NE_Q KC_P // Q
+#define NE_SS KC_LBRC // ß
+#define NE_ACUT KC_RBRC // ´ (dead)
+// Row 3
+#define NE_L3L KC_CAPS // (layer 3)
+#define NE_U KC_A // U
+#define NE_I KC_S // I
+#define NE_A KC_D // A
+#define NE_E KC_F // E
+#define NE_O KC_G // O
+#define NE_S KC_H // S
+#define NE_N KC_J // N
+#define NE_R KC_K // R
+#define NE_T KC_L // T
+#define NE_D KC_SCLN // D
+#define NE_Y KC_QUOT // Y
+#define NE_L3R KC_NUHS // (layer 3)
+// Row 4
+#define NE_L4L KC_NUBS // (layer 4)
+#define NE_UDIA KC_Z // Ü
+#define NE_ODIA KC_X // Ö
+#define NE_ADIA KC_C // Ä
+#define NE_P KC_V // P
+#define NE_Z KC_B // Z
+#define NE_B KC_N // B
+#define NE_M KC_M // M
+#define NE_COMM KC_COMM // ,
+#define NE_DOT KC_DOT // .
+#define NE_J KC_SLSH // J
+// Row 5
+#define NE_L4R KC_ALGR // (layer 4)
-#endif
+// DEPRECATED
+#define NEO_A NE_A
+#define NEO_B NE_B
+#define NEO_C NE_C
+#define NEO_D NE_D
+#define NEO_E NE_E
+#define NEO_F NE_F
+#define NEO_G NE_G
+#define NEO_H NE_H
+#define NEO_I NE_I
+#define NEO_J NE_J
+#define NEO_K NE_K
+#define NEO_L NE_L
+#define NEO_M NE_M
+#define NEO_N NE_N
+#define NEO_O NE_O
+#define NEO_P NE_P
+#define NEO_Q NE_Q
+#define NEO_R NE_R
+#define NEO_S NE_S
+#define NEO_T NE_T
+#define NEO_U NE_U
+#define NEO_V NE_V
+#define NEO_W NE_W
+#define NEO_X NE_X
+#define NEO_Y NE_Y
+#define NEO_Z NE_Z
+#define NEO_AE NE_ADIA
+#define NEO_OE NE_ODIA
+#define NEO_UE NE_UDIA
+#define NEO_SS NE_SS
+#define NEO_DOT NE_DOT
+#define NEO_COMM NE_COMM
+#define NEO_1 NE_1
+#define NEO_2 NE_2
+#define NEO_3 NE_3
+#define NEO_4 NE_4
+#define NEO_5 NE_5
+#define NEO_6 NE_6
+#define NEO_7 NE_7
+#define NEO_8 NE_8
+#define NEO_9 NE_9
+#define NEO_0 NE_0
+#define NEO_MINS NE_MINS
+#define NEO_ACUT NE_ACUT
+#define NEO_GRV NE_GRV
+#define NEO_CIRC NE_CIRC
+#define NEO_L1_L NE_L3L
+#define NEO_L1_R NE_L3R
+#define NEO_L2_L NE_L4L
+#define NEO_L2_R NE_L4R
diff --git a/quantum/keymap_extras/sendstring_canadian_multilingual.h b/quantum/keymap_extras/sendstring_canadian_multilingual.h
new file mode 100644
index 0000000000..c3fcc62c37
--- /dev/null
+++ b/quantum/keymap_extras/sendstring_canadian_multilingual.h
@@ -0,0 +1,100 @@
+/* Copyright 2020
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Sendstring lookup tables for Canadian Multilingual layouts
+
+#pragma once
+
+#include "keymap_canadian_multilingual.h"
+#include "quantum.h"
+
+// clang-format off
+
+const uint8_t ascii_to_shift_lut[16] PROGMEM = {
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+
+ KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 1),
+ KCLUT_ENTRY(1, 1, 1, 1, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 1, 0, 0, 0, 0, 1),
+ KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
+ KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
+ KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1),
+ KCLUT_ENTRY(1, 1, 1, 0, 1, 0, 0, 1),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0)
+};
+
+const uint8_t ascii_to_altgr_lut[16] PROGMEM = {
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 1, 0, 1, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 1, 0, 1, 0, 0),
+ KCLUT_ENTRY(1, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0),
+ KCLUT_ENTRY(0, 0, 0, 1, 1, 1, 1, 0)
+};
+
+const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
+ // NUL SOH STX ETX EOT ENQ ACK BEL
+ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
+ // BS TAB LF VT FF CR SO SI
+ KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
+ // DLE DC1 DC2 DC3 DC4 NAK SYN ETB
+ XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
+ // CAN EM SUB ESC FS GS RS US
+ XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
+
+ // ! " # $ % & '
+ KC_SPC, CA_1, CA_DOT, CA_3, CA_4, CA_5, CA_7, CA_COMM,
+ // ( ) * + , - . /
+ CA_9, CA_0, CA_8, CA_EQL, CA_COMM, CA_MINS, CA_DOT, CA_SLSH,
+ // 0 1 2 3 4 5 6 7
+ CA_0, CA_1, CA_2, CA_3, CA_4, CA_5, CA_6, CA_7,
+ // 8 9 : ; < = > ?
+ CA_8, CA_9, CA_SCLN, CA_SCLN, CA_DOT, CA_EQL, CA_COMM, CA_6,
+ // @ A B C D E F G
+ CA_2, CA_A, CA_B, CA_C, CA_D, CA_E, CA_F, CA_G,
+ // H I J K L M N O
+ CA_H, CA_I, CA_J, CA_K, CA_L, CA_M, CA_N, CA_O,
+ // P Q R S T U V W
+ CA_P, CA_Q, CA_R, CA_S, CA_T, CA_U, CA_V, CA_W,
+ // X Y Z [ \ ] ^ _
+ CA_X, CA_Y, CA_Z, CA_9, CA_SLSH, CA_0, CA_CIRC, CA_MINS,
+ // ` a b c d e f g
+ CA_CIRC, CA_A, CA_B, CA_C, CA_D, CA_E, CA_F, CA_G,
+ // h i j k l m n o
+ CA_H, CA_I, CA_J, CA_K, CA_L, CA_M, CA_N, CA_O,
+ // p q r s t u v w
+ CA_P, CA_Q, CA_R, CA_S, CA_T, CA_U, CA_V, CA_W,
+ // x y z { | } ~ DEL
+ CA_X, CA_Y, CA_Z, CA_7, CA_SLSH, CA_8, CA_CCED, KC_DEL
+};
diff --git a/quantum/pincontrol.h b/quantum/pincontrol.h
deleted file mode 100644
index 204fddf30c..0000000000
--- a/quantum/pincontrol.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2016 Wez Furlong
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-#pragma once
-// Some helpers for controlling gpio pins
-#include <avr/io.h>
-
-enum {
- PinDirectionInput = 0,
- PinDirectionOutput = 1,
- PinLevelHigh = 1,
- PinLevelLow = 0,
-};
-
-// ex: pinMode(B0, PinDirectionOutput);
-static inline void pinMode(uint8_t pin, int mode) {
- uint8_t bv = _BV(pin & 0xf);
- if (mode == PinDirectionOutput) {
- _SFR_IO8((pin >> 4) + 1) |= bv;
- } else {
- _SFR_IO8((pin >> 4) + 1) &= ~bv;
- _SFR_IO8((pin >> 4) + 2) &= ~bv;
- }
-}
-
-// ex: digitalWrite(B0, PinLevelHigh);
-static inline void digitalWrite(uint8_t pin, int mode) {
- uint8_t bv = _BV(pin & 0xf);
- if (mode == PinLevelHigh) {
- _SFR_IO8((pin >> 4) + 2) |= bv;
- } else {
- _SFR_IO8((pin >> 4) + 2) &= ~bv;
- }
-}
-
-// Return true if the pin is HIGH
-// digitalRead(B0)
-static inline bool digitalRead(uint8_t pin) { return _SFR_IO8(pin >> 4) & _BV(pin & 0xf); }
diff --git a/quantum/process_keycode/process_rgb.c b/quantum/process_keycode/process_rgb.c
index 627e5986fb..21164b8f9f 100644
--- a/quantum/process_keycode/process_rgb.c
+++ b/quantum/process_keycode/process_rgb.c
@@ -56,7 +56,7 @@ bool process_rgb(const uint16_t keycode, const keyrecord_t *record) {
// Split keyboards need to trigger on key-up for edge-case issue
if (!record->event.pressed) {
#endif
- uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT));
+ uint8_t shifted = get_mods() & MOD_MASK_SHIFT;
switch (keycode) {
case RGB_TOG:
rgblight_toggle();
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
index 48ce3961ad..fb50215012 100644
--- a/quantum/process_keycode/process_unicode_common.c
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -24,8 +24,8 @@ uint8_t unicode_saved_mods;
#if UNICODE_SELECTED_MODES != -1
static uint8_t selected[] = {UNICODE_SELECTED_MODES};
-static uint8_t selected_count = sizeof selected / sizeof *selected;
-static uint8_t selected_index;
+static int8_t selected_count = sizeof selected / sizeof *selected;
+static int8_t selected_index;
#endif
void unicode_input_mode_init(void) {
@@ -33,7 +33,7 @@ void unicode_input_mode_init(void) {
#if UNICODE_SELECTED_MODES != -1
# if UNICODE_CYCLE_PERSIST
// Find input_mode in selected modes
- uint8_t i;
+ int8_t i;
for (i = 0; i < selected_count; i++) {
if (selected[i] == unicode_config.input_mode) {
selected_index = i;
@@ -60,9 +60,12 @@ void set_unicode_input_mode(uint8_t mode) {
dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode);
}
-void cycle_unicode_input_mode(uint8_t offset) {
+void cycle_unicode_input_mode(int8_t offset) {
#if UNICODE_SELECTED_MODES != -1
- selected_index = (selected_index + offset) % selected_count;
+ selected_index = (selected_index + offset) % selected_count;
+ if (selected_index < 0) {
+ selected_index += selected_count;
+ }
unicode_config.input_mode = selected[selected_index];
# if UNICODE_CYCLE_PERSIST
persist_unicode_input_mode();
@@ -168,6 +171,8 @@ void register_hex32(uint32_t hex) {
}
}
+// clang-format off
+
void send_unicode_hex_string(const char *str) {
if (!str) {
return;
@@ -175,12 +180,11 @@ void send_unicode_hex_string(const char *str) {
while (*str) {
// Find the next code point (token) in the string
- for (; *str == ' '; str++)
- ;
+ for (; *str == ' '; str++); // Skip leading spaces
size_t n = strcspn(str, " "); // Length of the current token
- char code_point[n + 1];
- strncpy(code_point, str, n);
- code_point[n] = '\0'; // Make sure it's null-terminated
+ char code_point[n+1];
+ strncpy(code_point, str, n); // Copy token into buffer
+ code_point[n] = '\0'; // Make sure it's null-terminated
// Normalize the code point: make all hex digits lowercase
for (char *p = code_point; *p; p++) {
@@ -196,8 +200,10 @@ void send_unicode_hex_string(const char *str) {
}
}
+// clang-format on
+
// Borrowed from https://nullprogram.com/blog/2017/10/06/
-const char *decode_utf8(const char *str, int32_t *code_point) {
+static const char *decode_utf8(const char *str, int32_t *code_point) {
const char *next;
if (str[0] < 0x80) { // U+0000-007F
@@ -231,7 +237,6 @@ void send_unicode_string(const char *str) {
}
int32_t code_point = 0;
-
while (*str) {
str = decode_utf8(str, &code_point);
@@ -243,53 +248,70 @@ void send_unicode_string(const char *str) {
}
}
+// clang-format off
+
+static void audio_helper(void) {
+#ifdef AUDIO_ENABLE
+ switch (get_unicode_input_mode()) {
+# ifdef UNICODE_SONG_MAC
+ static float song_mac[][2] = UNICODE_SONG_MAC;
+ case UC_MAC:
+ PLAY_SONG(song_mac);
+ break;
+# endif
+# ifdef UNICODE_SONG_LNX
+ static float song_lnx[][2] = UNICODE_SONG_LNX;
+ case UC_LNX:
+ PLAY_SONG(song_lnx);
+ break;
+# endif
+# ifdef UNICODE_SONG_WIN
+ static float song_win[][2] = UNICODE_SONG_WIN;
+ case UC_WIN:
+ PLAY_SONG(song_win);
+ break;
+# endif
+# ifdef UNICODE_SONG_BSD
+ static float song_bsd[][2] = UNICODE_SONG_BSD;
+ case UC_BSD:
+ PLAY_SONG(song_bsd);
+ break;
+# endif
+# ifdef UNICODE_SONG_WINC
+ static float song_winc[][2] = UNICODE_SONG_WINC;
+ case UC_WINC:
+ PLAY_SONG(song_winc);
+ break;
+# endif
+ }
+#endif
+}
+
+// clang-format on
+
bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
+ bool shifted = get_mods() & MOD_MASK_SHIFT;
switch (keycode) {
case UNICODE_MODE_FORWARD:
- cycle_unicode_input_mode(+1);
+ cycle_unicode_input_mode(shifted ? -1 : +1);
+ audio_helper();
break;
case UNICODE_MODE_REVERSE:
- cycle_unicode_input_mode(-1);
+ cycle_unicode_input_mode(shifted ? +1 : -1);
+ audio_helper();
break;
- case UNICODE_MODE_MAC:
- set_unicode_input_mode(UC_MAC);
-#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_MAC)
- static float song_mac[][2] = UNICODE_SONG_MAC;
- PLAY_SONG(song_mac);
-#endif
- break;
- case UNICODE_MODE_LNX:
- set_unicode_input_mode(UC_LNX);
-#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_LNX)
- static float song_lnx[][2] = UNICODE_SONG_LNX;
- PLAY_SONG(song_lnx);
-#endif
- break;
- case UNICODE_MODE_WIN:
- set_unicode_input_mode(UC_WIN);
-#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WIN)
- static float song_win[][2] = UNICODE_SONG_WIN;
- PLAY_SONG(song_win);
-#endif
- break;
- case UNICODE_MODE_BSD:
- set_unicode_input_mode(UC_BSD);
-#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_BSD)
- static float song_bsd[][2] = UNICODE_SONG_BSD;
- PLAY_SONG(song_bsd);
-#endif
- break;
- case UNICODE_MODE_WINC:
- set_unicode_input_mode(UC_WINC);
-#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WINC)
- static float song_winc[][2] = UNICODE_SONG_WINC;
- PLAY_SONG(song_winc);
-#endif
+ case UNICODE_MODE_MAC ... UNICODE_MODE_WINC: {
+ // Keycodes and input modes follow the same ordering
+ uint8_t delta = keycode - UNICODE_MODE_MAC;
+ set_unicode_input_mode(UC_MAC + delta);
+ audio_helper();
break;
+ }
}
}
+
#if defined(UNICODE_ENABLE)
return process_unicode(keycode, record);
#elif defined(UNICODEMAP_ENABLE)
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
index 5421c28c7f..4579fde8d5 100644
--- a/quantum/process_keycode/process_unicode_common.h
+++ b/quantum/process_keycode/process_unicode_common.h
@@ -80,7 +80,7 @@ extern uint8_t unicode_saved_mods;
void unicode_input_mode_init(void);
uint8_t get_unicode_input_mode(void);
void set_unicode_input_mode(uint8_t mode);
-void cycle_unicode_input_mode(uint8_t offset);
+void cycle_unicode_input_mode(int8_t offset);
void persist_unicode_input_mode(void);
void unicode_input_start(void);
diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c
index 5445cde129..2f402a2fd2 100644
--- a/quantum/process_keycode/process_unicodemap.c
+++ b/quantum/process_keycode/process_unicodemap.c
@@ -21,7 +21,8 @@ __attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {
// Keycode is a pair: extract index based on Shift / Caps Lock state
uint16_t index = keycode - QK_UNICODEMAP_PAIR;
- bool shift = unicode_saved_mods & MOD_MASK_SHIFT, caps = IS_HOST_LED_ON(USB_LED_CAPS_LOCK);
+ bool shift = unicode_saved_mods & MOD_MASK_SHIFT;
+ bool caps = IS_HOST_LED_ON(USB_LED_CAPS_LOCK);
if (shift ^ caps) {
index >>= 7;
}
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 45f44f49a1..17d1d41cc9 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -197,6 +197,8 @@ typedef uint8_t pin_t;
# define readPin(pin) ((bool)(PINx_ADDRESS(pin) & _BV((pin)&0xF)))
+# define togglePin(pin) (PORTx_ADDRESS(pin) ^= _BV((pin)&0xF))
+
#elif defined(PROTOCOL_CHIBIOS)
typedef ioline_t pin_t;
@@ -210,6 +212,8 @@ typedef ioline_t pin_t;
# define writePin(pin, level) ((level) ? writePinHigh(pin) : writePinLow(pin))
# define readPin(pin) palReadLine(pin)
+
+# define togglePin(pin) palToggleLine(pin)
#endif
#define SEND_STRING(string) send_string_P(PSTR(string))
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 0958c4f4eb..d8f1fa4bbb 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -794,6 +794,7 @@ enum quantum_keycodes {
# define SH_T(kc) (QK_SWAP_HANDS | (kc))
# define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE)
# define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE)
+# define SH_OS (QK_SWAP_HANDS | OP_SH_ONESHOT)
# define SH_MON (QK_SWAP_HANDS | OP_SH_ON_OFF)
# define SH_MOFF (QK_SWAP_HANDS | OP_SH_OFF_ON)
# define SH_ON (QK_SWAP_HANDS | OP_SH_ON)
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c
index 3fae9d7378..91032b6564 100644
--- a/quantum/rgb_matrix.c
+++ b/quantum/rgb_matrix.c
@@ -440,6 +440,8 @@ void rgb_matrix_set_suspend_state(bool state) {
g_suspend_state = state;
}
+bool rgb_matrix_get_suspend_state(void) { return g_suspend_state; }
+
void rgb_matrix_toggle(void) {
rgb_matrix_config.enable ^= 1;
rgb_task_state = STARTING;
@@ -466,6 +468,8 @@ void rgb_matrix_disable_noeeprom(void) {
rgb_matrix_config.enable = 0;
}
+uint8_t rgb_matrix_is_enabled(void) { return rgb_matrix_config.enable; }
+
void rgb_matrix_step(void) {
rgb_matrix_config.mode++;
if (rgb_matrix_config.mode >= RGB_MATRIX_EFFECT_MAX) rgb_matrix_config.mode = 1;
@@ -521,6 +525,8 @@ void rgb_matrix_decrease_speed(void) {
eeconfig_update_rgb_matrix();
}
+uint8_t rgb_matrix_get_speed(void) { return rgb_matrix_config.speed; }
+
led_flags_t rgb_matrix_get_flags(void) { return rgb_effect_params.flags; }
void rgb_matrix_set_flags(led_flags_t flags) { rgb_effect_params.flags = flags; }
@@ -546,3 +552,8 @@ void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
rgb_matrix_config.hsv.v = val;
if (rgb_matrix_config.hsv.v > RGB_MATRIX_MAXIMUM_BRIGHTNESS) rgb_matrix_config.hsv.v = RGB_MATRIX_MAXIMUM_BRIGHTNESS;
}
+
+HSV rgb_matrix_get_hsv(void) { return rgb_matrix_config.hsv; }
+uint8_t rgb_matrix_get_hue(void) { return rgb_matrix_config.hsv.h; }
+uint8_t rgb_matrix_get_sat(void) { return rgb_matrix_config.hsv.s; }
+uint8_t rgb_matrix_get_val(void) { return rgb_matrix_config.hsv.v; }
diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h
index 96494836ee..7c37311b4e 100644
--- a/quantum/rgb_matrix.h
+++ b/quantum/rgb_matrix.h
@@ -104,11 +104,13 @@ void rgb_matrix_indicators_user(void);
void rgb_matrix_init(void);
void rgb_matrix_set_suspend_state(bool state);
+bool rgb_matrix_get_suspend_state(void);
void rgb_matrix_toggle(void);
void rgb_matrix_enable(void);
void rgb_matrix_enable_noeeprom(void);
void rgb_matrix_disable(void);
void rgb_matrix_disable_noeeprom(void);
+uint8_t rgb_matrix_is_enabled(void);
void rgb_matrix_step(void);
void rgb_matrix_step_reverse(void);
void rgb_matrix_increase_hue(void);
@@ -119,6 +121,7 @@ void rgb_matrix_increase_val(void);
void rgb_matrix_decrease_val(void);
void rgb_matrix_increase_speed(void);
void rgb_matrix_decrease_speed(void);
+uint8_t rgb_matrix_get_speed(void);
led_flags_t rgb_matrix_get_flags(void);
void rgb_matrix_set_flags(led_flags_t flags);
void rgb_matrix_mode(uint8_t mode);
@@ -126,6 +129,10 @@ void rgb_matrix_mode_noeeprom(uint8_t mode);
uint8_t rgb_matrix_get_mode(void);
void rgb_matrix_sethsv(uint16_t hue, uint8_t sat, uint8_t val);
void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);
+HSV rgb_matrix_get_hsv(void);
+uint8_t rgb_matrix_get_hue(void);
+uint8_t rgb_matrix_get_sat(void);
+uint8_t rgb_matrix_get_val(void);
#ifndef RGBLIGHT_ENABLE
# define rgblight_toggle rgb_matrix_toggle
@@ -133,6 +140,7 @@ void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);
# define rgblight_enable_noeeprom rgb_matrix_enable_noeeprom
# define rgblight_disable rgb_matrix_disable
# define rgblight_disable_noeeprom rgb_matrix_disable_noeeprom
+# define rgblight_is_enabled rgb_matrix_is_enabled
# define rgblight_step rgb_matrix_step
# define rgblight_sethsv rgb_matrix_sethsv
# define rgblight_sethsv_noeeprom rgb_matrix_sethsv_noeeprom
@@ -145,9 +153,14 @@ void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);
# define rgblight_decrease_val rgb_matrix_decrease_val
# define rgblight_increase_speed rgb_matrix_increase_speed
# define rgblight_decrease_speed rgb_matrix_decrease_speed
+# define rgblight_get_speed rgb_matrix_get_speed
# define rgblight_mode rgb_matrix_mode
# define rgblight_mode_noeeprom rgb_matrix_mode_noeeprom
# define rgblight_get_mode rgb_matrix_get_mode
+# define rgblight_get_hue rgb_matrix_get_hue
+# define rgblight_get_sat rgb_matrix_get_sat
+# define rgblight_get_val rgb_matrix_get_val
+# define rgblight_get_hsv rgb_matrix_get_hsv
#endif
typedef struct {
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index cc35b01ed4..b50be200ee 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -15,6 +15,7 @@
*/
#include <math.h>
#include <string.h>
+#include <stdlib.h>
#ifdef __AVR__
# include <avr/eeprom.h>
# include <avr/interrupt.h>
@@ -107,23 +108,19 @@ LED_TYPE led[RGBLED_NUM];
rgblight_segment_t const *const *rgblight_layers = NULL;
#endif
-static uint8_t clipping_start_pos = 0;
-static uint8_t clipping_num_leds = RGBLED_NUM;
-static uint8_t effect_start_pos = 0;
-static uint8_t effect_end_pos = RGBLED_NUM;
-static uint8_t effect_num_leds = RGBLED_NUM;
+rgblight_ranges_t rgblight_ranges = {0, RGBLED_NUM, 0, RGBLED_NUM, RGBLED_NUM};
void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) {
- clipping_start_pos = start_pos;
- clipping_num_leds = num_leds;
+ rgblight_ranges.clipping_start_pos = start_pos;
+ rgblight_ranges.clipping_num_leds = num_leds;
}
void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) {
if (start_pos >= RGBLED_NUM) return;
if (start_pos + num_leds > RGBLED_NUM) return;
- effect_start_pos = start_pos;
- effect_end_pos = start_pos + num_leds;
- effect_num_leds = num_leds;
+ rgblight_ranges.effect_start_pos = start_pos;
+ rgblight_ranges.effect_end_pos = start_pos + num_leds;
+ rgblight_ranges.effect_num_leds = num_leds;
}
void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
@@ -371,6 +368,8 @@ void rgblight_disable_noeeprom(void) {
rgblight_set();
}
+bool rgblight_is_enabled(void) { return rgblight_config.enable; }
+
void rgblight_increase_hue_helper(bool write_to_eeprom) {
uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP;
rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
@@ -468,15 +467,15 @@ void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool w
# else
uint8_t range = RGBLED_GRADIENT_RANGES[delta / 2];
# endif
- for (uint8_t i = 0; i < effect_num_leds; i++) {
- uint8_t _hue = ((uint16_t)i * (uint16_t)range) / effect_num_leds;
+ for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
+ uint8_t _hue = ((uint16_t)i * (uint16_t)range) / rgblight_ranges.effect_num_leds;
if (direction) {
_hue = hue + _hue;
} else {
_hue = hue - _hue;
}
dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range);
- sethsv(_hue, sat, val, (LED_TYPE *)&led[i + effect_start_pos]);
+ sethsv(_hue, sat, val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
}
rgblight_set();
}
@@ -525,12 +524,16 @@ uint8_t rgblight_get_sat(void) { return rgblight_config.sat; }
uint8_t rgblight_get_val(void) { return rgblight_config.val; }
+HSV rgblight_get_hsv(void) {
+ return (HSV){ rgblight_config.hue, rgblight_config.sat, rgblight_config.val };
+}
+
void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
if (!rgblight_config.enable) {
return;
}
- for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) {
+ for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
led[i].r = r;
led[i].g = g;
led[i].b = b;
@@ -565,7 +568,7 @@ void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) {
rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index);
}
-#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT)
+#if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT) || defined(RGBLIGHT_EFFECT_TWINKLE)
static uint8_t get_interval_time(const uint8_t *default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) {
return
@@ -616,7 +619,7 @@ void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) { rgblight_set
#ifdef RGBLIGHT_LAYERS
void rgblight_set_layer_state(uint8_t layer, bool enabled) {
- uint8_t mask = 1 << layer;
+ rgblight_layer_mask_t mask = 1 << layer;
if (enabled) {
rgblight_status.enabled_layer_mask |= mask;
} else {
@@ -630,7 +633,7 @@ void rgblight_set_layer_state(uint8_t layer, bool enabled) {
}
bool rgblight_get_layer_state(uint8_t layer) {
- uint8_t mask = 1 << layer;
+ rgblight_layer_mask_t mask = 1 << layer;
return (rgblight_status.enabled_layer_mask & mask) != 0;
}
@@ -662,12 +665,39 @@ static void rgblight_layers_write(void) {
}
}
}
+
+# ifdef RGBLIGHT_LAYER_BLINK
+uint8_t _blinked_layer_mask = 0;
+uint16_t _blink_duration = 0;
+static uint16_t _blink_timer;
+
+void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {
+ rgblight_set_layer_state(layer, true);
+ _blinked_layer_mask |= 1 << layer;
+ _blink_timer = timer_read();
+ _blink_duration = duration_ms;
+}
+
+void rgblight_unblink_layers(void) {
+ if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) {
+ for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
+ if ((_blinked_layer_mask & 1 << layer) != 0) {
+ rgblight_set_layer_state(layer, false);
+ }
+ }
+ _blinked_layer_mask = 0;
+ }
+}
+# endif
+
#endif
+__attribute__((weak)) void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds) { ws2812_setleds(start_led, num_leds); }
+
#ifndef RGBLIGHT_CUSTOM_DRIVER
void rgblight_set(void) {
LED_TYPE *start_led;
- uint16_t num_leds = clipping_num_leds;
+ uint8_t num_leds = rgblight_ranges.clipping_num_leds;
# ifdef RGBLIGHT_LAYERS
if (rgblight_layers != NULL) {
@@ -676,7 +706,7 @@ void rgblight_set(void) {
# endif
if (!rgblight_config.enable) {
- for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) {
+ for (uint8_t i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
led[i].r = 0;
led[i].g = 0;
led[i].b = 0;
@@ -691,9 +721,9 @@ void rgblight_set(void) {
for (uint8_t i = 0; i < RGBLED_NUM; i++) {
led0[i] = led[pgm_read_byte(&led_map[i])];
}
- start_led = led0 + clipping_start_pos;
+ start_led = led0 + rgblight_ranges.clipping_start_pos;
# else
- start_led = led + clipping_start_pos;
+ start_led = led + rgblight_ranges.clipping_start_pos;
# endif
# ifdef RGBW
@@ -701,7 +731,7 @@ void rgblight_set(void) {
convert_rgb_to_rgbw(&start_led[i]);
}
# endif
- ws2812_setleds(start_led, num_leds);
+ rgblight_call_driver(start_led, num_leds);
}
#endif
@@ -882,6 +912,12 @@ void rgblight_task(void) {
effect_func = (effect_func_t)rgblight_effect_alternating;
}
# endif
+# ifdef RGBLIGHT_EFFECT_TWINKLE
+ else if (rgblight_status.base_mode == RGBLIGHT_MODE_TWINKLE) {
+ interval_time = get_interval_time(&RGBLED_TWINKLE_INTERVALS[delta % 3], 5, 50);
+ effect_func = (effect_func_t)rgblight_effect_twinkle;
+ }
+# endif
if (animation_status.restart) {
animation_status.restart = false;
animation_status.last_timer = timer_read() - interval_time - 1;
@@ -911,6 +947,10 @@ void rgblight_task(void) {
# endif
}
}
+
+# ifdef RGBLIGHT_LAYER_BLINK
+ rgblight_unblink_layers();
+# endif
}
#endif /* RGBLIGHT_USE_TIMER */
@@ -961,9 +1001,9 @@ void rgblight_effect_rainbow_swirl(animation_status_t *anim) {
uint8_t hue;
uint8_t i;
- for (i = 0; i < effect_num_leds; i++) {
- hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / effect_num_leds * i + anim->current_hue);
- sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]);
+ for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
+ hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / rgblight_ranges.effect_num_leds * i + anim->current_hue);
+ sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
}
rgblight_set();
@@ -991,7 +1031,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
if (anim->pos == 0) { // restart signal
if (increment == 1) {
- pos = effect_num_leds - 1;
+ pos = rgblight_ranges.effect_num_leds - 1;
} else {
pos = 0;
}
@@ -999,8 +1039,8 @@ void rgblight_effect_snake(animation_status_t *anim) {
}
# endif
- for (i = 0; i < effect_num_leds; i++) {
- LED_TYPE *ledp = led + i + effect_start_pos;
+ for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
+ LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
ledp->r = 0;
ledp->g = 0;
ledp->b = 0;
@@ -1013,7 +1053,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
k = k % RGBLED_NUM;
}
if (k < 0) {
- k = k + effect_num_leds;
+ k = k + rgblight_ranges.effect_num_leds;
}
if (i == k) {
sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val * (RGBLIGHT_EFFECT_SNAKE_LENGTH - j) / RGBLIGHT_EFFECT_SNAKE_LENGTH), ledp);
@@ -1023,7 +1063,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
rgblight_set();
if (increment == 1) {
if (pos - 1 < 0) {
- pos = effect_num_leds - 1;
+ pos = rgblight_ranges.effect_num_leds - 1;
# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
anim->pos = 0;
# endif
@@ -1034,7 +1074,7 @@ void rgblight_effect_snake(animation_status_t *anim) {
# endif
}
} else {
- pos = (pos + 1) % effect_num_leds;
+ pos = (pos + 1) % rgblight_ranges.effect_num_leds;
# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
anim->pos = pos;
# endif
@@ -1060,7 +1100,7 @@ void rgblight_effect_knight(animation_status_t *anim) {
}
# endif
// Set all the LEDs to 0
- for (i = effect_start_pos; i < effect_end_pos; i++) {
+ for (i = rgblight_ranges.effect_start_pos; i < rgblight_ranges.effect_end_pos; i++) {
led[i].r = 0;
led[i].g = 0;
led[i].b = 0;
@@ -1070,7 +1110,7 @@ void rgblight_effect_knight(animation_status_t *anim) {
}
// Determine which LEDs should be lit up
for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) {
- cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % effect_num_leds + effect_start_pos;
+ cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % rgblight_ranges.effect_num_leds + rgblight_ranges.effect_start_pos;
if (i >= low_bound && i <= high_bound) {
sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]);
@@ -1107,9 +1147,9 @@ void rgblight_effect_christmas(animation_status_t *anim) {
uint8_t i;
anim->current_offset = (anim->current_offset + 1) % 2;
- for (i = 0; i < effect_num_leds; i++) {
+ for (i = 0; i < rgblight_ranges.effect_num_leds; i++) {
hue = 0 + ((i / RGBLIGHT_EFFECT_CHRISTMAS_STEP + anim->current_offset) % 2) * 85;
- sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]);
+ sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + rgblight_ranges.effect_start_pos]);
}
rgblight_set();
}
@@ -1148,11 +1188,11 @@ void rgblight_effect_rgbtest(animation_status_t *anim) {
#ifdef RGBLIGHT_EFFECT_ALTERNATING
void rgblight_effect_alternating(animation_status_t *anim) {
- for (int i = 0; i < effect_num_leds; i++) {
- LED_TYPE *ledp = led + i + effect_start_pos;
- if (i < effect_num_leds / 2 && anim->pos) {
+ for (int i = 0; i < rgblight_ranges.effect_num_leds; i++) {
+ LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
+ if (i < rgblight_ranges.effect_num_leds / 2 && anim->pos) {
sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
- } else if (i >= effect_num_leds / 2 && !anim->pos) {
+ } else if (i >= rgblight_ranges.effect_num_leds / 2 && !anim->pos) {
sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp);
} else {
sethsv(rgblight_config.hue, rgblight_config.sat, 0, ledp);
@@ -1162,3 +1202,58 @@ void rgblight_effect_alternating(animation_status_t *anim) {
anim->pos = (anim->pos + 1) % 2;
}
#endif
+
+#ifdef RGBLIGHT_EFFECT_TWINKLE
+__attribute__((weak)) const uint8_t RGBLED_TWINKLE_INTERVALS[] PROGMEM = {50, 25, 10};
+
+typedef struct PACKED {
+ HSV hsv;
+ uint8_t life;
+ bool up;
+} TwinkleState;
+
+static TwinkleState led_twinkle_state[RGBLED_NUM];
+
+void rgblight_effect_twinkle(animation_status_t *anim) {
+ bool random_color = anim->delta / 3;
+ bool restart = anim->pos == 0;
+ anim->pos = 1;
+
+ for (uint8_t i = 0; i < rgblight_ranges.effect_num_leds; i++) {
+ TwinkleState *t = &(led_twinkle_state[i]);
+ HSV * c = &(t->hsv);
+ if (restart) {
+ // Restart
+ t->life = 0;
+ t->hsv.v = 0;
+ } else if (t->life) {
+ // This LED is already on, either brightening or dimming
+ t->life--;
+ uint8_t on = t->up ? RGBLIGHT_EFFECT_TWINKLE_LIFE - t->life : t->life;
+ c->v = (uint16_t)rgblight_config.val * on / RGBLIGHT_EFFECT_TWINKLE_LIFE;
+ if (t->life == 0 && t->up) {
+ t->up = false;
+ t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
+ }
+ if (!random_color) {
+ c->h = rgblight_config.hue;
+ c->s = rgblight_config.sat;
+ }
+ } else if (rand() < RAND_MAX * RGBLIGHT_EFFECT_TWINKLE_PROBABILITY) {
+ // This LED is off, but was randomly selected to start brightening
+ c->h = random_color ? rand() % 0xFF : rgblight_config.hue;
+ c->s = random_color ? (rand() % (rgblight_config.sat / 2)) + (rgblight_config.sat / 2) : rgblight_config.sat;
+ c->v = 0;
+ t->life = RGBLIGHT_EFFECT_TWINKLE_LIFE;
+ t->up = true;
+ } else {
+ // This LED is off, and was NOT selected to start brightening
+ }
+
+ LED_TYPE *ledp = led + i + rgblight_ranges.effect_start_pos;
+ sethsv(c->h, c->s, c->v, ledp);
+ }
+
+ rgblight_set();
+}
+#endif
diff --git a/quantum/rgblight.h b/quantum/rgblight.h
index 97882c5b29..c36b328a35 100644
--- a/quantum/rgblight.h
+++ b/quantum/rgblight.h
@@ -59,6 +59,12 @@
| 34 | RGBLIGHT_MODE_STATIC_GRADIENT + 9 |
| 35 | RGBLIGHT_MODE_RGB_TEST |
| 36 | RGBLIGHT_MODE_ALTERNATING |
+| 37 | RGBLIGHT_MODE_TWINKLE |
+| 38 | RGBLIGHT_MODE_TWINKLE + 1 |
+| 39 | RGBLIGHT_MODE_TWINKLE + 2 |
+| 40 | RGBLIGHT_MODE_TWINKLE + 3 |
+| 41 | RGBLIGHT_MODE_TWINKLE + 4 |
+| 42 | RGBLIGHT_MODE_TWINKLE + 5 |
|-----------------|-----------------------------------|
*****/
@@ -73,6 +79,7 @@
# define RGBLIGHT_EFFECT_STATIC_GRADIENT
# define RGBLIGHT_EFFECT_RGB_TEST
# define RGBLIGHT_EFFECT_ALTERNATING
+# define RGBLIGHT_EFFECT_TWINKLE
#endif
#ifdef RGBLIGHT_STATIC_PATTERNS
@@ -89,7 +96,8 @@
|| defined(RGBLIGHT_EFFECT_KNIGHT) \
|| defined(RGBLIGHT_EFFECT_CHRISTMAS) \
|| defined(RGBLIGHT_EFFECT_RGB_TEST) \
- || defined(RGBLIGHT_EFFECT_ALTERNATING)
+ || defined(RGBLIGHT_EFFECT_ALTERNATING) \
+ || defined(RGBLIGHT_EFFECT_TWINKLE)
# define RGBLIGHT_USE_TIMER
#endif
@@ -130,7 +138,7 @@ enum RGBLIGHT_EFFECT_MODE {
# endif
# ifndef RGBLIGHT_EFFECT_KNIGHT_LED_NUM
-# define RGBLIGHT_EFFECT_KNIGHT_LED_NUM (effect_num_leds)
+# define RGBLIGHT_EFFECT_KNIGHT_LED_NUM (rgblight_ranges.effect_num_leds)
# endif
# ifndef RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL
@@ -141,6 +149,14 @@ enum RGBLIGHT_EFFECT_MODE {
# define RGBLIGHT_EFFECT_CHRISTMAS_STEP 2
# endif
+# ifndef RGBLIGHT_EFFECT_TWINKLE_LIFE
+# define RGBLIGHT_EFFECT_TWINKLE_LIFE 75
+# endif
+
+# ifndef RGBLIGHT_EFFECT_TWINKLE_PROBABILITY
+# define RGBLIGHT_EFFECT_TWINKLE_PROBABILITY 1 / 127
+# endif
+
# ifndef RGBLIGHT_HUE_STEP
# define RGBLIGHT_HUE_STEP 8
# endif
@@ -160,9 +176,7 @@ enum RGBLIGHT_EFFECT_MODE {
# include <stdint.h>
# include <stdbool.h>
# include "eeconfig.h"
-# ifndef RGBLIGHT_CUSTOM_DRIVER
-# include "ws2812.h"
-# endif
+# include "ws2812.h"
# include "color.h"
# include "rgblight_list.h"
@@ -182,7 +196,20 @@ typedef struct {
# define RGBLIGHT_END_SEGMENT_INDEX (255)
# define RGBLIGHT_END_SEGMENTS \
{ RGBLIGHT_END_SEGMENT_INDEX, 0, 0, 0 }
-# define RGBLIGHT_MAX_LAYERS 8
+# ifndef RGBLIGHT_MAX_LAYERS
+# define RGBLIGHT_MAX_LAYERS 8
+# endif
+# if RGBLIGHT_MAX_LAYERS <= 0
+# error invalid RGBLIGHT_MAX_LAYERS value (must be >= 1)
+# elif RGBLIGHT_MAX_LAYERS <= 8
+typedef uint8_t rgblight_layer_mask_t;
+# elif RGBLIGHT_MAX_LAYERS <= 16
+typedef uint16_t rgblight_layer_mask_t;
+# elif RGBLIGHT_MAX_LAYERS <= 32
+typedef uint32_t rgblight_layer_mask_t;
+# else
+# error invalid RGBLIGHT_MAX_LAYERS value (must be <= 32)
+# endif
# define RGBLIGHT_LAYER_SEGMENTS(...) \
{ __VA_ARGS__, RGBLIGHT_END_SEGMENTS }
# define RGBLIGHT_LAYERS_LIST(...) \
@@ -194,6 +221,12 @@ bool rgblight_get_layer_state(uint8_t layer);
// Point this to an array of rgblight_segment_t arrays in keyboard_post_init_user to use rgblight layers
extern const rgblight_segment_t *const *rgblight_layers;
+
+# ifdef RGBLIGHT_LAYER_BLINK
+# define RGBLIGHT_USE_TIMER
+void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms);
+# endif
+
# endif
extern LED_TYPE led[RGBLED_NUM];
@@ -204,6 +237,7 @@ extern const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[3] PROGMEM;
extern const uint8_t RGBLED_SNAKE_INTERVALS[3] PROGMEM;
extern const uint8_t RGBLED_KNIGHT_INTERVALS[3] PROGMEM;
extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM;
+extern const uint8_t RGBLED_TWINKLE_INTERVALS[3] PROGMEM;
extern bool is_rgblight_initialized;
// Should stay in sycn with rgb matrix config as we reuse eeprom storage for both (for now)
@@ -226,10 +260,23 @@ typedef struct _rgblight_status_t {
uint8_t change_flags;
# endif
# ifdef RGBLIGHT_LAYERS
- uint8_t enabled_layer_mask;
+ rgblight_layer_mask_t enabled_layer_mask;
# endif
} rgblight_status_t;
+/*
+ * Structure for RGB Light clipping ranges
+ */
+typedef struct _rgblight_ranges_t {
+ uint8_t clipping_start_pos;
+ uint8_t clipping_num_leds;
+ uint8_t effect_start_pos;
+ uint8_t effect_end_pos;
+ uint8_t effect_num_leds;
+} rgblight_ranges_t;
+
+extern rgblight_ranges_t rgblight_ranges;
+
/* === Utility Functions ===*/
void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1);
void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1); // without RGBLIGHT_LIMIT_VAL check
@@ -303,6 +350,8 @@ uint8_t rgblight_get_mode(void);
uint8_t rgblight_get_hue(void);
uint8_t rgblight_get_sat(void);
uint8_t rgblight_get_val(void);
+bool rgblight_is_enabled(void);
+HSV rgblight_get_hsv(void);
/* === qmk_firmware (core)internal Functions === */
void rgblight_init(void);
@@ -381,6 +430,7 @@ void rgblight_effect_knight(animation_status_t *anim);
void rgblight_effect_christmas(animation_status_t *anim);
void rgblight_effect_rgbtest(animation_status_t *anim);
void rgblight_effect_alternating(animation_status_t *anim);
+void rgblight_effect_twinkle(animation_status_t *anim);
# endif
diff --git a/quantum/rgblight_modes.h b/quantum/rgblight_modes.h
index 40c9ce4980..7abdb87bc6 100644
--- a/quantum/rgblight_modes.h
+++ b/quantum/rgblight_modes.h
@@ -53,6 +53,14 @@ _RGBM_SINGLE_DYNAMIC(RGB_TEST)
# ifdef RGBLIGHT_EFFECT_ALTERNATING
_RGBM_SINGLE_DYNAMIC(ALTERNATING)
# endif
+# ifdef RGBLIGHT_EFFECT_TWINKLE
+_RGBM_MULTI_DYNAMIC(TWINKLE)
+_RGBM_TMP_DYNAMIC(twinkle_38, TWINKLE)
+_RGBM_TMP_DYNAMIC(twinkle_39, TWINKLE)
+_RGBM_TMP_DYNAMIC(twinkle_40, TWINKLE)
+_RGBM_TMP_DYNAMIC(twinkle_41, TWINKLE)
+_RGBM_TMP_DYNAMIC(TWINKLE_end, TWINKLE)
+# endif
//// Add a new mode here.
// #ifdef RGBLIGHT_EFFECT_<name>
// _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> )
diff --git a/quantum/stm32/halconf.h b/quantum/stm32/halconf.h
index 106f0f5755..533803a25f 100644
--- a/quantum/stm32/halconf.h
+++ b/quantum/stm32/halconf.h
@@ -156,7 +156,7 @@
* @brief Enables the SPI subsystem.
*/
# if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
-# define HAL_USE_SPI FALSE
+# define HAL_USE_SPI TRUE
# endif
/**
diff --git a/quantum/stm32/mcuconf.h b/quantum/stm32/mcuconf.h
index ca4ad7b515..71994a98e0 100644
--- a/quantum/stm32/mcuconf.h
+++ b/quantum/stm32/mcuconf.h
@@ -227,7 +227,7 @@
* SPI driver system settings.
*/
#define STM32_SPI_USE_SPI1 FALSE
-#define STM32_SPI_USE_SPI2 FALSE
+#define STM32_SPI_USE_SPI2 TRUE
#define STM32_SPI_USE_SPI3 FALSE
#define STM32_SPI_SPI1_DMA_PRIORITY 1
#define STM32_SPI_SPI2_DMA_PRIORITY 1
diff --git a/quantum/template/avr/rules.mk b/quantum/template/avr/rules.mk
index 4053484219..2ea91a3013 100644
--- a/quantum/template/avr/rules.mk
+++ b/quantum/template/avr/rules.mk
@@ -27,6 +27,6 @@ BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
MIDI_ENABLE = no # MIDI support
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
-AUDIO_ENABLE = no # Audio output on port C6
+AUDIO_ENABLE = no # Audio output
FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
HD44780_ENABLE = no # Enable support for HD44780 based LCDs
diff --git a/quantum/template/ps2avrgb/rules.mk b/quantum/template/ps2avrgb/rules.mk
index b9b81a6750..9e18b33827 100644
--- a/quantum/template/ps2avrgb/rules.mk
+++ b/quantum/template/ps2avrgb/rules.mk
@@ -22,5 +22,3 @@ COMMAND_ENABLE = yes # Commands for debug and configuration
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow
WS2812_DRIVER = i2c
-
-OPT_DEFS = -DDEBUG_LEVEL=0