1
0

Compare commits

...

23 Commits

Author SHA1 Message Date
Joel Challis
2bd8e43256 Enhance checks for invalid keyboard build targets (#26122)
Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>
2026-04-05 15:38:40 +10:00
Joel Challis
933cb8cc35 Update CI workflow to dynamically set keymaps (#26120) 2026-04-05 15:37:41 +10:00
Joel Challis
1426eedfc1 Fix cache list command in CI workflow 2026-04-02 08:23:41 +01:00
Joel Challis
e4b998ccb0 Only attempt cache deletion if exists (#26124) 2026-04-02 16:00:00 +11:00
Joel Challis
b5af7a3390 Enable ccache within CI (#26121) 2026-04-01 19:41:19 +11:00
Joel Challis
ed80e21858 Resolve 'using serial compilation of 2 LTRANS jobs' warning (#26113) 2026-03-30 15:25:29 +11:00
Joel Challis
9d24bc8a33 Fix userspace detection in Makefile (#26117) 2026-03-30 11:24:32 +08:00
QMK Bot
c7fde3d8cc [CI] Format code according to conventions (#26108)
Format code according to conventions
2026-03-27 03:56:53 +00:00
Sebastian Morgenstern
0fdb5df94d Added new pttbutton keyboard (#25952) 2026-03-27 03:15:28 +00:00
Joel Challis
bd500ae092 Detect PRs bypassing DD changes (#26094) 2026-03-20 06:27:49 +11:00
Peter Cock
fec01edaa4 Explain how to use STORE_SETUPS and PRINT_SETUPS (#26070)
* Explain how to use STORE_SETUPS and PRINT_SETUPS

I found the instructions a little terse, but managed.

This also adds a note about PRINT_SETUPS reporting random numbers if STORE_SETUPS hasn't been used.

* Remove line breaks

Existing docs seem to use a mix of hard line breaks at sentence
ends, or 80 chars-ish, versus no line breaks in paragraphs.

* Suggestion during review

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>

---------

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>
2026-03-19 11:40:49 +08:00
Peter Cock
7619e991cf QMK avoids raw line breaks within paragraphs in Markdown (#26080)
* QMK avoids raw line breaks within paragraphs in Markdown

Mentioned in passing during a few of my recent documentation pull requests, eg #26070.

* Suggestion during review

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>

---------

Co-authored-by: フィルターペーパー <76888457+filterpaper@users.noreply.github.com>
2026-03-19 10:16:35 +08:00
Dasky
627ad33233 Fix pointing device driver typo (#26091)
fix typo
2026-03-18 18:50:33 -07:00
フィルターペーパー
2cbcd76ef0 License violations updates. (#26076) 2026-03-16 03:12:18 +00:00
Joel Challis
322e673bcb Remove use of andstor/file-existence-action (#26078) 2026-03-16 03:12:04 +00:00
dependabot[bot]
4be8880177 Bump geekyeggo/delete-artifact from 5 to 6 (#26077)
Bumps [geekyeggo/delete-artifact](https://github.com/geekyeggo/delete-artifact) from 5 to 6.
- [Release notes](https://github.com/geekyeggo/delete-artifact/releases)
- [Changelog](https://github.com/GeekyEggo/delete-artifact/blob/main/CHANGELOG.md)
- [Commits](https://github.com/geekyeggo/delete-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: geekyeggo/delete-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 02:23:53 +00:00
Jalal El Mansouri
709628dfb2 Honor BUILD_DIR in mass_compile.py (#25586) 2026-03-15 22:07:43 +11:00
Joel Challis
e5faeea94d Unit tests should not run when docs change (#26068) 2026-03-14 15:31:07 +00:00
vuvoth
7ec819eb22 docs: remove hardware link in Ferris Sweep README (#26069)
remove hardware link in Ferris Sweep readme

Corrected wording for Ferris sweep hardware description.
2026-03-14 07:30:14 -06:00
Brandon
7785e87029 Add nulldesignco/v1/nullpad (#26057) 2026-03-13 23:17:29 +00:00
Peter Cock
afb5335bf3 Switch missing default handler in OS detection docs (#26064)
Switch was missing default handler: control reaches end of non-void function

This warning gets treated as an error on Github Actions
2026-03-13 22:59:54 +00:00
Nick Brassel
9fd72b352b Extra bootstrap release package filtering. (#26039) 2026-03-12 21:05:24 +11:00
Joel Challis
7fe0c9c746 [CI] Build unit tests in parallel (#26058) 2026-03-11 16:43:02 +00:00
23 changed files with 400 additions and 58 deletions

View File

@@ -32,6 +32,7 @@ jobs:
container: ghcr.io/qmk/qmk_cli
outputs:
keymaps: ${{ steps.generate_slice_length.outputs.keymaps }}
slice_length: ${{ steps.generate_slice_length.outputs.slice_length }}
steps:
@@ -47,12 +48,20 @@ jobs:
- name: Determine concurrency
id: generate_slice_length
shell: 'bash {0}'
run: |
target_count=$( {
qmk find -km default 2>/dev/null
qmk find -km xap 2>/dev/null
} | sort | uniq | wc -l)
targets=()
target_count=0
for target in "default" "xap"; do
count=$(qmk find -km $target 2>/dev/null | wc -l)
if [ $count -gt 0 ]; then
target_count=$(($target_count + $count))
targets+=($target)
fi
done
keymaps=$(jq -c -n '$ARGS.positional' --args "${targets[@]}")
slice_length=$((target_count / ($CONCURRENT_JOBS - 1))) # Err on the side of caution
echo "keymaps=$keymaps" >> $GITHUB_OUTPUT
echo "slice_length=$slice_length" >> $GITHUB_OUTPUT
build_targets:
@@ -61,7 +70,7 @@ jobs:
strategy:
fail-fast: false
matrix:
keymap: [default, xap]
keymap: ${{ fromJson(needs.determine_concurrency.outputs.keymaps) }}
uses: ./.github/workflows/ci_build_major_branch_keymap.yml
with:
branch: ${{ inputs.branch || github.ref_name }}
@@ -123,14 +132,7 @@ jobs:
SOURCE_DIR: .
DEST_DIR: ${{ inputs.branch || github.ref_name }}/latest
- name: Check if failure marker file exists
id: check_failure_marker
uses: andstor/file-existence-action@v3
with:
files: ./.failed
- name: Fail build if needed
if: steps.check_failure_marker.outputs.files_exists == 'true'
run: |
# Exit with failure if the compilation stage failed
exit 1
[ ! -e .failed ] || exit 1

View File

@@ -38,17 +38,18 @@ jobs:
run: pip3 install -r requirements-dev.txt
- name: Generate build targets
shell: 'bash {0}'
id: generate_targets
run: |
{ # Intentionally use `shuf` here so that we share manufacturers across all build groups -- some have a lot of ARM-based boards which inherently take longer
counter=0
echo -n '{'
qmk find -km ${{ inputs.keymap }} 2>/dev/null | sort | uniq | shuf | xargs -L${{ inputs.slice_length }} | while IFS=$'\n' read target ; do
qmk find -km ${{ inputs.keymap }} 2>/dev/null | sort | uniq | shuf --random-source=<(openssl enc -aes-256-ctr -pass pass:qmk -nosalt </dev/zero 2>/dev/null) | xargs -L${{ inputs.slice_length }} | while IFS=$'\n' read target ; do
if [ $counter -gt 0 ]; then
echo -n ','
fi
counter=$((counter+1))
printf "\"group %02d\":{" $counter
printf "\"group-%02d\":{" $counter
echo -n '"targets":"'
echo $target | tr ' ' '\n' | sort | uniq | xargs echo -n
echo -n '"}'
@@ -72,6 +73,9 @@ jobs:
container: ghcr.io/qmk/qmk_cli
continue-on-error: true
env:
CCACHE_CONFIGPATH: ~/.cache
strategy:
matrix:
target: ${{ fromJson(needs.generate_targets.outputs.targets) }}
@@ -83,6 +87,8 @@ jobs:
- name: Checkout QMK Firmware
uses: actions/checkout@v6
with:
submodules: recursive
- name: Install dependencies
run: pip3 install -r requirements-dev.txt
@@ -93,24 +99,47 @@ jobs:
name: targets-${{ inputs.keymap }}
path: .
- name: Deploy submodules
run: |
qmk git-submodule -f
- name: Dump targets
run: |
jq -r '.["${{ matrix.target }}"].targets' targets.json | tr ' ' '\n' | sort
- name: Restore Cache
id: cache
uses: actions/cache/restore@v5
with:
path: ${{ env.CCACHE_CONFIGPATH }}
key: compile-${{ inputs.keymap }}-${{ matrix.target }}
- name: Build targets
continue-on-error: true
run: |
export NCPUS=$(( $(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null) -1 ))
targets=$(jq -r '.["${{ matrix.target }}"].targets' targets.json | tr ' ' '\n' | sort)
if [ -z "${targets}" ]; then
echo "Zero build targets detected"
exit 0
fi
qmk mass-compile -t -j $NCPUS -e DUMP_CI_METADATA=yes $targets || touch .failed
qmk mass-compile -t -j $(nproc) -e DUMP_CI_METADATA=yes -e USE_CCACHE=yes $targets || touch .failed
- name: Dump ccache stats
run: |
ccache -s
# Delete the old cache on hit to emulate a cache update. See https://github.com/actions/cache/issues/342.
- name: Delete old cache
env:
GH_TOKEN: ${{ github.token }}
if: steps.cache.outputs.cache-hit
run: |
count=$(gh cache list --ref ${{ github.ref }} --key ${{ steps.cache.outputs.cache-primary-key }} --json id | jq length)
if [ $count -gt 0 ]; then
gh cache delete --ref ${{ github.ref }} ${{ steps.cache.outputs.cache-primary-key }}
fi
- name: Save Cache
uses: actions/cache/save@v5
with:
path: ${{ env.CCACHE_CONFIGPATH }}
key: compile-${{ inputs.keymap }}-${{ matrix.target }}
- name: Upload binaries
uses: actions/upload-artifact@v7
@@ -166,7 +195,7 @@ jobs:
truncate --size='<960K' $GITHUB_STEP_SUMMARY || true
- name: Delete temporary build artifacts
uses: geekyeggo/delete-artifact@v5
uses: geekyeggo/delete-artifact@v6
with:
name: |
firmware-${{ inputs.keymap }}-*

View File

@@ -89,23 +89,7 @@ jobs:
if: always()
shell: 'bash {0}'
run: |
exit_code=0
for file in $(find keyboards/ -name rules.mk | grep -v /keymaps/ | grep -v /common/ | grep -v /lib/); do
dir=$(dirname $file)
$(find $dir -name keyboard.json -exec false {} +)
if [[ $? == 0 ]]; then
echo "$dir::Legacy target detected"
((++exit_code))
fi
done
if [[ $exit_code -gt 255 ]]; then
exit 255
fi
exit $exit_code
qmk ci-validate-keyboard-targets
- name: Verify keyboard aliases
if: always()

View File

@@ -8,6 +8,9 @@ on:
paths:
- 'data/constants/**'
- 'lib/python/**'
- 'quantum/rgblight/rgblight_breathe_table.h'
- 'quantum/keycodes.h'
- 'quantum/keymap_extras/**'
jobs:
regen:

View File

@@ -11,6 +11,7 @@ on:
pull_request:
paths:
- 'builddefs/**'
- '!builddefs/docsgen/**'
- 'quantum/**'
- 'platforms/**'
- 'tmk_core/**'
@@ -34,4 +35,4 @@ jobs:
run: pip3 install -r requirements-dev.txt
- name: Run tests
run: qmk test-c
run: qmk test-c -j $(nproc)

View File

@@ -38,14 +38,16 @@ $(info QMK Firmware $(QMK_VERSION))
endif
endif
# Try to determine userspace from qmk config, if set.
ifeq ($(QMK_USERSPACE),)
QMK_USERSPACE = $(shell qmk config -ro user.overlay_dir | cut -d= -f2 | sed -e 's@^None$$@@g')
endif
# Determine which qmk cli to use
QMK_BIN := qmk
# Try to determine userspace from qmk config, if set. Handle direct query on qmk_cli>=1.1.7
# falling back to legacy method of only supporting user.overlay_dir config
export override QMK_USERSPACE := $(shell \
$(QMK_BIN) env | grep -q QMK_USERSPACE \
&& $(QMK_BIN) env QMK_USERSPACE \
|| $(QMK_BIN) config -ro user.overlay_dir | cut -d= -f2 | sed -e 's@^None$$@@g')
# avoid 'Entering|Leaving directory' messages
MAKEFLAGS += --no-print-directory

View File

@@ -58,7 +58,7 @@ endif
#---------------- C Compiler Options ----------------
ifeq ($(strip $(LTO_ENABLE)), yes)
CDEFS += -flto
CDEFS += -flto=auto
CDEFS += -DLTO_ENABLE
endif

View File

@@ -14,6 +14,10 @@ Example:
This page covers my super cool feature. You can use this feature to make coffee, squeeze fresh oj, and have an egg mcmuffin and hashbrowns delivered from your local macca's by drone.
```
# Paragraphs
Do not use hard line breaks within the raw Markdown for each paragraph. These are optional in Markdown, and have no effect on the rendered output. This means each raw paragraph will be a single long line in your editor (best viewed with line wrapping enabled).
# Headings
Your page should generally have multiple "H1" headings. Only H1 and H2 headings will included in the Table of Contents, so plan them out appropriately. Excess width should be avoided in H1 and H2 headings to prevent the Table of Contents from getting too wide.

View File

@@ -136,12 +136,19 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
print_stored_setups();
}
return false;
default:
return true; // Process all other keycodes normally
}
}
```
Then please open an issue on Github with this information and tell what OS was not detected correctly and if you have any intermediate devices between keyboard and your computer.
Add both `STORE_SETUPS` and `PRINT_SETUPS` to your keyboard's keymap. Connect the keyboard to the device where the OS was not recognised, and press the `STORE_SETUPS` key to capture and store the fingerprint. On your development computer, run one of the suggested [console debugging tools](/faq_debug#debugging-tools), connect the keyboard, and press the `PRINT_SETUPS` key. The console should display multiple lines of data from the most recent `STORE_SETUPS` run.
Open an issue on GitHub and paste the console output into the issue. Also tell us which OS (including the version, if possible) was not detected correctly and whether any intermediate devices, such as a USB hub, were used between the keyboard and the target device.
::: tip
If `STORE_SETUPS` has not been used previously, `PRINT_SETUPS` will report whatever values are already present in the controller's EEPROM. These may appear as random numbers.
:::
## Credits

View File

@@ -33,11 +33,13 @@ If you own a board from one of the following vendors already, consider asking th
| iLovBee | Official 30-day copyright source code request issued Sep 11 2024 due to deception on PR, no response received. Ambiguity on PRs -- marketing says wireless, PR author said wired-only, then included wireless code anyway. Seemingly intentionally deceptive. |
| KiiBOOM | Seems to use the same OEM as Epomaker, same problems. |
| kprepublic | Makes no attempt to release source code, all boards in QMK are reverse-engineered, created, and supported by the community. New board variants magically appear without telling customers they're incompatible with existing QMK versions, in some cases bricking boards or requiring ISP flashing. |
| Lofree | Selling tri-mode boards based on QMK without sources, just `via.json` provided. |
| Luminkey | Selling tri-mode boards based on QMK without sources, just `via.json` provided. |
| Meletrix | Selling tri-mode boards based on QMK without sources, just `via.json` provided. |
| mmd / Smartmmd / i-game.tech | Ambiguity on PRs -- marketing says wireless, PR author said wired-only, then included wireless code anyway. Seemingly intentionally deceptive. |
| MyKeyClub | Community-supported JRIS75, vendor was contacted by community members and refused to cooperate. |
| owlab | Selling wired based on QMK without sources, just `via.json` provided. Ambiguous as to whether or not wireless firmware is based on QMK, given that their configuration tool looks very similar to VIA. |
| PMO Lab | Selling tri-mode boards based on QMK without sources, just `via.json` provided. |
| pressplayid | Selling wired and tri-mode boards based on QMK without sources, just `via.json` provided |
| qwertykeys | Selling wired and tri-mode boards based on QMK without sources, just `via.json` provided. |
| Redragon | Selling tri-mode boards based on QMK without sources, attempted upstreaming crippled firmware without wireless. |

View File

@@ -23,7 +23,7 @@
#include "gpio.h"
#include "pointing_device_internal.h"
const pointing_device_driver_t pmw3320_pointing_device_drivera = {
const pointing_device_driver_t pmw3320_pointing_device_driver = {
.init = pmw3320_init,
.get_report = pmw3320_get_report,
.set_cpi = pmw3320_set_cpi,

View File

@@ -8,8 +8,7 @@ A split 34 keys column staggered keyboard named and decorated after the rustlang
* Hardware Supported:
* Ferris 0.1 (With atmega32u4 chip. Comes in 4 variants: base, low, high and compact)
* Ferris 0.2 (With stm32f072 chip. Comes in 4 variants: bling, mini, high and compact)
* Ferris sweep (With pro-micro. Comes in a couple of PCB edge cuts shapes, but with identical pinout)
* Hardware Availability: [Cuddly Keyboards](https://cuddlykeyboards.com)
* Ferris sweep (With pro-micro. Comes in a couple of PCB edge cut shapes, but with an identical pinout)
Make examples for this keyboard (after setting up your build environment):

View File

@@ -0,0 +1,28 @@
{
"manufacturer": "Sebastian Morgenstern",
"keyboard_name": "pttbutton",
"maintainer": "morningstar1",
"bootloader": "stm32-dfu",
"diode_direction": "COL2ROW",
"features": {
"extrakey": true
},
"matrix_pins": {
"cols": ["B0"],
"rows": ["A0"]
},
"processor": "STM32F042",
"url": "https://github.com/morningstar1/pttbutton",
"usb": {
"device_version": "1.0.0",
"vid": "0x736D",
"pid": "0xAFFE"
},
"layouts": {
"LAYOUT": {
"layout": [
{"matrix": [0, 0], "x": 0, "y": 0}
]
}
}
}

View File

@@ -0,0 +1,10 @@
// Copyright 2026 SEbastian Morgenstern
// SPDX-License-Identifier: GPL-2.0-or-later
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_F14
)
};

View File

@@ -0,0 +1,42 @@
/* Copyright 2026 Sebastian Morgenstern
*
* 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"
#include "hal.h"
void board_init(void) {
// Remap PA11->PA9 and PA12->PA10 for USB
SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
}
void keyboard_pre_init_kb(void) {
// Immediately set the LED pin as an output and set it ON
gpio_set_pin_output(A15);
gpio_write_pin_high(A15);
keyboard_pre_init_user();
}
void keyboard_post_init_kb(void) {
// Blink the LED so we know everything is running OK
// Finish with LED OFF
gpio_write_pin_low(A15);
wait_ms(100);
gpio_write_pin_high(A15);
wait_ms(100);
gpio_write_pin_low(A15);
keyboard_post_init_user();
}

View File

@@ -0,0 +1,25 @@
# pttbutton
![pttbutton](https://github.com/morningstar1/PTTButton/blob/main/image/PTTButton.png?raw=true)
A simple one button keyboard with a USB Hub. Primary intention is to use it as a Push To Talk (PTT) button.
* Keyboard Maintainer: [Sebastian Morgenstern](https://github.com/morningstar1)
* Hardware Supported: [PTTButton V1.0](https://github.com/morningstar1/PTTButton)
* Hardware Availability: please contact me <sebastian.morgenstern@gmail.com>
Make example for this keyboard (after setting up your build environment):
make morningstar1/pttbutton:default
Flashing example for this keyboard:
make morningstar1/pttbutton: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 one way:
* **Physical reset button**: Briefly press the small button on the PCB

View File

@@ -0,0 +1,126 @@
{
"manufacturer": "nulldesignco",
"keyboard_name": "nullpad",
"maintainer": "quark-works",
"bootloader": "rp2040",
"diode_direction": "COL2ROW",
"features": {
"bootmagic": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"rgb_matrix": true
},
"matrix_pins": {
"cols": ["GP27", "GP28", "GP8", "GP10"],
"rows": ["GP12", "GP25", "GP11", "GP26", "GP9", "GP21"]
},
"processor": "RP2040",
"rgb_matrix": {
"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
},
"driver": "ws2812",
"layout": [
{"matrix": [5, 1], "x": 37, "y": 0, "flags": 4},
{"matrix": [3, 0], "x": 0, "y": 16, "flags": 4},
{"matrix": [3, 1], "x": 75, "y": 16, "flags": 4},
{"matrix": [3, 2], "x": 150, "y": 16, "flags": 4},
{"matrix": [4, 2], "x": 150, "y": 0, "flags": 4},
{"matrix": [4, 3], "x": 224, "y": 8, "flags": 4},
{"matrix": [2, 2], "x": 150, "y": 32, "flags": 4},
{"matrix": [2, 1], "x": 75, "y": 32, "flags": 4},
{"matrix": [2, 0], "x": 0, "y": 32, "flags": 4},
{"matrix": [1, 0], "x": 0, "y": 48, "flags": 4},
{"matrix": [1, 1], "x": 75, "y": 48, "flags": 4},
{"matrix": [1, 2], "x": 150, "y": 48, "flags": 4},
{"matrix": [2, 3], "x": 224, "y": 40, "flags": 4},
{"matrix": [0, 3], "x": 224, "y": 64, "flags": 4},
{"matrix": [0, 2], "x": 150, "y": 64, "flags": 4},
{"matrix": [0, 1], "x": 75, "y": 64, "flags": 4},
{"matrix": [0, 0], "x": 0, "y": 64, "flags": 4}
],
"sleep": true
},
"url": "https://nulldesignco.com/",
"usb": {
"device_version": "1.0.0",
"pid": "0x0011",
"vid": "0x6E6C"
},
"ws2812": {
"driver": "vendor",
"pin": "GP18"
},
"community_layouts": ["numpad_5x4"],
"layouts": {
"LAYOUT_numpad_5x4": {
"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": [1, 0], "x": 0, "y": 1},
{"matrix": [1, 1], "x": 1, "y": 1},
{"matrix": [1, 2], "x": 2, "y": 1},
{"matrix": [2, 0], "x": 0, "y": 2},
{"matrix": [2, 1], "x": 1, "y": 2},
{"matrix": [2, 2], "x": 2, "y": 2},
{"matrix": [2, 3], "x": 3, "y": 1, "h": 2},
{"matrix": [3, 0], "x": 0, "y": 3},
{"matrix": [3, 1], "x": 1, "y": 3},
{"matrix": [3, 2], "x": 2, "y": 3},
{"matrix": [5, 1], "x": 0, "y": 4, "w": 2},
{"matrix": [4, 2], "x": 2, "y": 4},
{"matrix": [4, 3], "x": 3, "y": 3, "h": 2}
]
}
}
}

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_numpad_5x4(
KC_NUM, KC_PSLS, KC_PAST, KC_PMNS,
KC_P7, KC_P8, KC_P9,
KC_P4, KC_P5, KC_P6, KC_PPLS,
KC_P1, KC_P2, KC_P3,
KC_P0, KC_PDOT, KC_PENT
)
};
bool rgb_matrix_indicators_user(void) {
if (host_keyboard_led_state().num_lock) {
rgb_matrix_set_color(16, 255, 0, 0);
}
return false;
}

View File

@@ -0,0 +1,27 @@
# nullpad v1
![sp](https://i.imgur.com/069rfPe.png)
Numpad 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/nullpad/v1:default
Flashing example for this keyboard:
make nulldesignco/nullpad/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 (top left key or NumLock) and plug in the keyboard
* **Physical boot button**: Hold the button labeled as "BOOT" on the back of the board while you connect the keyboard to your computer.
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available

View File

@@ -56,6 +56,7 @@ safe_commands = [
subcommands = [
'qmk.cli.ci.validate_aliases',
'qmk.cli.ci.validate_keyboard_targets',
'qmk.cli.bux',
'qmk.cli.c2json',
'qmk.cli.cd',

View File

@@ -0,0 +1,28 @@
"""Validates the list of keyboard targets.
"""
from milc import cli
from pathlib import Path
@cli.subcommand('Validates the list of keyboard targets.', hidden=True)
def ci_validate_keyboard_targets(cli):
errors = set()
for rules_mk in Path('keyboards').glob('**/rules.mk'):
if any({'keymaps', 'common', 'lib'} & set(rules_mk.parts)):
continue
folder = rules_mk.parent
if not any(folder.glob('**/keyboard.json')):
errors.add(folder)
for keymap in Path('keyboards').glob('**/keymaps/'):
folder = keymap.parent
if not any(folder.glob('**/keyboard.json')):
errors.add(folder)
for error in errors:
print(f"{error}::Legacy target detected")
exit(min(len(errors), 255))

View File

@@ -23,7 +23,7 @@ def mass_compile_targets(targets: List[BuildTarget], clean: bool, dry_run: bool,
os.environ.setdefault('SKIP_SCHEMA_VALIDATION', '1')
make_cmd = find_make()
builddir = Path(QMK_FIRMWARE) / '.build'
builddir = Path(env.get("BUILD_DIR")) if env.get("BUILD_DIR") is not None else Path(QMK_FIRMWARE) / '.build'
makefile = builddir / 'parallel_kb_builds.mk'
if dry_run:
@@ -71,8 +71,8 @@ print_failures: all_targets
command = target.compile_command(**env)
command[0] = '+@$(MAKE)' # Override the make so that we can use jobserver to handle parallelism
extra_args = '_'.join([f"{k}_{v}" for k, v in target.extra_args.items()])
build_log = f"{QMK_FIRMWARE}/.build/build.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
failed_log = f"{QMK_FIRMWARE}/.build/failed.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
build_log = f"{builddir}/build.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
failed_log = f"{builddir}/failed.log.{os.getpid()}.{keyboard_safe}.{keymap_name}"
target_suffix = ''
if len(extra_args) > 0:
build_log += f".{extra_args}"
@@ -101,9 +101,9 @@ all_targets: {target_filename}{target_suffix}_binary
# yapf: disable
f.write(
f"""\
@rm -rf "{QMK_FIRMWARE}/.build/{target_filename}.elf" 2>/dev/null || true
@rm -rf "{QMK_FIRMWARE}/.build/{target_filename}.map" 2>/dev/null || true
@rm -rf "{QMK_FIRMWARE}/.build/obj_{target_filename}" || true
@rm -rf "{builddir}/{target_filename}.elf" 2>/dev/null || true
@rm -rf "{builddir}/{target_filename}.map" 2>/dev/null || true
@rm -rf "{builddir}/obj_{target_filename}" || true
"""# noqa
)
# yapf: enable

View File

@@ -418,7 +418,7 @@ __EOT__
# 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))
local toolchain_url=$(github_api_call repos/qmk/qmk_toolchains/releases/tags/$latest_toolchains_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep -E "qmk_toolchains-.*$(fn_os)$(fn_arch)")
if [ -z "$toolchain_url" ]; then
echo "No toolchain found for this OS/Arch combination." >&2
exit 1
@@ -445,7 +445,7 @@ __EOT__
# 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 "$osarchvariant")
local flashutils_url=$(github_api_call repos/qmk/qmk_flashutils/releases/tags/$latest_flashutils_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep -E "qmk_flashutils-.*$osarchvariant")
if [ -z "$flashutils_url" ]; then
echo "No flashing tools found for this OS/Arch combination." >&2
exit 1