Compare commits

...

21 Commits

Author SHA1 Message Date
bluepython508
5559ea50db Add REP/AREP keys; swap RALT and RCTL 2025-07-12 12:03:57 +01:00
bluepython508
8119741bbd Add Rcmd, Rctl, Rsft, Ralt as non-oneshots on RHS 2024-10-21 22:52:52 +01:00
bluepython508
57942ef8bb Remove game layer 2024-10-21 22:52:04 +01:00
bluepython508
a042a8266a Use esc as a lock-ending key 2024-05-19 21:12:32 +01:00
bluepython508
c8704dbe6b Move tab down; move = down; add semicolon on sym-home 2024-04-11 13:37:54 +01:00
bluepython508
9762887d45 Formatting 2024-03-14 10:44:18 +00:00
bluepython508
bae54f3cad Formatting, remove numbers from SYM layer, use KC_LSFT instead of OS_ 2024-03-14 10:13:38 +00:00
bluepython508
b6b33e0131 Formatting 2024-03-12 09:01:59 +00:00
bluepython508
9d6db95f0b Timer on oneshot mods: held for one second doesn't queue modifiers 2024-03-07 16:22:06 +00:00
bluepython508
373ccbec40 Further OSM improvements:
locking support (double-tap to lock, tap to unlock or use KC_NO)
 includes word-lock (shift-lock: ' ' -> _)
2024-03-05 22:05:50 +00:00
bluepython508
c65beba3bb Better OSM: callum mods
this removes the delay, and improves composition
2024-03-05 20:37:49 +00:00
bluepython508
a10d21773f Repeat and AltRepeat keys
C-Space, C-Return
Enter on right side for game layers
2024-02-27 20:48:19 +00:00
bluepython508
5d97a22236 Add colon to home row on symbol layer for helix
Adjust tapping to avoid shift-delay
2024-02-26 15:12:22 +00:00
bluepython508
03915a876f Numpad layer, game layer, use XXXXXX over _______ for all non-thumb keys 2024-02-26 10:59:34 +00:00
bluepython508
3d02c0789e Ignore qmk_firmware for helix file open 2024-02-20 21:53:21 +00:00
bluepython508
55ec6f29a6 Move parens, add Pause key 2024-02-20 21:52:03 +00:00
bluepython508
e24fcdc91d Remove incorrect readme 2024-02-20 12:50:38 +00:00
bluepython508
42039d5cce Improve mod-taps for OSM
Swap NAV and SYM layers, because backspace gets awkward otherwise
2024-02-20 12:18:02 +00:00
bluepython508
6a82f1360f Update dependencies; support macOS 2024-02-20 12:14:54 +00:00
bluepython508
d315e63ac5 Add GACS on symbol layer, just replacing most of the symbols. The numbers are directly above, and we have shift on L-thumb
Keeping parens on that row, as they're often useful
Update TODO: disable leds - that was done a while ago
2023-12-15 22:48:26 +00:00
bluepython508
7a0934b471 My setup, with initial keymap 2023-12-15 22:35:51 +00:00
11 changed files with 351 additions and 1 deletions

View File

@@ -13,7 +13,7 @@ AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'false'
BinPackArguments: 'true'
BinPackParameters: 'true'
ColumnLimit: '1000'
ColumnLimit: '100'
IndentCaseLabels: 'true'
IndentPPDirectives: AfterHash
IndentWidth: '4'

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

3
.gitignore vendored
View File

@@ -4,8 +4,11 @@
*~
.DS_Store
._*
.cache/
# Firmware files
*.hex
*.bin
*.uf2
/.direnv/
compile_commands.json

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "qmk_firmware"]
path = qmk_firmware
url = git@github.com:qmk/qmk_firmware

2
.ignore Normal file
View File

@@ -0,0 +1,2 @@
qmk_firmware/

39
flake.lock generated Normal file
View File

@@ -0,0 +1,39 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1708118438,
"narHash": "sha256-kk9/0nuVgA220FcqH/D2xaN6uGyHp/zoxPNUmPCMmEE=",
"path": "/nix/store/bg5fbkfa5x53clcjf4p5p92k1l3w8x38-source",
"rev": "5863c27340ba4de8f83e7e3c023b9599c3cb3c80",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"systems": "systems"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"id": "systems",
"type": "indirect"
}
}
},
"root": "root",
"version": 7
}

63
flake.nix Normal file
View File

@@ -0,0 +1,63 @@
{
outputs = {
self,
nixpkgs,
systems,
}: let
eachSystem = f:
nixpkgs.lib.genAttrs (import systems) (sys:
f {
inherit sys;
pkgs = nixpkgs.legacyPackages.${sys};
});
in {
packages = eachSystem ({
sys,
pkgs,
}: rec {
python3 = pkgs.python3.override {
packageOverrides = final: prev: {
milc = prev.milc.overrideAttrs {
patches = [
# Logs pre-initialization give long exceptions without this - they try to write directly to str('/dev/null')
# This effects every `qmk` command post-userspaces, as they have an import-time 'find the userspace' operation
# that logs in several different substeps
# I have *no* idea how noone else has run into this at all, but I can't find any mention of it as an issue anywhere
(pkgs.writeText "patch" ''
diff --git a/milc/__init__.py b/milc/__init__.py
index b3e7158..4f2843e 100644
--- a/milc/__init__.py
+++ b/milc/__init__.py
@@ -39,7 +39,7 @@ if 'MILC_IGNORE_DEPRECATED' not in os.environ:
if name in os.environ:
warnings.warn(f'Using {name} is deprecated and will not be supported in the future, please use set_metadata() instead.', stacklevel=2)
-logging.basicConfig(stream=os.devnull) # Disable logging until we can configure it how the user wants
+logging.basicConfig(filename=os.devnull) # Disable logging until we can configure it how the user wants
cli = MILC(APP_NAME, APP_VERSION, APP_AUTHOR)
'')
];
};
};
};
qmk = pkgs.qmk.override {inherit python3;};
});
devShells = eachSystem ({
sys,
pkgs,
}: {
default = pkgs.mkShell {
packages = with pkgs; [
self.packages.${sys}.qmk
clang
clang-tools
];
shellHook = ''
export QMK_HOME=$PWD/qmk_firmware
'';
};
});
};
}

View File

@@ -0,0 +1,17 @@
/* Copyright 2022 Thomas Baart <thomas@splitkb.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

View File

@@ -0,0 +1,219 @@
/* Copyright 2019 Thomas Baart <thomas@splitkb.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
enum keycodes {
OS_LSFT = SAFE_RANGE,
OS_LCTL,
OS_LALT,
OS_LGUI,
};
enum layers {
_TYPE = 0,
_GAME,
_SYM,
_NUM,
_NAV,
_FUN,
};
// Aliases for readability
#define SYM MO(_SYM)
#define NUM MO(_NUM)
#define NAV MO(_NAV)
#define FUN MO(_FUN)
#define TYPE DF(_TYPE)
#define C_SPC C(KC_SPACE)
#define C_RET C(KC_ENTER)
/* TODO:
* - Mouse Keys?
* - Swap hand keys?
*/
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_TYPE] = LAYOUT(
XXXXXXX, KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_RCTL,
KC_TAB, KC_A, KC_R, KC_S, KC_T, KC_G, KC_M, KC_N, KC_E, KC_I, KC_O, KC_QUOT,
XXXXXXX, KC_Z, KC_X, KC_C, KC_D, KC_V, QK_REP, NUM, FUN, QK_AREP, KC_K, KC_H, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
XXXXXXX, XXXXXXX, OS_LSFT, KC_ENT, SYM, NAV, KC_SPC, KC_ESC, KC_RGUI, KC_RALT
),
[_NAV] = LAYOUT(
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PGUP, KC_HOME, KC_UP, KC_END, KC_DEL, XXXXXXX,
XXXXXXX, OS_LGUI, OS_LALT, OS_LCTL, OS_LSFT, XXXXXXX, KC_PGDN, KC_LEFT, KC_DOWN, KC_RGHT, KC_BSPC, XXXXXXX,
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, XXXXXXX, C_SPC, C_RET, XXXXXXX, XXXXXXX, XXXXXXX,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
[_SYM] = LAYOUT(
KC_GRV, KC_PIPE, XXXXXXX, XXXXXXX, XXXXXXX, KC_LCBR, KC_RCBR, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
KC_TILD, OS_LGUI, OS_LALT, OS_LCTL, OS_LSFT, KC_LPRN, KC_RPRN, KC_COLN, XXXXXXX, XXXXXXX, KC_SCLN, KC_EQL,
XXXXXXX, KC_BSLS, XXXXXXX, XXXXXXX, KC_MINS, KC_LBRC, _______, _______, _______, _______, KC_RBRC, KC_UNDS, KC_COMM, KC_DOT, KC_SLSH, XXXXXXX,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
[_FUN] = LAYOUT(
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PAUS, KC_F9, KC_F10, KC_F11, KC_F12, KC_VOLU,
XXXXXXX, OS_LGUI, OS_LALT, OS_LCTL, OS_LSFT, XXXXXXX, XXXXXXX, KC_F5, KC_F6, KC_F7, KC_F8, KC_VOLD,
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, XXXXXXX, KC_F1, KC_F2, KC_F3, KC_F4, KC_MUTE,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
[_NUM] = LAYOUT(
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_1, KC_2, KC_3, KC_PLUS, XXXXXXX,
XXXXXXX, OS_LGUI, OS_LALT, OS_LCTL, OS_LSFT, XXXXXXX, KC_0, KC_4, KC_5, KC_6, KC_DOT, XXXXXXX,
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, XXXXXXX, KC_7, KC_8, KC_9, KC_SLSH, XXXXXXX,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
// [_LAYERINDEX] = LAYOUT(
// XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
// XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
// XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
// ),
};
// clang-format on
void keyboard_pre_init_user(void) {
setPinOutput(24);
writePinHigh(24);
}
typedef enum {
os_up_unqueued = 0,
os_up_queued,
os_down_unused,
os_down_used,
os_locked
} oneshot_mode_t;
typedef struct {
uint16_t time;
uint16_t mod;
uint16_t trigger;
oneshot_mode_t mode;
} oneshot_state_t;
oneshot_state_t oneshot_state[4] = {{0, KC_LSFT, OS_LSFT, os_up_unqueued},
{0, KC_LCTL, OS_LCTL, os_up_unqueued},
{0, KC_LALT, OS_LALT, os_up_unqueued},
{0, KC_LGUI, OS_LGUI, os_up_unqueued}};
bool is_oneshot_ignored_key(uint16_t keycode) {
switch (keycode) {
case OS_LSFT:
case OS_LCTL:
case OS_LALT:
case OS_LGUI:
case NAV:
case SYM:
case NUM:
case FUN:
return true;
default:
return false;
}
}
bool is_oneshot_cancel_key(uint16_t keycode, oneshot_mode_t mode) {
return keycode == KC_NO || (keycode == KC_ESCAPE && mode == os_locked);
}
// Based on
// https://github.com/qmk/qmk_firmware/blob/user-keymaps-still-present/users/callum/oneshot.c
void update_oneshot(oneshot_state_t *state, uint16_t keycode, keyrecord_t *record) {
if (keycode == state->trigger) {
if (record->event.pressed) {
// Trigger keydown
switch (state->mode) {
case os_up_queued:
state->mode = os_locked;
break;
case os_up_unqueued:
register_code(state->mod);
state->time = timer_read();
state->mode = os_down_unused;
break;
case os_locked:
state->mode = os_down_used;
break;
default:
state->mode = os_down_unused;
break;
}
} else {
// Trigger keyup
switch (state->mode) {
case os_down_unused:
// If we didn't use the mod while trigger was held, queue it.
if (timer_elapsed(state->time) < 1000) {
state->mode = os_up_queued;
} else {
state->mode = os_up_unqueued;
unregister_code(state->mod);
}
break;
case os_down_used:
// If we did use the mod while trigger was held, unregister it.
state->mode = os_up_unqueued;
unregister_code(state->mod);
break;
default:
break;
}
}
} else {
if (record->event.pressed) {
if (is_oneshot_cancel_key(keycode, state->mode) && state->mode != os_up_unqueued) {
// Cancel oneshot on designated cancel keydown.
state->mode = os_up_unqueued;
unregister_code(state->mod);
}
} else {
if (!is_oneshot_ignored_key(keycode)) {
// On non-ignored keyup, consider the oneshot used.
switch (state->mode) {
case os_down_unused:
state->mode = os_down_used;
break;
case os_up_queued:
state->mode = os_up_unqueued;
unregister_code(state->mod);
break;
default:
break;
}
}
}
}
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
update_oneshot(&oneshot_state[0], keycode, record);
update_oneshot(&oneshot_state[1], keycode, record);
update_oneshot(&oneshot_state[2], keycode, record);
update_oneshot(&oneshot_state[3], keycode, record);
if (oneshot_state[0].mode == os_locked && keycode == KC_SPACE) {
if (record->event.pressed) {
register_code(KC_MINUS);
} else {
unregister_code(KC_MINUS);
}
return false;
}
return true;
}

View File

@@ -0,0 +1,2 @@
CONVERT_TO = liatris
REPEAT_KEY_ENABLE = yes

1
qmk_firmware Submodule

Submodule qmk_firmware added at 52c794b9fc