瀏覽代碼

Merge pull request #746 from DidierLoiseau/bépo

Bépo with firmware remapping for software CSA layout
Erez Zukerman 8 年之前
父節點
當前提交
fe4b379287

+ 527 - 0
keyboards/ergodox/keymaps/bepo_csa/keymap.c

@@ -0,0 +1,527 @@
+/* TypeMatrix-2030-like keymap  */
+#include "ergodox.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "action_util.h"
+#include "led.h"
+#include "keymap_extras/keymap_bepo.h"
+#include "keymap_extras/keymap_canadian_multilingual.h"
+
+enum layers {
+    LR_BASE, // default layer
+    LR_CSA, // BÉPO over Canadian Multilingual (CSA)
+    LR_CSA_SFT, // shifted BÉPO over CSA
+    LR_CSA_AGR, // altgr-ed BÉPO over CSA
+    LR_CSA_AGR_SFT, // altgr-shifted BÉPO over CSA
+    LR_NUMR, // numeric layer
+    LR_FN, // fn layer
+};
+
+#define IS_CA_MULT_ENABLED()    (layer_state & (1 << LR_CSA))
+
+enum macros {
+    // Characters that do not exist in CSA and must be implemented based on unicode support
+    // Note: these are intentionally declared first to be used as indexes in spec_chars below
+    UC_NDSH, // –
+    UC_MDSH, // —
+    UC_ELPS, // …
+    END_UC, // indicates the last unicode character macro
+    // other macros
+    M_CSA_SFT, // toggle shift on CSA
+    M_CSA_AGR_SFT, // toggle shift on LR_CSA_AGR (goes to LR_CSA_AGR_SFT)
+    M_CSA_SFT_AGR, // toggle AltGr on LR_CSA_SFT (goes to LR_CSA_AGR_SFT)
+    // macros for characters that need to be un-shifted in LR_CA_MULT_SHIFT
+    M_1,
+    M_2,
+    M_3,
+    M_4,
+    M_5,
+    M_6,
+    M_7,
+    M_8,
+    M_9,
+    M_0,
+    M_DEGR,
+    M_SCLN,
+    M_GRV,
+    M_NBSP,
+    // macros for characters that don't have a simple key combination in LR_CA_MULT_ALTGR
+    M_CRC,
+    // other layer macros
+    M_DBL0, // double 0
+    M_FNLR, // fn layer
+    M_NMAL, // num+alt
+};
+
+#define CSA(name)   M(M_CSA_##name)     // calls a CSA macro
+
+const uint16_t unicode_chars[] = {
+        [UC_NDSH] = L'–',
+        [UC_MDSH] = L'—',
+        [UC_ELPS] = L'…',
+};
+
+/* shortcut for unicode character macros */
+#define MUC(name)   M(UC_##name)    // calls a unicode macro
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Basic layer
+ *
+ * ,--------------------------------------------------.           ,--------------------------------------------------.
+ * |   $    |   "  |   «  |   »  |   (  |   )  | Del  |           | Del  |   @  |   +  |   -  |   /  |   *  |   W    |
+ * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+ * | Tab    |   B  |   É  |   P  |   O  |   È  |Backsp|           |Backsp|   ^  |   V  |   D  |   L  |   J  |   Z    |
+ * |--------+------+------+------+------+------|ace   |           |ace   |------+------+------+------+------+--------|
+ * |   =    |   A  |   U  |   I  |   E  |   ,  |------|           |------|   C  |   T  |   S  |   R  |   N  |   M    |
+ * |--------+------+------+------+------+------|Enter |           |Enter |------+------+------+------+------+--------|
+ * | LShift |   À  |   Y  |   X  |   .  |   K  |      |           |      |   '  |   Q  |   G  |   H  |   F  | RShift |
+ * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+ *   |LCtrl |  fn  | LGui |numAlt| LAlt |                                       |Alt Gr|   %  |  App |   Ç  | RCtrl|
+ *   `----------------------------------'                                       `----------------------------------'
+ *                                       ,--------------.       ,-------------.
+ *                                       |  Esc  | num  |       | Left |Right |
+ *                                ,------+-------+------|       |------+------+------.
+ *                                |      |       | PgUp |       |  Up  |      |      |
+ *                                |Space | Home  |------|       |------| End  |Space |
+ *                                |      |       | PgDn |       | Down |      |      |
+ *                                `---------------------'       `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[LR_BASE] = KEYMAP(  // layer 0 : default
+        // left hand
+        BP_DLR,     KC_1,      KC_2,    KC_3,      KC_4,     KC_5,    KC_DELT,
+        KC_TAB,     BP_B,      BP_ECUT, BP_P,      BP_O,     BP_EGRV, KC_BSPC,
+        BP_EQL,     BP_A,      BP_U,    BP_I,      BP_E,     BP_COMM,
+        KC_LSFT,    BP_AGRV,   BP_Y,    BP_X,      BP_DOT,   BP_K,    KC_ENT,
+        KC_LCTL,    M(M_FNLR), KC_LGUI, M(M_NMAL), KC_LALT,
+
+                                                   KC_ESC,   TG(LR_NUMR),
+                                                             KC_PGUP,
+                                          KC_SPC,  KC_HOME,  KC_PGDN,
+
+        // right hand
+        KC_DELT,   KC_6,     KC_7,    KC_8,    KC_9,    KC_0,     BP_W,
+        KC_BSPC,   BP_DCRC,  BP_V,    BP_D,    BP_L,    BP_J,     BP_Z,
+                   BP_C,     BP_T,    BP_S,    BP_R,    BP_N,     BP_M,
+        KC_ENT,    BP_APOS,  BP_Q,    BP_G,    BP_H,    BP_F,     KC_RSFT,
+                             BP_ALGR, BP_PERC, KC_APP,  BP_CCED,  KC_RCTL,
+
+        KC_LEFT, KC_RGHT,
+        KC_UP,
+        KC_DOWN, KC_END,   KC_SPC
+    ),
+/**
+ * Same as default but for use with Canadian Multilingual on OS side
+ */
+[LR_CSA] = KEYMAP(
+        // left hand
+        KC_DLR,      CSA_DQOT,   CSA_LGIL,  CSA_RGIL,  KC_LPRN,  KC_RPRN,   KC_TRNS,
+        KC_TRNS,     KC_B,       CSA_ECUT,  KC_P,      KC_O,     CSA_EGRV,  KC_TRNS,
+        KC_EQL,      KC_A,       KC_U,      KC_I,      KC_E,     KC_COMM,
+        CSA(SFT),    CSA_AGRV,   KC_Y,      KC_X,      KC_DOT,   KC_K,      KC_TRNS,
+        KC_TRNS,     KC_TRNS,    KC_TRNS,   KC_TRNS,   KC_TRNS,
+
+                                                       KC_TRNS,  KC_TRNS,
+                                                                 KC_TRNS,
+                                            KC_TRNS,   KC_TRNS,  KC_TRNS,
+
+        // right hand
+        KC_TRNS,  KC_AT,     KC_PLUS,  KC_MINS,  CSA_SLSH,  KC_ASTR,   KC_W,
+        KC_TRNS,  CSA_DCRC,  KC_V,     KC_D,     KC_L,      KC_J,      KC_Z,
+                  KC_C,      KC_T,     KC_S,     KC_R,      KC_N,      KC_M,
+        KC_TRNS,  CSA_APOS,  KC_Q,     KC_G,     KC_H,      KC_F,      CSA(SFT),
+                      MO(LR_CSA_AGR),  KC_PERC,  KC_TRNS,   CSA_CCED,  KC_LCTL, // RCTL has a special behaviour in CSA so use LCTL
+
+        KC_TRNS,  KC_TRNS,
+        KC_TRNS,
+        KC_TRNS,  KC_TRNS,  KC_TRNS
+    ),
+/* Shifted BÉPO over Canadian Multilingual
+ *
+ * ,--------------------------------------------------.           ,--------------------------------------------------.
+ * |   #    |   1  |   2  |   3  |   4  |   5  |      |           |      |   6  |   7  |   8  |   9  |   0  |        |
+ * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+ * |        |      |      |      |      |      |      |           |      |   !  |      |      |      |      |        |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * |   °    |      |      |      |      |   ;  |------|           |------|      |      |      |      |      |        |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * |        |      |      |      |   :  |      |      |           |      |   ?  |      |      |      |      |        |
+ * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+ *   |      |      |      |      |      |                                       |      |   `  |      |      |       |
+ *   `----------------------------------'                                       `-----------------------------------'
+ *                                        ,-------------.       ,-------------.
+ *                                        |      |      |       |      |      |
+ *                                 ,------|------|------|       |------+------+------.
+ *                                 |      |      |      |       |      |      |      |
+ *                                 |      |      |------|       |------|      |      |
+ *                                 |      |      |      |       |      |      |      |
+ *                                 `--------------------'       `--------------------'
+ */
+[LR_CSA_SFT] = KEYMAP(
+        // left hand
+        KC_HASH,  M(M_1),   M(M_2),   M(M_3),  M(M_4),   M(M_5),   KC_TRNS,
+        KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS, KC_TRNS,  KC_TRNS,  KC_TRNS,
+        M(M_DEGR),KC_TRNS,  KC_TRNS,  KC_TRNS, KC_TRNS,  M(M_SCLN),
+        KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS, KC_COLN,  KC_TRNS,  KC_TRNS,
+        KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS, KC_TRNS,
+
+                                                      KC_TRNS,  KC_TRNS,
+                                                                KC_TRNS,
+                                          M(M_NBSP),  KC_TRNS,  KC_TRNS,
+
+        // right hand
+        KC_TRNS,  M(M_6),    M(M_7),   M(M_8),   M(M_9),   M(M_0),   KC_TRNS,
+        KC_TRNS,  KC_EXLM,   KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,
+                  KC_TRNS,   KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,
+        KC_TRNS,  CSA_QEST,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,  KC_TRNS,
+                        CSA(SFT_AGR),  M(M_GRV), KC_TRNS,  KC_TRNS,  KC_TRNS,
+
+        KC_TRNS,  KC_TRNS,
+        KC_TRNS,
+        KC_TRNS,  KC_TRNS,  M(M_NBSP)
+    ),
+/* AltGr-ed BÉPO over Canadian Multilingual
+ * "////" indicates that the key is disabled (unsupported bépo character)
+ *
+ * ,--------------------------------------------------.           ,--------------------------------------------------.
+ * |    –   |   —  |   <  |   >  |   [  |   ]  |      |           |      |   ^  |   ±  | //// |   ÷  |   ×  | dead ˘ |
+ * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+ * |        |   |  |dead '|   &  |   œ  |dead `|      |           |      |   ¡  |dead ˇ|   ð  | //// |   ij  | ////// |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * | ////// |   æ  |   ù  |dead "|   €  |   ̛’  |------|           |------|   ©  |   þ  |   ß  |   ®  |dead ~| dead ¯ |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * |        |   \  |   {  |   }  |   …  |   ~  |      |           |      |   ¿  |dead °|   μ  | //// |dead ˛|        |
+ * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+ *   |      |      |      |      |      |                                       |      | //// |      |dead ¸|       |
+ *   `----------------------------------'                                       `-----------------------------------'
+ *                                        ,-------------.       ,-------------.
+ *                                        |      |      |       |      |      |
+ *                                 ,------|------|------|       |------+------+------.
+ *                                 |      |      |      |       |      |      |      |
+ *                                 |   _  |      |------|       |------|      |  _   |
+ *                                 |      |      |      |       |      |      |      |
+ *                                 `--------------------'       `--------------------'
+ */
+[LR_CSA_AGR] = KEYMAP(
+        // left hand
+        MUC(NDSH),    MUC(MDSH),  CSA_LESS,  CSA_GRTR,  CSA_LBRC,   CSA_RBRC,  KC_TRNS,
+        KC_TRNS,      CSA_PIPE,   CSA_DACT,  KC_AMPR,   CSA_OE,     CSA_DGRV,  KC_TRNS,
+        KC_NO,        CSA_AE,     CSA_UGRV,  CSA_DTRM,  CSA_EURO,   CSA_RQOT,
+        CSA(AGR_SFT), CSA_BSLS,   CSA_LCBR,  CSA_RCBR,  MUC(ELPS),  CSA_TILD,  KC_TRNS,
+        KC_TRNS,      KC_TRNS,    KC_TRNS,   KC_TRNS,   KC_TRNS,
+
+                                                      KC_TRNS,  KC_TRNS,
+                                                                KC_TRNS,
+                                        KC_UNDS, CSA(AGR_SFT),  KC_TRNS,
+
+        // right hand
+        KC_TRNS,  M(M_CRC),  CSA_PSMS,  KC_NO,     CSA_DVSN, CSA_TIMS,  CSA_DBRV,
+        KC_TRNS,  CSA_IXLM,  CSA_DCAR,  CSA_ETH,   KC_NO,    CSA_IJ,    KC_NO,
+                  CSA_CPRT,  CSA_THRN,  CSA_SRPS,  CSA_RTM,  CSA_DTLD,  CSA_DMCR,
+        KC_TRNS,  CSA_IQST,  CSA_DRNG,  CSA_MU,    KC_NO,    CSA_DOGO,  CSA(AGR_SFT),
+                             KC_TRNS,   KC_NO,     KC_TRNS,  CSA_DCED,  KC_TRNS,
+
+        KC_TRNS,  KC_TRNS,
+        KC_TRNS,
+        KC_TRNS,  CSA(AGR_SFT),  KC_UNDS
+    ),
+/* AltGr-shifted BÉPO over Canadian Multilingual
+ * "////" indicates that the key is disabled (unsupported bépo character or unused in bépo)
+ *
+ * ,--------------------------------------------------.           ,--------------------------------------------------.
+ * |    ¶   | //// |   “  |   ”  | //// | //// |      |           |      | //// |   ¬  |   ¼  |   ½  |   ¾  | ////// |
+ * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+ * |        |   ¦  |   ˝  |   §  |   Œ  |   `  |      |           |      | //// | //// |   Ð  | //// |   IJ  | ////// |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * | ////// |   Æ  |   Ù  |dead-˙| //// | //// |------|           |------| //// |   Þ  |   ẞ   |   ™  | //// |   º    |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * |        | //// |   ‘  |   ’  | //// | //// |      |           |      | //// | //// | //// | //// |   ª  |        |
+ * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+ *   |      |      |      |      |      |                                       |      |      |      |      |      |
+ *   `----------------------------------'                                       `----------------------------------'
+ *                                        ,-------------.       ,-------------.
+ *                                        |      |      |       |      |      |
+ *                                 ,------|------|------|       |------+------+------.
+ *                                 |      |      |      |       |      |      |      |
+ *                                 |      |      |------|       |------|      |      |
+ *                                 |      |      |      |       |      |      |      |
+ *                                 `--------------------'       `--------------------'
+ */
+[LR_CSA_AGR_SFT] = KEYMAP(
+        // left hand
+        CSA_PARG,      KC_NO,     CSA_LDQT,    CSA_RDQT,  KC_NO,     KC_NO,     KC_TRNS,
+        KC_TRNS,       CSA_BPIP,  CSA_DDCT,    CSA_SECT,  S(CSA_OE), M(M_GRV),  KC_TRNS,
+        KC_NO,         S(CSA_AE), S(CSA_UGRV), CSA_DDTA,  KC_NO,     KC_NO,
+        CSA(AGR_SFT),  KC_NO,     CSA_LQOT,    CSA_RQOT,  KC_NO,     KC_NO,     KC_TRNS,
+        KC_TRNS,       KC_TRNS,   KC_TRNS,     KC_TRNS,   KC_TRNS,
+
+        KC_TRNS,  KC_TRNS,
+        KC_TRNS,
+        KC_TRNS,  CSA(AGR_SFT),  KC_TRNS,
+
+        // right hand
+        KC_TRNS,  KC_NO,     CSA_NEGT,    CSA_1QRT,    CSA_1HLF,  CSA_3QRT,   KC_NO,
+        KC_TRNS,  KC_NO,     KC_NO,       S(CSA_ETH),  KC_NO,     S(CSA_IJ),  KC_NO,
+                  KC_NO,     S(CSA_THRN), S(CSA_SRPS), CSA_TM,    KC_NO,      CSA_ORDO,
+        KC_TRNS,  KC_NO,     KC_NO,       KC_NO,       KC_NO,     CSA_ORDA,   CSA(AGR_SFT),
+                        CSA(SFT_AGR),     KC_TRNS,     KC_TRNS,   KC_TRNS,    KC_TRNS,
+
+        KC_TRNS,  KC_TRNS,
+        KC_TRNS,
+        KC_TRNS,  CSA(AGR_SFT),  KC_TRNS
+    ),
+/* Numeric Layer
+ *
+ * ,--------------------------------------------------.           ,--------------------------------------------------.
+ * |        |  F1  |  F2  |  F3  |  F4  |  F5  |      |           |      |      |      |  Tab |   /  |   *  |   -    |
+ * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+ * |        |  F6  |  F7  |  F8  |  F9  |  F10 |      |           |      |      | Home |   7  |   8  |   9  |   +    |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * |        |  F11 |  F12 |      |      |      |------|           |------|  Up  | End  |   4  |   5  |   6  |   +    |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * |        |      |      |      |      |      |      |           | Left | Down | Right|   1  |   2  |   3  |KpEnter |
+ * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+ *   |      |      |      |      |      |                                       |      |   0  |  00  |   .  |Etr/Ctl|
+ *   `----------------------------------'                                       `-----------------------------------'
+ *                                        ,-------------.       ,-------------.
+ *                                        |      |      |       |n.lock|c.lock|
+ *                                 ,------|------|------|       |------+------+------.
+ *                                 |      |      |      |       |      |      |      |
+ *                                 |      |      |------|       |------|      |      |
+ *                                 |      |      |      |       |      |      |      |
+ *                                 `--------------------'       `--------------------'
+ */
+// SYMBOLS
+[LR_NUMR] = KEYMAP(
+       // left hand
+       KC_TRNS, KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_TRNS,
+       KC_TRNS, KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_TRNS,
+       KC_TRNS, KC_F11,  KC_F12,  KC_TRNS, KC_TRNS, KC_TRNS,
+       KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+       KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+
+                                       KC_TRNS,KC_TRNS,
+                                               KC_TRNS,
+                              KC_TRNS, KC_TRNS,KC_TRNS,
+
+       // right hand
+       KC_TRNS, KC_F6,   KC_F7,   KC_TAB,  KC_PSLS,  KC_PAST, KC_PMNS,
+       KC_TRNS, KC_TRNS, KC_HOME, KC_P7,   KC_P8,    KC_P9,   KC_PPLS,
+                KC_UP,   KC_END,  KC_P4,   KC_P5,    KC_P6,   KC_PPLS,
+       KC_LEFT, KC_DOWN, KC_RGHT, KC_P1,   KC_P2,    KC_P3,   KC_PENT,
+                         KC_TRNS, KC_P0,   M(M_DBL0),KC_PDOT, CTL_T(KC_PENT),
+
+       KC_NLCK, KC_CAPS,
+       KC_TRNS,
+       KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* fn layer
+ *
+ * ,--------------------------------------------------.           ,--------------------------------------------------.
+ * |~CA-mult|      |      |      |      |      |Insert|           |Insert|Eject |Power |Sleep | Wake |PrtScr|ScrollLk|
+ * |--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+ * |        |      |      |      |      |      |VolUp |           |      |      |      |      |      |      | Pause  |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * |  RESET |      |      | Calc | Mail |Browsr|------|           |------|      |      |      |      |      |        |
+ * |--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+ * |        | App  | cut  | copy |paste | Mute |VolDn |           |      |      |      |      |      |      |        |
+ * `--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+ *   |      |      |      |      |      |                                       |      |      |      |      |      |
+ *   `----------------------------------'                                       `----------------------------------'
+ *                                        ,-------------.       ,-------------.
+ *                                        |      |      |       |      |      |
+ *                                 ,------|------|------|       |------+------+------.
+ *                                 |      |      | Next |       |      |      |      |
+ *                                 | Mute | play |------|       |------|      |      |
+ *                                 |      |      | Prev |       |      |      |      |
+ *                                 `--------------------'       `--------------------'
+ */
+// MEDIA AND MOUSE
+[LR_FN] = KEYMAP(
+       TG(LR_CSA), KC_TRNS, KC_TRNS,      KC_TRNS,     KC_TRNS,      KC_TRNS, KC_INS,
+       KC_TRNS,    KC_TRNS, KC_TRNS,      KC_TRNS,     KC_TRNS,      KC_TRNS, KC_VOLU,
+       RESET,      KC_TRNS, KC_TRNS,      KC_CALC,     KC_MAIL,      KC_WHOM,
+       KC_TRNS,    KC_APP,  S(KC_DELT),   LCTL(KC_INS),S(KC_INS),    KC_MUTE, KC_VOLD,
+       KC_TRNS,    KC_TRNS, KC_TRNS,      KC_TRNS,     KC_TRNS,
+
+                                           KC_TRNS, KC_TRNS,
+                                                    KC_MPRV,
+                                  KC_MUTE, KC_MPLY, KC_MNXT,
+
+    // right hand
+       KC_INS,   KC_EJCT, KC_PWR,  KC_SLEP, KC_WAKE, KC_PSCR, KC_SLCK,
+       KC_TRNS,  KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PAUS,
+                 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+       KC_TRNS,  KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+                          KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+
+       KC_TRNS, KC_TRNS,
+       KC_TRNS,
+       KC_TRNS, KC_TRNS, KC_TRNS
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+void hold_shift(void) {
+    register_code(KC_LSHIFT);
+}
+
+void release_shift(void) {
+    unregister_code(KC_LSHIFT);
+}
+
+uint16_t hextokeycode(int hex) {
+    if (hex == 0x0) {
+        return KC_P0;
+    } else if (hex < 0xA) {
+        return KC_P1 + (hex - 0x1);
+    } else {
+        return KC_A + (hex - 0xA);
+    }
+}
+
+void send_unicode(uint16_t unicode)
+{
+    // For more info on how this works per OS, see here: https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input
+    // Implemented for Windows:
+    // Pressing ALT followed by + followed by the unicode code point in hex.
+    // Requires registry key HKEY_CURRENT_USER\Control Panel\Input Method\EnableHexNumpad set to String 1
+    register_code(KC_LALT);
+    register_code(KC_PPLS);
+    unregister_code(KC_PPLS);
+
+    for (int i = 12; i >= 0; i -= 4) {
+        register_code(hextokeycode((unicode >> i) & 0xF));
+        unregister_code(hextokeycode((unicode >> i) & 0xF));
+    }
+
+    unregister_code(KC_LALT);
+}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+  // MACRODOWN only works in this function
+    switch(id) {
+        case 0 ... END_UC:
+            if (record->event.pressed) {
+                send_unicode(unicode_chars[id]);
+            }
+            break;
+        case M_CSA_SFT:
+            // BÉPO over CSA: toggle shift layer
+            layer_invert(LR_CSA_SFT);
+            if (record->event.pressed) {
+                hold_shift();
+            } else {
+                release_shift();
+            }
+            break;
+        case M_CSA_SFT_AGR:
+            // BÉPO over CSA: from shift layer, momentary altgr+shift layer
+            layer_invert(LR_CSA_AGR);
+            layer_invert(LR_CSA_AGR_SFT);
+            if (record->event.pressed) {
+                // shift not needed for LR_CSA_AGR_SFT
+                release_shift();
+            } else {
+                // back to shift layer
+                hold_shift();
+            }
+            break;
+        case M_CSA_AGR_SFT:
+            // BÉPO over CSA: from altgr layer, momentary altgr+shift layer
+            layer_invert(LR_CSA_SFT);
+            layer_invert(LR_CSA_AGR_SFT);
+            break;
+        case M_1 ... M_0:
+        case M_DEGR:
+        case M_SCLN:
+        case M_GRV:
+        case M_NBSP:
+            // macros of the shift layer that require to release shift
+            if (record->event.pressed) {
+                release_shift();
+                switch (id) {
+                    case M_1 ... M_0:
+                        register_code(KC_1 + (id - M_1));
+                        break;
+                    case M_DEGR:
+                        return MACRO(DOWN(CSA_ALTGR), D(SCLN), END);
+                    case M_SCLN:
+                        return MACRO(D(SCLN), END);
+                    case M_GRV:
+                        return MACRO(I(75), DOWN(CSA_ALTGR), TYPE(CSA_DCRC), UP(CSA_ALTGR), T(SPACE), END);
+                    case M_NBSP:
+                        // use weak mod such that pressing another key will not be affected
+                        add_weak_mods(MOD_BIT(CSA_ALTGR));
+                        return MACRO(D(SPACE), END);
+                }
+            } else {
+                hold_shift();
+                switch (id) {
+                    case M_1 ... M_0:
+                        unregister_code(KC_1 + (id - M_1));
+                        break;
+                    case M_DEGR:
+                        return MACRO(UP(CSA_ALTGR), U(SCLN), END);
+                    case M_SCLN:
+                        return MACRO(U(SCLN), END);
+                    case M_NBSP:
+                        del_weak_mods(MOD_BIT(CSA_ALTGR));
+                        return MACRO(U(SPACE), END);
+                }
+            }
+            break;
+        case M_CRC:
+            if (record->event.pressed) {
+                return MACRO(I(75), TYPE(CSA_DCRC), T(SPACE), END);
+            }
+            break;
+        case M_DBL0:
+            if (record->event.pressed) {
+                return MACRO( I(25), T(P0), T(P0), END );
+            }
+        break;
+        case M_FNLR:
+            layer_invert(LR_NUMR);
+            layer_invert(LR_FN);
+            break;
+        case M_NMAL:
+            layer_invert(LR_NUMR);
+            if (record->event.pressed) {
+                register_code(KC_LALT);
+            } else {
+                unregister_code(KC_LALT);
+            }
+            break;
+    }
+    return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+    ergodox_board_led_off();
+    ergodox_right_led_1_off();
+    ergodox_right_led_2_off();
+    ergodox_right_led_3_off();
+    // led 1: numeric layer
+    if (layer_state & (1 << LR_NUMR)) {
+        ergodox_right_led_1_on();
+    }
+    // led 2: BÉPO over Canadian Multilingual
+    if (IS_CA_MULT_ENABLED()) {
+        ergodox_right_led_2_on();
+    }
+    // led 3: caps lock
+    if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) {
+      ergodox_right_led_3_on();
+    }
+};

+ 162 - 0
keyboards/ergodox/keymaps/bepo_csa/readme.md

@@ -0,0 +1,162 @@
+# BÉPO Keymap with firmware-remapping for software CSA layout
+
+This is a keymap intended to be used with the [BÉPO layout](http://bepo.fr), a French ergonomic layout designed by following Dvorak's principles.
+
+The particularity of this keymap is that it supports using the [Canadian Multilingual Standard layout](https://en.wikipedia.org/wiki/QWERTY#Canadian_Multilingual_Standard) (also known as _ACNOR keyboard_ or _CSA keyboard_, see also the [French page](https://fr.wikipedia.org/wiki/QWERTY#Clavier_canadien_multilingue_standard) which contains more details) on the OS side, by enabling the _CSA_ layer. This is especially useful for operating systems that natively provide CSA, but not BÉPO, like Windows. The CSA layout was chosen because it is probably the standard layout that provides the best character set coverage.
+
+This keymap is based on the [tm2030](../tm2030/) keymap, whose goal was to have a [TypeMatrix™ 2030](http://typematrix.com/2030/features.php) inspired layout for the ErgoDox EZ.
+
+As this keyboard is intended for French people, the rest of this page will be in French.
+
+# Keymap BÉPO avec support en firmware pour utilisation avec la disposition CSA en software
+
+Cette keymap a été conçue pour être utilisée avec la [disposition BÉPO](http://bepo.fr), la disposition francophone, ergonomique et libre basée sure les principes de Dvorak.
+
+La particularité de cette keymap est qu'elle supporte l'utilisation du [clavier canadien multilingue standard](https://fr.wikipedia.org/wiki/QWERTY#Clavier_canadien_multilingue_standard) (aussi appelé _clavier ACNOR_ ou _clavier CSA_) du côté du système d'exploitation, en activant la couche _CSA_. Ceci s'avère particulièrement utile pour les systèmes d'exploitations qui fournissent nativement le CSA, mais pas le BÉPO, comme Windows. Le clavier CSA a été choisi comme base car c'est probablement la disposition standard qui fournit la meilleure couverture en termes de caractères disponibles.
+
+Cette keymap est basée sur la keymap [tm2030](../tm2030/), dont le but est de fournir une disposition inspirée du [TypeMatrix™ 2030](http://typematrix.com/2030/features.php) pour l'ErgoDox EZ.
+
+## Couche de base
+C'est la couche par défaut, proche du TypeMatrix, avec les différences suivantes:
+- La ligne du haut (les touches `F`) et la colonne de droite sont retirées, les touches correspondantes étant déplacées ailleurs.
+- Les touches situés en bas à gauche sont redisposées dans cet ordre: `Ctrl`, `fn`, `Gui`, `num+Alt`, `Alt`
+- Les touches `shuffle` (`Alt+Tab`) et `desktop` ne sont pas supportés
+- `W` est déplacé à la place de `=`
+- `=` est déplacé sous `Tab` (au lieu d'avoir un grand `Shift`)
+- `%` et `Ç` sont déplacés à la place de `Home` et `End` respectivement
+- Les flèches ainsi que `PgUp`/`PgDown`/`Home`/`End` sont déplacées sur les pouces
+
+À noter que pour `W` et `Ç`, le but a été de ne pas les déplacer trop par rapport à la disposition BÉPO _standard_, afin de pouvoir repasser facilement sur un TypeMatrix ou un clavier traditionnel.
+
+
+```
+,--------------------------------------------------.           ,--------------------------------------------------.
+|   $    |   "  |   «  |   »  |   (  |   )  | Del  |           | Del  |   @  |   +  |   -  |   /  |   *  |   W    |
+|--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+| Tab    |   B  |   É  |   P  |   O  |   È  |Backsp|           |Backsp|   ^  |   V  |   D  |   L  |   J  |   Z    |
+|--------+------+------+------+------+------|ace   |           |ace   |------+------+------+------+------+--------|
+|   =    |   A  |   U  |   I  |   E  |   ,  |------|           |------|   C  |   T  |   S  |   R  |   N  |   M    |
+|--------+------+------+------+------+------|Enter |           |Enter |------+------+------+------+------+--------|
+| LShift |   À  |   Y  |   X  |   .  |   K  |      |           |      |   '  |   Q  |   G  |   H  |   F  | RShift |
+`--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+  |LCtrl |  fn  | LGui |numAlt| LAlt |                                       |Alt Gr|   %  |  App |   Ç  | RCtrl|
+  `----------------------------------'                                       `----------------------------------'
+                                      ,--------------.       ,-------------.
+                                      |  Esc  | num  |       | Left |Right |
+                               ,------+-------+------|       |------+------+------.
+                               |      |       | PgUp |       |  Up  |      |      |
+                               |Space | Home  |------|       |------| End  |Space |
+                               |      |       | PgDn |       | Down |      |      |
+                               `---------------------'       `--------------------'
+```
+
+### Changer de couche
+
+- Utilisez `num` pour activer/désactiver [la couche numérique](#couche-numérique)
+- Maintenez `fn` pour activer temporairement [les couches numériques et Fn](#couche-fn)
+- Maintenez `numAlt` pour activer temporairement la couche numérique combinée avec `Alt` (facilite l'utilisation des raccourcis tels que `Alt`+`F4`)
+
+### Diodes
+Les diodes de l'ErgoDox EZ (côté droit) sont utilisées de la façon suivante :
+
+- diode de gauche (rouge) : indique l'activation de [la couche numérique](#couche-numérique)
+- diode du milieu (verte) : indique l'activation du [mode CSA](#couche-csa)
+- diode de droite (bleue) : indique le verrouillage majuscules
+
+## Couche CSA
+La couche _CSA_ est la même que la couche de base, pour une utilisation avec un clavier Canadien Multilingue configuré dans le système d'exploitation.
+
+Pour l'activer, appuyez sur `fn`+`$`. La [diode](#diodes) verte indique que la couche CSA est activée.
+
+### Limitations
+Seuls les caractères présents dans le clavier CSA sont parfaitement supportés. De manière générale, il s'agit des caractères suivants :
+
+- toute la couche de base
+- tous les caractères accessibles en `Shift`
+- tous les caractères de la main gauche accessibles en `AltGr` à l'exception du `≠`
+- environ la moitié des caractères de la main droite accessibles en `AltGr` et la moitié des caractères accessibles en `AltGr`+`Shift` (consultez [le fichier source](keymap.c) pour voir les caractères supportés)
+
+En particulier, les caractères suivants sont émulés via le support Unicode (Windows seulement):
+
+- le tiret cadratin (tiret long) : —
+- le tiret demi-cadratin (demi tiret) : –
+- les points de suspension : …
+
+L'implémentation actuelle ne fonctionne pas dans toutes les applications, en particulier les applications MS Office.
+
+Il est probable que l'utilisation de la couche CSA ne fonctionne pas correctement dans certains jeux vidéos.
+
+Cette fonctionnalité a été conçue et testée essentiellment pour Windows (7).
+
+### Détails techniques
+Techniquement, la couche CSA est en réalité composée de 4 couches servant à émuler la couche de base, les appuis sur `Shift` ou `Alt` et la combinaison des deux.
+
+Le changement de couches se fait par des macros afin d'activer ou désactiver plusieurs couches et la touche `Shift` en même temps.
+
+Certains caractères sont également implémentés par des macros, notamment ceux de la couche `Shift` qui n'ont pas besoin de cette touche en CSA, comme les chiffres.
+
+Les caractères Unicode se basent sur une implémentation spécifique et non celle fournie dans QMK — il faudrait sans doute migrer le code. Notez la façon dont ces caractères sont déclarés tels quels dans [le code source](keymap.c) (tableau `unicode_char`).
+
+## Couche numérique
+Couche numérique proche du TM lorsqu'on active `num`, avec les différences suivantes :
+
+- Le clavier numérique est déplacés de 1 vers le haut et vers la droite.
+- Les flèches sont décalées de 1 vers la gauche.
+- Fournit l'accès aux touches `F1` à `F12`, `caps-lock` et `num-lock`.
+
+La couche numérique est indiquée par la [diode](#diodes) de gauche (rouge). Caps-lock est indiqué par la diode de droite (bleue).
+
+La touche `numAlt` de [la couche de base](#couche-de-base) permet d'activer la couche numérique et la touche `Alt` simultanément, afin de faciliter les raccourcis claviers comme `Alt`+`F4`.
+
+```
+,--------------------------------------------------.           ,--------------------------------------------------.
+|        |  F1  |  F2  |  F3  |  F4  |  F5  |      |           |      |      |      |  Tab |   /  |   *  |   -    |
+|--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+|        |  F6  |  F7  |  F8  |  F9  |  F10 |      |           |      |      | Home |   7  |   8  |   9  |   +    |
+|--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+|        |  F11 |  F12 |      |      |      |------|           |------|  Up  | End  |   4  |   5  |   6  |   +    |
+|--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+|        |      |      |      |      |      |      |           | Left | Down | Right|   1  |   2  |   3  |KpEnter |
+`--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+  |      |      |      |      |      |                                       |      |   0  |  00  |   .  |Etr/Ctl|
+  `----------------------------------'                                       `-----------------------------------'
+                                       ,-------------.       ,-------------.
+                                       |      |      |       |n.lock|c.lock|
+                                ,------|------|------|       |------+------+------.
+                                |      |      |      |       |      |      |      |
+                                |      |      |------|       |------|      |      |
+                                |      |      |      |       |      |      |      |
+                                `--------------------'       `--------------------'
+```
+
+## Couche Fn
+Activée simultanément avec la couche numérique lorsque l'on maintient la touche `fn`. Comme sur le TM, elle fournit l'accès aux fonctionnalités suivantes :
+
+- `couper`, `copier` et `coller` — attention: ne pas utiliser dans l'explorateur de fichiers.
+- monter/baisser/couper le volume — seulement accessible en main gauche, contrairement au TM.
+- piste précédente/suivante
+- calculatrice, e-mail et page d'accueil du navigateur web
+- `insert`, `power`, `sleep`, `wake`, `print screen`, `scroll-lock` et `pause`
+- ~CSA: (dés)activation de [la couche CSA](#couche-csa) sur `$`
+- RESET: rechargement du firmware avec Teensy-Loader (pour les développeurs)
+
+```
+,--------------------------------------------------.           ,--------------------------------------------------.
+|  ~CSA  |      |      |      |      |      |Insert|           |Insert|Eject |Power |Sleep | Wake |PrtScr|ScrollLk|
+|--------+------+------+------+------+-------------|           |------+------+------+------+------+------+--------|
+|        |      |      |      |      |      |VolUp |           |      |      |      |      |      |      | Pause  |
+|--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+|  RESET |      |      | Calc | Mail |Browsr|------|           |------|      |      |      |      |      |        |
+|--------+------+------+------+------+------|      |           |      |------+------+------+------+------+--------|
+|        | App  | cut  | copy |paste | Mute |VolDn |           |      |      |      |      |      |      |        |
+`--------+------+------+------+------+-------------'           `-------------+------+------+------+------+--------'
+  |      |      |      |      |      |                                       |      |      |      |      |      |
+  `----------------------------------'                                       `----------------------------------'
+                                       ,-------------.       ,-------------.
+                                       |      |      |       |      |      |
+                                ,------|------|------|       |------+------+------.
+                                |      |      | Next |       |      |      |      |
+                                | Mute | play |------|       |------|      |      |
+                                |      |      | Prev |       |      |      |      |
+                                `--------------------'       `--------------------'
+```

+ 255 - 0
quantum/keymap_extras/keymap_canadian_multilingual.h

@@ -0,0 +1,255 @@
+#ifndef KEYMAP_CANADIAN_MULTILINGUAG_H
+#define KEYMAP_CANADIAN_MULTILINGUAG_H
+
+#include "keymap.h"
+
+// Alt gr
+#ifndef ALTGR
+#define ALTGR(kc)   RALT(kc)
+#endif
+#ifndef ALGR
+#define ALGR(kc)    ALTGR(kc)
+#endif
+
+#define CSA_ALTGR   KC_RALT
+#define CSA_ALGR    CSA_ALTGR
+
+#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                ALTGR(CSA_SLASH)        // |
+#define CSA_CURRENCY            ALTGR(KC_4)             // ¤
+#define CSA_CURR                CSA_CURRENCY
+#define CSA_LEFT_CURLY_BRACE    ALTGR(KC_7)             // {
+#define CSA_LCBR                CSA_LEFT_CURLY_BRACE
+#define CSA_RIGHT_CURLY_BRACE   ALTGR(KC_8)             // }
+#define CSA_RCBR                CSA_RIGHT_CURLY_BRACE
+#define CSA_LBRACKET            ALTGR(KC_9)             // [
+#define CSA_LBRC                CSA_LBRACKET
+#define CSA_RBRACKET            ALTGR(KC_0)             // ]
+#define CSA_RBRC                CSA_RBRACKET
+#define CSA_NEGATION            ALTGR(KC_EQUAL)         // ¬
+#define CSA_NEGT                CSA_NEGATION
+
+// Second row
+// euro symbol not available on Linux? (X.org)
+#define CSA_EURO        ALTGR(KC_E)                 // €
+#define CSA_DEAD_GRAVE  ALTGR(CSA_DEAD_CIRCUMFLEX)
+#define CSA_DGRV        CSA_DEAD_GRAVE              // dead `
+#define CSA_DEAD_TILDE  ALTGR(CSA_C_CEDILLA)        // ~
+#define CSA_DTLD        CSA_DEAD_TILDE
+
+// Third row
+#define CSA_DEGREE  ALTGR(KC_SCOLON)    // °
+#define CSA_DEGR    CSA_DEGREE
+
+// Fourth row
+#define CSA_LEFT_GUILLEMET      ALTGR(KC_Z)         // «
+#define CSA_LGIL                CSA_LEFT_GUILLEMET
+#define CSA_RIGHT_GUILLEMET     ALTGR(KC_X)         // »
+#define CSA_RGIL                CSA_RIGHT_GUILLEMET
+#define CSA_LESS                ALTGR(KC_COMMA)     // <
+#define CSA_GREATER             ALTGR(KC_DOT)       // >
+#define CSA_GRTR                CSA_GREATER
+
+// Space bar
+#define CSA_NON_BREAKING_SPACE  ALTGR(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
+
+// 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 È & À
+
+// 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
+
+// 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 ALTGR(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
+
+// 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
+
+// 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
+
+// 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))
+
+#endif