aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrashna Jaelre <drashna@live.com>2020-08-22 07:44:42 -0700
committerGitHub <noreply@github.com>2020-08-22 07:44:42 -0700
commit220b1c9db40d95271dcdd8d8050e46a2a3143c65 (patch)
treef98a2177f5ec0009df4400cfd5b100a3ff816297
parent346bfb2a052f4e05cc91e55e1317c8529c405ac6 (diff)
downloadqmk_firmware-220b1c9db40d95271dcdd8d8050e46a2a3143c65.tar.gz
qmk_firmware-220b1c9db40d95271dcdd8d8050e46a2a3143c65.zip
[Keyboard] Add ZSA Moonlander (#9853)
-rw-r--r--keyboards/moonlander/config.h103
-rw-r--r--keyboards/moonlander/info.json31
-rw-r--r--keyboards/moonlander/keymaps/default/config.h21
-rw-r--r--keyboards/moonlander/keymaps/default/keymap.c109
-rw-r--r--keyboards/moonlander/keymaps/drashna/config.h21
-rw-r--r--keyboards/moonlander/keymaps/drashna/keymap.c279
-rw-r--r--keyboards/moonlander/keymaps/drashna/rules.mk4
-rw-r--r--keyboards/moonlander/matrix.c270
-rw-r--r--keyboards/moonlander/moonlander.c466
-rw-r--r--keyboards/moonlander/moonlander.h81
-rw-r--r--keyboards/moonlander/readme.md28
-rw-r--r--keyboards/moonlander/rules.mk29
12 files changed, 1442 insertions, 0 deletions
diff --git a/keyboards/moonlander/config.h b/keyboards/moonlander/config.h
new file mode 100644
index 000000000..b77fcbd1e
--- /dev/null
+++ b/keyboards/moonlander/config.h
@@ -0,0 +1,103 @@
1/* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
2 * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
3 * Copyright 2020 Drashna Jael're <drashna@live.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#include "config_common.h"
22
23/* USB Device descriptor parameter */
24// clang-format off
25#define VENDOR_ID 0x3297
26#define PRODUCT_ID 0x1969
27#define MANUFACTURER ZSA Technology Labs
28#define PRODUCT Moonlander Mark I
29#define DEVICE_VER 0x0001
30#define WEBUSB_LANDING_PAGE_URL u8"configure.ergodox-ez.com"
31
32// clang-format on
33
34/* key matrix size */
35#define MATRIX_ROWS 12
36#define MATRIX_COLS 7
37
38/* PCB default pin-out */
39// #define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 }
40// #define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 }
41
42// #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 }
43// #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 }
44
45// #define MCP23_LED_R GPB7
46// #define MCP23_LED_G GPB6
47// #define MCP23_LED_B GPA7
48
49#define EEPROM_I2C_24LC128
50
51// Not needed, is default address:
52// #define EXTERNAL_EEPROM_I2C_BASE_ADDRESS 0b10100000
53
54/* COL2ROW or ROW2COL */
55#define DIODE_DIRECTION ROW2COL
56
57/* Set 0 if debouncing isn't needed */
58#define DEBOUNCE 5
59
60/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
61#define LOCKING_SUPPORT_ENABLE
62/* Locking resynchronize hack */
63#define LOCKING_RESYNC_ENABLE
64
65/*
66 * Feature disable options
67 * These options are also useful to firmware size reduction.
68 */
69
70/* disable debug print */
71//#define NO_DEBUG
72
73/* disable print */
74//#define NO_PRINT
75
76/* disable action features */
77//#define NO_ACTION_LAYER
78//#define NO_ACTION_TAPPING
79//#define NO_ACTION_ONESHOT
80#define NO_ACTION_MACRO
81#define NO_ACTION_FUNCTION
82
83#define DRIVER_ADDR_1 0b1110100
84#define DRIVER_ADDR_2 0b1110111
85
86#define DRIVER_COUNT 2
87#define DRIVER_1_LED_TOTAL 36
88#define DRIVER_2_LED_TOTAL 36
89#define DRIVER_LED_TOTAL (DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL)
90#define RGB_MATRIX_CENTER { 125, 26 }
91#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 175
92#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
93#define RGB_MATRIX_KEYPRESSES
94#define RGB_DISABLE_WHEN_USB_SUSPENDED true
95
96#define MUSIC_MAP
97
98#define FIRMWARE_VERSION_SIZE 17
99#define DYNAMIC_KEYMAP_EEPROM_ADDR (EECONFIG_SIZE + FIRMWARE_VERSION_SIZE)
100#ifdef EEPROM_I2C
101# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 16383
102# define DYNAMIC_KEYMAP_LAYER_COUNT 32
103#endif
diff --git a/keyboards/moonlander/info.json b/keyboards/moonlander/info.json
new file mode 100644
index 000000000..1a12b665a
--- /dev/null
+++ b/keyboards/moonlander/info.json
@@ -0,0 +1,31 @@
1{
2 "keyboard_name": "Moonlander Mark I",
3 "url": "zsa.io/moonlander",
4 "maintainer": "ZSA via Drashna",
5 "manufacturer": "ZSA Technology Labs Inc",
6 "width": 17,
7 "height": 8,
8
9 "layouts": {
10 "LAYOUT_moonlander": {
11 "layout": [
12 {"x":0, "y":0.375}, {"x":1, "y":0.375}, {"x":2, "y":0.125}, {"x":3, "y":0}, {"x":4, "y":0.125}, {"x":5, "y":0.25}, {"x":6, "y":0.25},
13 {"x":10, "y":0.25}, {"x":11, "y":0.25}, {"x":12, "y":0.125}, {"x":13, "y":0}, {"x":14, "y":0.125}, {"x":15, "y":0.375}, {"x":16, "y":0.375},
14
15 {"x":0, "y":1.375}, {"x":1, "y":1.375}, {"x":2, "y":1.125}, {"x":3, "y":1}, {"x":4, "y":1.125}, {"x":5, "y":1.25}, {"x":6, "y":1.25},
16 {"x":10, "y":1.25}, {"x":11, "y":1.25}, {"x":12, "y":1.125}, {"x":13, "y":1}, {"x":14, "y":1.125}, {"x":15, "y":1.375}, {"x":16, "y":1.375},
17
18 {"x":0, "y":2.375}, {"x":1, "y":2.375}, {"x":2, "y":2.125}, {"x":3, "y":2}, {"x":4, "y":2.125}, {"x":5, "y":2.25}, {"x":6, "y":2.25},
19 {"x":10, "y":2.25}, {"x":11, "y":2.25}, {"x":12, "y":2.125}, {"x":13, "y":2}, {"x":14, "y":2.125}, {"x":15, "y":2.375}, {"x":16, "y":2.375},
20
21 {"x":0, "y":3.375}, {"x":1, "y":3.375}, {"x":2, "y":3.125}, {"x":3, "y":3}, {"x":4, "y":3.125}, {"x":5, "y":3.25},
22 {"x":11, "y":3.25}, {"x":12, "y":3.125}, {"x":13, "y":3}, {"x":14, "y":3.125}, {"x":15, "y":3.375}, {"x":16, "y":3.375},
23
24 {"x":0, "y":4.375}, {"x":1, "y":4.375}, {"x":2, "y":4.125}, {"x":3, "y":4}, {"x":4, "y":4.125}, {"x":5, "y":4.5, "w":2},
25 {"x":10, "y":4.5, "w":2}, {"x":12, "y":4.125}, {"x":13, "y":4}, {"x":14, "y":4.125}, {"x":15, "y":4.375}, {"x":16, "y":4.375},
26
27 {"x":5, "y":5.5, "h":1.5}, {"x":6, "y":5.5, "h":1.5}, {"x":7, "y":5.5, "h":1.5}, {"x":9, "y":5.5, "h":1.5}, {"x":10, "y":5.5, "h":1.5}, {"x":11, "y":5.5, "h":1.5}
28 ]
29 }
30 }
31}
diff --git a/keyboards/moonlander/keymaps/default/config.h b/keyboards/moonlander/keymaps/default/config.h
new file mode 100644
index 000000000..95b05a5a6
--- /dev/null
+++ b/keyboards/moonlander/keymaps/default/config.h
@@ -0,0 +1,21 @@
1/* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
2 * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
3 * Copyright 2020 Drashna Jael're <drashna@live.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#define ORYX_CONFIGURATOR
diff --git a/keyboards/moonlander/keymaps/default/keymap.c b/keyboards/moonlander/keymaps/default/keymap.c
new file mode 100644
index 000000000..67a2cd53a
--- /dev/null
+++ b/keyboards/moonlander/keymaps/default/keymap.c
@@ -0,0 +1,109 @@
1/* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
2 * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
3 * Copyright 2020 Drashna Jael're <drashna@live.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20
21#include QMK_KEYBOARD_H
22#include "version.h"
23
24enum layers {
25 BASE, // default layer
26 SYMB, // symbols
27 MDIA, // media keys
28};
29
30enum custom_keycodes {
31 VRSN = ML_SAFE_RANGE,
32};
33
34// clang-format off
35const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
36 [BASE] = LAYOUT_moonlander(
37 KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT, KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
38 KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB), TG(SYMB), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
39 KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_HYPR, KC_MEH, KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN), GUI_T(KC_QUOT),
40 KC_LSFT, LCTL_T(KC_Z),KC_X,KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, LCTL_T(KC_SLSH), KC_LSFT,
41 LT(SYMB,KC_GRV),WEBUSB_PAIR,A(KC_LSFT),KC_LEFT, KC_RGHT, LALT_T(KC_APP), RCTL_T(KC_ESC), KC_UP, KC_DOWN, KC_LBRC, KC_RBRC, TT(SYMB),
42 KC_SPC, KC_BSPC, KC_LGUI, KC_RALT, KC_TAB, KC_ENT
43 ),
44
45 [SYMB] = LAYOUT_moonlander(
46 VRSN, 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_F11,
47 KC_TRNS, KC_EXLM, KC_AT, KC_LCBR, KC_RCBR, KC_PIPE, KC_TRNS, KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
48 KC_TRNS, KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV, KC_TRNS, KC_TRNS, KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
49 KC_TRNS, KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
50 EEP_RST, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_VAI, RGB_TOG, KC_TRNS, KC_DOT, KC_0, KC_EQL, KC_TRNS,
51 RGB_HUD, RGB_VAD, RGB_HUI, TOGGLE_LAYER_COLOR,KC_TRNS, KC_TRNS
52 ),
53
54 [MDIA] = LAYOUT_moonlander(
55 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,
56 KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
57 KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
58 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
59 KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2, KC_TRNS, KC_TRNS, KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
60 KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
61 ),
62};
63
64layer_state_t layer_state_set_user(layer_state_t state) {
65 ML_LED_1(false);
66 ML_LED_2(false);
67 ML_LED_3(false);
68 ML_LED_4(false);
69 ML_LED_5(false);
70 ML_LED_6(false);
71
72 switch (get_highest_layer(state)) {
73 case 1:
74 ML_LED_1(1);
75 ML_LED_4(1);
76 break;
77 case 2:
78 ML_LED_2(1);
79 ML_LED_5(1);
80 break;
81 case 3:
82 ML_LED_3(1);
83 break;
84 case 4:
85 ML_LED_4(1);
86 break;
87 case 5:
88 ML_LED_5(1);
89 break;
90 case 6:
91 ML_LED_6(1);
92 break;
93 default:
94 break;
95 }
96
97 return state;
98}
99
100bool process_record_user(uint16_t keycode, keyrecord_t *record) {
101 if (record->event.pressed) {
102 switch (keycode) {
103 case VRSN:
104 SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
105 return false;
106 }
107 }
108 return true;
109}
diff --git a/keyboards/moonlander/keymaps/drashna/config.h b/keyboards/moonlander/keymaps/drashna/config.h
new file mode 100644
index 000000000..dd49eaf4b
--- /dev/null
+++ b/keyboards/moonlander/keymaps/drashna/config.h
@@ -0,0 +1,21 @@
1/* Copyright 2020 Drashna Jael're <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17
18
19#pragma once
20
21#define TAPPING_TERM_PER_KEY
diff --git a/keyboards/moonlander/keymaps/drashna/keymap.c b/keyboards/moonlander/keymaps/drashna/keymap.c
new file mode 100644
index 000000000..b8754673b
--- /dev/null
+++ b/keyboards/moonlander/keymaps/drashna/keymap.c
@@ -0,0 +1,279 @@
1/* Copyright 2020 Drashna Jael're <drashna@live.com>
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17
18
19#include "drashna.h"
20
21#ifndef UNICODE_ENABLE
22# define UC(x) KC_NO
23#endif
24
25enum more_custom_keycodes { KC_SWAP_NUM = NEW_SAFE_RANGE };
26
27// clang-format off
28#define LAYOUT_moonlander_wrapper(...) LAYOUT_moonlander(__VA_ARGS__)
29
30#define LAYOUT_moonlander_base( \
31 K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, \
32 K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, \
33 K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A \
34 ) \
35 LAYOUT_moonlander_wrapper( \
36 KC_ESC, ________________NUMBER_LEFT________________, UC_FLIP, UC_TABL, ________________NUMBER_RIGHT_______________, KC_MINS, \
37 KC_TAB, K01, K02, K03, K04, K05, TG(_DIABLO),TG(_DIABLO), K06, K07, K08, K09, K0A, KC_BSLS, \
38 KC_C1R3, K11, K12, K13, K14, K15, TG(_GAMEPAD),TG(_GAMEPAD), K16, K17, K18, K19, K1A, RALT_T(KC_QUOT), \
39 KC_MLSF, CTL_T(K21), K22, K23, K24, K25, K26, K27, K28, K29, RCTL_T(K2A),KC_MRSF, \
40 KC_GRV, OS_MEH, OS_HYPR, KC_LBRC, KC_RBRC, KC_NO, KC_DEL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, UC(0x2E2E), \
41 KC_SPC, BK_LWER, OS_LALT, OS_RGUI, DL_RAIS, KC_ENT \
42 )
43
44#define LAYOUT_moonlander_base_wrapper(...) LAYOUT_moonlander_base(__VA_ARGS__)
45
46const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
47
48 [_QWERTY] = LAYOUT_moonlander_base_wrapper(
49 _________________QWERTY_L1_________________, _________________QWERTY_R1_________________,
50 _________________QWERTY_L2_________________, _________________QWERTY_R2_________________,
51 _________________QWERTY_L3_________________, _________________QWERTY_R3_________________
52 ),
53
54 [_COLEMAK] = LAYOUT_moonlander_base_wrapper(
55 _________________COLEMAK_L1________________, _________________COLEMAK_R1________________,
56 _________________COLEMAK_L2________________, _________________COLEMAK_R2________________,
57 _________________COLEMAK_L3________________, _________________COLEMAK_R3________________
58 ),
59
60 [_DVORAK] = LAYOUT_moonlander_base_wrapper(
61 _________________DVORAK_L1_________________, _________________DVORAK_R1_________________,
62 _________________DVORAK_L2_________________, _________________DVORAK_R2_________________,
63 _________________DVORAK_L3_________________, _________________DVORAK_R3_________________
64 ),
65
66 [_WORKMAN] = LAYOUT_moonlander_base_wrapper(
67 _________________WORKMAN_L1________________, _________________WORKMAN_R1________________,
68 _________________WORKMAN_L2________________, _________________WORKMAN_R2________________,
69 _________________WORKMAN_L3________________, _________________WORKMAN_R3________________
70 ),
71
72 [_NORMAN] = LAYOUT_moonlander_base_wrapper(
73 _________________NORMAN_L1_________________, _________________NORMAN_L1_________________,
74 _________________NORMAN_L2_________________, _________________NORMAN_R2_________________,
75 _________________NORMAN_L3_________________, _________________NORMAN_R3_________________
76 ),
77
78 [_MALTRON] = LAYOUT_moonlander_base_wrapper(
79 _________________MALTRON_L1________________, _________________MALTRON_R1________________,
80 _________________MALTRON_L2________________, _________________MALTRON_R2________________,
81 _________________MALTRON_L3________________, _________________MALTRON_R3________________
82 ),
83
84 [_EUCALYN] = LAYOUT_moonlander_base_wrapper(
85 _________________EUCALYN_L1________________, _________________EUCALYN_R1________________,
86 _________________EUCALYN_L2________________, _________________EUCALYN_R2________________,
87 _________________EUCALYN_L3________________, _________________EUCALYN_R3________________
88 ),
89
90 [_CARPLAX] = LAYOUT_moonlander_base_wrapper(
91 _____________CARPLAX_QFMLWY_L1_____________, _____________CARPLAX_QFMLWY_R1_____________,
92 _____________CARPLAX_QFMLWY_L2_____________, _____________CARPLAX_QFMLWY_R2_____________,
93 _____________CARPLAX_QFMLWY_L3_____________, _____________CARPLAX_QFMLWY_R3_____________
94 ),
95
96#ifdef _MODS
97 [_MODS] = LAYOUT_moonlander_wrapper(
98 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
99 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
100 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
101 KC_LSFT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_RSFT,
102 _______, KC_MEH, KC_HYPR, _______, _______, _______, _______, _______, _______, _______, _______, _______,
103 KC_LALT, _______, _______, _______, _______, KC_RGUI
104 ),
105#endif
106
107 [_GAMEPAD] = LAYOUT_moonlander_wrapper(
108 KC_ESC, KC_NO, KC_1, KC_2, KC_3, KC_4, HYPR(KC_Q), KC_TRNS, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO,
109 KC_F1, KC_K, KC_Q, KC_W, KC_E, KC_R, KC_T, UC_SHRG, UC_DISA, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
110 KC_TAB, KC_G, KC_A, KC_S, KC_D, KC_F, KC_TRNS, TG(_GAMEPAD), KC_I, KC_O, KC_NO, KC_NO, KC_NO, KC_NO,
111 KC_LCTL, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_N, KC_M, KC_NO, KC_NO, KC_NO, KC_NO,
112 KC_GRV, KC_U, KC_I, KC_Y, KC_T, KC_PSCR, _______, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_NO,
113 KC_V, KC_SPC, KC_H, KC_NO, KC_NO, KC_SWAP_NUM
114 ),
115 [_DIABLO] = LAYOUT_moonlander_wrapper(
116 KC_ESC, KC_V, KC_D, KC_LALT, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO,
117 KC_TAB, KC_S, KC_I, KC_F, KC_M, KC_T, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
118 KC_NO, KC_1, KC_2, KC_3, KC_4, KC_G, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
119 KC_LCTL, KC_D3_1, KC_D3_2, KC_D3_3, KC_D3_4, KC_Z, KC_N, KC_M, KC_NO, KC_NO, KC_NO, KC_NO,
120 KC_NO, KC_NO, KC_L, KC_J, KC_F, KC_PSCR, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
121 KC_DIABLO_CLEAR, SFT_T(KC_SPACE), ALT_T(KC_Q), KC_PGDN, KC_DEL, KC_ENT
122 ),
123
124 [_LOWER] = LAYOUT_moonlander_wrapper(
125 KC_F12, _________________FUNC_LEFT_________________, _______, _______, _________________FUNC_RIGHT________________, KC_F11,
126 _______, _________________LOWER_L1__________________, _______, _______, _________________LOWER_R1__________________, KC_PIPE,
127 _______, _________________LOWER_L2__________________, _______, _______, _________________LOWER_R2__________________, KC_DQUO,
128 _______, _________________LOWER_L3__________________, _________________LOWER_R3__________________, KC_PSCR,
129 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PAUS,
130 _______, _______, _______, _______, _______, _______
131 ),
132
133 [_RAISE] = LAYOUT_moonlander_wrapper(
134 KC_F12, _________________FUNC_LEFT_________________, _______, _______, _________________FUNC_RIGHT________________, KC_F11,
135 _______, _________________RAISE_L1__________________, _______, _______, _________________RAISE_R1__________________, KC_BSLS,
136 _______, _________________RAISE_L2__________________, _______, _______, _________________RAISE_R2__________________, KC_QUOT,
137 _______, _________________RAISE_L3__________________, _________________RAISE_R3__________________, KC_PSCR,
138 _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END, KC_PAUS,
139 _______, _______, _______, _______, _______, _______
140 ),
141
142 [_ADJUST] = LAYOUT_moonlander_wrapper(
143 KC_MAKE, _________________FUNC_LEFT_________________, UC_MOD, KC_NUKE, _________________ADJUST_R1_________________, KC_RST,
144 VRSN, _________________ADJUST_L1_________________, _______, _______, _________________ADJUST_R1_________________, EEP_RST,
145 _______, _________________ADJUST_L2_________________, _______, _______, _________________ADJUST_R2_________________, RGB_IDL,
146 _______, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS,
147 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PAUS,
148 _______, _______, _______, _______, _______, _______
149 ),
150};
151
152/* Blank
153
154 [_LAYER] = LAYOUT_moonlander_wrapper(
155 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
156 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
157 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
158 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
159 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
160 _______, _______, _______, _______, _______, _______
161 ),
162
163*/
164
165
166bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
167 switch (keycode) {
168 case KC_1:
169 if (layer_state_is(_GAMEPAD) && userspace_config.swapped_numbers) {
170 if (record->event.pressed) {
171 register_code(KC_2);
172 } else {
173 unregister_code(KC_2);
174 }
175 return false;
176 }
177 break;
178 case KC_2:
179 if (layer_state_is(_GAMEPAD) && userspace_config.swapped_numbers) {
180 if (record->event.pressed) {
181 register_code(KC_1);
182 } else {
183 unregister_code(KC_1);
184 }
185 return false;
186 }
187 break;
188 case KC_SWAP_NUM:
189 if (record->event.pressed) {
190 userspace_config.swapped_numbers ^= 1;
191 eeconfig_update_user(userspace_config.raw);
192 unregister_code(KC_1);
193 unregister_code(KC_2);
194 }
195 break;
196 }
197 return true;
198}
199
200#ifdef RGB_MATRIX_ENABLE
201# ifndef RGB_MATRIX_INDICATOR_SET_COLOR
202# define RGB_MATRIX_INDICATOR_SET_COLOR(i, r, g, b) rgb_matrix_set_color(i, r, g, b)
203void rgb_matrix_indicators_user(void) {
204 #else
205void rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
206# endif
207 if (g_suspend_state || !rgb_matrix_config.enable) return;
208
209 if (layer_state_is(_GAMEPAD)) {
210 RGB_MATRIX_INDICATOR_SET_COLOR(11, 0x00, 0xFF, 0x00); // Q
211 RGB_MATRIX_INDICATOR_SET_COLOR(16, 0x00, 0xFF, 0xFF); // W
212 RGB_MATRIX_INDICATOR_SET_COLOR(21, 0xFF, 0x00, 0x00); // E
213 RGB_MATRIX_INDICATOR_SET_COLOR(26, 0xFF, 0x80, 0x00); // R
214 RGB_MATRIX_INDICATOR_SET_COLOR(12, 0x00, 0xFF, 0xFF); // A
215 RGB_MATRIX_INDICATOR_SET_COLOR(17, 0x00, 0xFF, 0xFF); // S
216 RGB_MATRIX_INDICATOR_SET_COLOR(22, 0x00, 0xFF, 0xFF); // D
217 RGB_MATRIX_INDICATOR_SET_COLOR(27, 0x7A, 0x00, 0xFF); // F
218
219 RGB_MATRIX_INDICATOR_SET_COLOR((userspace_config.swapped_numbers ? 10 : 15), 0xFF, 0xFF, 0xFF); // 1
220 RGB_MATRIX_INDICATOR_SET_COLOR((userspace_config.swapped_numbers ? 15 : 10), 0x00, 0xFF, 0x00); // 2
221 RGB_MATRIX_INDICATOR_SET_COLOR(20, 0x7A, 0x00, 0xFF); // 3
222 }
223
224 if (userspace_config.rgb_layer_change) {
225 switch (get_highest_layer(layer_state|default_layer_state)) {
226 case _QWERTY:
227 rgb_matrix_layer_helper(HSV_CYAN, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
228 break;
229 case _COLEMAK:
230 rgb_matrix_layer_helper(HSV_MAGENTA, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
231 break;
232 case _DVORAK:
233 rgb_matrix_layer_helper(HSV_SPRINGGREEN, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
234 break;
235 case _WORKMAN:
236 rgb_matrix_layer_helper(HSV_GOLDENROD, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
237 break;
238 case _NORMAN:
239 rgb_matrix_layer_helper(HSV_CORAL, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
240 break;
241 case _MALTRON:
242 rgb_matrix_layer_helper(HSV_YELLOW, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
243 break;
244 case _EUCALYN:
245 rgb_matrix_layer_helper(HSV_PINK, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
246 break;
247 case _CARPLAX:
248 rgb_matrix_layer_helper(HSV_BLUE, 0, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
249 break;
250 case _GAMEPAD:
251 rgb_matrix_layer_helper(HSV_ORANGE, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
252 break;
253 case _DIABLO:
254 rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed * 8, LED_FLAG_MODIFIER);
255 break;
256 case _RAISE:
257 rgb_matrix_layer_helper(HSV_YELLOW, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
258 break;
259 case _LOWER:
260 rgb_matrix_layer_helper(HSV_GREEN, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
261 break;
262 case _ADJUST:
263 rgb_matrix_layer_helper(HSV_RED, 1, rgb_matrix_config.speed, LED_FLAG_MODIFIER);
264 break;
265 }
266 }
267}
268#endif
269
270#ifdef TAPPING_TERM_PER_KEY
271uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
272 if (keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) {
273 if (mod_config(keycode & 0xf) & MOD_MASK_ALT) {
274 return (2 * TAPPING_TERM);
275 }
276 }
277 return TAPPING_TERM;
278}
279#endif
diff --git a/keyboards/moonlander/keymaps/drashna/rules.mk b/keyboards/moonlander/keymaps/drashna/rules.mk
new file mode 100644
index 000000000..480e97446
--- /dev/null
+++ b/keyboards/moonlander/keymaps/drashna/rules.mk
@@ -0,0 +1,4 @@
1TAP_DANCE_ENABLE = yes
2BOOTMAGIC_ENABLE = lite
3UNICODE_ENABLE = yes
4UNICODEMAP_ENABLE = no
diff --git a/keyboards/moonlander/matrix.c b/keyboards/moonlander/matrix.c
new file mode 100644
index 000000000..774b01187
--- /dev/null
+++ b/keyboards/moonlander/matrix.c
@@ -0,0 +1,270 @@
1/* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
2 * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
3 * Copyright 2020 Drashna Jael're <drashna@live.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19
20
21#include <stdint.h>
22#include <stdbool.h>
23#include <string.h>
24#include "hal.h"
25#include "timer.h"
26#include "wait.h"
27#include "printf.h"
28#include "matrix.h"
29#include "action.h"
30#include "keycode.h"
31#include <string.h>
32#include "moonlander.h"
33#include "i2c_master.h"
34#include "debounce.h"
35
36/*
37#define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 } outputs
38#define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 } inputs
39 */
40/* matrix state(1:on, 0:off) */
41static matrix_row_t matrix[MATRIX_ROWS];
42static matrix_row_t matrix_debouncing[MATRIX_ROWS];
43static matrix_row_t matrix_debouncing_right[MATRIX_COLS];
44static bool debouncing = false;
45static uint16_t debouncing_time = 0;
46static bool debouncing_right = false;
47static uint16_t debouncing_time_right = 0;
48
49#define ROWS_PER_HAND (MATRIX_ROWS / 2)
50
51#ifndef MATRIX_IO_DELAY
52# define MATRIX_IO_DELAY 20
53#endif
54
55extern bool mcp23018_leds[3];
56extern bool is_launching;
57
58__attribute__((weak)) void matrix_init_user(void) {}
59
60__attribute__((weak)) void matrix_scan_user(void) {}
61
62__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
63
64__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
65
66__attribute__((weak)) void matrix_io_delay(void) { wait_us(MATRIX_IO_DELAY); }
67
68bool mcp23018_initd = false;
69static uint8_t mcp23018_reset_loop;
70
71uint8_t mcp23018_tx[3];
72uint8_t mcp23018_rx[1];
73
74void mcp23018_init(void) {
75 i2c_init();
76
77 // #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs
78 // #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs
79
80 mcp23018_tx[0] = 0x00; // IODIRA
81 mcp23018_tx[1] = 0b00000000; // A is output
82 mcp23018_tx[2] = 0b00111111; // B is inputs
83
84 if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) {
85 printf("error hori\n");
86 } else {
87 mcp23018_tx[0] = 0x0C; // GPPUA
88 mcp23018_tx[1] = 0b10000000; // A is not pulled-up
89 mcp23018_tx[2] = 0b11111111; // B is pulled-up
90
91 if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) {
92 printf("error hori\n");
93 } else {
94 mcp23018_initd = is_launching = true;
95 }
96 }
97}
98
99void matrix_init(void) {
100 printf("matrix init\n");
101 // debug_matrix = true;
102
103 // outputs
104 setPinOutput(B10);
105 setPinOutput(B11);
106 setPinOutput(B12);
107 setPinOutput(B13);
108 setPinOutput(B14);
109 setPinOutput(B15);
110
111 // inputs
112 setPinInputLow(A0);
113 setPinInputLow(A1);
114 setPinInputLow(A2);
115 setPinInputLow(A3);
116 setPinInputLow(A6);
117 setPinInputLow(A7);
118 setPinInputLow(B0);
119
120 memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t));
121 memset(matrix_debouncing, 0, MATRIX_ROWS * sizeof(matrix_row_t));
122 memset(matrix_debouncing_right, 0, MATRIX_COLS * sizeof(matrix_row_t));
123
124 mcp23018_init();
125
126 matrix_init_quantum();
127}
128
129uint8_t matrix_scan(void) {
130 bool changed = false;
131
132 matrix_row_t data = 0;
133 // actual matrix
134 for (uint8_t row = 0; row < ROWS_PER_HAND; row++) {
135 // strobe row
136 switch (row) {
137 case 0: writePinHigh(B10); break;
138 case 1: writePinHigh(B11); break;
139 case 2: writePinHigh(B12); break;
140 case 3: writePinHigh(B13); break;
141 case 4: writePinHigh(B14); break;
142 case 5: writePinHigh(B15); break;
143 }
144
145 // need wait to settle pin state
146 matrix_io_delay();
147
148 // read col data
149 data = (
150 (readPin(A0) << 0 ) |
151 (readPin(A1) << 1 ) |
152 (readPin(A2) << 2 ) |
153 (readPin(A3) << 3 ) |
154 (readPin(A6) << 4 ) |
155 (readPin(A7) << 5 ) |
156 (readPin(B0) << 6 )
157 );
158
159 // unstrobe row
160 switch (row) {
161 case 0: writePinLow(B10); break;
162 case 1: writePinLow(B11); break;
163 case 2: writePinLow(B12); break;
164 case 3: writePinLow(B13); break;
165 case 4: writePinLow(B14); break;
166 case 5: writePinLow(B15); break;
167 }
168
169 if (matrix_debouncing[row] != data) {
170 matrix_debouncing[row] = data;
171 debouncing = true;
172 debouncing_time = timer_read();
173 changed = true;
174 }
175 }
176
177 for (uint8_t row = 0; row <= ROWS_PER_HAND; row++) {
178 // right side
179
180 if (!mcp23018_initd) {
181 if (++mcp23018_reset_loop == 0) {
182 // if (++mcp23018_reset_loop >= 1300) {
183 // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
184 // this will be approx bit more frequent than once per second
185 print("trying to reset mcp23018\n");
186 mcp23018_init();
187 if (!mcp23018_initd) {
188 print("left side not responding\n");
189 } else {
190 print("left side attached\n");
191#ifdef RGB_MATRIX_ENABLE
192 rgb_matrix_init();
193#endif
194 }
195 }
196 }
197
198 // #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs
199 // #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs
200
201 // select row
202
203 mcp23018_tx[0] = 0x12; // GPIOA
204 mcp23018_tx[1] = (0b01111111 & ~(1 << (row))) | ((uint8_t)!mcp23018_leds[2] << 7); // activate row
205 mcp23018_tx[2] = ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7); // activate row
206
207 if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, I2C_TIMEOUT)) {
208 printf("error hori\n");
209 mcp23018_initd = false;
210 }
211
212 // read col
213
214 mcp23018_tx[0] = 0x13; // GPIOB
215 if (MSG_OK != i2c_readReg(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx[0], &mcp23018_rx[0], 1, I2C_TIMEOUT)) {
216 printf("error vert\n");
217 mcp23018_initd = false;
218 }
219
220 data = ~(mcp23018_rx[0] & 0b00111111);
221 // data = 0x01;
222
223 if (matrix_debouncing_right[row] != data) {
224 matrix_debouncing_right[row] = data;
225 debouncing_right = true;
226 debouncing_time_right = timer_read();
227 changed = true;
228 }
229 }
230
231 if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
232 for (int row = 0; row < ROWS_PER_HAND; row++) {
233 matrix[row] = matrix_debouncing[row];
234 }
235 debouncing = false;
236 }
237
238 if (debouncing_right && timer_elapsed(debouncing_time_right) > DEBOUNCE && mcp23018_initd) {
239 for (int row = 0; row < ROWS_PER_HAND; row++) {
240 matrix[11 - row] = 0;
241 for (int col = 0; col < MATRIX_COLS; col++) {
242 matrix[11 - row] |= ((matrix_debouncing_right[6 - col] & (1 << row) ? 1 : 0) << col);
243 }
244 }
245 debouncing_right = false;
246 }
247
248 matrix_scan_quantum();
249
250 return (uint8_t)changed;
251}
252
253bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & (1 << col)); }
254
255matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; }
256
257void matrix_print(void) {
258 printf("\nr/c 01234567\n");
259 for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
260 printf("%X0: ", row);
261 matrix_row_t data = matrix_get_row(row);
262 for (int col = 0; col < MATRIX_COLS; col++) {
263 if (data & (1 << col))
264 printf("1");
265 else
266 printf("0");
267 }
268 printf("\n");
269 }
270}
diff --git a/keyboards/moonlander/moonlander.c b/keyboards/moonlander/moonlander.c
new file mode 100644
index 000000000..403e6aef8
--- /dev/null
+++ b/keyboards/moonlander/moonlander.c
@@ -0,0 +1,466 @@
1/* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
2 * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
3 * Copyright 2020 Drashna Jael're <drashna@live.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19
20
21#include "moonlander.h"
22#ifdef WEBUSB_ENABLE
23# include "webusb.h"
24#endif
25
26keyboard_config_t keyboard_config;
27
28bool mcp23018_leds[3] = {0, 0, 0};
29bool is_launching = false;
30
31#ifdef DYNAMIC_MACRO_ENABLE
32static bool is_dynamic_recording = false;
33
34void dynamic_macro_record_start_user(void) { is_dynamic_recording = true; }
35
36void dynamic_macro_record_end_user(int8_t direction) {
37 is_dynamic_recording = false;
38 ML_LED_3(false);
39}
40#endif
41
42void moonlander_led_task(void) {
43 if (is_launching) {
44 ML_LED_1(false);
45 ML_LED_2(false);
46 ML_LED_3(false);
47 ML_LED_4(false);
48 ML_LED_5(false);
49 ML_LED_6(false);
50
51 ML_LED_1(true);
52 wait_ms(250);
53 ML_LED_2(true);
54 wait_ms(250);
55 ML_LED_3(true);
56 wait_ms(250);
57 ML_LED_4(true);
58 wait_ms(250);
59 ML_LED_5(true);
60 wait_ms(250);
61 ML_LED_6(true);
62 wait_ms(250);
63 ML_LED_1(false);
64 wait_ms(250);
65 ML_LED_2(false);
66 wait_ms(250);
67 ML_LED_3(false);
68 wait_ms(250);
69 ML_LED_4(false);
70 wait_ms(250);
71 ML_LED_5(false);
72 wait_ms(250);
73 ML_LED_6(false);
74 wait_ms(250);
75 is_launching = false;
76 layer_state_set_kb(layer_state);
77 }
78#ifdef DYNAMIC_MACRO_ENABLE
79 else if (is_dynamic_recording) {
80 ML_LED_3(true);
81 wait_ms(100);
82 ML_LED_3(false);
83 wait_ms(155);
84 }
85#endif
86#ifdef WEBUSB_ENABLE
87 else if (webusb_state.pairing == true) {
88 static uint8_t led_mask;
89
90 ML_LED_1(false);
91 ML_LED_2(false);
92 ML_LED_3(false);
93 ML_LED_4(false);
94 ML_LED_5(false);
95 ML_LED_6(false);
96
97 if (!led_mask) {
98 led_mask = 1;
99 } else {
100 led_mask++;
101 if (led_mask > 12) led_mask = 1;
102 }
103 switch (led_mask) {
104 case 1:
105 case 12:
106 ML_LED_1(true);
107 break;
108 case 2:
109 case 11:
110 ML_LED_2(true);
111 break;
112 case 3:
113 case 10:
114 ML_LED_3(true);
115 break;
116 case 4:
117 case 9:
118 ML_LED_4(true);
119 break;
120 case 5:
121 case 8:
122 ML_LED_5(true);
123 break;
124 case 6:
125 case 7:
126 ML_LED_6(true);
127 break;
128 }
129 wait_ms(150);
130 }
131#endif
132}
133
134static THD_WORKING_AREA(waLEDThread, 128);
135static THD_FUNCTION(LEDThread, arg) {
136 (void)arg;
137 chRegSetThreadName("LEDThread");
138 while (true) {
139 moonlander_led_task();
140 }
141}
142
143void keyboard_pre_init_kb(void) {
144 setPinOutput(B5);
145 setPinOutput(B4);
146 setPinOutput(B3);
147
148 writePinLow(B5);
149 writePinLow(B4);
150 writePinLow(B3);
151
152 chThdCreateStatic(waLEDThread, sizeof(waLEDThread), NORMALPRIO - 16, LEDThread, NULL);
153
154 /* the array is initialized to 0, no need to re-set it here */
155 // mcp23018_leds[0] = 0; // blue
156 // mcp23018_leds[1] = 0; // green
157 // mcp23018_leds[2] = 0; // red
158
159 keyboard_pre_init_user();
160}
161
162#ifdef ORYX_CONFIGURATOR
163layer_state_t layer_state_set_kb(layer_state_t state) {
164 state = layer_state_set_user(state);
165 if (is_launching) return state;
166
167 ML_LED_1(false);
168 ML_LED_2(false);
169 ML_LED_3(false);
170 ML_LED_4(false);
171 ML_LED_5(false);
172 ML_LED_6(false);
173
174 uint8_t layer = get_highest_layer(state);
175 switch (layer) {
176 case 1:
177 ML_LED_1(1);
178 ML_LED_4(1);
179 break;
180 case 2:
181 ML_LED_2(1);
182 ML_LED_5(1);
183 break;
184 case 3:
185 ML_LED_3(1);
186 break;
187 case 4:
188 ML_LED_4(1);
189 break;
190 case 5:
191 ML_LED_5(1);
192 break;
193 case 6:
194 ML_LED_6(1);
195 break;
196 default:
197 break;
198 }
199
200 return state;
201}
202#endif
203
204#ifdef RGB_MATRIX_ENABLE
205// clang-format off
206const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
207/* Refer to IS31 manual for these locations
208 * driver
209 * | R location
210 * | | G location
211 * | | | B location
212 * | | | | */
213 {0, C3_2, C1_1, C4_2}, // 1
214 {0, C2_2, C1_2, C4_3},
215 {0, C2_3, C1_3, C3_3},
216 {0, C2_4, C1_4, C3_4},
217 {0, C2_5, C1_5, C3_5},
218 {0, C2_6, C1_6, C3_6},
219 {0, C2_7, C1_7, C3_7},
220 {0, C2_8, C1_8, C3_8},
221 {0, C3_1, C2_1, C4_1},
222
223 {0, C7_8, C6_8, C8_8}, // 10
224 {0, C7_7, C6_7, C9_8},
225 {0, C8_7, C6_6, C9_7},
226 {0, C8_6, C7_6, C9_6},
227 {0, C8_5, C7_5, C9_5},
228 {0, C8_4, C7_4, C9_4},
229 {0, C8_3, C7_3, C9_3},
230 {0, C8_2, C7_2, C9_2},
231 {0, C8_1, C7_1, C9_1},
232
233 {0, C3_10, C1_9, C4_10}, // 19
234 {0, C2_10, C1_10, C4_11},
235 {0, C2_11, C1_11, C3_11},
236 {0, C2_12, C1_12, C3_12},
237 {0, C2_13, C1_13, C3_13},
238 {0, C2_14, C1_14, C3_14},
239 {0, C2_15, C1_15, C3_15},
240 {0, C2_16, C1_16, C3_16},
241 {0, C3_9, C2_9, C4_9},
242
243 {0, C7_16, C6_16, C8_16}, // 28
244 {0, C7_15, C6_15, C9_16},
245 {0, C8_15, C6_14, C9_15},
246 {0, C8_10, C7_10, C9_10},
247 {0, C8_9, C7_9, C9_9},
248 {0, C8_11, C7_11, C9_11},
249 {0, C8_12, C7_12, C9_12},
250 {0, C8_13, C7_13, C9_13},
251 {0, C8_14, C7_14, C9_14},
252
253 {1, C3_2, C1_1, C4_2}, // 1
254 {1, C2_2, C1_2, C4_3},
255 {1, C2_3, C1_3, C3_3},
256 {1, C2_4, C1_4, C3_4},
257 {1, C2_5, C1_5, C3_5},
258 {1, C2_6, C1_6, C3_6},
259 {1, C2_7, C1_7, C3_7},
260 {1, C2_8, C1_8, C3_8},
261 {1, C3_1, C2_1, C4_1},
262
263 {1, C7_8, C6_8, C8_8}, // 10
264 {1, C7_7, C6_7, C9_8},
265 {1, C8_7, C6_6, C9_7},
266 {1, C8_6, C7_6, C9_6},
267 {1, C8_5, C7_5, C9_5},
268 {1, C8_4, C7_4, C9_4},
269 {1, C8_3, C7_3, C9_3},
270 {1, C8_2, C7_2, C9_2},
271 {1, C8_1, C7_1, C9_1},
272
273 {1, C3_10, C1_9, C4_10}, // 19
274 {1, C2_10, C1_10, C4_11},
275 {1, C2_11, C1_11, C3_11},
276 {1, C2_12, C1_12, C3_12},
277 {1, C2_13, C1_13, C3_13},
278 {1, C2_14, C1_14, C3_14},
279 {1, C2_15, C1_15, C3_15},
280 {1, C2_16, C1_16, C3_16},
281 {1, C3_9, C2_9, C4_9},
282
283 {1, C7_16, C6_16, C8_16}, // 28
284 {1, C7_15, C6_15, C9_16},
285 {1, C8_15, C6_14, C9_15},
286 {1, C8_10, C7_10, C9_10},
287 {1, C8_9, C7_9, C9_9},
288 {1, C8_11, C7_11, C9_11},
289 {1, C8_12, C7_12, C9_12},
290 {1, C8_13, C7_13, C9_13},
291 {1, C8_14, C7_14, C9_14},
292
293};
294
295led_config_t g_led_config = { {
296 { 0, 5, 10, 15, 20, 25, 29 },
297 { 1, 6, 11, 16, 21, 26, 30 },
298 { 2, 7, 12, 17, 22, 27, 31 },
299 { 3, 8, 13, 18, 23, 28, NO_LED },
300 { 4, 9, 14, 19, 24, NO_LED, NO_LED },
301 { 32, 33, 34, 35, NO_LED, NO_LED, NO_LED },
302 { 65, 61, 56, 51, 46, 41, 36 },
303 { 66, 62, 57, 52, 47, 42, 37 },
304 { 67, 63, 58, 53, 48, 43, 38 },
305 { NO_LED, 64, 59, 54, 49, 44, 39 },
306 { NO_LED, NO_LED, 60, 55, 50, 45, 40 },
307 { NO_LED, NO_LED, NO_LED, 71, 70, 69, 68 },
308}, {
309 { 0, 0 }, { 0, 12 }, { 0, 25 }, { 0, 38 }, { 0, 51 },
310 { 17, 0 }, { 17, 12 }, { 17, 25 }, { 17, 38 }, { 17, 51 },
311 { 34, 0 }, { 34, 12 }, { 34, 25 }, { 34, 38 }, { 34, 51 },
312 { 51, 0 }, { 51, 12 }, { 51, 25 }, { 51, 38 }, { 51, 51 },
313 { 68, 0 }, { 68, 12 }, { 68, 25 }, { 68, 38 }, { 68, 51 },
314 { 86, 0 }, { 86, 12 }, { 86, 25 }, { 86, 38 },
315 { 105, 0 }, { 105, 12 }, { 105, 25 },
316 { 90, 55 }, { 105, 68 }, { 116, 86 }, { 116, 59 },
317
318 { 250, 0 }, { 250, 12 }, { 250, 25 }, { 250, 38 }, { 250, 51 },
319 { 233, 0 }, { 233, 12 }, { 233, 25 }, { 233, 38 }, { 233, 51 },
320 { 216, 0 }, { 216, 12 }, { 216, 25 }, { 216, 38 }, { 216, 51 },
321 { 198, 0 }, { 198, 12 }, { 198, 25 }, { 198, 38 }, { 198, 51 },
322 { 181, 0 }, { 181, 12 }, { 181, 25 }, { 181, 38 }, { 181, 51 },
323 { 163, 0 }, { 163, 12 }, { 163, 25 }, { 163, 38 },
324 { 146, 0 }, { 146, 12 }, { 146, 25 },
325 { 161, 55 }, { 161, 68 }, { 146, 86 }, { 131, 59 }
326
327}, {
328 1, 1, 1, 1, 1, 4,
329 4, 4, 4, 1, 4, 4,
330 4, 4, 1, 4, 4, 4,
331 4, 1, 4, 4, 4, 4,
332 1, 4, 4, 4, 4, 4,
333 4, 4, 1, 1, 1, 1,
334 1, 1, 1, 1, 1, 4,
335 4, 4, 4, 1, 4, 4,
336 4, 4, 1, 4, 4, 4,
337 4, 1, 4, 4, 4, 4,
338 1, 4, 4, 4, 4, 4,
339 4, 4, 1, 1, 1, 1
340} };
341// clang-format on
342
343void suspend_power_down_kb(void) {
344 rgb_matrix_set_suspend_state(true);
345 suspend_power_down_user();
346}
347
348void suspend_wakeup_init_kb(void) {
349 rgb_matrix_set_suspend_state(false);
350 suspend_wakeup_init_user();
351}
352#endif
353
354#ifdef AUDIO_ENABLE
355bool music_mask_kb(uint16_t keycode) {
356 switch (keycode) {
357 case QK_LAYER_TAP ... QK_ONE_SHOT_LAYER_MAX:
358 case QK_LAYER_TAP_TOGGLE ... QK_LAYER_MOD_MAX:
359 case QK_MOD_TAP ... QK_MOD_TAP_MAX:
360 case AU_ON ... MUV_DE:
361 case RESET:
362 case EEP_RST:
363 return false;
364 default:
365 return music_mask_user(keycode);
366 }
367}
368#endif
369
370#ifdef SWAP_HANDS_ENABLE
371// swap-hands action needs a matrix to define the swap
372// clang-format off
373const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
374 /* Left hand, matrix positions */
375 {{6,6}, {5,6}, {4,6}, {3,6}, {2,6}, {1,6},{0,6}},
376 {{6,7}, {5,7}, {4,7}, {3,7}, {2,7}, {1,7},{0,7}},
377 {{6,8}, {5,8}, {4,8}, {3,8}, {2,8}, {1,8},{0,8}},
378 {{6,9}, {5,9}, {4,9}, {3,9}, {2,9}, {1,9},{0,9}},
379 {{6,10},{5,10},{4,10},{3,10},{2,10},{1,10},{0,10}},
380 {{6,11},{5,11},{4,11},{3,11},{2,11},{1,11},{0,11}},
381 /* Right hand, matrix positions */
382 {{6,0}, {5,0}, {4,0}, {3,0}, {2,0}, {1,0},{0,0}},
383 {{6,1}, {5,1}, {4,1}, {3,1}, {2,1}, {1,1},{0,1}},
384 {{6,2}, {5,2}, {4,2}, {3,2}, {2,2}, {1,2},{0,2}},
385 {{6,3}, {5,3}, {4,3}, {3,3}, {2,3}, {1,3},{0,3}},
386 {{6,4}, {5,4}, {4,4}, {3,4}, {2,4}, {1,4},{0,4}},
387 {{6,5}, {5,5}, {4,5}, {3,5}, {2,5}, {1,5},{0,5}},
388};
389// clang-format on
390
391void keyboard_post_init_kb(void) {
392 rgb_matrix_enable_noeeprom();
393 keyboard_post_init_user();
394}
395#endif
396
397#if defined(AUDIO_ENABLE) && defined(MUSIC_MAP)
398// clang-format off
399const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS] = LAYOUT_moonlander(
400 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
401 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
402 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
403 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
404 8, 9, 10, 11, 12, 3, 4, 13, 14, 15, 16, 17,
405 0, 1, 2, 5, 6, 7
406);
407// clang-format on
408#endif
409
410#ifdef ORYX_CONFIGURATOR
411bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
412 switch (keycode) {
413#ifdef WEBUSB_ENABLE
414 case WEBUSB_PAIR:
415 if (!record->event.pressed && !webusb_state.pairing) layer_state_set_kb(layer_state);
416 break;
417#endif
418#ifdef RGB_MATRIX_ENABLE
419 case TOGGLE_LAYER_COLOR:
420 if (record->event.pressed) {
421 keyboard_config.disable_layer_led ^= 1;
422 if (keyboard_config.disable_layer_led) rgb_matrix_set_color_all(0, 0, 0);
423 eeconfig_update_kb(keyboard_config.raw);
424 }
425 break;
426 case RGB_TOG:
427 if (record->event.pressed) {
428 switch (rgb_matrix_get_flags()) {
429 case LED_FLAG_ALL: {
430 rgb_matrix_set_flags(LED_FLAG_NONE);
431 keyboard_config.rgb_matrix_enable = false;
432 rgb_matrix_set_color_all(0, 0, 0);
433 } break;
434 default: {
435 rgb_matrix_set_flags(LED_FLAG_ALL);
436 keyboard_config.rgb_matrix_enable = true;
437 } break;
438 }
439 eeconfig_update_kb(keyboard_config.raw);
440 }
441 return false;
442#endif
443 }
444 return process_record_user(keycode, record);
445}
446
447#endif
448
449void matrix_init_kb(void) {
450 keyboard_config.raw = eeconfig_read_kb();
451
452#ifdef RGB_MATRIX_ENABLE
453 if (keyboard_config.rgb_matrix_enable) {
454 rgb_matrix_set_flags(LED_FLAG_ALL);
455 } else {
456 rgb_matrix_set_flags(LED_FLAG_NONE);
457 }
458#endif
459}
460
461void eeconfig_init_kb(void) { // EEPROM is getting reset!
462 keyboard_config.raw = 0;
463 keyboard_config.rgb_matrix_enable = true;
464 eeconfig_update_kb(keyboard_config.raw);
465 eeconfig_init_user();
466}
diff --git a/keyboards/moonlander/moonlander.h b/keyboards/moonlander/moonlander.h
new file mode 100644
index 000000000..0e2dc880e
--- /dev/null
+++ b/keyboards/moonlander/moonlander.h
@@ -0,0 +1,81 @@
1/* Copyright 2020 ZSA Technology Labs, Inc <@zsa>
2 * Copyright 2020 Jack Humbert <jack.humb@gmail.com>
3 * Copyright 2020 Drashna Jael're <drashna@live.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19
20
21#pragma once
22
23#include "quantum.h"
24
25extern bool mcp23018_leds[];
26
27#define MCP23018_DEFAULT_ADDRESS 0b0100000
28
29#define ML_LED_1(status) writePin(B5, (bool)status)
30#define ML_LED_2(status) writePin(B4, (bool)status)
31#define ML_LED_3(status) writePin(B3, (bool)status)
32
33#define ML_LED_4(status) mcp23018_leds[0] = (bool)status
34#define ML_LED_5(status) mcp23018_leds[1] = (bool)status
35#define ML_LED_6(status) mcp23018_leds[2] = (bool)status
36
37
38// clang-format off
39#define LAYOUT_moonlander( \
40 k00, k01, k02, k03, k04, k05, k06, k60, k61, k62, k63, k64, k65, k66, \
41 k10, k11, k12, k13, k14, k15, k16, k70, k71, k72, k73, k74, k75, k76, \
42 k20, k21, k22, k23, k24, k25, k26, k80, k81, k82, k83, k84, k85, k86, \
43 k30, k31, k32, k33, k34, k35, k91, k92, k93, k94, k95, k96, \
44 k40, k41, k42, k43, k44, k53, kb3, ka2, ka3, ka4, ka5, ka6, \
45 k50, k51, k52, kb4, kb5, kb6 \
46) \
47{ \
48 { k00, k01, k02, k03, k04, k05, k06 }, \
49 { k10, k11, k12, k13, k14, k15, k16 }, \
50 { k20, k21, k22, k23, k24, k25, k26 }, \
51 { k30, k31, k32, k33, k34, k35, KC_NO }, \
52 { k40, k41, k42, k43, k44, KC_NO, KC_NO }, \
53 { k50, k51, k52, k53, KC_NO, KC_NO, KC_NO }, \
54\
55 { k60, k61, k62, k63, k64, k65, k66 }, \
56 { k70, k71, k72, k73, k74, k75, k76 }, \
57 { k80, k81, k82, k83, k84, k85, k86 }, \
58 { KC_NO,k91, k92, k93, k94, k95, k96 }, \
59 { KC_NO, KC_NO, ka2, ka3, ka4, ka5, ka6 }, \
60 { KC_NO, KC_NO, KC_NO, kb3, kb4, kb5, kb6 } \
61}
62// clang-format on
63
64enum planck_ez_keycodes {
65 TOGGLE_LAYER_COLOR = SAFE_RANGE,
66 ML_SAFE_RANGE,
67};
68
69#ifndef WEBUSB_ENABLE
70# define WEBUSB_PAIR KC_NO
71#endif
72
73typedef union {
74 uint32_t raw;
75 struct {
76 bool disable_layer_led :1;
77 bool rgb_matrix_enable :1;
78 };
79} keyboard_config_t;
80
81extern keyboard_config_t keyboard_config;
diff --git a/keyboards/moonlander/readme.md b/keyboards/moonlander/readme.md
new file mode 100644
index 000000000..7ddfdb84a
--- /dev/null
+++ b/keyboards/moonlander/readme.md
@@ -0,0 +1,28 @@
1# Moonlander
2
3![Moonlander](https://zsa.io/static/gallery-white-case-7a2ef555f8f7f4ce1b9030477b16e517.png)
4
5A next-gen split, ergonomic keyboard with an active left side, USB type C, integrated wrist rest, and a thumb cluster that can move.
6
7
8* Keyboard Maintainer: [drashna](https://github.com/drashna), [ZSA](https://github.com/zsa/)
9* Hardware Supported: Moonlander MK 1 (STM32F303xC)
10* Hardware Availability: [ZSA Store](https://zsa.io/moonlander/)
11
12Make example for this keyboard (after setting up your build environment):
13
14 make moonlander:default
15
16Flashing example for this keyboard:
17
18 make moonlander:default:flash
19
20See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
21
22## Oryx Configuation
23
24If you're using the Smart LED (layer indication) feature from the Oryx Configurator, you want to make sure that you enable these options by adding `#define ORYX_CONFIGURATOR` to your keymap's `config.h`.
25
26This changes the `RGB_TOG` keycode so that it will toggle the lights on and off, in a way that will allow the Smart LEDs to continue to work, even with the rest of the LEDs turned off.
27
28Additionally, a new keycode has been added to toggle the Smart LEDs. Use `TOGGLE_LAYER_COLOR`, if you aren't already.
diff --git a/keyboards/moonlander/rules.mk b/keyboards/moonlander/rules.mk
new file mode 100644
index 000000000..63e91fabb
--- /dev/null
+++ b/keyboards/moonlander/rules.mk
@@ -0,0 +1,29 @@
1# MCU name
2MCU = STM32F303
3
4# Build Options
5# change yes to no to disable
6#
7BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration
8MOUSEKEY_ENABLE = yes # Mouse keys
9EXTRAKEY_ENABLE = yes # Audio control and System control
10CONSOLE_ENABLE = yes # Console for debug
11COMMAND_ENABLE = yes # Commands for debug and configuration
12# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
13SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
14# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
15NKRO_ENABLE = yes # USB Nkey Rollover
16BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
17RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
18BLUETOOTH_ENABLE = no # Enable Bluetooth
19AUDIO_ENABLE = yes # Audio output
20CUSTOM_MATRIX = yes
21DEBOUNCE_TYPE = custom
22SWAP_HANDS_ENABLE = yes
23RGB_MATRIX_ENABLE = IS31FL3731
24#SERIAL_LINK_ENABLE = yes
25EEPROM_DRIVER = i2c
26
27#project specific files
28SRC += matrix.c
29QUANTUM_LIB_SRC += i2c_master.c