|
|
@@ -0,0 +1,232 @@
|
|
|
+/*
|
|
|
+ * Dan's Magicforce 68 (MF68) QMK Keyboard
|
|
|
+ * Copyright (C) Dan <https://github.com/delivrance>
|
|
|
+ *
|
|
|
+ * This file is part of Dan's MF68 QMK Keyboard.
|
|
|
+ *
|
|
|
+ * Dan's MF68 QMK Keyboard is free software: you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
|
+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
+ * (at your option) any later version.
|
|
|
+ *
|
|
|
+ * Dan's MF68 QMK Keyboard is distributed in the hope that it will be useful,
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+ * GNU General Public License for more details.
|
|
|
+ *
|
|
|
+ * You should have received a copy of the GNU General Public License
|
|
|
+ * along with Dan's MF68 QMK Keyboard. If not, see <https://www.gnu.org/licenses/>.
|
|
|
+ */
|
|
|
+
|
|
|
+#include QMK_KEYBOARD_H
|
|
|
+
|
|
|
+#define KC_ KC_TRNS
|
|
|
+
|
|
|
+#define KC_FN1 MO(_FN)
|
|
|
+#define KC_FN2 LT(_FN, KC_CAPS)
|
|
|
+
|
|
|
+#define KC_BLUP BL_INC // Backlight increase
|
|
|
+#define KC_BLDN BL_DEC // Backlight decrease
|
|
|
+#define KC_BLTOG BL_TOGG // Backlight toggle
|
|
|
+#define KC_TERM TERM_ON // Terminal mode on
|
|
|
+#define KC_REC1 DM_REC1 // Record macro 1
|
|
|
+#define KC_PLY1 DM_PLY1 // Play macro 1
|
|
|
+#define KC_REC2 DM_REC2 // Record macro 2
|
|
|
+#define KC_PLY2 DM_PLY2 // Play macro 1
|
|
|
+#define KC_RSTP DM_RSTP // Stop macro recording
|
|
|
+
|
|
|
+enum {
|
|
|
+ _QWERTY,
|
|
|
+ _FN
|
|
|
+};
|
|
|
+
|
|
|
+/* ┏━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━━━━━┓ ┏━━━━┳━━━━┓
|
|
|
+ ┃Esc ┃ 1! ┃ 2@ ┃ 3# ┃ 4$ ┃ 5% ┃ 6^ ┃ 7& ┃ 8* ┃ 9( ┃ 0) ┃ -_ ┃ =+ ┃ ←─ ┃ ┃Ins ┃PgUp┃
|
|
|
+ ┣━━━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━━━━━┫ ┣━━━━╋━━━━┫
|
|
|
+ ┃ Tab ┃ Q ┃ W ┃ E ┃ R ┃ T ┃ Y ┃ U ┃ I ┃ O ┃ P ┃ [{ ┃ ]} ┃ \| ┃ ┃Del ┃PgDn┃
|
|
|
+ ┣━━━━━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━━━━━━┫ ┗━━━━┻━━━━┛
|
|
|
+ ┃ Caps ┃ A ┃ S ┃ D ┃ F ┃ G ┃ H ┃ J ┃ K ┃ L ┃ ;: ┃ '" ┃ Enter ┃ Magicforce
|
|
|
+ ┣━━━━━━━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━━━━━━━━━┫ ┏━━━━┓
|
|
|
+ ┃ Shift ┃ Z ┃ X ┃ C ┃ V ┃ B ┃ N ┃ M ┃ ,< ┃ .> ┃ /? ┃ Shift ┃ ┃ ↑ ┃ Dan
|
|
|
+ ┣━━━━━┳━━━━┻┳━━━┻━┳━━┻━━━━┻━━━━┻━━━━┻━━━━┻━━━━┻━━━┳┻━━━━╋━━━━┻┳━━━━━┳━━┳━━┻━╋━━━━╋━━━━┓
|
|
|
+ ┃Ctrl ┃ GUI ┃ Alt ┃ ━━━━━ ┃ Alt ┃ Fn ┃Ctrl ┃ ┃ ← ┃ ↓ ┃ → ┃
|
|
|
+ ┗━━━━━┻━━━━━┻━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━┻━━━━━┻━━━━━┛ ┗━━━━┻━━━━┻━━━━┛ */
|
|
|
+
|
|
|
+// clang-format off
|
|
|
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
|
+[_QWERTY] = LAYOUT_kc( /* Default layer
|
|
|
+ ┏━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━━━━━┓ ┏━━━━┳━━━━┓ */
|
|
|
+ GESC, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 ,MINS,EQL , BSPC , INS ,PGUP, /*
|
|
|
+ ┣━━━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━━━━━┫ ┣━━━━╋━━━━┫ */
|
|
|
+ TAB , Q , W , E , R , T , Y , U , I , O , P ,LBRC,RBRC, BSLS , DEL ,PGDN, /*
|
|
|
+ ┣━━━━━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━━━━━━┫ ┗━━━━┻━━━━┛ */
|
|
|
+ FN2 , A , S , D , F , G , H , J , K , L ,SCLN,QUOT, ENTER , /*
|
|
|
+ ┣━━━━━━━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━┳━━┻━━━━━━━━━┫ ┏━━━━┓ */
|
|
|
+ LSFT , Z , X , C , V , B , N , M ,COMM,DOT ,SLSH, RSFT , UP , /*
|
|
|
+ ┣━━━━━┳━━━━┻┳━━━┻━┳━━┻━━━━┻━━━━┻━━━━┻━━━━┻━━━━┻━━━┳┻━━━━╋━━━━┻┳━━━━━┳━━┳━━┻━╋━━━━╋━━━━┓ */
|
|
|
+ LCTL ,LGUI ,LALT , SPACE ,RALT , FN1 ,RCTL , LEFT,DOWN,RGHT /*
|
|
|
+ ┗━━━━━┻━━━━━┻━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━┻━━━━━┻━━━━━┛ ┗━━━━┻━━━━┻━━━━┛ */),
|
|
|
+
|
|
|
+[_FN] = LAYOUT_kc( /* FN & CAPS layer
|
|
|
+ ┏━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━┳━━━━━━━━┓ ┏━━━━┳━━━━┓ */
|
|
|
+ GRV , F1 , F2 , F3 , F4 , F5 , F6 , F7 , F8 , F9 , F10, F11, F12, RSTP , PSCR,HOME, /*
|
|
|
+ ┣Esc ┻ 1! ┻ 2@ ┻ 3# ┻ 4$ ┻ 5% ┻ 6^ ┻ 7& ┻ 8* ┻ 9( ┻ 0) ┻ -_ ┻ =+ ┻━┳━ ←─ ━┫ ┣Ins ╋PgUp┫ */
|
|
|
+ ,PLY1,PLY2, , , , , , 7 , 8 , 9 ,BLDN,BLUP,BLTOG , ,END , /*
|
|
|
+ ┣ Tab ━┻ Q ━┻ W ━┻ E ━┻ R ━┻ T ━┻ Y ━┻ U ━┻ I ━┻ O ━┻ P ━┻ [{ ┻ ]} ┻━ \| ━┫ ┗Del ┻PgDn┛ */
|
|
|
+ , , , , , , , , 4 , 5 , 6 , , TERM , /*
|
|
|
+ ┣━ Caps ━┻ A ━┻ S ━┻ D ━┻ F ━┻ G ━┻ H ━┻ J ━┻ K ━┻ L ━┻ ;: ┻ '" ┻━ Enter ━┫ ┏━━━━┓ */
|
|
|
+ ,REC1,REC2, , ,MSTP, ,MUTE, 1 , 2 , 3 , , VOLU, /*
|
|
|
+ ┣━━ Shift ━┻ Z ━┻ X ━┻ C ━┻ V ━┻ B ━┻ N ━┻ M ━┻ ,< ┻ .> ╋ /? ┻┳━━ Shift ━━┻━╋ ↑ ━╋━━━━┓ */
|
|
|
+ , , , MPLY , 0 , , , MPRV,VOLD,MNXT /*
|
|
|
+ ┗Ctrl ┻ GUI ┻ Alt ┻━━━━━━━━━━━━ Space ━━━━━━━━━━━━┻ Alt ┻ Fn ━┻Ctrl ┛ ┗ ← ━┻ ↓ ━┻ → ━┛ */)
|
|
|
+};
|
|
|
+// clang-format on
|
|
|
+
|
|
|
+// Initialization code
|
|
|
+// -------------------
|
|
|
+
|
|
|
+void keyboard_post_init_user(void) {
|
|
|
+ backlight_level(2);
|
|
|
+}
|
|
|
+
|
|
|
+// Custom backlight driver
|
|
|
+// -----------------------
|
|
|
+
|
|
|
+// http://jared.geek.nz/2013/feb/linear-led-pwm
|
|
|
+float cie1931(float x) {
|
|
|
+ x *= 100.0 / BACKLIGHT_LEVELS;
|
|
|
+ float y;
|
|
|
+
|
|
|
+ if (x < 8) {
|
|
|
+ y = x / 902.3;
|
|
|
+ } else {
|
|
|
+ y = (x + 16.0) / 116.0;
|
|
|
+ y = y * y * y;
|
|
|
+ }
|
|
|
+
|
|
|
+ return round(y * 255);
|
|
|
+}
|
|
|
+
|
|
|
+void backlight_init_ports(void) {
|
|
|
+ setPinOutput(BACKLIGHT_PIN);
|
|
|
+ writePinLow(BACKLIGHT_PIN);
|
|
|
+
|
|
|
+ TCCR1A = _BV(COM1A1) | _BV(WGM11);
|
|
|
+ TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
|
|
|
+
|
|
|
+ ICR1 = 0xFFU; // Set PWM levels to 255 (enables high-frequency PWM)
|
|
|
+}
|
|
|
+
|
|
|
+void backlight_set(uint8_t level) {
|
|
|
+ if (level > BACKLIGHT_LEVELS) {
|
|
|
+ level = BACKLIGHT_LEVELS;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (level == 0) {
|
|
|
+ TCCR1A &= ~(_BV(COM1A1)); // Disable PWM
|
|
|
+ } else {
|
|
|
+ TCCR1A |= _BV(COM1A1); // Enable PWM
|
|
|
+ }
|
|
|
+
|
|
|
+ OCR1A = cie1931(level);
|
|
|
+}
|
|
|
+
|
|
|
+// Custom macro hooks
|
|
|
+// ------------------
|
|
|
+
|
|
|
+// Redefine with lower delay
|
|
|
+void led_blink(void) {
|
|
|
+ backlight_toggle();
|
|
|
+ wait_ms(25);
|
|
|
+ backlight_toggle();
|
|
|
+}
|
|
|
+
|
|
|
+void dynamic_macro_record_start_user(void) {
|
|
|
+ led_blink();
|
|
|
+}
|
|
|
+
|
|
|
+void dynamic_macro_play_user(int8_t direction) {
|
|
|
+ led_blink();
|
|
|
+}
|
|
|
+
|
|
|
+void dynamic_macro_record_key_user(int8_t direction, keyrecord_t *record) {
|
|
|
+ led_blink();
|
|
|
+}
|
|
|
+
|
|
|
+void dynamic_macro_record_end_user(int8_t direction) {
|
|
|
+ led_blink();
|
|
|
+}
|
|
|
+
|
|
|
+// Custom Caps Lock backlight behaviour
|
|
|
+// ------------------------------------
|
|
|
+
|
|
|
+void led_set_user(uint8_t usb_led) {
|
|
|
+ // This exists because I don't like the backlight to turn OFF when the Caps Lock is ON.
|
|
|
+ // That is, this will turn the backlight ON (at half the brightness) when the Caps Lock is ON as well.
|
|
|
+ static bool prev_is_caps_on;
|
|
|
+ bool is_caps_on = IS_LED_ON(usb_led, USB_LED_CAPS_LOCK);
|
|
|
+
|
|
|
+ if (prev_is_caps_on != is_caps_on) {
|
|
|
+ prev_is_caps_on = is_caps_on;
|
|
|
+
|
|
|
+ if (is_caps_on) {
|
|
|
+ backlight_set(BACKLIGHT_LEVELS / 2);
|
|
|
+ } else {
|
|
|
+ if (is_backlight_enabled()) {
|
|
|
+ backlight_set(get_backlight_level());
|
|
|
+ } else {
|
|
|
+ backlight_set(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Turn on the Pro Micro's on-board LEDs for Caps Lock
|
|
|
+ if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
|
|
|
+ // Set to low
|
|
|
+ setPinOutput(B0);
|
|
|
+ writePinLow(B0);
|
|
|
+ setPinOutput(D5);
|
|
|
+ writePinLow(D5);
|
|
|
+ } else {
|
|
|
+ // Set to Hi-Z
|
|
|
+ setPinInput(B0);
|
|
|
+ setPinInput(D5);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Backlight idle timeout feature
|
|
|
+// ------------------------------
|
|
|
+
|
|
|
+static uint32_t timer;
|
|
|
+static bool is_idle;
|
|
|
+
|
|
|
+void matrix_scan_user() {
|
|
|
+ // Check the timer only if the keyboard is not idle
|
|
|
+ if (!is_idle) {
|
|
|
+ if (timer_elapsed32(timer) >= (uint32_t) BACKLIGHT_IDLE_TIMEOUT * 1000) {
|
|
|
+ is_idle = true;
|
|
|
+
|
|
|
+ // Both backlight_level and backlight_level_noeeprom modify the global backlight config (not useful)
|
|
|
+ // Instead, use backlight_set in order to restore the current backlight level later on
|
|
|
+ backlight_set(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|
|
+ // Reset timer on each keypress
|
|
|
+ timer = timer_read32();
|
|
|
+
|
|
|
+ // Enable backlight back only when keyboard is idling (which implies the backlight was turned off previously)
|
|
|
+ if (is_idle) {
|
|
|
+ is_idle = false;
|
|
|
+
|
|
|
+ // Set back the original backlight level only if it is actually enabled globally
|
|
|
+ if (is_backlight_enabled()) {
|
|
|
+ // The current backlight level can be obtained with get_backlight_level
|
|
|
+ backlight_set(get_backlight_level());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|