Compare commits

...

88 Commits

Author SHA1 Message Date
Nick Brassel
843fdba1d4 OpenSUSE support. 2025-08-07 19:49:18 +10:00
Nick Brassel
b0ca90520e xargs 2025-08-07 19:18:23 +10:00
Nick Brassel
a8cdb0c59b Can we fix it? 2025-08-07 19:08:29 +10:00
Nick Brassel
5e2ea31187 OpenSUSE support. 2025-08-07 18:39:46 +10:00
Nick Brassel
4c09a9fe15 Add CachyOS due to $ID_LIKE not reporting Arch any more. 2025-08-07 14:38:47 +10:00
Nick Brassel
1650dccef0 msys2 system variant tests. 2025-08-07 11:50:11 +10:00
Nick Brassel
c05ffd8777 Oops. 2025-08-07 11:41:03 +10:00
Nick Brassel
4633459329 GH API auth? 2025-08-07 11:35:07 +10:00
Nick Brassel
5de15af41f Windows? 2025-08-07 11:27:42 +10:00
Nick Brassel
00d3627d9d macOS workflow? 2025-08-07 09:08:46 +10:00
Nick Brassel
75115250a6 Fail. 2025-08-07 08:52:18 +10:00
Nick Brassel
cabda8be67 We use which to find a compatible RV32 compiler. 2025-08-07 08:51:38 +10:00
Nick Brassel
d425385664 Print $PATH 2025-08-07 08:36:24 +10:00
Nick Brassel
24492d4058 Dump failures? 2025-08-07 01:31:24 +10:00
Nick Brassel
7af4ead24a Older tar means oblivious to zstd. 2025-08-07 01:22:01 +10:00
Nick Brassel
a369a10ded EPEL? 2025-08-07 01:15:57 +10:00
Nick Brassel
b9991cb6b8 Apparently we need EPEL on RHEL-likes. 2025-08-07 01:11:43 +10:00
Nick Brassel
48846aaa93 qmk setup implies qmk doctor. 2025-08-07 01:04:51 +10:00
Nick Brassel
4d869011af RHEL-like libusb naming woes. 2025-08-07 01:02:03 +10:00
Nick Brassel
a77acc04a0 Workflow? 2025-08-07 00:57:24 +10:00
Nick Brassel
445c12e552 Graceful degradation. 2025-08-06 23:30:56 +10:00
Nick Brassel
0a41dd5b8d Merge remote-tracking branch 'upstream/master' into bootstrap 2025-08-05 12:57:21 +10:00
Joel Challis
ae07dee941 Improve 'new-keymap' error handling when default keymap is missing (#25536) 2025-08-03 04:01:13 +01:00
Nick Brassel
d575bf7ddc Add proprietary libraries policy page. (#25532) 2025-08-01 23:26:30 +10:00
Joel Challis
36c3f4deba [docs] Align more keyboard placeholders (#25510) 2025-07-23 13:08:48 +01:00
Joel Challis
74d64c7f43 [docs] Align keyboard and keymap placeholders (#25509) 2025-07-23 04:33:37 +01:00
Brandon
7098252252 Add null65ansi keyboard (#25464) 2025-07-17 18:09:17 +01:00
Brandon
16ffaa6482 Add null65iso keyboard (#25465) 2025-07-17 18:09:01 +01:00
Jack Sangdahl
86badb394e Enable correct SPI peripheral dilemma/3x5_2/assembled (#25479)
Initial
2025-07-12 19:38:32 -06:00
Joel Challis
c7a24a441f Add zip to .gitignore (#25483) 2025-07-12 16:56:32 +01:00
Jon Henry Fernandez
9e757bc2ec [Keyboard] Add togkey/pad_pocket (#25470)
* Initial Source for Pad Pocket

* Added Tap Dance and Combo Configurations

* Updated LED Count

* Updated read me

* Updated Readme

* -Removed config.h file
- Added tap dance and combos to keymap level
- Removed tap dance and combos from keyboard.json
- Fixed conflict with submodules

* Fixed Formatting
2025-07-11 21:29:16 -06:00
TweyHugs
c3773d9c35 [Keyboard] Add cloud_macro (#24904)
* Added cloud_macro to keyboards folder

* Update readme.md

* Update readme.md

* Update readme.md

* Add files via upload

* Update keyboards/cloud_macro/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/cloud_macro/keymaps/default/keymap.c

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/cloud_macro/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

* Update keyboards/cloud_macro/keyboard.json

Co-authored-by: Joel Challis <git@zvecr.com>

* Update readme.md

* Update keyboards/cloud_macro/readme.md

Co-authored-by: Thanh Son Tran <62438883+trnthsn@users.noreply.github.com>

* Update keyboards/cloud_macro/keyboard.json

Co-authored-by: jack <jack@pngu.org>

* Update keyboards/cloud_macro/keymaps/default/keymap.c

Co-authored-by: jack <jack@pngu.org>

* Update keyboards/cloud_macro/readme.md

Co-authored-by: jack <jack@pngu.org>

* Update readme.md

* Update readme.md

reverting description to KB2040

---------

Co-authored-by: Joel Challis <git@zvecr.com>
Co-authored-by: Thanh Son Tran <62438883+trnthsn@users.noreply.github.com>
Co-authored-by: jack <jack@pngu.org>
2025-07-11 10:51:45 -06:00
Andrew Cooney
87e5df1b9e Changes to the Stenography documentation page. (#25426) 2025-07-10 12:02:08 +01:00
jack
c3b3f09702 [Docs] Tidy up keyboard guidelines (#25461)
* Initial

* Grammar
2025-07-08 13:17:33 -06:00
JhaKob
8a47896263 [Keyboard] Add Monsgeek M2 (#25387)
* Adding Monsgeek M2 keyboard

* Update readme.md

* Switch tab -> space

* Addressing PR comments.
- Removing values that are set to defaults
- Updating readme verbiage
- Using host nkro instead of usb force_nkro
2025-07-08 00:03:12 -06:00
ASHIJA
f1b2449ce5 [Keyboard] Add Slimorta (#25348)
* Add Slimorta

* Update readme.md

* Apply suggestions from code review for #25348

Co-authored-by: jack <jack@pngu.org>

---------

Co-authored-by: jack <jack@pngu.org>
2025-07-08 00:00:20 -06:00
Cipulot
a26dbbfe96 [Keyboard] Add MX65X (#25214)
* Addition of MX65X

* Folder separation

* Fix

* Update readme

* Update keymap.c

Co-authored-by: Drashna Jaelre <drashna@live.com>

* Update keymap.c

Co-authored-by: Drashna Jaelre <drashna@live.com>

* Update keymap.c

Co-authored-by: Drashna Jaelre <drashna@live.com>

* Update keymap.c

Co-authored-by: Drashna Jaelre <drashna@live.com>

* Update keymap.c

Co-authored-by: Drashna Jaelre <drashna@live.com>

* Update info.json

---------

Co-authored-by: Drashna Jaelre <drashna@live.com>
2025-07-07 23:59:45 -06:00
Ning
2916c3f098 [Keyboard] Update ning_tinyboard_tb16rgb diode direction (#25379)
* Update ning_tinyboard_tb16rgb diode_direction

* enable LTO
add rules.mk and enable RGB_MATRIX_CUSTOM_USER
add
add rgb_matrix_user.inc

* remove files
2025-07-07 23:49:44 -06:00
srk24
0524a6d848 [keyboard]Graystudio BD60 Support (#25337) 2025-07-07 20:23:46 +01:00
Ryan
8ff7b1de11 [docs] WS2812: rewrite Open Drain section (#25454) 2025-07-07 13:12:11 -06:00
snappykey
9c965bb62e Add Snappy Pad v.1 (#25419) 2025-07-06 08:39:10 +01:00
Ryan
ba63bac661 Add short aliases for OSM() (#25443) 2025-07-06 16:57:51 +10:00
Nick Brassel
d28377237f Merge remote-tracking branch 'upstream/master' into bootstrap 2025-06-20 21:58:37 +10:00
Nick Brassel
2c8b8ef713 Add CachyOS as apparently some installs don't include $ID_LIKE. 2025-06-19 10:04:12 +10:00
Nick Brassel
44ec55032e sh. 2025-06-04 23:45:24 +10:00
Nick Brassel
d4cb53e264 Merge remote-tracking branch 'upstream/master' into bootstrap 2025-06-04 23:05:30 +10:00
Nick Brassel
70ce814790 Allow for missing udevadm (i.e. GHA) 2025-06-04 23:04:27 +10:00
Nick Brassel
4d7764f7f6 bash-isms not welcome here. 2025-06-04 23:00:31 +10:00
Pascal Getreuer
558cce683f Elaborate error message when a binary is missing. 2025-05-26 08:23:06 +10:00
Nick Brassel
cb46402a5f Apply suggestions from code review
Co-authored-by: Joel Challis <git@zvecr.com>
2025-05-24 09:34:15 +10:00
Nick Brassel
5920274d70 Add warning about distro-provided qmk packages. 2025-05-22 20:30:20 +10:00
Nick Brassel
90ed47945f Add udev rule installation support. 2025-05-22 20:21:43 +10:00
Nick Brassel
6d481f176d Add distribution information to qmk doctor 2025-05-22 19:40:45 +10:00
Nick Brassel
ef67e89836 Oops. 2025-05-13 10:32:14 +10:00
Nick Brassel
92bc5ec044 Merge remote-tracking branch 'upstream/master' into bootstrap 2025-05-13 10:04:14 +10:00
Nick Brassel
c80de06b66 Oops. 2025-05-13 10:02:19 +10:00
Nick Brassel
454767e758 Script args comments. 2025-04-22 22:41:26 +10:00
Nick Brassel
176aa1f7db Docs, first pass. 2025-04-22 22:32:02 +10:00
Nick Brassel
e52491a71f Attempt at installing Windows drivers. 2025-04-22 22:28:34 +10:00
Nick Brassel
758ae5d584 Merge remote-tracking branch 'upstream/master' into bootstrap 2025-04-22 14:22:31 +10:00
Nick Brassel
65c3c0bf6a Merge remote-tracking branch 'upstream/master' into bootstrap 2025-04-22 11:59:17 +10:00
Nick Brassel
77366af7ec uv tools directory move. 2025-04-22 11:35:52 +10:00
Nick Brassel
b998dcfd0e More Windows deps. 2025-04-22 09:43:39 +10:00
Nick Brassel
decf39592e Package naming on QMK MSYS. 2025-04-22 09:25:57 +10:00
Nick Brassel
de8d66b6fd No need for sudo under QMK MSYS 2025-04-22 09:19:07 +10:00
Nick Brassel
a171b36eaf stderr. 2025-04-22 00:49:32 +10:00
Nick Brassel
36c2db8629 Cleanup. 2025-04-22 00:44:10 +10:00
Nick Brassel
c57add534e Apple diff 2025-04-22 00:38:06 +10:00
Nick Brassel
7c7a9e0e34 I suppose we need git too. 2025-04-22 00:28:54 +10:00
Nick Brassel
fa1e51dd19 Python version. 2025-04-21 23:38:33 +10:00
Nick Brassel
0d38d2adcf Fixup chicken-and-egg problem with uv installation. 2025-04-21 23:22:57 +10:00
Nick Brassel
d10d637762 Hard-coded default distrib directory. 2025-04-21 17:26:46 +10:00
Nick Brassel
1fb6323a0d macOS path fix, dos2unix dependency. 2025-04-21 11:32:01 +10:00
Nick Brassel
10faf16edf Potentially uninitialised variable. 2025-04-04 22:01:19 +11:00
Nick Brassel
a8d4e89e41 Allow relocation of uv tools directory, defaulting to inside the MSYS tree on Windows. 2025-04-02 17:08:14 +11:00
Nick Brassel
9b201d362c Spaaaaaaaaace 2025-04-02 16:41:15 +11:00
Nick Brassel
1e80179941 Merge remote-tracking branch 'upstream/master' into bootstrap 2025-04-02 16:41:10 +11:00
Nick Brassel
0d18136fdb Use --confirm or CONFIRM=1 to skip delay, fixup use of sudo when unavailable as root. 2025-03-30 00:28:06 +11:00
Nick Brassel
73b0a6d37c GHA. 2025-03-30 00:24:12 +11:00
Nick Brassel
99bf22a50e Windows doesn't like /dev/tty, pivot to delay with Ctrl-C prompt. 2025-03-28 22:52:52 +11:00
Nick Brassel
1921a4808f Formatting. 2025-03-27 22:39:55 +11:00
Nick Brassel
4ef00cd6e8 Argument parsing. 2025-03-27 22:36:37 +11:00
Nick Brassel
fa170a7c15 Basic package manager stuff on macOS/Linux. 2025-03-27 21:41:02 +11:00
Nick Brassel
6c92b08d8f Update __init__.py 2025-03-21 00:07:35 +11:00
Nick Brassel
ad8c332b59 Distribution path. 2025-03-20 23:53:19 +11:00
Nick Brassel
99f2b767be More essential binaries. 2025-03-19 14:01:02 +11:00
Nick Brassel
ddd0f54c94 Hook up internals of the qmk CLI to use $QMK_DISTRIB_DIR. 2025-03-19 12:15:13 +11:00
Nick Brassel
cb4043ec4c Add environment bootstrap script. 2025-03-19 12:05:06 +11:00
92 changed files with 4172 additions and 167 deletions

236
.github/workflows/bootstrap_testing.yml vendored Normal file
View File

@@ -0,0 +1,236 @@
name: Bootstrap Script Testing
on:
push:
branches: [bootstrap]
paths:
- "util/env-bootstrap.sh"
- ".github/workflows/bootstrap_testing.yml"
pull_request:
branches: [master, develop, xap]
paths:
- "util/env-bootstrap.sh"
- ".github/workflows/bootstrap_testing.yml"
workflow_dispatch:
permissions:
contents: read
jobs:
bootstrap-test-linux:
name: Bootstrap (Linux)
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
distribution:
# Ubuntu/Debian based
- debian:11
- debian:12
- ubuntu:20.04
- ubuntu:22.04
- ubuntu:24.04
# RHEL/CentOS/Fedora based
- fedora:40
- fedora:41
- fedora:42
- rockylinux:8
- rockylinux:9
- rockylinux/rockylinux:10
- almalinux:8
- almalinux:9
- almalinux:10
# OpenSUSE based
- opensuse/leap:latest
- opensuse/tumbleweed:latest
# Arch based
- archlinux:latest
- cachyos/cachyos:latest
- manjarolinux/base:latest
container:
image: ${{ matrix.distribution }}
options: --privileged
steps:
- name: Install base dependencies
run: |
case "${{ matrix.distribution }}" in
*ubuntu*|*debian*)
apt-get update
apt-get install -y sudo git passwd
;;
*fedora*|*rockylinux*|*almalinux*)
dnf install -y sudo git passwd findutils # findutils=xargs
;;
*suse*)
zypper --non-interactive refresh
zypper --non-interactive install sudo git shadow findutils # findutils=xargs
;;
*archlinux*|*cachyos*|*manjaro*)
pacman -Syu --noconfirm
pacman -S --noconfirm sudo git
;;
esac
# Fix PAM configuration for sudo in containers
# Fix /etc/shadow permissions - common issue in container environments
chmod 640 /etc/shadow || chmod 400 /etc/shadow || true
# Disable problematic PAM modules that commonly fail in RHEL-like containers
sed -i 's/^session.*pam_systemd.so/#&/' /etc/pam.d/sudo || true
sed -i 's/^session.*pam_loginuid.so/#&/' /etc/pam.d/sudo || true
# Ensure proper sudoers configuration
echo "Defaults !requiretty" >> /etc/sudoers
echo "Defaults secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"" >> /etc/sudoers
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
submodules: recursive
path: qmk_firmware
- name: Create test user
run: |
# Create a test user for the bootstrap script
useradd -m -s /bin/bash -U testuser
echo 'testuser:testpassword' | chpasswd
# Configure passwordless sudo
echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers # some distros complain about root not being in sudoers
echo "testuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# Test sudo functionality
sudo -u testuser whoami || echo "Sudo test failed, but continuing..."
- name: Move QMK repository to test user home
run: |
# Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
git -C qmk_firmware remote add upstream https://github.com/qmk/qmk_firmware.git
# Move the QMK repository to the test user's home directory
mv qmk_firmware /home/testuser/qmk_firmware
chown -R testuser:testuser /home/testuser/qmk_firmware
- name: Run bootstrap script
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Ensure the bootstrap script can access sudo
sudo -u testuser --preserve-env=GITHUB_TOKEN bash -c "
export CONFIRM=1
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
cd /home/testuser
bash /home/testuser/qmk_firmware/util/env-bootstrap.sh
"
- name: Test QMK CLI
run: |
sudo -u testuser bash -c "
export PATH=/home/testuser/.local/bin:\$PATH
cd /home/testuser
qmk setup -y -H /home/testuser/qmk_firmware # setup implies doctor, no need to run it separately
qmk mass-compile -j $(nproc) -e DUMP_CI_METADATA=yes -f 'keyboard_name==*onekey*' -km reset || touch .failed # Compile a bunch of different platforms
"
cd /home/testuser/qmk_firmware
./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
[ ! -e .failed ] || exit 1
bootstrap-test-macos:
name: Bootstrap (macOS)
strategy:
fail-fast: false
matrix:
os:
- macos-13 # Intel x64
- macos-14 # Apple Silicon ARM64
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
submodules: recursive
- name: Run bootstrap script
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
git remote add upstream https://github.com/qmk/qmk_firmware.git
# Run the bootstrap script
export CONFIRM=1
sh ./util/env-bootstrap.sh
- name: Test QMK CLI
run: |
# Add QMK CLI to PATH (bootstrap script installs it to ~/.local/bin on macOS)
export PATH="$HOME/.local/bin:$PATH"
qmk setup -y -H . # setup implies doctor, no need to run it separately
qmk mass-compile -j $(sysctl -n hw.ncpu) -e DUMP_CI_METADATA=yes -f 'keyboard_name==*onekey*' -km reset || touch .failed # Compile a bunch of different platforms
./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
[ ! -e .failed ] || exit 1
bootstrap-test-windows:
name: Bootstrap (Windows)
strategy:
fail-fast: false
matrix:
msys-variant:
- mingw64
- clang64
- ucrt64
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- name: Install MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msys-variant }}
pacboy: >-
git:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
submodules: recursive
- name: Run bootstrap script
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Add upstream remote to the cloned repository so `qmk doctor` doesn't flag a warning
git remote add upstream https://github.com/qmk/qmk_firmware.git
# Run the bootstrap script
export CONFIRM=1
sh ./util/env-bootstrap.sh
- name: Test QMK CLI
run: |
# Add QMK CLI to PATH (bootstrap script installs it to /opt/uv/tools/bin on Windows MSYS2)
export PATH="/opt/uv/tools/bin:$PATH"
qmk setup -y -H . # setup implies doctor, no need to run it separately
# Temporary workaround for lockups on Windows, fix TBD
qmk config user.parallel_search=False
qmk mass-compile -j $(nproc) -e DUMP_CI_METADATA=yes -f 'keyboard_name==*onekey*' -km reset || touch .failed # Compile a bunch of different platforms
./util/ci/generate_failure_markdown.sh > $GITHUB_STEP_SUMMARY || true
[ ! -e .failed ] || exit 1

1
.gitignore vendored
View File

@@ -64,6 +64,7 @@ build/
cmake-build-debug
CMakeLists.txt
*.pdf
*.zip
# Let these ones be user specific, since we have so many different configurations
*.code-workspace

View File

@@ -21,8 +21,14 @@
{ "text": "Debugging QMK", "link": "/faq_debug" },
{ "text": "Keymap FAQ", "link": "/faq_keymap" },
{ "text": "Squeezing Space from AVR", "link": "/squeezing_avr" },
{ "text": "Glossary", "link": "/reference_glossary" },
{ "text": "License Violations", "link": "/license_violations" }
{ "text": "Glossary", "link": "/reference_glossary" }
]
},
{
"text": "Licensing",
"items": [
{ "text": "License Violations", "link": "/license_violations" },
{ "text": "Proprietary Libraries", "link": "/proprietary_libs" }
]
},
{

View File

@@ -17,12 +17,12 @@ qmk compile [-c] <configuratorExport.json>
**Usage for Keymaps**:
```
qmk compile [-c] [-e <var>=<value>] [-j <num_jobs>] [--compiledb] -kb <keyboard_name> -km <keymap_name>
qmk compile [-c] [-e <var>=<value>] [-j <num_jobs>] [--compiledb] -kb <keyboard> -km <keymap>
```
**Usage in Keyboard Directory**:
Must be in keyboard directory with a default keymap, or in keymap directory for keyboard, or supply one with `--keymap <keymap_name>`
Must be in keyboard directory with a default keymap, or in keymap directory for keyboard, or supply one with `--keymap <keymap>`
```
qmk compile
```
@@ -30,7 +30,7 @@ qmk compile
**Usage for building all keyboards that support a specific keymap**:
```
qmk compile -kb all -km <keymap_name>
qmk compile -kb all -km <keymap>
```
**Example**:
@@ -62,7 +62,7 @@ $ qmk compile
Must be under `qmk_firmware/layouts/`, and in a keymap folder.
```
qmk compile -kb <keyboard_name>
qmk compile -kb <keyboard>
```
**Example**:
@@ -77,11 +77,11 @@ $ qmk compile -kb dz60
It is possible to speed up compilation by adding the `-j`/`--parallel` flag.
```
qmk compile -j <num_jobs> -kb <keyboard_name>
qmk compile -j <num_jobs> -kb <keyboard>
```
The `num_jobs` argument determines the maximum number of jobs that can be used. Setting it to zero will enable parallel compilation without limiting the maximum number of jobs.
```
qmk compile -j 0 -kb <keyboard_name>
qmk compile -j 0 -kb <keyboard>
```
**Compilation Database**:
@@ -120,7 +120,7 @@ qmk flash [-bl <bootloader>] [-c] [-e <var>=<value>] [-j <num_jobs>] <configurat
**Usage for Keymaps**:
```
qmk flash -kb <keyboard_name> -km <keymap_name> [-bl <bootloader>] [-c] [-e <var>=<value>] [-j <num_jobs>]
qmk flash -kb <keyboard> -km <keymap_name> [-bl <bootloader>] [-c] [-e <var>=<value>] [-j <num_jobs>]
```
**Usage for pre-compiled firmwares**:

View File

@@ -4,7 +4,7 @@ QMK presents itself to the host as a regular HID keyboard device, and as such re
There are two notable exceptions: the Caterina bootloader, usually seen on Pro Micros, and the HalfKay bootloader shipped with PJRC Teensys, appear as a serial port and a generic HID device respectively, and so do not require a driver.
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2, the `qmk_install.sh` script will have already installed the drivers for you.
We recommend the use of the [Zadig](https://zadig.akeo.ie/) utility. If you have set up the development environment with MSYS2, the QMK CLI installation script will have already installed the drivers for you.
## Installation

View File

@@ -44,7 +44,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const aw20216s_led_t PROGMEM g_aw20216s_leds[AW20216S_LED_COUNT] = {

View File

@@ -37,7 +37,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3218_led_t PROGMEM g_is31fl3218_leds[IS31FL3218_LED_COUNT] = {

View File

@@ -50,7 +50,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3236_led_t PROGMEM g_is31fl3236_leds[IS31FL3236_LED_COUNT] = {

View File

@@ -120,7 +120,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3729_led_t PROGMEM g_is31fl3729_leds[IS31FL3729_LED_COUNT] = {

View File

@@ -61,7 +61,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {

View File

@@ -145,7 +145,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3733_led_t PROGMEM g_is31fl3733_leds[IS31FL3733_LED_COUNT] = {

View File

@@ -129,7 +129,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3736_led_t PROGMEM g_is31fl3736_leds[IS31FL3736_LED_COUNT] = {

View File

@@ -117,7 +117,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3737_led_t PROGMEM g_is31fl3737_leds[IS31FL3737_LED_COUNT] = {

View File

@@ -117,7 +117,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3741_led_t PROGMEM g_is31fl3741_leds[IS31FL3741_LED_COUNT] = {

View File

@@ -117,7 +117,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3742a_led_t PROGMEM g_is31fl3742a_leds[IS31FL3742A_LED_COUNT] = {

View File

@@ -127,7 +127,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3743a_led_t PROGMEM g_is31fl3743a_leds[IS31FL3743A_LED_COUNT] = {

View File

@@ -127,7 +127,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3745_led_t PROGMEM g_is31fl3745_leds[IS31FL3745_LED_COUNT] = {

View File

@@ -132,7 +132,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const is31fl3746a_led_t PROGMEM g_is31fl3746a_leds[IS31FL3746A_LED_COUNT] = {

View File

@@ -52,7 +52,7 @@ Depending on the ChibiOS board configuration, you may need to [enable and config
## LED Mapping {#led-mapping}
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboardname>.c`:
In order to use this driver, each output must be mapped to an LED index, by adding the following to your `<keyboard>.c`:
```c
const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT] = {

View File

@@ -144,18 +144,30 @@ The following defines apply only to ARM devices:
|`WS2812_T1L`|`(WS2812_TIMING - WS2812_T1H)`|The length of a "1" bit's low phase in nanoseconds (bitbang and PIO drivers only)|
|`WS2812_T0L`|`(WS2812_TIMING - WS2812_T0H)`|The length of a "0" bit's low phase in nanoseconds (bitbang and PIO drivers only)|
### Push-Pull and Open Drain {#push-pull-open-drain}
### Logic Levels {#logic-levels}
By default, the GPIO used for data transmission is configured as a *push-pull* output, meaning the pin is effectively always driven either to VCC or to ground.
WS2812 LEDs usually operate at 5V, but some microcontrollers, particularly ARM-based ones, run on 3.3V. This can pose an issue when driving the LED chain as the logic level voltage is lower than the power supply voltage, leading to unreliable data transmission. There are two main workarounds:
For situations where the logic level voltage is lower than the power supply voltage, however, this can pose an issue. The solution is to configure the pin for *open drain* mode instead, and use a pullup resistor between the DI pin and VCC. In this mode, the MCU can only pull the GPIO *low*, or leave it floating. The pullup resistor is then responsible for pulling the line high, when the MCU is not driving the GPIO.
#### 1. Open Drain Circuit {#open-drain-circuit}
To configure the DI pin for open drain configuration, add the following to your `config.h`:
By default, `WS2812_DI_PIN` is configured as a *push-pull* output, meaning the pin is effectively always driven either to VCC or to ground; however, it can be configured in *open drain* mode instead.
In this mode, the MCU will only pull the GPIO *low*, and leaves it floating otherwise. A pullup resistor (typically around 10kΩ) between DI and 5V is then responsible for pulling the line high when the MCU is not driving the GPIO.
To use the DI pin in open drain configuration, add the following to your `config.h`:
```c
#define WS2812_EXTERNAL_PULLUP
```
::: warning
Because the GPIO is being pulled to 5V in this situation rather than VCC (3.3V), **it must be a 5V tolerant pin**. Consult your MCU's datasheet first if there are no eligible pins, you must use a level shifter instead.
:::
#### 2. Level Shifter {#level-shifter}
A level shifter IC, such as the SN74LV1T34, can be placed between the GPIO and the first LED's DI pin to convert the 3.3V logic to 5V. This requires no additional configuration in the firmware, nor a 5V tolerant GPIO, but may be more expensive and is generally less handwire-friendly.
### SPI Driver {#arm-spi-driver}
Depending on the ChibiOS board configuration, you may need to enable SPI at the keyboard level. For STM32, this would look like:

View File

@@ -44,7 +44,7 @@ Pro Micro (Atmega32u4), make sure to include `CONFIG_USB_ACM=y`. Other devices m
Issues encountered when flashing keyboards on Windows are most often due to having the wrong drivers installed for the bootloader, or none at all.
Re-running the QMK installation script (`./util/qmk_install.sh` from the `qmk_firmware` directory in MSYS2 or WSL) or reinstalling the QMK Toolbox may fix the issue. Alternatively, you can download and run the [`qmk_driver_installer`](https://github.com/qmk/qmk_driver_installer) package manually.
Re-running the QMK installation script (`curl -fsSL https://install.qmk.fm | sh`) or reinstalling the QMK Toolbox may fix the issue. Alternatively, you can download and run the [`qmk_driver_installer`](https://github.com/qmk/qmk_driver_installer) package manually.
If that doesn't work, then you may need to download and run Zadig. See [Bootloader Driver Installation with Zadig](driver_installation_zadig) for more detailed information.

View File

@@ -4,6 +4,14 @@
The [Open Steno Project](https://www.openstenoproject.org/) has built an open-source program called Plover that provides real-time translation of steno strokes into words and commands. It has an established dictionary and supports
## Steno Support in QMK
There are three ways that QMK keyboards can support steno, with varying degrees of configuration required:
1. Plover with [Arpeggiation](https://plover.wiki/index.php/Glossary#Arpeggiate) requires no changes to any keyboard and is supported by QMK as well as any other QWERTY keyboard.
2. Plover with [NKRO](https://plover.wiki/index.php/Using_a_standard_keyboard_with_Plover#NKRO). If your keyboard supports NKRO in hardware and you have NKRO enabled as a USB endpoint, you can chord with the keyboard. Many devices will arrive stock like this and will require no changes.
3. Steno Machine Protocols. This requires the most configuration, but this has the advantage of allowing you to use your keyboard keys normally (either on another layer or another piece of hardware) without enabling and disabling your steno software.
## Plover with QWERTY Keyboard {#plover-with-qwerty-keyboard}
Plover can work with any standard QWERTY keyboard, although it is more efficient if the keyboard supports NKRO (n-key rollover) to allow Plover to see all the pressed keys at once. An example keymap for Plover can be found in `planck/keymaps/default`. Switching to the `PLOVER` layer adjusts the position of the keyboard to support the number bar.
@@ -14,14 +22,14 @@ You may also need to adjust your layout, either in QMK or in Plover, if you have
## Plover with Steno Protocol {#plover-with-steno-protocol}
Plover also understands the language of several steno machines. QMK can speak a couple of these languages: TX Bolt and GeminiPR. An example layout can be found in `planck/keymaps/steno`.
Plover also understands the language of several steno machines. QMK can speak a couple of these languages: TX Bolt and GeminiPR. An example layout can be found in `splitography/keymaps/default`.
When QMK speaks to Plover over a steno protocol, Plover will not use the keyboard as input. This means that you can switch back and forth between a standard keyboard and your steno keyboard, or even switch layers from Plover to standard and back without needing to activate/deactivate Plover.
In this mode, Plover expects to speak with a steno machine over a serial port so QMK will present itself to the operating system as a virtual serial port in addition to a keyboard.
::: info
Note: Due to hardware limitations, you might not be able to run both a virtual serial port and mouse emulation at the same time.
Due to hardware limitations, you might not be able to run both a virtual serial port and other features (mouse keys, NKRO, or MIDI support) at the same time. You will likely encounter a compile time error if this is the case. Disable those other features as necessary.
:::
::: warning
@@ -156,7 +164,7 @@ At the end of this scenario given as an example, `chord` would have five bits se
## Keycode Reference {#keycode-reference}
::: info
Note: TX Bolt does not support the full set of keys. The TX Bolt implementation in QMK will map the GeminiPR keys to the nearest TX Bolt key so that one key map will work for both.
TX Bolt does not support the full set of keys. The TX Bolt implementation in QMK will map the GeminiPR keys to the nearest TX Bolt key so that one key map will work for both.
:::
|GeminiPR|TX Bolt|Steno Key|

View File

@@ -19,8 +19,8 @@ Within the folder `keyboards`, its subfolder `handwired` and its vendor and manu
* `config.h`: The file that sets the default compile time options. Do not edit this file directly, instead use a keymap specific `config.h`.
* `info.json`: The file used for setting layout for QMK Configurator. See [Configurator Support](reference_configurator_support) for more information.
* `readme.md`: A brief overview of the keyboard.
* `<keyboardName>.h`: This file is where the keyboard layout is defined against the keyboard's switch matrix.
* `<keyboardName>.c`: This file is where you can find custom code for the keyboard.
* `<keyboard>.h`: This file is where the keyboard layout is defined against the keyboard's switch matrix.
* `<keyboard>.c`: This file is where you can find custom code for the keyboard.
For more information on project structure, see [QMK Keyboard Guidelines](hardware_keyboard_guidelines).

View File

@@ -1,8 +1,8 @@
# More Detailed `make` Instructions
The full syntax of the `make` command is `<keyboard_folder>:<keymap>:<target>`, where:
The full syntax of the `make` command is `<keyboard>:<keymap>:<target>`, where:
* `<keyboard_folder>` is the path of the keyboard, for example `planck`
* `<keyboard>` is the path of the keyboard, for example `planck`
* Use `all` to compile all keyboards
* Specify the path to compile a revision, for example `planck/rev4` or `planck/rev3`
* If the keyboard doesn't have any folders, it can be left out

View File

@@ -44,7 +44,11 @@ QMK uses sub-folders both for organization and to share code between revisions o
qmk_firmware/keyboards/top_folder/sub_1/sub_2/sub_3/sub_4
```
If a sub-folder has a `rules.mk` file it will be considered a compilable keyboard. It will be available in QMK Configurator and tested with `make all`. If you are using a folder to organize several keyboards from the same maker you should not have a `rules.mk` file.
If a sub-folder has a `keyboard.json` file it will be considered a compilable keyboard. It will be available in QMK Configurator and tested with `make all`. If you are using a folder to organize several keyboards from the same maker you should not have a `keyboard.json` file.
::: tip
When configuring a keyboard with multiple revisions (like the `clueboard/66` example below), an `info.json` file at the top keyboard level (eg. `clueboard/66`) should be used for configuration shared between revisions. Then `keyboard.json` in each revision directory containing revision-specific configuration, and indicating a buildable keyboard.
:::
Example:
@@ -52,35 +56,49 @@ Clueboard uses sub-folders for both purposes, organization and keyboard revision
* [`qmk_firmware`](https://github.com/qmk/qmk_firmware/tree/master)
* [`keyboards`](https://github.com/qmk/qmk_firmware/tree/master/keyboards)
* [`clueboard`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard) &larr; This is the organization folder, there's no `rules.mk` file
* [`60`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/60) &larr; This is a compilable keyboard, it has a `rules.mk` file
* [`66`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66) &larr; This is also compilable- it uses `DEFAULT_FOLDER` to specify `rev3` as the default revision
* [`clueboard`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard) &larr; This is the organization folder, there's no `keyboard.json` file
* [`60`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/60) &larr; This is a compilable keyboard - it has a `keyboard.json` file
* [`66`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66) &larr; This is not a compilable keyboard - a revision must be specified
* [`rev1`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66/rev1) &larr; compilable: `make clueboard/66/rev1`
* [`rev2`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66/rev2) &larr; compilable: `make clueboard/66/rev2`
* [`rev3`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66/rev3) &larr; compilable: `make clueboard/66/rev3` or `make clueboard/66`
* [`rev3`](https://github.com/qmk/qmk_firmware/tree/master/keyboards/clueboard/66/rev3) &larr; compilable: `make clueboard/66/rev3`
## Keyboard Folder Structure
Your keyboard should be located in `qmk_firmware/keyboards/` and the folder name should be your keyboard's name as described in the previous section. Inside this folder should be several files:
Your keyboard should be located in `qmk_firmware/keyboards/` and the folder name should be your keyboard's name as described in the previous section. Inside this folder should be several files, some of which are optional:
* `readme.md`
* `info.json`
* `keyboard.json` (or `info.json`)
* `config.h`
* `rules.mk`
* `<keyboard_name>.c`
* `<keyboard_name>.h`
* `<keyboard>.c`
* `<keyboard>.h`
### `readme.md`
All projects need to have a `readme.md` file that explains what the keyboard is, who made it and where it's available. If applicable, it should also contain links to more information, such as the maker's website. Please follow the [published template](documentation_templates#keyboard-readmemd-template).
### `info.json`
### `keyboard.json`/`info.json`
This file is used by the [QMK API](https://github.com/qmk/qmk_api). It contains the information [QMK Configurator](https://config.qmk.fm/) needs to display a representation of your keyboard. You can also set metadata here. For more information see the [reference page](reference_info_json).
The `keyboard.json` file is necessary for your keyboard (or keyboard revision) to be considered a buildable keyboard. The same content is valid in both `info.json` and `keyboard.json`. For the available configuration options of this file, see the [reference page](reference_info_json). This file is also used by the [QMK API](https://github.com/qmk/qmk_api), and by the [QMK Configurator](https://config.qmk.fm/) to display a representation of the available layouts of your keyboard.
Additionally, this is where layouts available on your keyboard are defined. If you only have a single layout, it should be named `LAYOUT`. When defining multiple layouts, you should have a base layout, named `LAYOUT_all`, that supports all possible switch positions in your matrix, even if that layout is impossible to build physically. This is the layout that should be used in the `default` keymap. You should then have additional keymaps named `default_<layout>` that configure keymaps for the other layouts. Layout macro names are entirely lowercase, except for the prefix of `LAYOUT`.
As an example, if you have a 60% PCB that supports ANSI and ISO, you might define the following layouts and keymaps:
| Layout Name | Keymap Name | Description |
|-------------|--------------|------------------------------------------|
| LAYOUT_all | default | A layout that supports both ISO and ANSI |
| LAYOUT_ansi | default_ansi | An ANSI layout |
| LAYOUT_iso | default_iso | An ISO layout |
::: tip
Providing only `LAYOUT_all` is invalid, as is providing a `LAYOUT` when multiple layouts are present.
:::
### `config.h`
All projects need to have a `config.h` file that sets things like the matrix size, product name, USB VID/PID, description and other settings. In general, use this file to set essential information and defaults for your keyboard that will always work.
Some projects will need to have a `config.h` that configures parameters that are not possible to be set in `keyboard.json`. This is not a required file.
The `config.h` files can also be placed in sub-folders, and the order in which they are read is as follows:
@@ -138,7 +156,7 @@ If you define options using `post_config.h` as in the above example, you should
### `rules.mk`
The presence of this file means that the folder is a keyboard target and can be used in `make` commands. This is where you setup the build environment for your keyboard and configure the default set of features.
This file is typically used to configure hardware drivers (eg. pointing device), or to include additional C files in compilation. This is not a required file.
The `rules.mk` file can also be placed in a sub-folder, and its reading order is as follows:
@@ -185,9 +203,9 @@ The `post_rules.mk` file can interpret `features` of a keyboard-level before `co
See `build_keyboard.mk` and `common_features.mk` for more details.
:::
### `<keyboard_name.c>`
### `<keyboard>.c`
This is where you will write custom code for your keyboard. Typically you will write code to initialize and interface with the hardware in your keyboard. If your keyboard consists of only a key matrix with no LEDs, speakers, or other auxiliary hardware this file can be blank.
This file should contain C code required for the functionality of your keyboard, for example hardware initialisation code, OLED display code, and so on. This file should only contain code necessary for the keyboard to work, and *not* things that should be left to the end user to configure in their keymap. This file is automatically included in compilation if it exists. This is not a required file.
The following functions are typically defined in this file:
@@ -196,33 +214,13 @@ The following functions are typically defined in this file:
* `bool process_record_kb(uint16_t keycode, keyrecord_t *record)`
* `bool led_update_kb(led_t led_state)`
### `<keyboard_name.h>`
### `<keyboard>.h`
This file is used to define the matrix for your keyboard. You should define at least one C macro which translates an array into a matrix representing the physical switch matrix for your keyboard. If it's possible to build your keyboard with multiple layouts you should define additional macros.
If you have only a single layout you should call this macro `LAYOUT`.
When defining multiple layouts you should have a base layout, named `LAYOUT_all`, that supports all possible switch positions on your matrix, even if that layout is impossible to build physically. This is the macro you should use in your `default` keymap. You should then have additional keymaps named `default_<layout>` that use your other layout macros. This will make it easier for people to use the layouts you define.
Layout macro names are entirely lowercase, except for the word `LAYOUT` at the front.
As an example, if you have a 60% PCB that supports ANSI and ISO you might define the following layouts and keymaps:
| Layout Name | Keymap Name | Description |
|-------------|-------------|-------------|
| LAYOUT_all | default | A layout that supports both ISO and ANSI |
| LAYOUT_ansi | default_ansi | An ANSI layout |
| LAYOUT_iso | default_iso | An ISO layout |
::: tip
Providing only `LAYOUT_all` is invalid - especially when implementing the additional layouts within 3rd party tooling.
:::
This file can contain function prototypes for custom functions and other header file code utilised by `<keyboard>.c`. The `<keyboard>.c` file should include this file. This is not a required file.
## Image/Hardware Files
In an effort to keep the repo size down we're no longer accepting binary files of any format, with few exceptions. Hosting them elsewhere (such as <https://imgur.com>) and linking them in the `readme.md` is preferred.
Hardware files (such as plates, cases, pcb) can be contributed to the [qmk.fm repo](https://github.com/qmk/qmk.fm) and they will be made available on [qmk.fm](https://qmk.fm). Downloadable files are stored in `/<keyboard>/` (name follows the same format as above) which are served at `https://qmk.fm/<keyboard>/`, and pages are generated from `/_pages/<keyboard>/` which are served at the same location (.md files are generated into .html files through Jekyll). Check out the `lets_split` folder for an example.
In an effort to keep the repo size down we do not accept binary files of any format, with few exceptions. Hosting them elsewhere (such as <https://imgur.com>) and linking them in the `readme.md` is preferred. Hardware files such as plates, cases, and PCBs can be published in a personal repository or elsewhere, and linked to by your keyboard's `readme.md` file.
## Keyboard Defaults
@@ -232,8 +230,6 @@ Given the amount of functionality that QMK exposes it's very easy to confuse new
[Magic Keycodes](keycodes_magic) and [Command](features/command) are two related features that allow a user to control their keyboard in non-obvious ways. We recommend you think long and hard about if you're going to enable either feature, and how you will expose this functionality. Keep in mind that users who want this functionality can enable it in their personal keymaps without affecting all the novice users who may be using your keyboard as their first programmable board.
By far the most common problem new users encounter is accidentally triggering Bootmagic while they're plugging in their keyboard. They're holding the keyboard by the bottom, unknowingly pressing in alt and spacebar, and then they find that these keys have been swapped on them. We recommend leaving this feature disabled by default, but if you do turn it on consider setting `BOOTMAGIC_KEY_SALT` to a key that is hard to press while plugging your keyboard in.
If your keyboard does not have 2 shift keys you should provide a working default for `IS_COMMAND`, even when you have set `COMMAND_ENABLE = no`. This will give your users a default to conform to if they do enable Command.
## Custom Keyboard Programming
@@ -242,7 +238,7 @@ As documented on [Customizing Functionality](custom_quantum_functions) you can d
## Non-Production/Handwired Projects
We're happy to accept any project that uses QMK, including prototypes and handwired ones, but we have a separate `/keyboards/handwired/` folder for them, so the main `/keyboards/` folder doesn't get overcrowded. If a prototype project becomes a production project at some point in the future, we'd be happy to move it to the main `/keyboards/` folder!
We're happy to accept any project that uses QMK, including handwired ones, but we have a separate `/keyboards/handwired/` folder for them, so the main `/keyboards/` folder doesn't get overcrowded. If a prototype project becomes a production project at some point in the future, we'd be happy to move it to the main `/keyboards/` folder!
## Warnings as Errors

View File

@@ -404,7 +404,6 @@ See also: [Layer Switching](feature_layers#switching-and-toggling-layers)
|`DF(layer)` |Set the base (default) layer until the keyboard loses power |
|`PDF(layer)` |Set the base (default) layer in EEPROM |
|`MO(layer)` |Momentarily turn on `layer` when pressed (requires `KC_TRNS` on destination layer)|
|`OSL(layer)` |Momentarily activates `layer` until a key is pressed. See [One Shot Keys](one_shot_keys) for details. |
|`LM(layer, mod)`|Momentarily turn on `layer` (like MO) with `mod` active as well. Where `mod` is a mods_bit. Mods can be viewed [here](mod_tap). Example Implementation: `LM(LAYER_1, MOD_LALT)`|
|`LT(layer, kc)` |Turn on `layer` when held, `kc` when tapped |
|`TG(layer)` |Toggle `layer` on or off |
@@ -817,13 +816,41 @@ See also: [US ANSI Shifted Symbols](keycodes_us_ansi_shifted)
See also: [One Shot Keys](one_shot_keys)
|Key |Aliases |Description |
|--------------------|---------|----------------------------------|
|`OSM(mod)` | |Hold `mod` for one keypress |
|`OSL(layer)` | |Switch to `layer` for one keypress|
|`QK_ONE_SHOT_TOGGLE`|`OS_TOGG`|Toggles One Shot keys status |
|`QK_ONE_SHOT_ON` |`OS_ON` |Turns One Shot keys on |
|`QK_ONE_SHOT_OFF` |`OS_OFF` |Turns One Shot keys off |
|Key |Aliases |Description |
|--------------------|---------|---------------------------------------------------------------------|
|`QK_ONE_SHOT_TOGGLE`|`OS_TOGG`|Toggles One Shot keys status |
|`QK_ONE_SHOT_ON` |`OS_ON` |Turns One Shot keys on |
|`QK_ONE_SHOT_OFF` |`OS_OFF` |Turns One Shot keys off |
|`OSL(layer)` | |Switch to `layer` for one keypress |
|`OSM(mod)` | |Hold `mod` for one keypress |
|`OS_LCTL` | |Hold Left Control for one keypress |
|`OS_LSFT` | |Hold Left Shift for one keypress |
|`OS_LALT` | |Hold Left Alt for one keypress |
|`OS_LGUI` | |Hold Left GUI for one keypress |
|`OS_LCS` | |Hold Left Control and Left Shift for one keypress |
|`OS_LCA` | |Hold Left Control and left Alt for one keypress |
|`OS_LCG` | |Hold Left Control and Left GUI for one keypress |
|`OS_LSA` | |Hold Left Shift and Left Alt for one keypress |
|`OS_LSG` | |Hold Left Shift and Left GUI for one keypress |
|`OS_LAG` | |Hold Left Alt and Left GUI for one keypress |
|`OS_LCSG` | |Hold Left Control, Left Shift and Left GUI for one keypress |
|`OS_LCAG` | |Hold Left Control, Left Alt and Left GUI for one keypress |
|`OS_LSAG` | |Hold Left Shift, Left Alt and Left GUI for one keypress |
|`OS_RCTL` | |Hold Right Control for one keypress |
|`OS_RSFT` | |Hold Right Shift for one keypress |
|`OS_RALT` | |Hold Right Alt for one keypress |
|`OS_RGUI` | |Hold Right GUI for one keypress |
|`OS_RCS` | |Hold Right Control and Right Shift for one keypress |
|`OS_RCA` | |Hold Right Control and Right Alt for one keypress |
|`OS_RCG` | |Hold Right Control and Right GUI for one keypress |
|`OS_RSA` | |Hold Right Shift and Right Alt for one keypress |
|`OS_RSG` | |Hold Right Shift and Right GUI for one keypress |
|`OS_RAG` | |Hold Right Alt and Right GUI for one keypress |
|`OS_RCSG` | |Hold Right Control, Right Shift and Right GUI for one keypress |
|`OS_RCAG` | |Hold Right Control, Right Alt and Right GUI for one keypress |
|`OS_RSAG` | |Hold Right Shift, Right Alt and Right GUI for one keypress |
|`OS_MEH` | |Hold Left Control, Left Shift and Left Alt for one keypress |
|`OS_HYPR` | |Hold Left Control, Left Shift, Left Alt and Left GUI for one keypress|
## Programmable Button Support {#programmable-button}

View File

@@ -33,7 +33,7 @@ qmk new-keymap
If you did not configure your environment, or you have multiple keyboards, you can specify a keyboard name:
```sh
qmk new-keymap -kb <keyboard_name>
qmk new-keymap -kb <keyboard>
```
Look at the output from that command, you should see something like this:

View File

@@ -60,7 +60,7 @@ open .
The firmware file always follows this naming format:
```
<keyboard_name>_<keymap_name>.{bin,hex}
<keyboard>_<keymap>.{bin,hex}
```
For example, the `planck/rev5` with a `default` keymap will have this filename:

View File

@@ -50,90 +50,64 @@ You will need to install [MSYS2](https://www.msys2.org). Once installed, close a
Install the QMK CLI by running:
```sh
pacman --needed --noconfirm --disable-download-timeout -S git mingw-w64-x86_64-python-qmk
curl -fsSL https://install.qmk.fm | sh
```
::::
==== macOS
QMK maintains a Homebrew tap and formula which will automatically install the CLI and all necessary dependencies.
#### Prerequisites
You will need to install Homebrew. Follow the instructions on https://brew.sh.
::: tip
If you are using an Apple Silicon machine, the installation process will take significantly longer because GitHub actions do not have native runners to build binary packages for the ARM and AVR toolchains.
:::
#### Installation
Install the QMK CLI by running:
```sh
brew install qmk/qmk/qmk
curl -fsSL https://install.qmk.fm | sh
```
==== Linux/WSL
#### Installation
::: info
Many Linux distributions are supported, but not all. Mainstream distributions will have best success -- if possible, choose either Debian or its derivatives (such as Ubuntu, or Mint), CentOS or its derivatives (such as Fedora, or Rocky Linux), and Arch or its derivatives (such as Manjaro, or CachyOS).
:::
Install the QMK CLI by running:
```sh
curl -fsSL https://install.qmk.fm | sh
```
::: tip
**Note for WSL users**: By default, the installation process will clone the QMK repository into your WSL home directory, but if you have cloned manually, ensure that it is located inside the WSL instance instead of the Windows filesystem (ie. not in `/mnt`), as accessing it is currently [extremely slow](https://github.com/microsoft/WSL/issues/4197).
:::
#### Prerequisites
You will need to install Git and Python. It's very likely that you already have both, but if not, one of the following commands should install them:
* Debian / Ubuntu / Devuan: `sudo apt install -y git python3-pip`
* Fedora / Red Hat / CentOS: `sudo yum -y install git python3-pip`
* Arch / Manjaro: `sudo pacman --needed --noconfirm -S git python-pip libffi`
* Void: `sudo xbps-install -y git python3-pip`
* Solus: `sudo eopkg -y install git python3`
* Sabayon: `sudo equo install dev-vcs/git dev-python/pip`
* Gentoo: `sudo emerge dev-vcs/git dev-python/pip`
#### Installation
Install the QMK CLI by running:
```sh
python3 -m pip install --user qmk
```
Alternatively, install the QMK CLI as a [uv](https://docs.astral.sh/uv/) managed tool, kept isolated in a virtual environment (requires uv to be installed):
```sh
uv tool install qmk
```
#### Community Packages
These packages are maintained by community members, so may not be up to date or completely functional. If you encounter problems, please report them to their respective maintainers.
On Arch-based distros you can install the CLI from the official repositories (NOTE: at the time of writing this package marks some dependencies as optional that should not be):
```sh
sudo pacman -S qmk
```
You can also try the `qmk-git` package from AUR:
```sh
yay -S qmk-git
```
::: warning
Any QMK packages provided by your distribution's package manager are almost certainly out of date. It is strongly suggested the installation script above is used instead.
:::
==== FreeBSD
#### Installation
::: warning
FreeBSD support is provided on a best-effort basis by the community instead of the QMK maintainers. It is strongly suggested that you use either Windows, macOS, or a supported distribution of Linux instead.
:::
Install the FreeBSD package for QMK CLI by running:
```sh
pkg install -g "py*-qmk"
```
NOTE: remember to follow the instructions printed at the end of installation (use `pkg info -Dg "py*-qmk"` to show them again).
::: info NOTE
Remember to follow the instructions printed at the end of installation (use `pkg info -Dg "py*-qmk"` to show them again).
:::
:::::

View File

@@ -15,11 +15,49 @@ You can control the behavior of one shot keys by defining these in `config.h`:
#define ONESHOT_TIMEOUT 5000 /* Time (in ms) before the one shot key is released */
```
* `OSM(mod)` - Momentarily hold down *mod*. You must use the `MOD_*` keycodes as shown in [Mod Tap](mod_tap), not the `KC_*` codes.
* `OSL(layer)` - momentary switch to *layer*.
* `OS_ON` - Turns on One Shot keys.
* `OS_OFF` - Turns off One Shot keys. OSM act as regular mod keys, OSL act like `MO`.
* `OS_TOGG` - Toggles the one shot key status.
## Keycodes {#keycodes}
|Key |Aliases |Description |
|--------------------|---------|---------------------------------------------------------------------|
|`QK_ONE_SHOT_TOGGLE`|`OS_TOGG`|Toggles One Shot keys status |
|`QK_ONE_SHOT_ON` |`OS_ON` |Turns One Shot keys on |
|`QK_ONE_SHOT_OFF` |`OS_OFF` |Turns One Shot keys off |
|`OSL(layer)` | |Switch to `layer` for one keypress |
|`OSM(mod)` | |Hold `mod` for one keypress |
|`OS_LCTL` | |Hold Left Control for one keypress |
|`OS_LSFT` | |Hold Left Shift for one keypress |
|`OS_LALT` | |Hold Left Alt for one keypress |
|`OS_LGUI` | |Hold Left GUI for one keypress |
|`OS_LCS` | |Hold Left Control and Left Shift for one keypress |
|`OS_LCA` | |Hold Left Control and left Alt for one keypress |
|`OS_LCG` | |Hold Left Control and Left GUI for one keypress |
|`OS_LSA` | |Hold Left Shift and Left Alt for one keypress |
|`OS_LSG` | |Hold Left Shift and Left GUI for one keypress |
|`OS_LAG` | |Hold Left Alt and Left GUI for one keypress |
|`OS_LCSG` | |Hold Left Control, Left Shift and Left GUI for one keypress |
|`OS_LCAG` | |Hold Left Control, Left Alt and Left GUI for one keypress |
|`OS_LSAG` | |Hold Left Shift, Left Alt and Left GUI for one keypress |
|`OS_RCTL` | |Hold Right Control for one keypress |
|`OS_RSFT` | |Hold Right Shift for one keypress |
|`OS_RALT` | |Hold Right Alt for one keypress |
|`OS_RGUI` | |Hold Right GUI for one keypress |
|`OS_RCS` | |Hold Right Control and Right Shift for one keypress |
|`OS_RCA` | |Hold Right Control and Right Alt for one keypress |
|`OS_RCG` | |Hold Right Control and Right GUI for one keypress |
|`OS_RSA` | |Hold Right Shift and Right Alt for one keypress |
|`OS_RSG` | |Hold Right Shift and Right GUI for one keypress |
|`OS_RAG` | |Hold Right Alt and Right GUI for one keypress |
|`OS_RCSG` | |Hold Right Control, Right Shift and Right GUI for one keypress |
|`OS_RCAG` | |Hold Right Control, Right Alt and Right GUI for one keypress |
|`OS_RSAG` | |Hold Right Shift, Right Alt and Right GUI for one keypress |
|`OS_MEH` | |Hold Left Control, Left Shift and Left Alt for one keypress |
|`OS_HYPR` | |Hold Left Control, Left Shift, Left Alt and Left GUI for one keypress|
When One Shot keys are turned off, `OSM()` and `OSL()` will behave like normal modifier keys and `MO()`, respectively.
::: info
The `mod` parameter to the `OSM()` keycode must use the `MOD_*` prefix, rather than `KC_*`, eg. `OSM(MOD_LCTL | MOD_LSFT)`.
:::
Sometimes, you want to activate a one-shot key as part of a macro or tap dance routine.

171
docs/proprietary_libs.md Normal file
View File

@@ -0,0 +1,171 @@
# Proprietary Vendor Libraries
QMK Firmware cannot include support for any proprietary vendor libraries that impose additional restrictions beyond those in the GPL. This includes binary-only distributions, hardware-locked libraries, and code with redistribution limitations. This document explains why such libraries are incompatible with the GPL-based QMK Firmware and addresses commonly proposed workarounds.
## Architecture Constraints
Firmware presents unique licensing challenges:
- **Monolithic binary**: All code compiles into a single executable image
- **No OS isolation**: No operating system provides process or memory separation
- **Shared resources**: All code shares the same memory space, peripherals, and execution context
- **Static linking**: Everything is statically linked at compile time
This monolithic nature means any proprietary code becomes inseparable from GPL code, creating immediate license violations.
## Common Vendor Library Restrictions
Proprietary vendor libraries typically impose restrictions incompatible with GPL freedoms:
**Hardware Lock-in:**
- Library only licensed for specific vendor's chips
- Cannot port firmware to alternative hardware
- Examples: Nordic's and ST's chip-only clauses in their respective licenses
**No Source Distribution:**
- Binary-only libraries without corresponding source
- Precompiled static libraries (.a/.lib files)
- No ability to modify or fix bugs
- Examples: WCH CH582 precompiled libraries, Nordic SoftDevice
**Redistribution Limitations:**
- Restrictions on who can distribute
- Limitations on commercial use
- Required permissions or fees
**Additional Legal Terms:**
- Patent assertions beyond GPL's scope
- Indemnification requirements
- Jurisdiction restrictions
- Explicit anti-GPL clauses
## Bluetooth Stack Licensing Examples
Both Nordic and ST provide Bluetooth stacks under restrictive licenses:
**Nordic SoftDevice (under Nordic 5-clause license):**
- Binary-only Bluetooth/radio stack
- License restricts to Nordic hardware
- No source code available
- Communicates via SVC interface (still not GPL-compatible)
**ST's Bluetooth Stack (under SLA0044 license):**
- Explicitly forbids being subject to "Open Source Terms", specifically mentioning incompatibility with the GPL
- Restricted to ST microcontrollers only
- Similar functional role to Nordic's SoftDevice
Both represent the same fundamental problem: critical wireless functionality locked behind proprietary licenses.
## Why the System Library Exception Doesn't Apply
The GPL's System Library exception **cannot** rescue proprietary vendor libraries.
### System Library Requirements
The exception only covers libraries that:
1. Are part of the "normal form of packaging a Major Component"
2. The Major Component is an OS kernel, compiler, or similar system software
3. Are not distributed with the application
4. Are not part of the application itself
### Why Vendor Libraries Fail These Requirements
1. **No operating system**: Bare-metal firmware has no OS to provide system libraries
2. **Not Major Components**: Hardware drivers and HALs aren't kernels or compilers
3. **Distributed together**: Vendor code becomes part of the firmware binary
4. **Application-level code**: Peripheral drivers are application functionality
The exception covers things like Windows system DLLs or Linux glibc, not microcontroller vendor libraries or Bluetooth stacks.
## Attempted Workarounds
### Architectural Separation Attempts
**Supervisor Call (SVC) Interfaces:**
Nordic's SoftDevice uses supervisor call based APIs instead of direct linking:
- Fixed memory regions for proprietary code
- Communication through CPU exception mechanisms
- Claims of "no linking" between components
**Why this fails:** The GPL considers functional integration, not just linking methods. In Bluetooth-capable boards, these would require the proprietary component to function, thus they form a single work regardless of the communication mechanism. This applies equally to Nordic's SoftDevice and any similar architecture ST provides.
**Binary-Only Distributions:**
Multiple vendors provide precompiled libraries:
- WCH: Precompiled BLE stack
- Nordic: Binary-only SoftDevice library
- ST: Same solution as Nordic
**Why this fails:** This is classic static linking of proprietary code into GPL code. The inability to modify these libraries violates GPL's fundamental requirements.
### Loader-Based Separation
- Write a GPL bootloader/loader
- Load proprietary firmware (such as Nordic/ST Bluetooth) from external storage
- Claim they're separate works
**Problems:**
- If designed as a system, courts view as single work
- Distribution patterns matter (shipped together?)
- Functional interdependence suggests unity
- Appears designed to circumvent GPL
## Real-World Examples
### Bluetooth/Wireless Stacks
- **Nordic SoftDevice**: Binary-only, SVC-interface, hardware-locked
- **ST Bluetooth**: Binary-only, license explicitly GPL-incompatible
- **WCH CH582**: Precompiled Bluetooth libraries
### HAL and Driver Libraries
- **ST HAL/LL drivers**: Source available but SLA0044 restricted
- **Nordic SDK**: Source visible but 5-Clause restricted
- **Various vendor HALs**: Platform-locked licenses
### Mixed Proprietary/Open
- Open peripheral drivers with closed protocol stacks
- Basic HAL with proprietary performance libraries
- Partially documented systems requiring binary supplements
## Legal and Practical Consequences
Including any proprietary vendor library means:
1. **License Violation**: Immediate GPL non-compliance
2. **Distribution Ban**: Users cannot legally share modified firmware
3. **Commercial Risk**: Products using the firmware face legal liability
4. **Contributor Tainting**: All GPL contributions become legally problematic
5. **Update Restrictions**: Cannot fix bugs in proprietary components
## Evaluation Criteria for Libraries
Before including any library, QMK needs to verify:
- Complete source code available
- GPL-compatible license (GPL, LGPL, MIT, BSD, Apache)
- No hardware restrictions
- No redistribution limitations
- No additional legal terms
- No anti-GPL clauses
## Policy Implementation
QMK Firmware maintains a strict policy:
1. **No proprietary libraries**: Regardless of technical workarounds
2. **No binary blobs**: All code must have source available
3. **No platform restrictions**: Must allow porting to any hardware
4. **No additional terms**: Only GPL restrictions permitted
## Summary
There is no legally safe way to include proprietary vendor libraries in GPL firmware. This applies whether they're:
- Bluetooth stacks (Nordic SoftDevice, ST Bluetooth)
- Precompiled static libraries
- Binary blobs with SVC interfaces
- Source code with restrictive licenses
- Mixed open/closed systems
**Technical architectures cannot overcome license obligations.**
QMK chooses GPL compliance, ensuring users receive all freedoms the GPL promises.

View File

@@ -2,7 +2,7 @@
The information contained in `info.json` is combined with the `config.h` and `rules.mk` files, dynamically generating the necessary configuration for your keyboard at compile time. It is also used by the [QMK API](https://github.com/qmk/qmk_api), and contains the information [QMK Configurator](https://config.qmk.fm/) needs to display a representation of your keyboard. Its key/value pairs are ruled by the [`data/schemas/keyboard.jsonschema`](https://github.com/qmk/qmk_firmware/blob/master/data/schemas/keyboard.jsonschema) file. To learn more about the why and how of the schema file see the [Data Driven Configuration](data_driven_config) page.
You can create `info.json` files at every level under `qmk_firmware/keyboards/<keyboard_name>`. These files are combined, with more specific files overriding keys in less specific files. This means you do not need to duplicate your metadata information. For example, `qmk_firmware/keyboards/clueboard/info.json` specifies information common to all Clueboard products, such as `manufacturer` and `maintainer`, while `qmk_firmware/keyboards/clueboard/66/info.json` contains more specific information about Clueboard 66%.
You can create `info.json` files at every level under `qmk_firmware/keyboards/<keyboard>`. These files are combined, with more specific files overriding keys in less specific files. This means you do not need to duplicate your metadata information. For example, `qmk_firmware/keyboards/clueboard/info.json` specifies information common to all Clueboard products, such as `manufacturer` and `maintainer`, while `qmk_firmware/keyboards/clueboard/66/info.json` contains more specific information about Clueboard 66%.
## General Metadata {#general-metadata}

View File

@@ -19,5 +19,5 @@
#include_next <mcuconf.h>
#undef RP_SPI_USE_SPI1
#define RP_SPI_USE_SPI1 TRUE
#undef RP_SPI_USE_SPI0
#define RP_SPI_USE_SPI0 TRUE

View File

@@ -0,0 +1,24 @@
/* Copyright 2025 Cipulot
*
* 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 3 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
// PWM driver with direct memory access (DMA) support
#define WS2812_PWM_DRIVER PWMD1
#define WS2812_PWM_CHANNEL 2
#define WS2812_PWM_PAL_MODE 2
#define WS2812_DMA_STREAM STM32_DMA1_STREAM5
#define WS2812_DMA_CHANNEL 6

View File

@@ -0,0 +1,21 @@
/* Copyright 2025 Cipulot
*
* 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 3 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
#define HAL_USE_PWM TRUE
#include_next <halconf.h>

View File

@@ -0,0 +1,6 @@
{
"keyboard_name": "MX65X Hotswap",
"usb": {
"pid": "0x6BD8"
}
}

View File

@@ -0,0 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF

View File

@@ -0,0 +1,421 @@
{
"manufacturer": "Cipulot",
"maintainer": "Cipulot",
"bootloader": "stm32-dfu",
"build": {
"lto": true
},
"diode_direction": "COL2ROW",
"encoder": {
"rotary": [
{"pin_a": "F0", "pin_b": "F1"}
]
},
"features": {
"bootmagic": true,
"encoder": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"rgblight": true
},
"matrix_pins": {
"cols": ["B14", "B12", "B11", "B10", "B2", "B1", "B0", "A7", "A6", "A5", "A4", "A3", "A2", "A1", "A0"],
"rows": ["A15", "B7", "B13", "B15", "A8"]
},
"processor": "STM32F072",
"qmk": {
"locking": {
"enabled": true,
"resync": true
}
},
"rgblight": {
"animations": {
"alternating": true,
"breathing": true,
"christmas": true,
"knight": true,
"rainbow_mood": true,
"rainbow_swirl": true,
"rgb_test": true,
"snake": true,
"static_gradient": true,
"twinkle": true
},
"led_count": 26
},
"usb": {
"device_version": "0.0.1",
"shared_endpoint": {
"keyboard": true
},
"vid": "0x6369"
},
"ws2812": {
"driver": "pwm",
"pin": "A9"
},
"layouts": {
"LAYOUT_65_ansi_blocker": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 14], "x": 13, "y": 0, "w": 2},
{"matrix": [1, 14], "x": 15, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 1], "x": 1.5, "y": 1},
{"matrix": [1, 2], "x": 2.5, "y": 1},
{"matrix": [1, 3], "x": 3.5, "y": 1},
{"matrix": [1, 4], "x": 4.5, "y": 1},
{"matrix": [1, 5], "x": 5.5, "y": 1},
{"matrix": [1, 6], "x": 6.5, "y": 1},
{"matrix": [1, 7], "x": 7.5, "y": 1},
{"matrix": [1, 8], "x": 8.5, "y": 1},
{"matrix": [1, 9], "x": 9.5, "y": 1},
{"matrix": [1, 10], "x": 10.5, "y": 1},
{"matrix": [1, 11], "x": 11.5, "y": 1},
{"matrix": [1, 12], "x": 12.5, "y": 1},
{"matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
{"matrix": [2, 14], "x": 15, "y": 1},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 1], "x": 1.75, "y": 2},
{"matrix": [2, 2], "x": 2.75, "y": 2},
{"matrix": [2, 3], "x": 3.75, "y": 2},
{"matrix": [2, 4], "x": 4.75, "y": 2},
{"matrix": [2, 5], "x": 5.75, "y": 2},
{"matrix": [2, 6], "x": 6.75, "y": 2},
{"matrix": [2, 7], "x": 7.75, "y": 2},
{"matrix": [2, 8], "x": 8.75, "y": 2},
{"matrix": [2, 9], "x": 9.75, "y": 2},
{"matrix": [2, 10], "x": 10.75, "y": 2},
{"matrix": [2, 11], "x": 11.75, "y": 2},
{"matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"matrix": [3, 14], "x": 15, "y": 2},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 12], "x": 12.25, "y": 3, "w": 1.75},
{"matrix": [3, 13], "x": 14, "y": 3},
{"matrix": [4, 14], "x": 15, "y": 3},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
{"matrix": [4, 6], "x": 3.75, "y": 4, "w": 6.25},
{"matrix": [4, 9], "x": 10, "y": 4, "w": 1.25},
{"matrix": [4, 10], "x": 11.25, "y": 4, "w": 1.25},
{"matrix": [4, 11], "x": 13, "y": 4},
{"matrix": [4, 12], "x": 14, "y": 4},
{"matrix": [4, 13], "x": 15, "y": 4}
]
},
"LAYOUT_65_ansi_blocker_tsangan": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 14], "x": 13, "y": 0, "w": 2},
{"matrix": [1, 14], "x": 15, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 1], "x": 1.5, "y": 1},
{"matrix": [1, 2], "x": 2.5, "y": 1},
{"matrix": [1, 3], "x": 3.5, "y": 1},
{"matrix": [1, 4], "x": 4.5, "y": 1},
{"matrix": [1, 5], "x": 5.5, "y": 1},
{"matrix": [1, 6], "x": 6.5, "y": 1},
{"matrix": [1, 7], "x": 7.5, "y": 1},
{"matrix": [1, 8], "x": 8.5, "y": 1},
{"matrix": [1, 9], "x": 9.5, "y": 1},
{"matrix": [1, 10], "x": 10.5, "y": 1},
{"matrix": [1, 11], "x": 11.5, "y": 1},
{"matrix": [1, 12], "x": 12.5, "y": 1},
{"matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
{"matrix": [2, 14], "x": 15, "y": 1},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 1], "x": 1.75, "y": 2},
{"matrix": [2, 2], "x": 2.75, "y": 2},
{"matrix": [2, 3], "x": 3.75, "y": 2},
{"matrix": [2, 4], "x": 4.75, "y": 2},
{"matrix": [2, 5], "x": 5.75, "y": 2},
{"matrix": [2, 6], "x": 6.75, "y": 2},
{"matrix": [2, 7], "x": 7.75, "y": 2},
{"matrix": [2, 8], "x": 8.75, "y": 2},
{"matrix": [2, 9], "x": 9.75, "y": 2},
{"matrix": [2, 10], "x": 10.75, "y": 2},
{"matrix": [2, 11], "x": 11.75, "y": 2},
{"matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"matrix": [3, 14], "x": 15, "y": 2},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 12], "x": 12.25, "y": 3, "w": 1.75},
{"matrix": [3, 13], "x": 14, "y": 3},
{"matrix": [4, 14], "x": 15, "y": 3},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.5},
{"matrix": [4, 1], "x": 1.5, "y": 4},
{"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.5},
{"matrix": [4, 6], "x": 4, "y": 4, "w": 7},
{"matrix": [4, 10], "x": 11, "y": 4, "w": 1.5},
{"matrix": [4, 11], "x": 13, "y": 4},
{"matrix": [4, 12], "x": 14, "y": 4},
{"matrix": [4, 13], "x": 15, "y": 4}
]
},
"LAYOUT_65_iso_blocker": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 14], "x": 13, "y": 0, "w": 2},
{"matrix": [1, 14], "x": 15, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 1], "x": 1.5, "y": 1},
{"matrix": [1, 2], "x": 2.5, "y": 1},
{"matrix": [1, 3], "x": 3.5, "y": 1},
{"matrix": [1, 4], "x": 4.5, "y": 1},
{"matrix": [1, 5], "x": 5.5, "y": 1},
{"matrix": [1, 6], "x": 6.5, "y": 1},
{"matrix": [1, 7], "x": 7.5, "y": 1},
{"matrix": [1, 8], "x": 8.5, "y": 1},
{"matrix": [1, 9], "x": 9.5, "y": 1},
{"matrix": [1, 10], "x": 10.5, "y": 1},
{"matrix": [1, 11], "x": 11.5, "y": 1},
{"matrix": [1, 12], "x": 12.5, "y": 1},
{"matrix": [2, 14], "x": 15, "y": 1},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 1], "x": 1.75, "y": 2},
{"matrix": [2, 2], "x": 2.75, "y": 2},
{"matrix": [2, 3], "x": 3.75, "y": 2},
{"matrix": [2, 4], "x": 4.75, "y": 2},
{"matrix": [2, 5], "x": 5.75, "y": 2},
{"matrix": [2, 6], "x": 6.75, "y": 2},
{"matrix": [2, 7], "x": 7.75, "y": 2},
{"matrix": [2, 8], "x": 8.75, "y": 2},
{"matrix": [2, 9], "x": 9.75, "y": 2},
{"matrix": [2, 10], "x": 10.75, "y": 2},
{"matrix": [2, 11], "x": 11.75, "y": 2},
{"matrix": [2, 12], "x": 12.75, "y": 2},
{"matrix": [2, 13], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
{"matrix": [3, 14], "x": 15, "y": 2},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
{"matrix": [3, 1], "x": 1.25, "y": 3},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 12], "x": 12.25, "y": 3, "w": 1.75},
{"matrix": [3, 13], "x": 14, "y": 3},
{"matrix": [4, 14], "x": 15, "y": 3},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
{"matrix": [4, 6], "x": 3.75, "y": 4, "w": 6.25},
{"matrix": [4, 9], "x": 10, "y": 4, "w": 1.25},
{"matrix": [4, 10], "x": 11.25, "y": 4, "w": 1.25},
{"matrix": [4, 11], "x": 13, "y": 4},
{"matrix": [4, 12], "x": 14, "y": 4},
{"matrix": [4, 13], "x": 15, "y": 4}
]
},
"LAYOUT_65_iso_blocker_tsangan": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 14], "x": 13, "y": 0, "w": 2},
{"matrix": [1, 14], "x": 15, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 1], "x": 1.5, "y": 1},
{"matrix": [1, 2], "x": 2.5, "y": 1},
{"matrix": [1, 3], "x": 3.5, "y": 1},
{"matrix": [1, 4], "x": 4.5, "y": 1},
{"matrix": [1, 5], "x": 5.5, "y": 1},
{"matrix": [1, 6], "x": 6.5, "y": 1},
{"matrix": [1, 7], "x": 7.5, "y": 1},
{"matrix": [1, 8], "x": 8.5, "y": 1},
{"matrix": [1, 9], "x": 9.5, "y": 1},
{"matrix": [1, 10], "x": 10.5, "y": 1},
{"matrix": [1, 11], "x": 11.5, "y": 1},
{"matrix": [1, 12], "x": 12.5, "y": 1},
{"matrix": [2, 14], "x": 15, "y": 1},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 1], "x": 1.75, "y": 2},
{"matrix": [2, 2], "x": 2.75, "y": 2},
{"matrix": [2, 3], "x": 3.75, "y": 2},
{"matrix": [2, 4], "x": 4.75, "y": 2},
{"matrix": [2, 5], "x": 5.75, "y": 2},
{"matrix": [2, 6], "x": 6.75, "y": 2},
{"matrix": [2, 7], "x": 7.75, "y": 2},
{"matrix": [2, 8], "x": 8.75, "y": 2},
{"matrix": [2, 9], "x": 9.75, "y": 2},
{"matrix": [2, 10], "x": 10.75, "y": 2},
{"matrix": [2, 11], "x": 11.75, "y": 2},
{"matrix": [2, 12], "x": 12.75, "y": 2},
{"matrix": [2, 13], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
{"matrix": [3, 14], "x": 15, "y": 2},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
{"matrix": [3, 1], "x": 1.25, "y": 3},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 12], "x": 12.25, "y": 3, "w": 1.75},
{"matrix": [3, 13], "x": 14, "y": 3},
{"matrix": [4, 14], "x": 15, "y": 3},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.5},
{"matrix": [4, 1], "x": 1.5, "y": 4},
{"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.5},
{"matrix": [4, 6], "x": 4, "y": 4, "w": 7},
{"matrix": [4, 10], "x": 11, "y": 4, "w": 1.5},
{"matrix": [4, 11], "x": 13, "y": 4},
{"matrix": [4, 12], "x": 14, "y": 4},
{"matrix": [4, 13], "x": 15, "y": 4}
]
},
"LAYOUT_all": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 13], "x": 13, "y": 0},
{"matrix": [0, 14], "x": 14, "y": 0},
{"matrix": [1, 14], "x": 15, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 1], "x": 1.5, "y": 1},
{"matrix": [1, 2], "x": 2.5, "y": 1},
{"matrix": [1, 3], "x": 3.5, "y": 1},
{"matrix": [1, 4], "x": 4.5, "y": 1},
{"matrix": [1, 5], "x": 5.5, "y": 1},
{"matrix": [1, 6], "x": 6.5, "y": 1},
{"matrix": [1, 7], "x": 7.5, "y": 1},
{"matrix": [1, 8], "x": 8.5, "y": 1},
{"matrix": [1, 9], "x": 9.5, "y": 1},
{"matrix": [1, 10], "x": 10.5, "y": 1},
{"matrix": [1, 11], "x": 11.5, "y": 1},
{"matrix": [1, 12], "x": 12.5, "y": 1},
{"matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
{"matrix": [2, 14], "x": 15, "y": 1},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 1], "x": 1.75, "y": 2},
{"matrix": [2, 2], "x": 2.75, "y": 2},
{"matrix": [2, 3], "x": 3.75, "y": 2},
{"matrix": [2, 4], "x": 4.75, "y": 2},
{"matrix": [2, 5], "x": 5.75, "y": 2},
{"matrix": [2, 6], "x": 6.75, "y": 2},
{"matrix": [2, 7], "x": 7.75, "y": 2},
{"matrix": [2, 8], "x": 8.75, "y": 2},
{"matrix": [2, 9], "x": 9.75, "y": 2},
{"matrix": [2, 10], "x": 10.75, "y": 2},
{"matrix": [2, 11], "x": 11.75, "y": 2},
{"matrix": [2, 12], "x": 12.75, "y": 2},
{"matrix": [2, 13], "x": 13.75, "y": 2, "w": 1.25},
{"matrix": [3, 14], "x": 15, "y": 2},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
{"matrix": [3, 1], "x": 1.25, "y": 3},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 12], "x": 12.25, "y": 3, "w": 1.75},
{"matrix": [3, 13], "x": 14, "y": 3},
{"matrix": [4, 14], "x": 15, "y": 3},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.5},
{"matrix": [4, 1], "x": 1.5, "y": 4},
{"matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.5},
{"matrix": [4, 4], "x": 4, "y": 4, "w": 2.5},
{"matrix": [4, 6], "x": 6.5, "y": 4},
{"matrix": [4, 8], "x": 7.5, "y": 4, "w": 2.5},
{"matrix": [4, 9], "x": 10, "y": 4},
{"matrix": [4, 10], "x": 11, "y": 4, "w": 1.5},
{"matrix": [4, 11], "x": 13, "y": 4},
{"matrix": [4, 12], "x": 14, "y": 4},
{"matrix": [4, 13], "x": 15, "y": 4}
]
}
}
}

View File

@@ -0,0 +1,50 @@
/* Copyright 2025 Cipulot
*
* 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 3 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
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_65_ansi_blocker(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENTER, KC_PGDN,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, MO(1),
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT),
[1] = LAYOUT_65_ansi_blocker(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, MO(2), _______, _______, _______),
[2] = LAYOUT_65_ansi_blocker(
QK_BOOT, NK_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(_______, _______) },
[2] = { ENCODER_CCW_CW(_______, _______) }
};
#endif
// clang-format on

View File

@@ -0,0 +1 @@
ENCODER_MAP_ENABLE = yes

View File

@@ -0,0 +1,50 @@
/* Copyright 2025 Cipulot
*
* 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 3 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
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_65_ansi_blocker_tsangan(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENTER, KC_PGDN,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, MO(1),
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT),
[1] = LAYOUT_65_ansi_blocker_tsangan(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, MO(2), _______, _______, _______),
[2] = LAYOUT_65_ansi_blocker_tsangan(
QK_BOOT, NK_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(_______, _______) },
[2] = { ENCODER_CCW_CW(_______, _______) }
};
#endif
// clang-format on

View File

@@ -0,0 +1 @@
ENCODER_MAP_ENABLE = yes

View File

@@ -0,0 +1,50 @@
/* Copyright 2025 Cipulot
*
* 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 3 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
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_65_iso_blocker(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENTER, KC_PGDN,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, MO(1),
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT),
[1] = LAYOUT_65_iso_blocker(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, MO(2), _______, _______, _______),
[2] = LAYOUT_65_iso_blocker(
QK_BOOT, NK_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(_______, _______) },
[2] = { ENCODER_CCW_CW(_______, _______) }
};
#endif
// clang-format on

View File

@@ -0,0 +1 @@
ENCODER_MAP_ENABLE = yes

View File

@@ -0,0 +1,50 @@
/* Copyright 2025 Cipulot
*
* 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 3 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
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_65_iso_blocker_tsangan(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENTER, KC_PGDN,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, MO(1),
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT),
[1] = LAYOUT_65_iso_blocker_tsangan(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, MO(2), _______, _______, _______),
[2] = LAYOUT_65_iso_blocker_tsangan(
QK_BOOT, NK_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(_______, _______) },
[2] = { ENCODER_CCW_CW(_______, _______) }
};
#endif
// clang-format on

View File

@@ -0,0 +1 @@
ENCODER_MAP_ENABLE = yes

View File

@@ -0,0 +1,50 @@
/* Copyright 2025 Cipulot
*
* 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 3 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
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_all(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENTER, KC_PGDN,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, MO(1),
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_SPC, KC_SPC, KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RIGHT),
[1] = LAYOUT_all(
_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, MO(2), _______, _______, _______),
[2] = LAYOUT_all(
QK_BOOT, NK_TOGG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______)
};
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(_______, _______) },
[2] = { ENCODER_CCW_CW(_______, _______) }
};
#endif
// clang-format on

View File

@@ -0,0 +1 @@
ENCODER_MAP_ENABLE = yes

View File

@@ -0,0 +1,22 @@
/* Copyright 2025 Cipulot
*
* 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 3 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
#include_next <mcuconf.h>
#undef STM32_PWM_USE_TIM1
#define STM32_PWM_USE_TIM1 TRUE

View File

@@ -0,0 +1,36 @@
# MX65X
A 65% solder and hotswap PCB.
Solder
![MX65X Solder](https://i.imgur.com/M2lyPuo.png)
Hotswap
![MX65X Hotswap](https://i.imgur.com/18DnNrw.png)
* Keyboard Maintainer: [cipulot](https://github.com/cipulot)
* Hardware Supported: MX65X Solder and Hotswap
* Hardware Availability: [Clever Keebs](https://cleverkeebs.com)
Make example for this keyboard (after setting up your build environment):
make cipulot/mx65x/solder:default
make cipulot/mx65x/hotswap:default
Flashing example for this keyboard:
make cipulot/mx65x/solder:default:flash
make cipulot/mx65x/hotswap:default:flash
See 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).
## Bootloader
Enter the bootloader in 3 ways:
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is configured.
* **Physical reset button**: Long press the reset button soldered on the PCB.
* **Bootmagic reset**: Hold down the top left key and plug in the controller.

View File

@@ -0,0 +1,6 @@
{
"keyboard_name": "MX65X Solder",
"usb": {
"pid": "0x6BD7"
}
}

View File

@@ -0,0 +1,2 @@
# Wildcard to allow APM32 MCU
DFU_SUFFIX_ARGS = -v FFFF -p FFFF

View File

@@ -0,0 +1,33 @@
{
"manufacturer": "Trey Wax",
"keyboard_name": "cloud_macro",
"maintainer": "TweyHugs",
"development_board": "kb2040",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true
},
"matrix_pins": {
"direct":[
["GP2", "GP3", "GP4", "GP5", "GP6"]
]
},
"usb": {
"device_version": "1.0.0",
"pid": "0x0000",
"vid": "0xFEED"
},
"layouts": {
"LAYOUT": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0}
]
}
}
}

View File

@@ -0,0 +1,8 @@
// Copyright 2023 QMK
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(KC_1, KC_2, KC_3, KC_4, KC_5)
};

View File

@@ -0,0 +1,27 @@
# cloud_macro
![cloud_macro](https://i.imgur.com/n0PMttQ.jpeg)
A 5 key macropad in the shape of a cloud
* Keyboard Maintainer: [Trey Wax](https://github.com/TweyHugs)
* Hardware Supported: Adafruit KB2040
* Hardware Availability: *https://circuitrey.carrd.co/*
Make example for this keyboard (after setting up your build environment):
make cloud_macro:default
Flashing example for this keyboard:
make cloud_macro:default:flash
See 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).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@@ -0,0 +1,41 @@
/* Copyright 2023 CMM.S Freather
*
* 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 "quantum.h"
#ifdef RGBLIGHT_LAYERS
const rgblight_segment_t PROGMEM my_capslock_layer[] = RGBLIGHT_LAYER_SEGMENTS(
{0, 1, HSV_WHITE}
);
// Now define the array of layers. Later layers take precedence
const rgblight_segment_t* const PROGMEM my_rgb_layers[] = RGBLIGHT_LAYERS_LIST(
my_capslock_layer
);
void keyboard_post_init_kb(void){
rgblight_layers = my_rgb_layers;
keyboard_post_init_user();
}
bool led_update_kb(led_t led_state){
bool res = led_update_user(led_state);
if (res) {
rgblight_set_layer_state(0, led_state.caps_lock);
}
return res;
}
#endif

View File

@@ -0,0 +1,312 @@
{
"manufacturer": "GrayStudio",
"keyboard_name": "BD60",
"maintainer": "srk24",
"bootloader": "stm32-dfu",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"rgblight": true
},
"matrix_pins": {
"cols": ["A3", "C14", "C13", "B9", "B8", "B7", "B6", "B5", "B4", "B3", "A15", "B0", "A8", "B15", "B14"],
"rows": ["B13", "B12", "A2", "A0", "A1"]
},
"processor": "STM32F072",
"rgblight": {
"animations": {
"alternating": true,
"breathing": true,
"christmas": true,
"knight": true,
"rainbow_mood": true,
"rainbow_swirl": true,
"snake": true,
"static_gradient": true,
"twinkle": true
},
"brightness_steps": 8,
"default": {
"animation": "rainbow_mood"
},
"layers": {
"enabled": true
},
"led_count": 1,
"max_brightness": 150,
"saturation_steps": 8,
"sleep": true
},
"usb": {
"device_version": "0.0.2",
"pid": "0x4060",
"vid": "0x4753"
},
"ws2812": {
"pin": "B10"
},
"community_layouts": ["60_ansi", "60_ansi_wkl", "60_hhkb"],
"layouts": {
"LAYOUT_60_ansi": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 13], "x": 13, "y": 0, "w": 2},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 2], "x": 1.5, "y": 1},
{"matrix": [1, 3], "x": 2.5, "y": 1},
{"matrix": [1, 4], "x": 3.5, "y": 1},
{"matrix": [1, 5], "x": 4.5, "y": 1},
{"matrix": [1, 6], "x": 5.5, "y": 1},
{"matrix": [1, 7], "x": 6.5, "y": 1},
{"matrix": [1, 8], "x": 7.5, "y": 1},
{"matrix": [1, 9], "x": 8.5, "y": 1},
{"matrix": [1, 10], "x": 9.5, "y": 1},
{"matrix": [1, 11], "x": 10.5, "y": 1},
{"matrix": [1, 12], "x": 11.5, "y": 1},
{"matrix": [1, 13], "x": 12.5, "y": 1},
{"matrix": [1, 14], "x": 13.5, "y": 1, "w": 1.5},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 2], "x": 1.75, "y": 2},
{"matrix": [2, 3], "x": 2.75, "y": 2},
{"matrix": [2, 4], "x": 3.75, "y": 2},
{"matrix": [2, 5], "x": 4.75, "y": 2},
{"matrix": [2, 6], "x": 5.75, "y": 2},
{"matrix": [2, 7], "x": 6.75, "y": 2},
{"matrix": [2, 8], "x": 7.75, "y": 2},
{"matrix": [2, 9], "x": 8.75, "y": 2},
{"matrix": [2, 10], "x": 9.75, "y": 2},
{"matrix": [2, 11], "x": 10.75, "y": 2},
{"matrix": [2, 12], "x": 11.75, "y": 2},
{"matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 13], "x": 12.25, "y": 3, "w": 2.75},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"matrix": [4, 3], "x": 2.5, "y": 4, "w": 1.25},
{"matrix": [4, 7], "x": 3.75, "y": 4, "w": 6.25},
{"matrix": [4, 10], "x": 10, "y": 4, "w": 1.25},
{"matrix": [4, 11], "x": 11.25, "y": 4, "w": 1.25},
{"matrix": [4, 13], "x": 12.5, "y": 4, "w": 1.25},
{"matrix": [4, 14], "x": 13.75, "y": 4, "w": 1.25}
]
},
"LAYOUT_60_ansi_wkl": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 13], "x": 13, "y": 0, "w": 2},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 2], "x": 1.5, "y": 1},
{"matrix": [1, 3], "x": 2.5, "y": 1},
{"matrix": [1, 4], "x": 3.5, "y": 1},
{"matrix": [1, 5], "x": 4.5, "y": 1},
{"matrix": [1, 6], "x": 5.5, "y": 1},
{"matrix": [1, 7], "x": 6.5, "y": 1},
{"matrix": [1, 8], "x": 7.5, "y": 1},
{"matrix": [1, 9], "x": 8.5, "y": 1},
{"matrix": [1, 10], "x": 9.5, "y": 1},
{"matrix": [1, 11], "x": 10.5, "y": 1},
{"matrix": [1, 12], "x": 11.5, "y": 1},
{"matrix": [1, 13], "x": 12.5, "y": 1},
{"matrix": [1, 14], "x": 13.5, "y": 1, "w": 1.5},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 2], "x": 1.75, "y": 2},
{"matrix": [2, 3], "x": 2.75, "y": 2},
{"matrix": [2, 4], "x": 3.75, "y": 2},
{"matrix": [2, 5], "x": 4.75, "y": 2},
{"matrix": [2, 6], "x": 5.75, "y": 2},
{"matrix": [2, 7], "x": 6.75, "y": 2},
{"matrix": [2, 8], "x": 7.75, "y": 2},
{"matrix": [2, 9], "x": 8.75, "y": 2},
{"matrix": [2, 10], "x": 9.75, "y": 2},
{"matrix": [2, 11], "x": 10.75, "y": 2},
{"matrix": [2, 12], "x": 11.75, "y": 2},
{"matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 13], "x": 12.25, "y": 3, "w": 2.75},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.5},
{"matrix": [4, 3], "x": 2.5, "y": 4, "w": 1.5},
{"matrix": [4, 7], "x": 3.75, "y": 4, "w": 7},
{"matrix": [4, 11], "x": 11.25, "y": 4, "w": 1.5},
{"matrix": [4, 14], "x": 13.75, "y": 4, "w": 1.5}
]
},
"LAYOUT_60_hhkb": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 13], "x": 13, "y": 0},
{"matrix": [0, 14], "x": 14, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 2], "x": 1.5, "y": 1},
{"matrix": [1, 3], "x": 2.5, "y": 1},
{"matrix": [1, 4], "x": 3.5, "y": 1},
{"matrix": [1, 5], "x": 4.5, "y": 1},
{"matrix": [1, 6], "x": 5.5, "y": 1},
{"matrix": [1, 7], "x": 6.5, "y": 1},
{"matrix": [1, 8], "x": 7.5, "y": 1},
{"matrix": [1, 9], "x": 8.5, "y": 1},
{"matrix": [1, 10], "x": 9.5, "y": 1},
{"matrix": [1, 11], "x": 10.5, "y": 1},
{"matrix": [1, 12], "x": 11.5, "y": 1},
{"matrix": [1, 13], "x": 12.5, "y": 1},
{"matrix": [1, 14], "x": 13.5, "y": 1, "w": 1.5},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 2], "x": 1.75, "y": 2},
{"matrix": [2, 3], "x": 2.75, "y": 2},
{"matrix": [2, 4], "x": 3.75, "y": 2},
{"matrix": [2, 5], "x": 4.75, "y": 2},
{"matrix": [2, 6], "x": 5.75, "y": 2},
{"matrix": [2, 7], "x": 6.75, "y": 2},
{"matrix": [2, 8], "x": 7.75, "y": 2},
{"matrix": [2, 9], "x": 8.75, "y": 2},
{"matrix": [2, 10], "x": 9.75, "y": 2},
{"matrix": [2, 11], "x": 10.75, "y": 2},
{"matrix": [2, 12], "x": 11.75, "y": 2},
{"matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 13], "x": 12.25, "y": 3, "w": 1.75},
{"matrix": [3, 14], "x": 14, "y": 3},
{"matrix": [4, 1], "x": 1.25, "y": 4, "w": 1},
{"matrix": [4, 3], "x": 2.5, "y": 4, "w": 1.5},
{"matrix": [4, 7], "x": 3.75, "y": 4, "w": 7},
{"matrix": [4, 11], "x": 11.25, "y": 4, "w": 1.5},
{"matrix": [4, 13], "x": 12.5, "y": 4, "w": 1}
]
},
"LAYOUT_all": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0},
{"matrix": [0, 2], "x": 2, "y": 0},
{"matrix": [0, 3], "x": 3, "y": 0},
{"matrix": [0, 4], "x": 4, "y": 0},
{"matrix": [0, 5], "x": 5, "y": 0},
{"matrix": [0, 6], "x": 6, "y": 0},
{"matrix": [0, 7], "x": 7, "y": 0},
{"matrix": [0, 8], "x": 8, "y": 0},
{"matrix": [0, 9], "x": 9, "y": 0},
{"matrix": [0, 10], "x": 10, "y": 0},
{"matrix": [0, 11], "x": 11, "y": 0},
{"matrix": [0, 12], "x": 12, "y": 0},
{"matrix": [0, 13], "x": 13, "y": 0},
{"matrix": [0, 14], "x": 14, "y": 0},
{"matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
{"matrix": [1, 2], "x": 1.5, "y": 1},
{"matrix": [1, 3], "x": 2.5, "y": 1},
{"matrix": [1, 4], "x": 3.5, "y": 1},
{"matrix": [1, 5], "x": 4.5, "y": 1},
{"matrix": [1, 6], "x": 5.5, "y": 1},
{"matrix": [1, 7], "x": 6.5, "y": 1},
{"matrix": [1, 8], "x": 7.5, "y": 1},
{"matrix": [1, 9], "x": 8.5, "y": 1},
{"matrix": [1, 10], "x": 9.5, "y": 1},
{"matrix": [1, 11], "x": 10.5, "y": 1},
{"matrix": [1, 12], "x": 11.5, "y": 1},
{"matrix": [1, 13], "x": 12.5, "y": 1},
{"matrix": [1, 14], "x": 13.5, "y": 1, "w": 1.5},
{"matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
{"matrix": [2, 2], "x": 1.75, "y": 2},
{"matrix": [2, 3], "x": 2.75, "y": 2},
{"matrix": [2, 4], "x": 3.75, "y": 2},
{"matrix": [2, 5], "x": 4.75, "y": 2},
{"matrix": [2, 6], "x": 5.75, "y": 2},
{"matrix": [2, 7], "x": 6.75, "y": 2},
{"matrix": [2, 8], "x": 7.75, "y": 2},
{"matrix": [2, 9], "x": 8.75, "y": 2},
{"matrix": [2, 10], "x": 9.75, "y": 2},
{"matrix": [2, 11], "x": 10.75, "y": 2},
{"matrix": [2, 12], "x": 11.75, "y": 2},
{"matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
{"matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
{"matrix": [3, 2], "x": 2.25, "y": 3},
{"matrix": [3, 3], "x": 3.25, "y": 3},
{"matrix": [3, 4], "x": 4.25, "y": 3},
{"matrix": [3, 5], "x": 5.25, "y": 3},
{"matrix": [3, 6], "x": 6.25, "y": 3},
{"matrix": [3, 7], "x": 7.25, "y": 3},
{"matrix": [3, 8], "x": 8.25, "y": 3},
{"matrix": [3, 9], "x": 9.25, "y": 3},
{"matrix": [3, 10], "x": 10.25, "y": 3},
{"matrix": [3, 11], "x": 11.25, "y": 3},
{"matrix": [3, 13], "x": 12.25, "y": 3, "w": 1.75},
{"matrix": [3, 14], "x": 14, "y": 3},
{"matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
{"matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
{"matrix": [4, 3], "x": 2.5, "y": 4, "w": 1.25},
{"matrix": [4, 7], "x": 3.75, "y": 4, "w": 6.25},
{"matrix": [4, 10], "x": 10, "y": 4, "w": 1.25},
{"matrix": [4, 11], "x": 11.25, "y": 4, "w": 1.25},
{"matrix": [4, 13], "x": 12.5, "y": 4, "w": 1.25},
{"matrix": [4, 14], "x": 13.75, "y": 4, "w": 1.25}
]
}
}
}

View File

@@ -0,0 +1,20 @@
// Copyright 2023 srk24
// SPDX-License-Identifier: GPL-2.0
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_all(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(1),
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_RCTL, MO(1)
),
[1] = LAYOUT_all(
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_INS,
_______, UG_TOGG, KC_UP, UG_NEXT, _______, _______, _______, UG_VALU, UG_VALD, _______, _______, _______, _______, KC_INS,
_______, KC_LEFT, KC_DOWN, KC_RGHT, _______, _______, _______, _______, _______, _______, _______, _______, _______,
KC_MPRV, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, _______,
_______, _______, _______, KC_MPLY, _______, KC_LEFT, KC_RGHT, _______
)
};

View File

@@ -0,0 +1,24 @@
# Matrix Diagram for GrayStudio BD60
```
┌───────┐
2u Backspace │0D │
└───────┘
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│00 │01 │02 │03 │04 │05 │06 │07 │08 │09 │0A │0B │0C │0D │0E │
├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴───┤
│10 │12 │13 │14 │15 │16 │17 │18 │19 │1A │1B │1C │1D │1E │
├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤
│20 │22 │23 │24 │25 │26 │27 │28 │29 │2A │2B │2C │2D │
├──────┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴────┬───┤
│30 │32 │33 │34 │35 │36 │37 │38 │39 │3A │3B │3D │3E │
├────┬───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴───┼───┴┬────┬┴───┤
│40 │41 │43 │47 │4A │4B │4D │4E │
└────┴────┴────┴────────────────────────┴────┴────┴────┴────┘
┌────────┐ ┌──────────┐
│30 │ 2.25u LShift 2.75u RShift │3D │
└────────┘ └──────────┘
┌─────┬───┬─────┬───────────────────────────┬─────┬───┬─────┐
│40 │41 │43 │47 │4B │4D │4E │ Tsangan/WKL/HHKB
└─────┴───┴─────┴───────────────────────────┴─────┴───┴─────┘
```

View File

@@ -0,0 +1,21 @@
# Gray Studio BD60
A 65% keyboard by Graystudio. PCB designed and manufactured by DEMO Studio.
* Keyboard Maintainer: [srk24](https://github.com/srk24)
* Hardware Support: BD60 PCB w/ STM32F072 microcontroller
* Hardware Availability: [graystudio.club/bd60](https://in-stock.graystudio.club/products/in-stock-bd60)
Make example for this keyboard (after setting up your build environment):
make gray_studio/bd60:default
Flashing example for this keyboard:
make gray_studio/bd60:default:flash
See 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).
## Bootloader
* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead

View File

@@ -0,0 +1,35 @@
/* Copyright (C) 2023 jonylee@hfd
*
* 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
/* LED Indicators */
#define LED_WIN_LOCK_PIN C11
/* SPI Config for spi flash*/
#define SPI_DRIVER SPIDQ
#define SPI_SCK_PIN B3
#define SPI_MOSI_PIN B5
#define SPI_MISO_PIN B4
#define SPI_MOSI_PAL_MODE 5
#define EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN C12
/* I2C Config for LED Driver */
#define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
#define SNLED27351_I2C_ADDRESS_2 SNLED27351_I2C_ADDRESS_VDDIO
#define I2C1_CLOCK_SPEED 400000 /* 400000 */
#define I2C1_OPMODE OPMODE_I2C

View File

@@ -0,0 +1,21 @@
/* Copyright (C) 2023 jonylee@hfd
*
* 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
#define HAL_USE_I2C TRUE
#define HAL_USE_SPI TRUE
#include_next <halconf.h>

View File

@@ -0,0 +1,279 @@
{
"manufacturer": "MonsGeek",
"keyboard_name": "M2",
"maintainer": "jonylee@hfd",
"bootloader": "wb32-dfu",
"diode_direction": "ROW2COL",
"dynamic_keymap": {
"layer_count": 6
},
"eeprom": {
"driver": "wear_leveling",
"wear_leveling": {
"backing_size": 8192,
"driver": "spi_flash"
}
},
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"rgb_matrix": true
},
"host": {
"default": {
"nkro": true
}
},
"indicators": {
"caps_lock": "A15",
"num_lock": "C10"
},
"matrix_pins": {
"cols": ["C1", "C2", "C3", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "C4", "C5", "B0", "B1", "B2", "B10", "B11", "B12", "B13", "B14"],
"rows": ["B15", "C6", "C7", "C8", "C9", "A8"]
},
"processor": "WB32FQ95",
"qmk": {
"locking": {
"enabled": true,
"resync": true
}
},
"rgb_matrix": {
"animations": {
"breathing": true,
"cycle_all": true,
"cycle_left_right": true,
"cycle_out_in": true,
"cycle_out_in_dual": true,
"cycle_pinwheel": true,
"cycle_spiral": true,
"cycle_up_down": true,
"dual_beacon": true,
"multisplash": true,
"rainbow_beacon": true,
"rainbow_moving_chevron": true,
"raindrops": true,
"solid_reactive": true,
"solid_reactive_cross": true,
"solid_reactive_simple": true,
"typing_heatmap": true
},
"driver": "snled27351",
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0, "flags": 1},
{"matrix": [0, 1], "x": 13, "y": 0, "flags": 4},
{"matrix": [0, 2], "x": 26, "y": 0, "flags": 4},
{"matrix": [0, 3], "x": 39, "y": 0, "flags": 4},
{"matrix": [0, 4], "x": 52, "y": 0, "flags": 4},
{"matrix": [0, 5], "x": 65, "y": 0, "flags": 4},
{"matrix": [0, 6], "x": 79, "y": 0, "flags": 4},
{"matrix": [0, 7], "x": 92, "y": 0, "flags": 4},
{"matrix": [0, 8], "x": 105, "y": 0, "flags": 4},
{"matrix": [0, 9], "x": 118, "y": 0, "flags": 4},
{"matrix": [0, 10], "x": 131, "y": 0, "flags": 4},
{"matrix": [0, 11], "x": 144, "y": 0, "flags": 4},
{"matrix": [0, 12], "x": 158, "y": 0, "flags": 4},
{"matrix": [0, 13], "x": 171, "y": 0, "flags": 1},
{"matrix": [0, 17], "x": 184, "y": 0, "flags": 1},
{"matrix": [0, 18], "x": 197, "y": 0, "flags": 1},
{"matrix": [0, 19], "x": 210, "y": 0, "flags": 1},
{"matrix": [0, 20], "x": 224, "y": 0, "flags": 1},
{"matrix": [1, 0], "x": 0, "y": 12, "flags": 4},
{"matrix": [1, 1], "x": 13, "y": 12, "flags": 4},
{"matrix": [1, 2], "x": 26, "y": 12, "flags": 4},
{"matrix": [1, 3], "x": 39, "y": 12, "flags": 4},
{"matrix": [1, 4], "x": 52, "y": 12, "flags": 4},
{"matrix": [1, 5], "x": 65, "y": 12, "flags": 4},
{"matrix": [1, 6], "x": 79, "y": 12, "flags": 4},
{"matrix": [1, 7], "x": 92, "y": 12, "flags": 4},
{"matrix": [1, 8], "x": 105, "y": 12, "flags": 4},
{"matrix": [1, 9], "x": 118, "y": 12, "flags": 4},
{"matrix": [1, 10], "x": 131, "y": 12, "flags": 4},
{"matrix": [1, 11], "x": 144, "y": 12, "flags": 4},
{"matrix": [1, 12], "x": 158, "y": 12, "flags": 4},
{"matrix": [1, 13], "x": 171, "y": 12, "flags": 1},
{"matrix": [1, 17], "x": 184, "y": 12, "flags": 4},
{"matrix": [1, 18], "x": 197, "y": 12, "flags": 4},
{"matrix": [1, 19], "x": 210, "y": 12, "flags": 4},
{"matrix": [1, 20], "x": 224, "y": 12, "flags": 4},
{"matrix": [2, 0], "x": 0, "y": 25, "flags": 1},
{"matrix": [2, 1], "x": 13, "y": 25, "flags": 4},
{"matrix": [2, 2], "x": 26, "y": 25, "flags": 4},
{"matrix": [2, 3], "x": 39, "y": 25, "flags": 4},
{"matrix": [2, 4], "x": 52, "y": 25, "flags": 4},
{"matrix": [2, 5], "x": 65, "y": 25, "flags": 4},
{"matrix": [2, 6], "x": 79, "y": 25, "flags": 4},
{"matrix": [2, 7], "x": 92, "y": 25, "flags": 4},
{"matrix": [2, 8], "x": 105, "y": 25, "flags": 4},
{"matrix": [2, 9], "x": 118, "y": 25, "flags": 4},
{"matrix": [2, 10], "x": 131, "y": 25, "flags": 4},
{"matrix": [2, 11], "x": 144, "y": 25, "flags": 4},
{"matrix": [2, 12], "x": 158, "y": 25, "flags": 4},
{"matrix": [2, 13], "x": 171, "y": 25, "flags": 1},
{"matrix": [2, 17], "x": 184, "y": 25, "flags": 4},
{"matrix": [2, 18], "x": 197, "y": 25, "flags": 4},
{"matrix": [2, 19], "x": 210, "y": 25, "flags": 4},
{"matrix": [2, 20], "x": 224, "y": 25, "flags": 4},
{"matrix": [3, 0], "x": 0, "y": 38, "flags": 1},
{"matrix": [3, 1], "x": 13, "y": 38, "flags": 4},
{"matrix": [3, 2], "x": 26, "y": 38, "flags": 4},
{"matrix": [3, 3], "x": 39, "y": 38, "flags": 4},
{"matrix": [3, 4], "x": 52, "y": 38, "flags": 4},
{"matrix": [3, 5], "x": 65, "y": 38, "flags": 4},
{"matrix": [3, 6], "x": 79, "y": 38, "flags": 4},
{"matrix": [3, 7], "x": 92, "y": 38, "flags": 4},
{"matrix": [3, 8], "x": 105, "y": 38, "flags": 4},
{"matrix": [3, 9], "x": 118, "y": 38, "flags": 4},
{"matrix": [3, 10], "x": 131, "y": 38, "flags": 4},
{"matrix": [3, 11], "x": 144, "y": 38, "flags": 4},
{"matrix": [3, 13], "x": 163, "y": 38, "flags": 1},
{"matrix": [3, 17], "x": 184, "y": 38, "flags": 4},
{"matrix": [3, 18], "x": 197, "y": 38, "flags": 4},
{"matrix": [3, 19], "x": 210, "y": 38, "flags": 4},
{"matrix": [4, 0], "x": 0, "y": 51, "flags": 1},
{"matrix": [4, 1], "x": 26, "y": 51, "flags": 4},
{"matrix": [4, 2], "x": 39, "y": 51, "flags": 4},
{"matrix": [4, 3], "x": 52, "y": 51, "flags": 4},
{"matrix": [4, 4], "x": 65, "y": 51, "flags": 4},
{"matrix": [4, 5], "x": 79, "y": 51, "flags": 4},
{"matrix": [4, 6], "x": 92, "y": 51, "flags": 4},
{"matrix": [4, 7], "x": 105, "y": 51, "flags": 4},
{"matrix": [4, 8], "x": 118, "y": 51, "flags": 4},
{"matrix": [4, 9], "x": 131, "y": 51, "flags": 4},
{"matrix": [4, 10], "x": 144, "y": 51, "flags": 4},
{"matrix": [4, 13], "x": 158, "y": 51, "flags": 1},
{"matrix": [4, 15], "x": 171, "y": 51, "flags": 1},
{"matrix": [4, 17], "x": 184, "y": 51, "flags": 4},
{"matrix": [4, 18], "x": 197, "y": 51, "flags": 4},
{"matrix": [4, 19], "x": 210, "y": 51, "flags": 4},
{"matrix": [4, 20], "x": 224, "y": 51, "flags": 1},
{"matrix": [5, 0], "x": 0, "y": 64, "flags": 1},
{"matrix": [5, 1], "x": 18, "y": 64, "flags": 1},
{"matrix": [5, 2], "x": 37, "y": 64, "flags": 1},
{"matrix": [5, 5], "x": 92, "y": 64, "flags": 4},
{"matrix": [5, 9], "x": 130, "y": 64, "flags": 1},
{"matrix": [5, 10], "x": 145, "y": 64, "flags": 1},
{"matrix": [5, 11], "x": 158, "y": 64, "flags": 1},
{"matrix": [5, 15], "x": 171, "y": 64, "flags": 1},
{"matrix": [5, 16], "x": 184, "y": 64, "flags": 1},
{"matrix": [5, 18], "x": 197, "y": 64, "flags": 4},
{"matrix": [5, 19], "x": 210, "y": 64, "flags": 4}
],
"max_brightness": 200,
"sleep": true,
"val_steps": 20
},
"usb": {
"device_version": "1.0.4",
"pid": "0x0008",
"suspend_wakeup_delay": 400,
"vid": "0xFFFE"
},
"layouts": {
"LAYOUT": {
"layout": [
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
{"label": "F1", "matrix": [0, 1], "x": 1.25, "y": 0},
{"label": "F2", "matrix": [0, 2], "x": 2.25, "y": 0},
{"label": "F3", "matrix": [0, 3], "x": 3.25, "y": 0},
{"label": "F4", "matrix": [0, 4], "x": 4.25, "y": 0},
{"label": "F5", "matrix": [0, 5], "x": 5.5, "y": 0},
{"label": "F6", "matrix": [0, 6], "x": 6.5, "y": 0},
{"label": "F7", "matrix": [0, 7], "x": 7.5, "y": 0},
{"label": "F8", "matrix": [0, 8], "x": 8.5, "y": 0},
{"label": "F9", "matrix": [0, 9], "x": 9.75, "y": 0},
{"label": "F10", "matrix": [0, 10], "x": 10.75, "y": 0},
{"label": "F11", "matrix": [0, 11], "x": 11.75, "y": 0},
{"label": "F12", "matrix": [0, 12], "x": 12.75, "y": 0},
{"label": "Delete", "matrix": [0, 13], "x": 14, "y": 0},
{"label": "PrtSc", "matrix": [0, 17], "x": 15.5, "y": 0},
{"label": "Home", "matrix": [0, 18], "x": 16.5, "y": 0},
{"label": "Pgup", "matrix": [0, 19], "x": 17.5, "y": 0},
{"label": "Pgdn", "matrix": [0, 20], "x": 18.5, "y": 0},
{"label": "~", "matrix": [1, 0], "x": 0, "y": 1.25},
{"label": "!", "matrix": [1, 1], "x": 1, "y": 1.25},
{"label": "@", "matrix": [1, 2], "x": 2, "y": 1.25},
{"label": "#", "matrix": [1, 3], "x": 3, "y": 1.25},
{"label": "$", "matrix": [1, 4], "x": 4, "y": 1.25},
{"label": "%", "matrix": [1, 5], "x": 5, "y": 1.25},
{"label": "^", "matrix": [1, 6], "x": 6, "y": 1.25},
{"label": "&", "matrix": [1, 7], "x": 7, "y": 1.25},
{"label": "*", "matrix": [1, 8], "x": 8, "y": 1.25},
{"label": "(", "matrix": [1, 9], "x": 9, "y": 1.25},
{"label": ")", "matrix": [1, 10], "x": 10, "y": 1.25},
{"label": "_", "matrix": [1, 11], "x": 11, "y": 1.25},
{"label": "+", "matrix": [1, 12], "x": 12, "y": 1.25},
{"label": "Bksp", "matrix": [1, 13], "x": 13, "y": 1.25, "w": 2},
{"label": "Numlock", "matrix": [1, 17], "x": 15.5, "y": 1.25},
{"label": "/", "matrix": [1, 18], "x": 16.5, "y": 1.25},
{"label": "*", "matrix": [1, 19], "x": 17.5, "y": 1.25},
{"label": "-", "matrix": [1, 20], "x": 18.5, "y": 1.25},
{"label": "Tab", "matrix": [2, 0], "x": 0, "y": 2.25, "w": 1.5},
{"label": "Q", "matrix": [2, 1], "x": 1.5, "y": 2.25},
{"label": "W", "matrix": [2, 2], "x": 2.5, "y": 2.25},
{"label": "E", "matrix": [2, 3], "x": 3.5, "y": 2.25},
{"label": "R", "matrix": [2, 4], "x": 4.5, "y": 2.25},
{"label": "T", "matrix": [2, 5], "x": 5.5, "y": 2.25},
{"label": "Y", "matrix": [2, 6], "x": 6.5, "y": 2.25},
{"label": "U", "matrix": [2, 7], "x": 7.5, "y": 2.25},
{"label": "I", "matrix": [2, 8], "x": 8.5, "y": 2.25},
{"label": "O", "matrix": [2, 9], "x": 9.5, "y": 2.25},
{"label": "P", "matrix": [2, 10], "x": 10.5, "y": 2.25},
{"label": "{", "matrix": [2, 11], "x": 11.5, "y": 2.25},
{"label": "}", "matrix": [2, 12], "x": 12.5, "y": 2.25},
{"label": "|", "matrix": [2, 13], "x": 13.5, "y": 2.25, "w": 1.5},
{"label": "7", "matrix": [2, 17], "x": 15.5, "y": 2.25},
{"label": "8", "matrix": [2, 18], "x": 16.5, "y": 2.25},
{"label": "9", "matrix": [2, 19], "x": 17.5, "y": 2.25},
{"label": "+", "matrix": [2, 20], "x": 18.5, "y": 2.25, "h": 2},
{"label": "Caps Lock", "matrix": [3, 0], "x": 0, "y": 3.25, "w": 1.75},
{"label": "A", "matrix": [3, 1], "x": 1.75, "y": 3.25},
{"label": "S", "matrix": [3, 2], "x": 2.75, "y": 3.25},
{"label": "D", "matrix": [3, 3], "x": 3.75, "y": 3.25},
{"label": "F", "matrix": [3, 4], "x": 4.75, "y": 3.25},
{"label": "G", "matrix": [3, 5], "x": 5.75, "y": 3.25},
{"label": "H", "matrix": [3, 6], "x": 6.75, "y": 3.25},
{"label": "J", "matrix": [3, 7], "x": 7.75, "y": 3.25},
{"label": "K", "matrix": [3, 8], "x": 8.75, "y": 3.25},
{"label": "L", "matrix": [3, 9], "x": 9.75, "y": 3.25},
{"label": ":", "matrix": [3, 10], "x": 10.75, "y": 3.25},
{"label": "'", "matrix": [3, 11], "x": 11.75, "y": 3.25},
{"label": "Enter", "matrix": [3, 13], "x": 12.75, "y": 3.25, "w": 2.25},
{"label": "4", "matrix": [3, 17], "x": 15.5, "y": 3.25},
{"label": "5", "matrix": [3, 18], "x": 16.5, "y": 3.25},
{"label": "6", "matrix": [3, 19], "x": 17.5, "y": 3.25},
{"label": "Shift", "matrix": [4, 0], "x": 0, "y": 4.25, "w": 2.25},
{"label": "Z", "matrix": [4, 1], "x": 2.25, "y": 4.25},
{"label": "X", "matrix": [4, 2], "x": 3.25, "y": 4.25},
{"label": "C", "matrix": [4, 3], "x": 4.25, "y": 4.25},
{"label": "V", "matrix": [4, 4], "x": 5.25, "y": 4.25},
{"label": "B", "matrix": [4, 5], "x": 6.25, "y": 4.25},
{"label": "N", "matrix": [4, 6], "x": 7.25, "y": 4.25},
{"label": "M", "matrix": [4, 7], "x": 8.25, "y": 4.25},
{"label": "<", "matrix": [4, 8], "x": 9.25, "y": 4.25},
{"label": ">", "matrix": [4, 9], "x": 10.25, "y": 4.25},
{"label": "?", "matrix": [4, 10], "x": 11.25, "y": 4.25},
{"label": "Shift", "matrix": [4, 13], "x": 12.25, "y": 4.25, "w": 1.75},
{"label": "Up", "matrix": [4, 15], "x": 14.25, "y": 4.5},
{"label": "1", "matrix": [4, 17], "x": 15.5, "y": 4.25},
{"label": "2", "matrix": [4, 18], "x": 16.5, "y": 4.25},
{"label": "3", "matrix": [4, 19], "x": 17.5, "y": 4.25},
{"label": "Enter", "matrix": [4, 20], "x": 18.5, "y": 4.25, "h": 2},
{"label": "Ctrl", "matrix": [5, 0], "x": 0, "y": 5.25, "w": 1.25},
{"label": "Win", "matrix": [5, 1], "x": 1.25, "y": 5.25, "w": 1.25},
{"label": "Alt", "matrix": [5, 2], "x": 2.5, "y": 5.25, "w": 1.25},
{"label": "Space", "matrix": [5, 5], "x": 3.75, "y": 5.25, "w": 6.25},
{"label": "Alt", "matrix": [5, 9], "x": 10, "y": 5.25, "w": 1.5},
{"label": "Fn", "matrix": [5, 10], "x": 11.5, "y": 5.25, "w": 1.5},
{"label": "Left", "matrix": [5, 11], "x": 13.25, "y": 5.5},
{"label": "Down", "matrix": [5, 15], "x": 14.25, "y": 5.5},
{"label": "Right", "matrix": [5, 16], "x": 15.25, "y": 5.5},
{"label": "0", "matrix": [5, 18], "x": 16.5, "y": 5.25},
{"label": ".", "matrix": [5, 19], "x": 17.5, "y": 5.25}
]
}
}
}

View File

@@ -0,0 +1,80 @@
/* Copyright (C) 2023 jonylee@hfd
*
* 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
// clang-format off
enum __layers {
WIN_B,
WIN_WASD,
WIN_FN,
MAC_B,
MAC_WASD,
MAC_FN
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[WIN_B] = LAYOUT( /* Base */
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_HOME, KC_END, KC_PGUP, KC_PGDN,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_NUM, KC_PSLS, KC_PAST, KC_PMNS,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_P7, KC_P8, KC_P9, KC_PPLS,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_P4, KC_P5, KC_P6,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_P1, KC_P2, KC_P3, KC_PENT,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(WIN_FN), KC_LEFT, KC_DOWN,KC_RGHT, KC_P0, KC_PDOT),
[WIN_WASD] = LAYOUT( /* WASD */
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, KC_UP, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, KC_LEFT, KC_DOWN, KC_RIGHT,_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_W, _______, _______, _______, _______,
_______, _______, _______, _______, _______, MO(WIN_FN), KC_A, KC_S, KC_D, _______, _______),
[WIN_FN] = LAYOUT( /* FN */
_______, KC_MYCM, KC_MAIL, KC_WSCH, KC_WHOM, KC_MSEL, KC_MPLY, KC_MPRV, KC_MNXT, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RM_SPDD, RM_SPDU, _______, _______, _______, _______, _______,
_______, _______, TG(WIN_WASD),_______,_______,_______,_______,_______, KC_INS, DF(MAC_B),KC_PSCR, _______, _______, RM_NEXT, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, RM_TOGG, _______, _______, RM_HUEU, _______, _______, _______,
_______, _______, _______, KC_CALC, _______, _______, _______, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, RM_VALU, _______, _______, _______, _______,
_______, GU_TOGG, _______, _______, _______, _______, RM_SATD, RM_VALD, RM_SATU, _______, _______),
[MAC_B] = LAYOUT( /* Base */
KC_ESC, KC_BRID, KC_BRIU, KC_MCTL, KC_LPAD, KC_F5, KC_F6, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_DEL, KC_HOME, KC_END, KC_PGUP, KC_PGDN,
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_NUM, KC_PSLS, KC_PAST, KC_PMNS,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_P7, KC_P8, KC_P9, KC_PPLS,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_P4, KC_P5, KC_P6,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_P1, KC_P2, KC_P3, KC_PENT,
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(MAC_FN), KC_LEFT, KC_DOWN, KC_RGHT, KC_P0, KC_PDOT),
[MAC_WASD] = LAYOUT( /* WASD */
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, KC_UP, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, KC_LEFT, KC_DOWN, KC_RIGHT,_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_W, _______, _______, _______, _______,
_______, _______, _______, _______, _______, MO(MAC_FN), KC_A, KC_S, KC_D, _______, _______),
[MAC_FN] = LAYOUT( /* FN */
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, _______, _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RM_SPDD, RM_SPDU, _______, _______, _______, _______, _______,
_______, _______, TG(MAC_WASD),_______,_______,_______,_______,_______, KC_INS, DF(WIN_B),KC_PSCR, _______, _______, RM_NEXT, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, RM_TOGG, _______, _______, RM_HUEU, _______, _______, _______,
_______, _______, _______, KC_CALC, _______, _______, _______, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, RM_VALU, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, RM_SATD, RM_VALD, RM_SATU, _______, _______)
};

142
keyboards/monsgeek/m2/m2.c Normal file
View File

@@ -0,0 +1,142 @@
/* Copyright (C) 2023 jonylee@hfd
*
* 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 "quantum.h"
#ifdef RGB_MATRIX_ENABLE
const snled27351_led_t PROGMEM g_snled27351_leds[SNLED27351_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{1, CB1_CA1, CB2_CA1, CB3_CA1},
{1, CB1_CA2, CB2_CA2, CB3_CA2},
{1, CB1_CA3, CB2_CA3, CB3_CA3},
{1, CB1_CA4, CB2_CA4, CB3_CA4},
{1, CB1_CA5, CB2_CA5, CB3_CA5},
{1, CB1_CA6, CB2_CA6, CB3_CA6},
{1, CB1_CA7, CB2_CA7, CB3_CA7},
{1, CB1_CA8, CB2_CA8, CB3_CA8},
{1, CB1_CA9, CB2_CA9, CB3_CA9},
{1, CB1_CA10, CB2_CA10, CB3_CA10},
{1, CB1_CA11, CB2_CA11, CB3_CA11},
{1, CB1_CA12, CB2_CA12, CB3_CA12},
{1, CB1_CA13, CB2_CA13, CB3_CA13},
{1, CB1_CA14, CB2_CA14, CB3_CA14},
{1, CB4_CA11, CB5_CA11, CB6_CA11},
{1, CB4_CA12, CB5_CA12, CB6_CA12},
{1, CB4_CA13, CB5_CA13, CB6_CA13},
{1, CB4_CA14, CB5_CA14, CB6_CA14},
{0, CB1_CA1, CB2_CA1, CB3_CA1},
{0, CB1_CA2, CB2_CA2, CB3_CA2},
{0, CB1_CA3, CB2_CA3, CB3_CA3},
{0, CB1_CA4, CB2_CA4, CB3_CA4},
{0, CB1_CA5, CB2_CA5, CB3_CA5},
{0, CB1_CA6, CB2_CA6, CB3_CA6},
{0, CB1_CA7, CB2_CA7, CB3_CA7},
{0, CB1_CA8, CB2_CA8, CB3_CA8},
{0, CB1_CA9, CB2_CA9, CB3_CA9},
{0, CB1_CA10, CB2_CA10, CB3_CA10},
{0, CB1_CA11, CB2_CA11, CB3_CA11},
{0, CB1_CA12, CB2_CA12, CB3_CA12},
{0, CB1_CA13, CB2_CA13, CB3_CA13},
{0, CB1_CA14, CB2_CA14, CB3_CA14},
{1, CB4_CA4, CB5_CA4, CB6_CA4},
{1, CB4_CA5, CB5_CA5, CB6_CA5},
{1, CB4_CA6, CB5_CA6, CB6_CA6},
{1, CB4_CA7, CB5_CA7, CB6_CA7},
{0, CB4_CA1, CB5_CA1, CB6_CA1},
{0, CB4_CA2, CB5_CA2, CB6_CA2},
{0, CB4_CA3, CB5_CA3, CB6_CA3},
{0, CB4_CA4, CB5_CA4, CB6_CA4},
{0, CB4_CA5, CB5_CA5, CB6_CA5},
{0, CB4_CA6, CB5_CA6, CB6_CA6},
{0, CB4_CA7, CB5_CA7, CB6_CA7},
{0, CB4_CA8, CB5_CA8, CB6_CA8},
{0, CB4_CA9, CB5_CA9, CB6_CA9},
{0, CB4_CA10, CB5_CA10, CB6_CA10},
{0, CB4_CA11, CB5_CA11, CB6_CA11},
{0, CB4_CA12, CB5_CA12, CB6_CA12},
{0, CB4_CA13, CB5_CA13, CB6_CA13},
{0, CB4_CA14, CB5_CA14, CB6_CA14},
{1, CB4_CA8, CB5_CA8, CB6_CA8},
{1, CB4_CA9, CB5_CA9, CB6_CA9},
{1, CB4_CA10, CB5_CA10, CB6_CA10},
{1, CB7_CA7, CB8_CA7, CB9_CA7},
{0, CB7_CA1, CB8_CA1, CB9_CA1},
{0, CB7_CA2, CB8_CA2, CB9_CA2},
{0, CB7_CA3, CB8_CA3, CB9_CA3},
{0, CB7_CA4, CB8_CA4, CB9_CA4},
{0, CB7_CA5, CB8_CA5, CB9_CA5},
{0, CB7_CA6, CB8_CA6, CB9_CA6},
{0, CB7_CA7, CB8_CA7, CB9_CA7},
{0, CB7_CA8, CB8_CA8, CB9_CA8},
{0, CB7_CA9, CB8_CA9, CB9_CA9},
{0, CB7_CA10, CB8_CA10, CB9_CA10},
{0, CB7_CA11, CB8_CA11, CB9_CA11},
{0, CB7_CA12, CB8_CA12, CB9_CA12},
{0, CB7_CA13, CB8_CA13, CB9_CA13},
{1, CB7_CA4, CB8_CA4, CB9_CA4},
{1, CB7_CA5, CB8_CA5, CB9_CA5},
{1, CB7_CA6, CB8_CA6, CB9_CA6},
{0, CB10_CA1, CB11_CA1, CB12_CA1},
{0, CB10_CA2, CB11_CA2, CB12_CA2},
{0, CB10_CA3, CB11_CA3, CB12_CA3},
{0, CB10_CA4, CB11_CA4, CB12_CA4},
{0, CB10_CA5, CB11_CA5, CB12_CA5},
{0, CB10_CA6, CB11_CA6, CB12_CA6},
{0, CB10_CA7, CB11_CA7, CB12_CA7},
{0, CB10_CA8, CB11_CA8, CB12_CA8},
{0, CB10_CA9, CB11_CA9, CB12_CA9},
{0, CB10_CA10, CB11_CA10, CB12_CA10},
{0, CB10_CA11, CB11_CA11, CB12_CA11},
{0, CB10_CA12, CB11_CA12, CB12_CA12},
{1, CB10_CA4, CB11_CA4, CB12_CA4},
{1, CB10_CA7, CB11_CA7, CB12_CA7},
{1, CB10_CA8, CB11_CA8, CB12_CA8},
{1, CB10_CA9, CB11_CA9, CB12_CA9},
{1, CB10_CA10, CB11_CA10, CB12_CA10},
{0, CB10_CA13, CB11_CA13, CB12_CA13},
{0, CB10_CA14, CB11_CA14, CB12_CA14},
{0, CB10_CA15, CB11_CA15, CB12_CA15},
{0, CB10_CA16, CB11_CA16, CB12_CA16},
{0, CB7_CA14, CB8_CA14, CB9_CA14},
{0, CB7_CA15, CB8_CA15, CB9_CA15},
{0, CB7_CA16, CB8_CA16, CB9_CA16},
{1, CB10_CA2, CB11_CA2, CB12_CA2},
{1, CB10_CA3, CB11_CA3, CB12_CA3},
{1, CB10_CA5, CB11_CA5, CB12_CA5},
{1, CB10_CA6, CB11_CA6, CB12_CA6},
};
#endif //RGB_MATRIX_ENABLE
void keyboard_pre_init_kb(void) {
gpio_set_pin_output(LED_WIN_LOCK_PIN); // LED3 Win Lock
gpio_write_pin_low(LED_WIN_LOCK_PIN);
keyboard_pre_init_user();
}
void housekeeping_task_kb(void) {
gpio_write_pin(LED_WIN_LOCK_PIN, keymap_config.no_gui);
}

View File

@@ -0,0 +1,24 @@
/* Copyright (C) 2023 jonylee@hfd
*
* 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
#include_next <mcuconf.h>
#undef WB32_SPI_USE_QSPI
#define WB32_SPI_USE_QSPI TRUE
#undef WB32_I2C_USE_I2C1
#define WB32_I2C_USE_I2C1 TRUE

View File

@@ -0,0 +1,25 @@
# MonsGeek M2
![M2](https://i.imgur.com/kv9ChJn.png)
A customizable 95% keyboard
* Keyboard Maintainer: [jonylee@hfd](https://github.com/jonylee1986)
* Hardware Supported: MonsGeek M2 PCB
* Hardware Availability: [monsgeek](https://www.monsgeek.com/product/m2/)
Make example for this keyboard (after setting up your build environment):
make monsgeek/m2:default
Flashing example for this keyboard:
make monsgeek/m2:default:flash
See 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).
## Bootloader
Enter the bootloader in 2 ways:
* **Bootmagic reset**: Hold down the top left key (commonly programmed as *Esc*) while plugging in the keyboard.
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@@ -2,7 +2,10 @@
"manufacturer": "Ning",
"keyboard_name": "TB16 RGB",
"maintainer": "ningjx",
"diode_direction": "COL2ROW",
"diode_direction": "ROW2COL",
"build": {
"lto": true
},
"features": {
"bootmagic": true,
"extrakey": true,

View File

@@ -0,0 +1,237 @@
{
"manufacturer": "nulldesignco",
"keyboard_name": "null65ansi",
"maintainer": "quark-works",
"processor": "RP2040",
"bootloader": "rp2040",
"usb": {
"vid": "0x6E6C",
"pid": "0x0001",
"device_version": "1.0.0"
},
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"rgb_matrix": true
},
"ws2812": {
"pin": "GP18",
"driver": "vendor"
},
"rgb_matrix": {
"max_brightness": 90,
"center_point": [120,32],
"sleep": true,
"driver": "ws2812",
"animations": {
"alphas_mods": true,
"band_pinwheel_sat": true,
"band_pinwheel_val": true,
"band_sat": true,
"band_spiral_sat": true,
"band_spiral_val": true,
"band_val": true,
"breathing": true,
"cycle_all": true,
"cycle_left_right": true,
"cycle_out_in": true,
"cycle_out_in_dual": true,
"cycle_pinwheel": true,
"cycle_spiral": true,
"cycle_up_down": true,
"digital_rain": true,
"dual_beacon": true,
"flower_blooming": true,
"gradient_left_right": true,
"gradient_up_down": true,
"hue_breathing": true,
"hue_pendulum": true,
"hue_wave": true,
"jellybean_raindrops": true,
"multisplash": true,
"pixel_flow": true,
"pixel_fractal": true,
"pixel_rain": true,
"rainbow_beacon": true,
"rainbow_moving_chevron": true,
"rainbow_pinwheels": true,
"raindrops": true,
"riverflow": true,
"solid_multisplash": true,
"solid_reactive": true,
"solid_reactive_cross": true,
"solid_reactive_multicross": true,
"solid_reactive_multinexus": true,
"solid_reactive_multiwide": true,
"solid_reactive_nexus": true,
"solid_reactive_simple": true,
"solid_reactive_wide": true,
"solid_splash": true,
"splash": true,
"starlight": true,
"starlight_dual_hue": true,
"starlight_dual_sat": true,
"typing_heatmap": true
},
"layout": [
{"matrix": [4, 5], "x": 102, "y": 64, "flags": 4},
{"matrix": [4, 9], "x": 102, "y": 64, "flags": 4},
{"matrix": [4, 10], "x": 160, "y": 64, "flags": 4},
{"matrix": [4, 11], "x": 176, "y": 64, "flags": 4},
{"matrix": [4, 12], "x": 192, "y": 64, "flags": 4},
{"matrix": [4, 13], "x": 208, "y": 64, "flags": 4},
{"matrix": [4, 14], "x": 240, "y": 64, "flags": 4},
{"matrix": [3, 14], "x": 240, "y": 48, "flags": 4},
{"matrix": [3, 13], "x": 224, "y": 48, "flags": 4},
{"matrix": [3, 12], "x": 202, "y": 48, "flags": 4},
{"matrix": [3, 10], "x": 180, "y": 48, "flags": 4},
{"matrix": [3, 9], "x": 164, "y": 48, "flags": 4},
{"matrix": [3, 8], "x": 148, "y": 48, "flags": 4},
{"matrix": [3, 7], "x": 132, "y": 48, "flags": 4},
{"matrix": [3, 6], "x": 116, "y": 48, "flags": 4},
{"matrix": [3, 5], "x": 100, "y": 48, "flags": 4},
{"matrix": [3, 4], "x": 84, "y": 48, "flags": 4},
{"matrix": [3, 3], "x": 68, "y": 48, "flags": 4},
{"matrix": [3, 2], "x": 52, "y": 48, "flags": 4},
{"matrix": [3, 1], "x": 36, "y": 48, "flags": 4},
{"matrix": [4, 2], "x": 42, "y": 64, "flags": 4},
{"matrix": [4, 1], "x": 22, "y": 64, "flags": 4},
{"matrix": [4, 0], "x": 2, "y": 64, "flags": 4},
{"matrix": [3, 0], "x": 10, "y": 48, "flags": 4},
{"matrix": [2, 0], "x": 6, "y": 32, "flags": 4},
{"matrix": [2, 1], "x": 28, "y": 32, "flags": 4},
{"matrix": [2, 2], "x": 44, "y": 32, "flags": 4},
{"matrix": [2, 3], "x": 60, "y": 32, "flags": 4},
{"matrix": [2, 4], "x": 76, "y": 32, "flags": 4},
{"matrix": [2, 5], "x": 92, "y": 32, "flags": 4},
{"matrix": [2, 6], "x": 108, "y": 32, "flags": 4},
{"matrix": [2, 7], "x": 124, "y": 32, "flags": 4},
{"matrix": [2, 8], "x": 140, "y": 32, "flags": 4},
{"matrix": [2, 9], "x": 156, "y": 32, "flags": 4},
{"matrix": [2, 10], "x": 172, "y": 32, "flags": 4},
{"matrix": [2, 11], "x": 188, "y": 32, "flags": 4},
{"matrix": [2, 13], "x": 214, "y": 32, "flags": 4},
{"matrix": [2, 14], "x": 240, "y": 32, "flags": 4},
{"matrix": [1, 14], "x": 240, "y": 16, "flags": 4},
{"matrix": [1, 13], "x": 220, "y": 16, "flags": 4},
{"matrix": [1, 12], "x": 200, "y": 16, "flags": 4},
{"matrix": [1, 11], "x": 184, "y": 16, "flags": 4},
{"matrix": [1, 10], "x": 168, "y": 16, "flags": 4},
{"matrix": [1, 9], "x": 152, "y": 16, "flags": 4},
{"matrix": [1, 8], "x": 136, "y": 16, "flags": 4},
{"matrix": [1, 7], "x": 120, "y": 16, "flags": 4},
{"matrix": [1, 6], "x": 104, "y": 16, "flags": 4},
{"matrix": [1, 5], "x": 88, "y": 16, "flags": 4},
{"matrix": [1, 4], "x": 72, "y": 16, "flags": 4},
{"matrix": [1, 3], "x": 56, "y": 16, "flags": 4},
{"matrix": [1, 2], "x": 40, "y": 16, "flags": 4},
{"matrix": [1, 1], "x": 24, "y": 16, "flags": 4},
{"matrix": [1, 0], "x": 4, "y": 16, "flags": 4},
{"matrix": [0, 0], "x": 0, "y": 0, "flags": 4},
{"matrix": [0, 1], "x": 16, "y": 0, "flags": 4},
{"matrix": [0, 2], "x": 32, "y": 0, "flags": 4},
{"matrix": [0, 3], "x": 48, "y": 0, "flags": 4},
{"matrix": [0, 4], "x": 64, "y": 0, "flags": 4},
{"matrix": [0, 5], "x": 80, "y": 0, "flags": 4},
{"matrix": [0, 6], "x": 96, "y": 0, "flags": 4},
{"matrix": [0, 7], "x": 112, "y": 0, "flags": 4},
{"matrix": [0, 8], "x": 128, "y": 0, "flags": 4},
{"matrix": [0, 9], "x": 144, "y": 0, "flags": 4},
{"matrix": [0, 10], "x": 160, "y": 0, "flags": 4},
{"matrix": [0, 11], "x": 176, "y": 0, "flags": 4},
{"matrix": [0, 12], "x": 192, "y": 0, "flags": 4},
{"matrix": [0, 13], "x": 216, "y": 0, "flags": 4},
{"matrix": [0, 14], "x": 240, "y": 0, "flags": 4}
]
},
"diode_direction": "COL2ROW",
"matrix_pins": {
"rows": ["GP4", "GP3", "GP2", "GP17", "GP15"],
"cols": ["GP28", "GP27", "GP29", "GP0", "GP1", "GP14", "GP13", "GP12", "GP11", "GP10", "GP9", "GP8", "GP7", "GP6", "GP5"]
},
"url": "https://nulldesignco.com/",
"community_layouts": ["65_ansi"],
"layouts": {
"LAYOUT_65_ansi": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 1, "y": 0 },
{ "matrix": [0, 2], "x": 2, "y": 0 },
{ "matrix": [0, 3], "x": 3, "y": 0 },
{ "matrix": [0, 4], "x": 4, "y": 0 },
{ "matrix": [0, 5], "x": 5, "y": 0 },
{ "matrix": [0, 6], "x": 6, "y": 0 },
{ "matrix": [0, 7], "x": 7, "y": 0 },
{ "matrix": [0, 8], "x": 8, "y": 0 },
{ "matrix": [0, 9], "x": 9, "y": 0 },
{ "matrix": [0, 10], "x": 10, "y": 0 },
{ "matrix": [0, 11], "x": 11, "y": 0 },
{ "matrix": [0, 12], "x": 12, "y": 0 },
{ "matrix": [0, 13], "w": 2, "x": 13, "y": 0 },
{ "matrix": [0, 14], "x": 15, "y": 0 },
{ "matrix": [1, 0], "w": 1.5, "x": 0, "y": 1 },
{ "matrix": [1, 1], "x": 1.5, "y": 1 },
{ "matrix": [1, 2], "x": 2.5, "y": 1 },
{ "matrix": [1, 3], "x": 3.5, "y": 1 },
{ "matrix": [1, 4], "x": 4.5, "y": 1 },
{ "matrix": [1, 5], "x": 5.5, "y": 1 },
{ "matrix": [1, 6], "x": 6.5, "y": 1 },
{ "matrix": [1, 7], "x": 7.5, "y": 1 },
{ "matrix": [1, 8], "x": 8.5, "y": 1 },
{ "matrix": [1, 9], "x": 9.5, "y": 1 },
{ "matrix": [1, 10], "x": 10.5, "y": 1 },
{ "matrix": [1, 11], "x": 11.5, "y": 1 },
{ "matrix": [1, 12], "x": 12.5, "y": 1 },
{ "matrix": [1, 13], "w": 1.5, "x": 13.5, "y": 1 },
{ "matrix": [1, 14], "x": 15, "y": 1 },
{ "matrix": [2, 0], "w": 1.75, "x": 0, "y": 2 },
{ "matrix": [2, 1], "x": 1.75, "y": 2 },
{ "matrix": [2, 2], "x": 2.75, "y": 2 },
{ "matrix": [2, 3], "x": 3.75, "y": 2 },
{ "matrix": [2, 4], "x": 4.75, "y": 2 },
{ "matrix": [2, 5], "x": 5.75, "y": 2 },
{ "matrix": [2, 6], "x": 6.75, "y": 2 },
{ "matrix": [2, 7], "x": 7.75, "y": 2 },
{ "matrix": [2, 8], "x": 8.75, "y": 2 },
{ "matrix": [2, 9], "x": 9.75, "y": 2 },
{ "matrix": [2, 10], "x": 10.75, "y": 2 },
{ "matrix": [2, 11], "x": 11.75, "y": 2 },
{ "matrix": [2, 13], "w": 2.25, "x": 12.75, "y": 2 },
{ "matrix": [2, 14], "x": 15, "y": 2 },
{ "matrix": [3, 0], "w": 2.25, "x": 0, "y": 3 },
{ "matrix": [3, 1], "x": 2.25, "y": 3 },
{ "matrix": [3, 2], "x": 3.25, "y": 3 },
{ "matrix": [3, 3], "x": 4.25, "y": 3 },
{ "matrix": [3, 4], "x": 5.25, "y": 3 },
{ "matrix": [3, 5], "x": 6.25, "y": 3 },
{ "matrix": [3, 6], "x": 7.25, "y": 3 },
{ "matrix": [3, 7], "x": 8.25, "y": 3 },
{ "matrix": [3, 8], "x": 9.25, "y": 3 },
{ "matrix": [3, 9], "x": 10.25, "y": 3 },
{ "matrix": [3, 10], "x": 11.25, "y": 3 },
{ "matrix": [3, 12], "w": 1.75, "x": 12.25, "y": 3 },
{ "matrix": [3, 13], "x": 14, "y": 3 },
{ "matrix": [3, 14], "x": 15, "y": 3 },
{ "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4 },
{ "matrix": [4, 1], "w": 1.25, "x": 1.25, "y": 4 },
{ "matrix": [4, 2], "w": 1.25, "x": 2.5, "y": 4 },
{ "matrix": [4, 5], "w": 6.25, "x": 3.75, "y": 4 },
{ "matrix": [4, 9], "x": 10, "y": 4 },
{ "matrix": [4, 10], "x": 11, "y": 4 },
{ "matrix": [4, 11], "x": 12, "y": 4 },
{ "matrix": [4, 12], "x": 13, "y": 4 },
{ "matrix": [4, 13], "x": 14, "y": 4 },
{ "matrix": [4, 14], "x": 15, "y": 4 }
]
}
}
}

View File

@@ -0,0 +1,22 @@
// Copyright 2025 quark-works
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_65_ansi(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_HOME,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGUP,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
)
};
bool rgb_matrix_indicators_user(void) {
if (host_keyboard_led_state().caps_lock) {
rgb_matrix_set_color(24, 255, 0, 0);
}
return false;
}

View File

@@ -0,0 +1,27 @@
# null65ansi v1
![sp](https://i.imgur.com/zO7Jlwj.png)
65% tray mount PCB with RGB per key.
* Keyboard Maintainer: [Quark](https://github.com/quark-works)
* Hardware Supported: PCB
* Hardware Availability: https://nulldesignco.com/
Make example for this keyboard (after setting up your build environment):
make nulldesignco/null65ansi/v1:default
Flashing example for this keyboard:
make nulldesignco/null65ansi/v1:default:flash
See 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).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
* **Physical boot button**: Hold the button labeled as "BOOT" on the back of the board or short the two pads on the front while you connect the keyboard to your computer.
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@@ -0,0 +1,240 @@
{
"manufacturer": "nulldesignco",
"keyboard_name": "null65iso",
"maintainer": "quark-works",
"processor": "RP2040",
"bootloader": "rp2040",
"usb": {
"vid": "0x6E6C",
"pid": "0x0010",
"device_version": "1.0.0"
},
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"rgb_matrix": true
},
"ws2812": {
"pin": "GP18",
"driver": "vendor"
},
"rgb_matrix": {
"max_brightness": 90,
"center_point": [120,32],
"sleep": true,
"driver": "ws2812",
"animations": {
"alphas_mods": true,
"band_pinwheel_sat": true,
"band_pinwheel_val": true,
"band_sat": true,
"band_spiral_sat": true,
"band_spiral_val": true,
"band_val": true,
"breathing": true,
"cycle_all": true,
"cycle_left_right": true,
"cycle_out_in": true,
"cycle_out_in_dual": true,
"cycle_pinwheel": true,
"cycle_spiral": true,
"cycle_up_down": true,
"digital_rain": true,
"dual_beacon": true,
"flower_blooming": true,
"gradient_left_right": true,
"gradient_up_down": true,
"hue_breathing": true,
"hue_pendulum": true,
"hue_wave": true,
"jellybean_raindrops": true,
"multisplash": true,
"pixel_flow": true,
"pixel_fractal": true,
"pixel_rain": true,
"rainbow_beacon": true,
"rainbow_moving_chevron": true,
"rainbow_pinwheels": true,
"raindrops": true,
"riverflow": true,
"solid_multisplash": true,
"solid_reactive": true,
"solid_reactive_cross": true,
"solid_reactive_multicross": true,
"solid_reactive_multinexus": true,
"solid_reactive_multiwide": true,
"solid_reactive_nexus": true,
"solid_reactive_simple": true,
"solid_reactive_wide": true,
"solid_splash": true,
"splash": true,
"starlight": true,
"starlight_dual_hue": true,
"starlight_dual_sat": true,
"typing_heatmap": true
},
"layout": [
{"matrix": [4, 6], "x": 102, "y": 64, "flags": 4},
{"matrix": [4, 9], "x": 102, "y": 64, "flags": 4},
{"matrix": [4, 10], "x": 160, "y": 64, "flags": 4},
{"matrix": [4, 11], "x": 176, "y": 64, "flags": 4},
{"matrix": [4, 12], "x": 192, "y": 64, "flags": 4},
{"matrix": [4, 13], "x": 208, "y": 64, "flags": 4},
{"matrix": [4, 14], "x": 240, "y": 64, "flags": 4},
{"matrix": [3, 14], "x": 240, "y": 48, "flags": 4},
{"matrix": [3, 13], "x": 224, "y": 48, "flags": 4},
{"matrix": [3, 12], "x": 202, "y": 48, "flags": 4},
{"matrix": [3, 11], "x": 180, "y": 48, "flags": 4},
{"matrix": [3, 10], "x": 164, "y": 48, "flags": 4},
{"matrix": [3, 9], "x": 148, "y": 48, "flags": 4},
{"matrix": [3, 8], "x": 132, "y": 48, "flags": 4},
{"matrix": [3, 7], "x": 116, "y": 48, "flags": 4},
{"matrix": [3, 6], "x": 100, "y": 48, "flags": 4},
{"matrix": [3, 5], "x": 84, "y": 48, "flags": 4},
{"matrix": [3, 4], "x": 68, "y": 48, "flags": 4},
{"matrix": [3, 3], "x": 52, "y": 48, "flags": 4},
{"matrix": [3, 2], "x": 36, "y": 48, "flags": 4},
{"matrix": [4, 2], "x": 42, "y": 64, "flags": 4},
{"matrix": [4, 1], "x": 22, "y": 64, "flags": 4},
{"matrix": [4, 0], "x": 2, "y": 64, "flags": 4},
{"matrix": [3, 1], "x": 20, "y": 48, "flags": 4},
{"matrix": [3, 0], "x": 2, "y": 48, "flags": 4},
{"matrix": [2, 0], "x": 6, "y": 32, "flags": 4},
{"matrix": [2, 1], "x": 28, "y": 32, "flags": 4},
{"matrix": [2, 2], "x": 44, "y": 32, "flags": 4},
{"matrix": [2, 3], "x": 60, "y": 32, "flags": 4},
{"matrix": [2, 4], "x": 76, "y": 32, "flags": 4},
{"matrix": [2, 5], "x": 92, "y": 32, "flags": 4},
{"matrix": [2, 6], "x": 108, "y": 32, "flags": 4},
{"matrix": [2, 7], "x": 124, "y": 32, "flags": 4},
{"matrix": [2, 8], "x": 140, "y": 32, "flags": 4},
{"matrix": [2, 9], "x": 156, "y": 32, "flags": 4},
{"matrix": [2, 10], "x": 172, "y": 32, "flags": 4},
{"matrix": [2, 11], "x": 188, "y": 32, "flags": 4},
{"matrix": [2, 12], "x": 214, "y": 32, "flags": 4},
{"matrix": [2, 14], "x": 240, "y": 32, "flags": 4},
{"matrix": [1, 14], "x": 240, "y": 16, "flags": 4},
{"matrix": [1, 13], "x": 220, "y": 24, "flags": 4},
{"matrix": [1, 12], "x": 200, "y": 16, "flags": 4},
{"matrix": [1, 11], "x": 184, "y": 16, "flags": 4},
{"matrix": [1, 10], "x": 168, "y": 16, "flags": 4},
{"matrix": [1, 9], "x": 152, "y": 16, "flags": 4},
{"matrix": [1, 8], "x": 136, "y": 16, "flags": 4},
{"matrix": [1, 7], "x": 120, "y": 16, "flags": 4},
{"matrix": [1, 6], "x": 104, "y": 16, "flags": 4},
{"matrix": [1, 5], "x": 88, "y": 16, "flags": 4},
{"matrix": [1, 4], "x": 72, "y": 16, "flags": 4},
{"matrix": [1, 3], "x": 56, "y": 16, "flags": 4},
{"matrix": [1, 2], "x": 40, "y": 16, "flags": 4},
{"matrix": [1, 1], "x": 24, "y": 16, "flags": 4},
{"matrix": [1, 0], "x": 4, "y": 16, "flags": 4},
{"matrix": [0, 0], "x": 0, "y": 0, "flags": 4},
{"matrix": [0, 1], "x": 16, "y": 0, "flags": 4},
{"matrix": [0, 2], "x": 32, "y": 0, "flags": 4},
{"matrix": [0, 3], "x": 48, "y": 0, "flags": 4},
{"matrix": [0, 4], "x": 64, "y": 0, "flags": 4},
{"matrix": [0, 5], "x": 80, "y": 0, "flags": 4},
{"matrix": [0, 6], "x": 96, "y": 0, "flags": 4},
{"matrix": [0, 7], "x": 112, "y": 0, "flags": 4},
{"matrix": [0, 8], "x": 128, "y": 0, "flags": 4},
{"matrix": [0, 9], "x": 144, "y": 0, "flags": 4},
{"matrix": [0, 10], "x": 160, "y": 0, "flags": 4},
{"matrix": [0, 11], "x": 176, "y": 0, "flags": 4},
{"matrix": [0, 12], "x": 192, "y": 0, "flags": 4},
{"matrix": [0, 13], "x": 216, "y": 0, "flags": 4},
{"matrix": [0, 14], "x": 240, "y": 0, "flags": 4}
]
},
"diode_direction": "COL2ROW",
"matrix_pins": {
"rows": ["GP4", "GP3", "GP2", "GP17", "GP15"],
"cols": ["GP28", "GP27", "GP29", "GP0", "GP1", "GP14", "GP13", "GP12", "GP11", "GP10", "GP9", "GP8", "GP7", "GP6", "GP5"]
},
"url": "https://nulldesignco.com/",
"community_layouts": ["65_iso"],
"layouts": {
"LAYOUT_65_iso": {
"layout": [
{ "matrix": [0, 0], "x": 0, "y": 0 },
{ "matrix": [0, 1], "x": 1, "y": 0 },
{ "matrix": [0, 2], "x": 2, "y": 0 },
{ "matrix": [0, 3], "x": 3, "y": 0 },
{ "matrix": [0, 4], "x": 4, "y": 0 },
{ "matrix": [0, 5], "x": 5, "y": 0 },
{ "matrix": [0, 6], "x": 6, "y": 0 },
{ "matrix": [0, 7], "x": 7, "y": 0 },
{ "matrix": [0, 8], "x": 8, "y": 0 },
{ "matrix": [0, 9], "x": 9, "y": 0 },
{ "matrix": [0, 10], "x": 10, "y": 0 },
{ "matrix": [0, 11], "x": 11, "y": 0 },
{ "matrix": [0, 12], "x": 12, "y": 0 },
{ "matrix": [0, 13], "w": 2, "x": 13, "y": 0 },
{ "matrix": [0, 14], "x": 15, "y": 0 },
{ "matrix": [1, 0], "w": 1.5, "x": 0, "y": 1 },
{ "matrix": [1, 1], "x": 1.5, "y": 1 },
{ "matrix": [1, 2], "x": 2.5, "y": 1 },
{ "matrix": [1, 3], "x": 3.5, "y": 1 },
{ "matrix": [1, 4], "x": 4.5, "y": 1 },
{ "matrix": [1, 5], "x": 5.5, "y": 1 },
{ "matrix": [1, 6], "x": 6.5, "y": 1 },
{ "matrix": [1, 7], "x": 7.5, "y": 1 },
{ "matrix": [1, 8], "x": 8.5, "y": 1 },
{ "matrix": [1, 9], "x": 9.5, "y": 1 },
{ "matrix": [1, 10], "x": 10.5, "y": 1 },
{ "matrix": [1, 11], "x": 11.5, "y": 1 },
{ "matrix": [1, 12], "x": 12.5, "y": 1 },
{ "matrix": [1, 14], "x": 15, "y": 1 },
{ "matrix": [2, 0], "w": 1.75, "x": 0, "y": 2 },
{ "matrix": [2, 1], "x": 1.75, "y": 2 },
{ "matrix": [2, 2], "x": 2.75, "y": 2 },
{ "matrix": [2, 3], "x": 3.75, "y": 2 },
{ "matrix": [2, 4], "x": 4.75, "y": 2 },
{ "matrix": [2, 5], "x": 5.75, "y": 2 },
{ "matrix": [2, 6], "x": 6.75, "y": 2 },
{ "matrix": [2, 7], "x": 7.75, "y": 2 },
{ "matrix": [2, 8], "x": 8.75, "y": 2 },
{ "matrix": [2, 9], "x": 9.75, "y": 2 },
{ "matrix": [2, 10], "x": 10.75, "y": 2 },
{ "matrix": [2, 11], "x": 11.75, "y": 2 },
{ "matrix": [2, 12], "x": 12.75, "y": 2 },
{ "matrix": [1, 13], "w": 1.25, "x": 13.75, "y": 1, "h": 2 },
{ "matrix": [2, 14], "x": 15, "y": 2 },
{ "matrix": [3, 0], "w": 1.25, "x": 0, "y": 3 },
{ "matrix": [3, 1], "x": 1.25, "y": 3 },
{ "matrix": [3, 2], "x": 2.25, "y": 3 },
{ "matrix": [3, 3], "x": 3.25, "y": 3 },
{ "matrix": [3, 4], "x": 4.25, "y": 3 },
{ "matrix": [3, 5], "x": 5.25, "y": 3 },
{ "matrix": [3, 6], "x": 6.25, "y": 3 },
{ "matrix": [3, 7], "x": 7.25, "y": 3 },
{ "matrix": [3, 8], "x": 8.25, "y": 3 },
{ "matrix": [3, 9], "x": 9.25, "y": 3 },
{ "matrix": [3, 10], "x": 10.25, "y": 3 },
{ "matrix": [3, 11], "x": 11.25, "y": 3 },
{ "matrix": [3, 12], "w": 1.75, "x": 12.25, "y": 3 },
{ "matrix": [3, 13], "x": 14, "y": 3 },
{ "matrix": [3, 14], "x": 15, "y": 3 },
{ "matrix": [4, 0], "w": 1.25, "x": 0, "y": 4 },
{ "matrix": [4, 1], "w": 1.25, "x": 1.25, "y": 4 },
{ "matrix": [4, 2], "w": 1.25, "x": 2.5, "y": 4 },
{ "matrix": [4, 6], "w": 6.25, "x": 3.75, "y": 4 },
{ "matrix": [4, 9], "x": 10, "y": 4 },
{ "matrix": [4, 10], "x": 11, "y": 4 },
{ "matrix": [4, 11], "x": 12, "y": 4 },
{ "matrix": [4, 12], "x": 13, "y": 4 },
{ "matrix": [4, 13], "x": 14, "y": 4 },
{ "matrix": [4, 14], "x": 15, "y": 4 }
]
}
}
}

View File

@@ -0,0 +1,22 @@
// Copyright 2025 quark-works
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_65_iso(
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_HOME,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGUP,
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_PGDN,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
)
};
bool rgb_matrix_indicators_user(void) {
if (host_keyboard_led_state().caps_lock) {
rgb_matrix_set_color(25, 255, 0, 0);
}
return false;
}

View File

@@ -0,0 +1,27 @@
# null65iso v1
![sp](https://i.imgur.com/dypoXbB.png)
65% tray mount PCB with RGB per key.
* Keyboard Maintainer: [Quark](https://github.com/quark-works)
* Hardware Supported: PCB
* Hardware Availability: https://nulldesignco.com/
Make example for this keyboard (after setting up your build environment):
make nulldesignco/null65iso/v1:default
Flashing example for this keyboard:
make nulldesignco/null65iso/v1:default:flash
See 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).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
* **Physical boot button**: Hold the button labeled as "BOOT" on the back of the board or short the two pads on the front while you connect the keyboard to your computer.
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@@ -0,0 +1,86 @@
{
"manufacturer": "ASHIJANKEN",
"keyboard_name": "Slimorta",
"maintainer": "ASHIJANKEN",
"development_board": "promicro",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true
},
"matrix_pins": {
"cols": ["D1", "D0", "D4", "C6", "D7", "E6"],
"rows": ["B4", "B5", "F4", "F5", "F6", "F7", "B1", "B3", "B2", "B6"]
},
"url": "https://github.com/ASHIJANKEN/Slimorta",
"usb": {
"device_version": "1.0.0",
"pid": "0x0001",
"vid": "0x4153"
},
"layouts": {
"LAYOUT": {
"layout": [
{"matrix": [2, 0], "x": 0, "y": 0},
{"matrix": [2, 1], "x": 1, "y": 0},
{"matrix": [2, 2], "x": 2, "y": 0},
{"matrix": [2, 3], "x": 3, "y": 0},
{"matrix": [2, 4], "x": 4, "y": 0},
{"matrix": [2, 5], "x": 5, "y": 0},
{"matrix": [0, 5], "x": 6, "y": 0},
{"matrix": [0, 4], "x": 7, "y": 0},
{"matrix": [0, 3], "x": 8, "y": 0},
{"matrix": [0, 2], "x": 9, "y": 0},
{"matrix": [0, 1], "x": 10, "y": 0},
{"matrix": [0, 0], "x": 11, "y": 0},
{"matrix": [3, 0], "x": 0, "y": 1},
{"matrix": [3, 1], "x": 1, "y": 1},
{"matrix": [3, 2], "x": 2, "y": 1},
{"matrix": [3, 3], "x": 3, "y": 1},
{"matrix": [3, 4], "x": 4, "y": 1},
{"matrix": [3, 5], "x": 5, "y": 1},
{"matrix": [1, 5], "x": 6, "y": 1},
{"matrix": [1, 4], "x": 7, "y": 1},
{"matrix": [1, 3], "x": 8, "y": 1},
{"matrix": [1, 2], "x": 9, "y": 1},
{"matrix": [1, 1], "x": 10, "y": 1},
{"matrix": [1, 0], "x": 11, "y": 1},
{"matrix": [4, 0], "x": 0, "y": 2},
{"matrix": [4, 1], "x": 1, "y": 2},
{"matrix": [4, 2], "x": 2, "y": 2},
{"matrix": [4, 3], "x": 3, "y": 2},
{"matrix": [4, 4], "x": 4, "y": 2},
{"matrix": [4, 5], "x": 5, "y": 2},
{"matrix": [7, 5], "x": 6, "y": 2},
{"matrix": [7, 4], "x": 7, "y": 2},
{"matrix": [7, 3], "x": 8, "y": 2},
{"matrix": [7, 2], "x": 9, "y": 2},
{"matrix": [7, 1], "x": 10, "y": 2},
{"matrix": [7, 0], "x": 11, "y": 2},
{"matrix": [5, 0], "x": 0, "y": 3},
{"matrix": [5, 1], "x": 1, "y": 3},
{"matrix": [5, 2], "x": 2, "y": 3},
{"matrix": [5, 3], "x": 3, "y": 3},
{"matrix": [5, 4], "x": 4, "y": 3},
{"matrix": [5, 5], "x": 5, "y": 3},
{"matrix": [8, 5], "x": 6, "y": 3},
{"matrix": [8, 4], "x": 7, "y": 3},
{"matrix": [8, 3], "x": 8, "y": 3},
{"matrix": [8, 2], "x": 9, "y": 3},
{"matrix": [8, 1], "x": 10, "y": 3},
{"matrix": [8, 0], "x": 11, "y": 3},
{"matrix": [6, 1], "x": 0.5, "y": 4},
{"matrix": [6, 2], "x": 1.5, "y": 4},
{"matrix": [6, 3], "x": 2.5, "y": 4},
{"matrix": [6, 4], "x": 3.5, "y": 4, "w": 1.25},
{"matrix": [6, 5], "x": 4.75, "y": 4, "w": 1.25},
{"matrix": [9, 5], "x": 6, "y": 4, "w": 1.25},
{"matrix": [9, 4], "x": 7.25, "y": 4, "w": 1.25},
{"matrix": [9, 3], "x": 8.5, "y": 4},
{"matrix": [9, 2], "x": 9.5, "y": 4},
{"matrix": [9, 1], "x": 10.5, "y": 4}
]
}
}
}

View File

@@ -0,0 +1,27 @@
// Copyright 2025 ASHIJANKEN (@ASHIJANKEN)
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
* ┌─────┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬─────┐
* │ Esc │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ BS │
* ├─────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼─────┤
* │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ - │
* ├─────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼─────┤
* │ Ctrl│ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │
* ├─────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼─────┤
* │Shift│ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │Shift│
* └──┬──┴─┬─┴─┬─┴─┬─┴──┬┴───┼───┴┬──┴─┬─┴─┬─┴──┬┴───┬─┘
* │LNG2|Alt│GUI│ │ SPC│ Ent│ │ │Ctrl│LNG1│
* └────┴───┴───┴────┴────┴────┴────┴───┴────┴────┘
*/
[0] = LAYOUT(
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_MINS,
KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
KC_LNG2, KC_LALT, KC_LGUI, KC_NO, KC_SPC, KC_ENT, KC_NO, KC_NO, KC_LCTL, KC_LNG1
)
};

View File

@@ -0,0 +1,23 @@
# Slimorta
![slimorta](https://i.imgur.com/edsao2S.jpeg)
Slimorta is a slim and portable ortholinear keyboard.
* Keyboard Maintainer: [ASHIJANKEN](https://github.com/ASHIJANKEN)
* Hardware Supported: Slimorta PCB, ProMicro
* Hardware Availability: [PCB & Case Data](https://github.com/ASHIJANKEN/Slimorta)
Make example for this keyboard (after setting up your build environment):
make slimorta:default
Flashing example for this keyboard:
make slimorta:default:flash
See 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).
## Bootloader
**Physical reset button**: Press the button on the PCB twice briefly.

View File

@@ -0,0 +1,5 @@
// Copyright 2025 Snappy Key <snappykey@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#define MATRIX_MASKED

View File

@@ -0,0 +1,48 @@
{
"manufacturer": "Snappy Key",
"keyboard_name": "Snappy Pad v1",
"maintainer": "snappykey",
"development_board": "promicro",
"diode_direction": "COL2ROW",
"encoder": {
"rotary": [
{"pin_a": "F4", "pin_b": "F5"}
]
},
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"encoder": true
},
"matrix_pins": {
"cols": ["E6", "B4", "D7", "C6", "B6", "F6"],
"rows": ["D4", "D0", "D1"]
},
"url": "snappykey.eu",
"usb": {
"device_version": "1.0.0",
"pid": "0x1451",
"vid": "0x16D0"
},
"layouts": {
"LAYOUT": {
"layout": [
{"matrix": [0, 4], "x": 0, "y": 0},
{"matrix": [0, 5], "x": 3, "y": 0},
{"matrix": [0, 0], "x": 0, "y": 1},
{"matrix": [0, 1], "x": 1, "y": 1},
{"matrix": [0, 2], "x": 2, "y": 1},
{"matrix": [0, 3], "x": 3, "y": 1},
{"matrix": [1, 0], "x": 0, "y": 2},
{"matrix": [1, 1], "x": 1, "y": 2},
{"matrix": [1, 2], "x": 2, "y": 2},
{"matrix": [1, 3], "x": 3, "y": 2},
{"matrix": [2, 0], "x": 0, "y": 3},
{"matrix": [2, 1], "x": 1, "y": 3},
{"matrix": [2, 2], "x": 2, "y": 3},
{"matrix": [2, 3], "x": 3, "y": 3}
]
}
}
}

View File

@@ -0,0 +1,65 @@
// Copyright 2025 Snappy Key <snappykey@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
TO(1), KC_MPLY,
KC_F13, KC_F14, KC_F15, KC_F16,
KC_F17, KC_F18, KC_F19, KC_F20,
KC_F21, KC_F22, KC_F23, KC_F24
),
[1] = LAYOUT(
TO(2), KC_TRNS,
LSFT(KC_F13), LSFT(KC_F14), LSFT(KC_F15), LSFT(KC_F16),
LSFT(KC_F17), LSFT(KC_F18), LSFT(KC_F19), LSFT(KC_F20),
LSFT(KC_F21), LSFT(KC_F22), LSFT(KC_F23), LSFT(KC_F24)
),
[2] = LAYOUT(
TO(3), KC_TRNS,
LCTL(KC_F13), LCTL(KC_F14), LCTL(KC_F15), LCTL(KC_F16),
LCTL(KC_F17), LCTL(KC_F18), LCTL(KC_F19), LCTL(KC_F20),
LCTL(KC_F21), LCTL(KC_F22), LCTL(KC_F23), LCTL(KC_F24)
),
[3] = LAYOUT(
TO(0), KC_TRNS,
LALT(KC_F13), LALT(KC_F14), LALT(KC_F15), LALT(KC_F16),
LALT(KC_F17), LALT(KC_F18), LALT(KC_F19), LALT(KC_F20),
LALT(KC_F21), LALT(KC_F22), LALT(KC_F23), LALT(KC_F24)
)
};
layer_state_t layer_state_set_user(layer_state_t state) {
switch (get_highest_layer(state)) {
case 0:
gpio_write_pin_low(F7);
gpio_write_pin_low(B2);
gpio_write_pin_low(B5);
break;
case 1:
gpio_write_pin_high(F7);
gpio_write_pin_low(B2);
gpio_write_pin_low(B5);
break;
case 2:
gpio_write_pin_high(F7);
gpio_write_pin_high(B2);
gpio_write_pin_low(B5);
break;
case 3:
gpio_write_pin_high(F7);
gpio_write_pin_high(B2);
gpio_write_pin_high(B5);
break;
}
return state;
}
#if defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
[0] = { ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
[1] = { ENCODER_CCW_CW(_______, _______) },
[2] = { ENCODER_CCW_CW(_______, _______) },
[3] = { ENCODER_CCW_CW(_______, _______) }
};
#endif

View File

@@ -0,0 +1,27 @@
# Snappy Pad v.1
![sp](https://i.imgur.com/Xgv5qky.jpeg)
Reliable macro pad for all use cases
* Keyboard Maintainer: [SnappyKey](https://github.com/snappykey)
* Hardware Supported: pcb, cad files
* Hardware Availability: Will be open sourced later
Make example for this keyboard (after setting up your build environment):
make snappypad/v1_3x4:default
Flashing example for this keyboard:
make snappypad/v1_3x4:default:flash
See 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).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard
* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@@ -0,0 +1,11 @@
// Copyright 2025 Snappy Key <snappykey@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "quantum.h"
void keyboard_post_init_kb(void) {
gpio_set_pin_output(F7);
gpio_set_pin_output(B2);
gpio_set_pin_output(B5);
keyboard_post_init_user();
}

View File

@@ -0,0 +1,49 @@
{
"manufacturer": "TogKey",
"keyboard_name": "Pad Pocket",
"maintainer": "togkey86",
"development_board": "promicro_rp2040",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"rgblight": true
},
"matrix_pins": {
"cols": ["GP29", "GP22"],
"rows": ["GP26"]
},
"rgblight": {
"animations": {
"alternating": true,
"breathing": true,
"christmas": true,
"knight": true,
"rainbow_mood": true,
"rainbow_swirl": true,
"snake": true,
"static_gradient": true,
"twinkle": true
},
"hue_steps": 10,
"led_count": 2
},
"url": "https://togkey.com/products/togkey-pad-pocket",
"usb": {
"device_version": "1.0.0",
"pid": "0x8688",
"vid": "0xFEED"
},
"ws2812": {
"driver": "vendor",
"pin": "GP21"
},
"layouts": {
"LAYOUT": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0},
{"matrix": [0, 1], "x": 1, "y": 0}
]
}
}
}

View File

@@ -0,0 +1,29 @@
// Copyright 2025 TogKey
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
//Tap Dances
enum {
TD_VOLDOWN_MEDIAPREV,
TD_VOLUP_MEDIANEXT
};
tap_dance_action_t tap_dance_actions[] = {
[TD_VOLDOWN_MEDIAPREV] = ACTION_TAP_DANCE_DOUBLE(KC_AUDIO_VOL_DOWN, KC_MEDIA_PREV_TRACK),
[TD_VOLUP_MEDIANEXT] = ACTION_TAP_DANCE_DOUBLE(KC_AUDIO_VOL_UP, KC_MEDIA_NEXT_TRACK)
};
//Combos
const uint16_t PROGMEM media_combo[] = {TD(TD_VOLDOWN_MEDIAPREV), TD(TD_VOLUP_MEDIANEXT), COMBO_END};
combo_t key_combos[] = {
COMBO(media_combo, KC_MEDIA_PLAY_PAUSE)
};
//Keymap
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
TD(TD_VOLDOWN_MEDIAPREV), TD(TD_VOLUP_MEDIANEXT)
)
};

View File

@@ -0,0 +1,2 @@
COMBO_ENABLE = yes
TAP_DANCE_ENABLE = yes

View File

@@ -0,0 +1,27 @@
# pad_pocket
![pad_pocket](https://i.imgur.com/yCrqAe5.jpeg)
A simple 2-Key Macropad Keychain based off an RP2040 Development Board and a custom PCB that is pre-programmed to control media.
* Keyboard Maintainer: [Jon Henry](https://github.com/togkey86)
* Hardware Supported: Togkey Pad Pocket/Duo PCB, RP2040 Pro Micro Development Board
* Hardware Availability: (https://togkey.com)
Make example for this keyboard (after setting up your build environment):
make togkey/pad_pocket:default
Flashing example for this keyboard:
make togkey/pad_pocket:default:flash
See 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).
## Bootloader
Enter the bootloader in 3 ways:
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (The left key closest to the USB Port) and plug in the keyboard
* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@@ -3,6 +3,8 @@
We list each subcommand here explicitly because all the reliable ways of searching for modules are slow and delay startup.
"""
import os
import platform
import platformdirs
import shlex
import sys
from importlib.util import find_spec
@@ -12,6 +14,12 @@ from subprocess import run
from milc import cli, __VERSION__
from milc.questions import yesno
# Ensure the QMK distribution is on the `$PATH` if present.
_default_distrib_path = cli.run(['cygpath', '-w', '/opt/qmk']).stdout.strip() if 'windows' in platform.platform().lower() else platformdirs.user_data_dir('qmk') # this must be kept in sync with the default values inside `util/env-bootstrap.sh`!
QMK_DISTRIB_DIR = Path(os.environ.get('QMK_DISTRIB_DIR', _default_distrib_path))
if QMK_DISTRIB_DIR.exists():
os.environ['PATH'] = str(QMK_DISTRIB_DIR / 'bin') + os.pathsep + os.environ['PATH']
import_names = {
# A mapping of package name to importable name
'pep8-naming': 'pep8ext_naming',

View File

@@ -1,7 +1,6 @@
"""Check for specific programs.
"""
from enum import Enum
import re
import shutil
from subprocess import DEVNULL, TimeoutExpired
from tempfile import TemporaryDirectory
@@ -18,6 +17,10 @@ class CheckStatus(Enum):
ESSENTIAL_BINARIES = {
'make': {},
'git': {},
'dos2unix': {},
'diff': {},
'dfu-programmer': {},
'avrdude': {},
'dfu-util': {},
@@ -30,14 +33,39 @@ ESSENTIAL_BINARIES = {
}
def _parse_gcc_version(version):
m = re.match(r"(\d+)(?:\.(\d+))?(?:\.(\d+))?", version)
def _check_make_version():
last_line = ESSENTIAL_BINARIES['make']['output'].split('\n')[0]
version_number = last_line.split()[2]
cli.log.info('Found make version %s', version_number)
return {
'major': int(m.group(1)),
'minor': int(m.group(2)) if m.group(2) else 0,
'patch': int(m.group(3)) if m.group(3) else 0,
}
return CheckStatus.OK
def _check_git_version():
last_line = ESSENTIAL_BINARIES['git']['output'].split('\n')[0]
version_number = last_line.split()[2]
cli.log.info('Found git version %s', version_number)
return CheckStatus.OK
def _check_dos2unix_version():
last_line = ESSENTIAL_BINARIES['dos2unix']['output'].split('\n')[0]
version_number = last_line.split()[1]
cli.log.info('Found dos2unix version %s', version_number)
return CheckStatus.OK
def _check_diff_version():
last_line = ESSENTIAL_BINARIES['diff']['output'].split('\n')[0]
if 'Apple diff' in last_line:
version_number = last_line
else:
version_number = last_line.split()[3]
cli.log.info('Found diff version %s', version_number)
return CheckStatus.OK
def _check_arm_gcc_version():
@@ -148,16 +176,24 @@ def check_binaries():
"""Iterates through ESSENTIAL_BINARIES and tests them.
"""
ok = CheckStatus.OK
missing_from_path = []
for binary in sorted(ESSENTIAL_BINARIES):
try:
if not is_executable(binary):
if not is_in_path(binary):
ok = CheckStatus.ERROR
missing_from_path.append(binary)
elif not is_executable(binary):
ok = CheckStatus.ERROR
except TimeoutExpired:
cli.log.debug('Timeout checking %s', binary)
if ok != CheckStatus.ERROR:
ok = CheckStatus.WARNING
if missing_from_path:
location_noun = 'its location' if len(missing_from_path) == 1 else 'their locations'
cli.log.error('{fg_red}' + ', '.join(missing_from_path) + f' may need to be installed, or {location_noun} added to your path.')
return ok
@@ -165,6 +201,10 @@ def check_binary_versions():
"""Check the versions of ESSENTIAL_BINARIES
"""
checks = {
'make': _check_make_version,
'git': _check_git_version,
'dos2unix': _check_dos2unix_version,
'diff': _check_diff_version,
'arm-none-eabi-gcc': _check_arm_gcc_version,
'avr-gcc': _check_avr_gcc_version,
'avrdude': _check_avrdude_version,
@@ -196,15 +236,18 @@ def check_submodules():
return CheckStatus.OK
def is_executable(command):
"""Returns True if command exists and can be executed.
def is_in_path(command):
"""Returns True if command is found in the path.
"""
# Make sure the command is in the path.
res = shutil.which(command)
if res is None:
if shutil.which(command) is None:
cli.log.error("{fg_red}Can't find %s in your path.", command)
return False
return True
def is_executable(command):
"""Returns True if command can be executed.
"""
# Make sure the command can be executed
version_arg = ESSENTIAL_BINARIES[command].get('version_arg', '--version')
check = cli.run([command, version_arg], combined_output=True, stdin=DEVNULL, timeout=5)

View File

@@ -16,6 +16,34 @@ from qmk.commands import in_virtualenv
from qmk.userspace import qmk_userspace_paths, qmk_userspace_validate, UserspaceValidationError
def distrib_tests():
def _parse_distrib_info_file(file):
"""Parse the QMK distribution info file
"""
try:
vars = {}
with open(file, 'r') as f:
for line in f:
if '=' in line:
key, value = line.split('=', 1)
vars[key.strip()] = value.strip()
return f'{vars.get("TOOLCHAIN_HOST", "unknown")}:{vars.get("TOOLCHAIN_TARGET", "unknown")}:{vars.get("COMMIT_HASH", "unknown")}'
except Exception as e:
cli.log.warning('Error reading QMK distribution info file: %s', e)
return f'Unknown toolchain info file: {file}'
try:
from qmk.cli import QMK_DISTRIB_DIR
if (QMK_DISTRIB_DIR / 'etc').exists():
cli.log.info('Found QMK tools distribution directory: {fg_cyan}%s', QMK_DISTRIB_DIR)
toolchains = [_parse_distrib_info_file(file) for file in (QMK_DISTRIB_DIR / 'etc').glob('toolchain_release_*')]
cli.log.info('Found QMK toolchains: {fg_cyan}%s', ', '.join(toolchains))
except ImportError:
cli.log.info('QMK tools distribution not found.')
return CheckStatus.OK
def os_tests():
"""Determine our OS and run platform specific tests
"""
@@ -128,6 +156,7 @@ def doctor(cli):
cli.log.info('QMK home: {fg_cyan}%s', QMK_FIRMWARE)
status = os_status = os_tests()
distrib_tests()
userspace_tests(None)

View File

@@ -9,6 +9,7 @@ from milc import cli
from milc.questions import question, choice
from qmk.constants import HAS_QMK_USERSPACE, QMK_USERSPACE
from qmk.errors import NoSuchKeyboardError
from qmk.path import is_keyboard, keymaps, keymap
from qmk.git import git_get_username
from qmk.decorators import automagic_keyboard, automagic_keymap
@@ -110,13 +111,18 @@ def new_keymap(cli):
cli.log.error(f'Keyboard {{fg_cyan}}{kb_name}{{fg_reset}} does not exist! Please choose a valid name.')
return False
# generate keymap paths
keymaps_dirs = keymaps(kb_name)
keymap_path_default = keymap(kb_name, 'default')
keymap_path_new = keymaps_dirs[0] / user_name
# validate before any keymap ops
try:
keymaps_dirs = keymaps(kb_name)
keymap_path_new = keymaps_dirs[0] / user_name
except NoSuchKeyboardError:
cli.log.error(f'Keymap folder for {{fg_cyan}}{kb_name}{{fg_reset}} does not exist!')
return False
if not keymap_path_default.exists():
cli.log.error(f'Default keymap {{fg_cyan}}{keymap_path_default}{{fg_reset}} does not exist!')
keymap_path_default = keymap(kb_name, 'default')
if not keymap_path_default:
cli.log.error(f'Default keymap for {{fg_cyan}}{kb_name}{{fg_reset}} does not exist!')
return False
if not validate_keymap_name(user_name):
@@ -134,7 +140,7 @@ def new_keymap(cli):
_set_converter(keymap_path_new / 'keymap.json', converter)
# end message to user
cli.log.info(f'{{fg_green}}Created a new keymap called {{fg_cyan}}{user_name}{{fg_green}} in: {{fg_cyan}}{keymap_path_new}.{{fg_reset}}')
cli.log.info(f'{{fg_green}}Created a new keymap called {{fg_cyan}}{user_name}{{fg_green}} in: {{fg_cyan}}{keymap_path_new}{{fg_reset}}.')
cli.log.info(f"Compile a firmware with your new keymap by typing: {{fg_yellow}}qmk compile -kb {kb_name} -km {user_name}{{fg_reset}}.")
# Add to userspace compile if we have userspace available

View File

@@ -128,6 +128,41 @@
#define OSM(mod) (QK_ONE_SHOT_MOD | ((mod)&0x1F))
#define QK_ONE_SHOT_MOD_GET_MODS(kc) ((kc)&0x1F)
#define OS_LCTL OSM(MOD_LCTL)
#define OS_LSFT OSM(MOD_LSFT)
#define OS_LALT OSM(MOD_LALT)
#define OS_LGUI OSM(MOD_LGUI)
#define OS_LCS OSM(MOD_LCTL | MOD_LSFT)
#define OS_LCA OSM(MOD_LCTL | MOD_LALT)
#define OS_LCG OSM(MOD_LCTL | MOD_LGUI)
#define OS_LSA OSM(MOD_LSFT | MOD_LALT)
#define OS_LSG OSM(MOD_LSFT | MOD_LGUI)
#define OS_LAG OSM(MOD_LALT | MOD_LGUI)
#define OS_LCSG OSM(MOD_LCTL | MOD_LSFT | MOD_LGUI)
#define OS_LCAG OSM(MOD_LCTL | MOD_LALT | MOD_LGUI)
#define OS_LSAG OSM(MOD_LSFT | MOD_LALT | MOD_LGUI)
#define OS_RCTL OSM(MOD_RCTL)
#define OS_RSFT OSM(MOD_RSFT)
#define OS_RALT OSM(MOD_RALT)
#define OS_RGUI OSM(MOD_RGUI)
#define OS_RCS OSM(MOD_RCTL | MOD_RSFT)
#define OS_RCA OSM(MOD_RCTL | MOD_RALT)
#define OS_RCG OSM(MOD_RCTL | MOD_RGUI)
#define OS_RSA OSM(MOD_RSFT | MOD_RALT)
#define OS_RSG OSM(MOD_RSFT | MOD_RGUI)
#define OS_RAG OSM(MOD_RALT | MOD_RGUI)
#define OS_RCSG OSM(MOD_RCTL | MOD_RSFT | MOD_RGUI)
#define OS_RCAG OSM(MOD_RCTL | MOD_RALT | MOD_RGUI)
#define OS_RSAG OSM(MOD_RSFT | MOD_RALT | MOD_RGUI)
#define OS_MEH OSM(MOD_LCTL | MOD_LSFT | MOD_LALT)
#define OS_HYPR OSM(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI)
// Layer tap-toggle - 32 layer max
#define TT(layer) (QK_LAYER_TAP_TOGGLE | ((layer)&0x1F))
#define QK_LAYER_TAP_TOGGLE_GET_LAYER(kc) ((kc)&0x1F)

551
util/env-bootstrap.sh Executable file
View File

@@ -0,0 +1,551 @@
#!/usr/bin/env sh
# Copyright 2025 Nick Brassel (@tzarc)
# SPDX-License-Identifier: GPL-2.0-or-later
################################################################################
# This script will install the QMK CLI, toolchains, and flashing utilities.
################################################################################
# Environment variables:
# CONFIRM: Skip the pre-install delay. (or: --confirm)
# QMK_DISTRIB_DIR: The directory to install the QMK distribution to. (or: --qmk-distrib-dir=...)
# UV_INSTALL_DIR: The directory to install `uv` to. (or: --uv-install-dir=...)
# UV_TOOL_DIR: The directory to install `uv` tools to. (or: --uv-tool-dir=...)
# SKIP_CLEAN: Skip cleaning the distribution directory. (or: --skip-clean)
# SKIP_PACKAGE_MANAGER: Skip installing the necessary packages for the package manager. (or: --skip-package-manager)
# SKIP_UV: Skip installing `uv`. (or: --skip-uv)
# SKIP_QMK_CLI: Skip installing the QMK CLI. (or: --skip-qmk-cli)
# SKIP_QMK_TOOLCHAINS: Skip installing the QMK toolchains. (or: --skip-qmk-toolchains)
# SKIP_QMK_FLASHUTILS: Skip installing the QMK flashing utilities. (or: --skip-qmk-flashutils)
# SKIP_UDEV_RULES: Skip installing the udev rules for Linux. (or: --skip-udev-rules)
# SKIP_WINDOWS_DRIVERS: Skip installing the Windows drivers for the flashing utilities. (or: --skip-windows-drivers)
#
# Arguments above may be negated by prefixing with `--no-` instead (e.g. `--no-skip-clean`).
################################################################################
# Usage:
# curl -fsSL https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/env-bootstrap.sh | sh
#
# Help:
# curl -fsSL https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/env-bootstrap.sh | sh -s -- --help
#
# An example which skips installing `uv` using environment variables:
# curl -fsSL https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/env-bootstrap.sh | SKIP_UV=1 sh
#
# ...or by using command line arguments:
# curl -fsSL https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/env-bootstrap.sh | sh -s -- --skip-uv
#
# Any other configurable items listed above may be specified in the same way.
################################################################################
{ # this ensures the entire script is downloaded #
set -eu
BOOTSTRAP_TMPDIR="$(mktemp -d /tmp/qmk-bootstrap-failure.XXXXXX)"
trap 'rm -rf "$BOOTSTRAP_TMPDIR" >/dev/null 2>&1 || true' EXIT
FAILURE_FILE="${BOOTSTRAP_TMPDIR}/fail"
# Work out which `sed` to use
command -v gsed >/dev/null 2>&1 && SED=gsed || SED=sed
script_args() {
cat <<__EOT__
--help -- Shows this help text
--confirm -- Skips the delay before installation
--uv-install-dir={path} -- The directory to install \`uv\` into
--uv-tool-dir={path} -- The directory to install \`uv\` tools into
--qmk-distrib-dir={path} -- The directory to install the QMK distribution into
--skip-clean -- Skip cleaning the QMK distribution directory
--skip-package-manager -- Skip installing the necessary packages for the package manager
--skip-uv -- Skip installing \`uv\`
--skip-qmk-cli -- Skip installing the QMK CLI
--skip-qmk-toolchains -- Skip installing the QMK toolchains
--skip-qmk-flashutils -- Skip installing the QMK flashing utilities
--skip-udev-rules -- Skip installing the udev rules for Linux
--skip-windows-drivers -- Skip installing the Windows drivers for the flashing utilities
__EOT__
}
signal_execution_failure() {
touch "$FAILURE_FILE" >/dev/null 2>&1 || true
}
exit_if_execution_failed() {
if [ -e "$FAILURE_FILE" ]; then
exit 1
fi
}
script_help() {
echo "$(basename ${this_script:-qmk-install.sh}) $(script_args | sort | ${SED} -e 's@^\s*@@g' -e 's@\s\+--.*@@g' -e 's@^@[@' -e 's@$@]@' | tr '\n' ' ')"
echo
echo "Arguments:"
script_args
echo
echo "Switch arguments may be negated by prefixing with '--no-' (e.g. '--no-skip-clean')."
}
script_parse_args() {
local N
local V
while [ ! -z "${1:-}" ]; do
case "$1" in
--help)
script_help
exit 0
;;
--*=*)
N=${1%%=*}
N=${N##--}
N=$(echo $N | tr '-' '_' | tr 'a-z' 'A-Z')
V=${1##*=}
export $N="$V"
;;
--no-*)
N=${1##--no-}
N=$(echo $N | tr '-' '_' | tr 'a-z' 'A-Z')
unset $N
;;
--*)
N=${1##--}
N=$(echo $N | tr '-' '_' | tr 'a-z' 'A-Z')
export $N=true
;;
*)
echo "Unknown argument: '$1'" >&2
echo
script_help >&2
exit 1
;;
esac
shift
unset N
unset V
done
}
nsudo() {
if [ "$(fn_os)" = "windows" ]; then
# No need for sudo under QMK MSYS
return
elif [ $(id -u) -ne 0 ]; then
echo "sudo"
fi
true
}
download_url() {
local url=$1
local filename=${2:-$(basename "$url")}
local quiet=''
if [ -n "$(command -v curl 2>/dev/null || true)" ]; then
[ "$filename" = "-" ] && quiet='-s' || echo "Downloading '$url' => '$filename'" >&2
curl -LSf $quiet -o "$filename" "$url"
elif [ -n "$(command -v wget 2>/dev/null || true)" ]; then
[ "$filename" = "-" ] && quiet='-q' || echo "Downloading '$url' => '$filename'" >&2
wget $quiet "-O$filename" "$url"
else
echo "Please install 'curl' to continue." >&2
exit 1
fi
}
github_api_call() {
local url="$1"
local token="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
if [ -n "${token:-}" ]; then
if [ -n "$(command -v curl 2>/dev/null || true)" ]; then
curl -fsSL -H "Authorization: token $token" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/$url"
elif [ -n "$(command -v wget 2>/dev/null || true)" ]; then
wget -q --header="Authorization: token $token" --header="Accept: application/vnd.github.v3+json" "https://api.github.com/$url" -O -
fi
else
download_url "https://api.github.com/$url" -
fi
}
fn_os() {
local os_name=$(echo ${1:-} | tr 'A-Z' 'a-z')
if [ -z "$os_name" ]; then
os_name=$(uname -s | tr 'A-Z' 'a-z')
fi
case "$os_name" in
*darwin* | *macos* | *apple*)
echo macos
;;
*windows* | *mingw* | *msys*)
echo windows
;;
*linux*)
echo linux
;;
*)
echo unknown
;;
esac
}
fn_arch() {
local arch_name=$(echo ${1:-} | tr 'A-Z' 'a-z')
if [ -z "$arch_name" ]; then
arch_name=$(uname -m | tr 'A-Z' 'a-z')
fi
case "$arch_name" in
*arm64* | *aarch64*)
echo ARM64
;;
*riscv64*)
echo RV64
;;
*x86_64* | *x64*)
echo X64
;;
*)
echo unknown
;;
esac
}
preinstall_delay() {
[ -z "${CONFIRM:-}" ] || return 0
echo >&2
echo "Waiting 10 seconds before proceeding. Press Ctrl+C to cancel installation." >&2
sleep 10
}
get_package_manager_deps() {
case $(fn_os) in
macos) echo "zstd clang-format make hidapi libusb dos2unix git" ;;
windows) echo "base-devel: zstd:p toolchain:p clang:p hidapi:p dos2unix: git: unzip:" ;;
linux)
case $(grep ID /etc/os-release) in
*arch* | *manjaro* | *cachyos*) echo "zstd base-devel clang diffutils wget unzip zip hidapi dos2unix git" ;;
*debian* | *ubuntu*) echo "zstd build-essential clang-format diffutils wget unzip zip libhidapi-hidraw0 dos2unix git" ;;
*fedora*) echo "zstd clang diffutils which gcc git wget unzip zip hidapi dos2unix libusb-devel libusb1-devel libusb-compat-0.1-devel libusb0-devel git epel-release" ;;
*suse*) echo "zstd clang diffutils wget unzip zip libhidapi-hidraw0 dos2unix git libusb-1_0-devel gzip" ;;
*)
echo >&2
echo "Sorry, we don't recognize your distribution." >&2
echo >&2
echo "Proceeding with the installation, however you will need to install at least the following tools manually:" >&2
echo " - make, git, curl, zstd, unzip, [lib]hidapi" >&2
echo "Other tools may be required depending on your distribution." >&2
echo >&2
echo "Alternatively, if you prefer Docker, try using the docker image instead:" >&2
echo " - https://docs.qmk.fm/#/getting_started_docker" >&2
;;
esac
;;
*)
# We can only really support macOS, Windows, and Linux at this time due to `uv` requirements.
echo >&2
echo "Sorry, we don't recognize your OS. Try using a compatible OS instead:" >&2
echo " - https://docs.qmk.fm/newbs_getting_started#set-up-your-environment" >&2
echo >&2
echo "If you cannot use a compatible OS, you can try installing the \`qmk\` Python package manually using \`pip\`, most likely requiring a virtual environment:" >&2
echo " % python3 -m pip install qmk" >&2
echo >&2
echo "All other dependencies will need to be installed manually, such as make, git, AVR and ARM toolchains, and associated flashing utilities." >&2
echo >&2
echo "**NOTE**: QMK does not provide official support for your environment. Here be dragons, you are on your own." >&2
signal_execution_failure
;;
esac
}
print_package_manager_deps_and_delay() {
get_package_manager_deps | tr ' ' '\n' | sort | xargs -I'{}' echo " - {}" >&2
exit_if_execution_failed
preinstall_delay || exit 1
}
install_package_manager_deps() {
# Install the necessary packages for the package manager
case $(fn_os) in
macos)
if [ -n "$(command -v brew 2>/dev/null || true)" ]; then
echo "It will also install the following system packages using 'brew':" >&2
print_package_manager_deps_and_delay
brew update && brew upgrade --formulae
brew install $(get_package_manager_deps)
else
echo "Please install 'brew' to continue. See https://brew.sh/ for more information." >&2
exit 1
fi
;;
windows)
echo "It will also install the following packages using 'pacman'/'pacboy':" >&2
print_package_manager_deps_and_delay
$(nsudo) pacman --needed --noconfirm --disable-download-timeout -S pactoys
$(nsudo) pacboy sync --needed --noconfirm --disable-download-timeout $(get_package_manager_deps)
;;
linux)
case $(grep ID /etc/os-release) in
*arch* | *manjaro* | *cachyos*)
echo "It will also install the following system packages using 'pacman':" >&2
print_package_manager_deps_and_delay
$(nsudo) pacman --needed --noconfirm -S $(get_package_manager_deps)
;;
*debian* | *ubuntu*)
echo "It will also install the following system packages using 'apt':" >&2
print_package_manager_deps_and_delay
$(nsudo) apt-get update
DEBIAN_FRONTEND=noninteractive \
$(nsudo) apt-get --quiet --yes install $(get_package_manager_deps)
;;
*fedora*)
echo "It will also install the following system packages using 'dnf':" >&2
print_package_manager_deps_and_delay
# Some RHEL-likes need EPEL for hidapi
$(nsudo) dnf -y install epel-release 2>/dev/null || true
# RHEL-likes have some naming differences in libusb packages, so manually handle those
$(nsudo) dnf -y install $(get_package_manager_deps | tr ' ' '\n' | grep -v 'epel-release' | grep -v libusb | tr '\n' ' ')
for pkg in $(get_package_manager_deps | tr ' ' '\n' | grep libusb); do
$(nsudo) dnf -y install "$pkg" 2>/dev/null || true
done
;;
*opensuse* | *suse*)
echo "It will also install development tools as well as the following system packages using 'zypper':" >&2
print_package_manager_deps_and_delay
$(nsudo) zypper --non-interactive refresh
$(nsudo) zypper --non-interactive install -t pattern devel_basis devel_C_C++
$(nsudo) zypper --non-interactive install $(get_package_manager_deps)
;;
*)
print_package_manager_deps_and_delay
echo "Proceeding with the installation, you will need to ensure prerequisites are installed." >&2
;;
esac
;;
*)
print_package_manager_deps_and_delay
;;
esac
}
install_uv() {
# Install `uv` (or update as necessary)
download_url https://astral.sh/uv/install.sh - | TMPDIR="$(windows_ish_path "${TMPDIR:-}")" UV_INSTALL_DIR="$(windows_ish_path "${UV_INSTALL_DIR:-}")" sh
}
setup_paths() {
# Set up the paths for any of the locations `uv` expects
if [ -n "${XDG_BIN_HOME:-}" ]; then
export PATH="$XDG_BIN_HOME:$PATH"
fi
if [ -n "${XDG_DATA_HOME:-}" ]; then
export PATH="$XDG_DATA_HOME/../bin:$PATH"
fi
[ ! -d "$HOME/.local/bin" ] || export PATH="$HOME/.local/bin:$PATH"
if [ -n "${UV_INSTALL_DIR:-}" ]; then
export PATH="$UV_INSTALL_DIR/bin:$UV_INSTALL_DIR:$PATH" # cater for both "flat" and "hierarchical" installs of `uv`
fi
if [ -n "${UV_TOOL_BIN_DIR:-}" ]; then
export PATH="$UV_TOOL_BIN_DIR:$PATH"
fi
}
uv_command() {
if [ "$(fn_os)" = "windows" ]; then
UV_TOOL_DIR="$(windows_ish_path "${UV_TOOL_DIR:-}")" \
UV_TOOL_BIN_DIR="$(windows_ish_path "${UV_TOOL_BIN_DIR:-}")" \
uv "$@"
else
uv "$@"
fi
}
install_qmk_cli() {
# Install the QMK CLI
uv_command tool install --force --with pip --upgrade --python $PYTHON_TARGET_VERSION qmk
# QMK is installed to...
local qmk_tooldir="$(posix_ish_path "$(uv_command tool dir)/qmk")"
# Activate the environment
if [ -e "$qmk_tooldir/bin" ]; then
. "$qmk_tooldir/bin/activate"
elif [ -e "$qmk_tooldir/Scripts" ]; then
. "$qmk_tooldir/Scripts/activate"
else
echo "Could not find the QMK environment to activate." >&2
exit 1
fi
# Install the QMK dependencies
uv_command pip install --upgrade -r https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/requirements.txt
uv_command pip install --upgrade -r https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/requirements-dev.txt
# Deactivate the environment
deactivate
}
install_toolchains() {
# Get the latest toolchain release from https://github.com/qmk/qmk_toolchains
local latest_toolchains_release=$(github_api_call repos/qmk/qmk_toolchains/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
# Download the specific release asset with a matching keyword
local toolchain_url=$(github_api_call repos/qmk/qmk_toolchains/releases/tags/$latest_toolchains_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep $(fn_os)$(fn_arch))
if [ -z "$toolchain_url" ]; then
echo "No toolchain found for this OS/Arch combination." >&2
exit 1
fi
# Download the toolchain release to the toolchains location
echo "Downloading compiler toolchains..." >&2
local target_file="$QMK_DISTRIB_DIR/$(basename "$toolchain_url")"
download_url "$toolchain_url" "$target_file"
# Extract the toolchain
echo "Extracting compiler toolchains to '$QMK_DISTRIB_DIR'..." >&2
zstdcat "$target_file" | tar xf - -C "$QMK_DISTRIB_DIR" --strip-components=1
}
install_flashing_tools() {
# Get the latest flashing tools release from https://github.com/qmk/qmk_flashutils
local latest_flashutils_release=$(github_api_call repos/qmk/qmk_flashutils/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
# Download the specific release asset with a matching keyword
local flashutils_url=$(github_api_call repos/qmk/qmk_flashutils/releases/tags/$latest_flashutils_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep $(fn_os)$(fn_arch))
if [ -z "$flashutils_url" ]; then
echo "No flashing tools found for this OS/Arch combination." >&2
exit 1
fi
# Download the flashing tools release to the toolchains location
echo "Downloading flashing tools..." >&2
local target_file="$QMK_DISTRIB_DIR/$(basename "$flashutils_url")"
download_url "$flashutils_url" "$target_file"
# Extract the flashing tools
echo "Extracting flashing tools to '$QMK_DISTRIB_DIR'..." >&2
zstdcat "$target_file" | tar xf - -C "$QMK_DISTRIB_DIR/bin"
}
install_linux_udev_rules() {
# Download the udev rules to the toolchains location
echo "Downloading QMK udev rules file..." >&2
local qmk_rules_target_file="$QMK_DISTRIB_DIR/50-qmk.rules"
download_url "https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/util/udev/50-qmk.rules" "$qmk_rules_target_file"
# Install the udev rules -- path list is aligned with qmk doctor's linux.py
local udev_rules_paths="
/usr/lib/udev/rules.d
/usr/local/lib/udev/rules.d
/run/udev/rules.d
/etc/udev/rules.d
"
for udev_rules_dir in $udev_rules_paths; do
if [ -d "$udev_rules_dir" ]; then
echo "Installing udev rules to $udev_rules_dir/50-qmk.rules ..." >&2
$(nsudo) mv "$qmk_rules_target_file" "$udev_rules_dir"
$(nsudo) chown 0:0 "$udev_rules_dir/50-qmk.rules"
$(nsudo) chmod 644 "$udev_rules_dir/50-qmk.rules"
break
fi
done
# Reload udev rules
if command -v udevadm >/dev/null 2>&1; then
echo "Reloading udev rules..." >&2
$(nsudo) udevadm control --reload-rules || true
$(nsudo) udevadm trigger || true
else
echo "udevadm not found, skipping udev rules reload." >&2
fi
}
install_windows_drivers() {
# Get the latest driver installer release from https://github.com/qmk/qmk_driver_installer
local latest_driver_installer_release=$(github_api_call repos/qmk/qmk_driver_installer/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
# Download the specific release asset
local driver_installer_url=$(github_api_call repos/qmk/qmk_driver_installer/releases/tags/$latest_driver_installer_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep '\.exe')
if [ -z "$driver_installer_url" ]; then
echo "No driver installer found." >&2
exit 1
fi
# Download the driver installer release to the toolchains location
echo "Downloading driver installer..." >&2
local target_file="$QMK_DISTRIB_DIR/$(basename "$driver_installer_url")"
download_url "$driver_installer_url" "$target_file"
# Download the drivers list
download_url "https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/util/drivers.txt" "$QMK_DISTRIB_DIR/drivers.txt"
# Execute the driver installer
cd "$QMK_DISTRIB_DIR"
cmd.exe //c "qmk_driver_installer.exe --all --force drivers.txt"
cd -
# Remove the temporary files
rm -f "$QMK_DISTRIB_DIR/qmk_driver_installer.exe" "$QMK_DISTRIB_DIR/drivers.txt" || true
}
clean_tarballs() {
# Clean up the tarballs
rm -f "$QMK_DISTRIB_DIR"/*.tar.zst || true
}
windows_ish_path() {
[ -n "$1" ] || return 0
[ "$(uname -o 2>/dev/null || true)" = "Msys" ] && cygpath -w "$1" || echo "$1"
}
posix_ish_path() {
[ -n "$1" ] || return 0
[ "$(uname -o 2>/dev/null || true)" = "Msys" ] && cygpath -u "$1" || echo "$1"
}
# Set the Python version we want to use with the QMK CLI
export PYTHON_TARGET_VERSION=3.13
# Windows/MSYS doesn't like `/tmp` so we need to set a different temporary directory.
# Also set the default `UV_INSTALL_DIR` and `QMK_DISTRIB_DIR` to locations which don't pollute the user's home directory, keeping the installation internal to MSYS.
if [ "$(uname -o 2>/dev/null || true)" = "Msys" ]; then
export TMPDIR="$(posix_ish_path "$TMP")"
export UV_INSTALL_DIR="$(posix_ish_path "${UV_INSTALL_DIR:-/opt/uv}")"
export QMK_DISTRIB_DIR="$(posix_ish_path "${QMK_DISTRIB_DIR:-/opt/qmk}")"
export UV_TOOL_DIR="$(posix_ish_path "${UV_TOOL_DIR:-"$UV_INSTALL_DIR/tools"}")"
export UV_TOOL_BIN_DIR="$(posix_ish_path "$UV_TOOL_DIR/bin")"
fi
script_parse_args "$@"
echo "This QMK CLI installation script will install \`uv\`, the QMK CLI, as well as QMK-supplied toolchains and flashing utilities." >&2
[ -z "${SKIP_PACKAGE_MANAGER:-}" ] || { preinstall_delay || exit 1; }
[ -n "${SKIP_PACKAGE_MANAGER:-}" ] || install_package_manager_deps
[ -n "${SKIP_UV:-}" ] || install_uv
# Make sure the usual `uv` and other associated directories are on the $PATH
setup_paths
# Work out where we want to install the distribution and tools now that `uv` is installed
export QMK_DISTRIB_DIR="$(posix_ish_path "${QMK_DISTRIB_DIR:-$(printf 'import platformdirs\nprint(platformdirs.user_data_dir("qmk"))' | uv_command run --quiet --python $PYTHON_TARGET_VERSION --with platformdirs -)}")"
# Clear out the distrib directory if necessary
if [ -z "${SKIP_CLEAN:-}" ] || [ -z "${SKIP_QMK_TOOLCHAINS:-}" -a -z "${SKIP_QMK_FLASHUTILS:-}" ]; then
if [ -d "$QMK_DISTRIB_DIR" ]; then
echo "Removing old QMK distribution..." >&2
rm -rf "$QMK_DISTRIB_DIR"
fi
fi
mkdir -p "$QMK_DISTRIB_DIR"
[ -n "${SKIP_QMK_CLI:-}" ] || install_qmk_cli
[ -n "${SKIP_QMK_TOOLCHAINS:-}" ] || install_toolchains
[ -n "${SKIP_QMK_FLASHUTILS:-}" ] || install_flashing_tools
if [ "$(uname -s 2>/dev/null || true)" = "Linux" ]; then
[ -n "${SKIP_UDEV_RULES:-}" ] || install_linux_udev_rules
fi
if [ "$(uname -o 2>/dev/null || true)" = "Msys" ]; then
[ -n "${SKIP_WINDOWS_DRIVERS:-}" ] || install_windows_drivers
fi
clean_tarballs
# Notify the user that they may need to restart their shell to get the `qmk` command
echo >&2
echo "QMK CLI installation complete." >&2
echo "The QMK CLI has been installed to '$(posix_ish_path "$(dirname "$(command -v qmk)")")'." >&2
echo "The QMK CLI venv has been created at '$(posix_ish_path "$(uv_command tool dir)/qmk")'." >&2
echo "Toolchains and flashing utilities have been installed to '$QMK_DISTRIB_DIR'." >&2
echo >&2
echo "You may need to restart your shell to gain access to the 'qmk' command." >&2
echo "Alternatively, add "$(posix_ish_path "$(dirname "$(command -v qmk)")")" to your \$PATH:" >&2
echo " export PATH=\"$(posix_ish_path "$(dirname "$(command -v qmk)")"):\$PATH\"" >&2
} # this ensures the entire script is downloaded #