From 27816b75458c8b8349019913ad0f55897f7f7af9 Mon Sep 17 00:00:00 2001 From: binaryDiv Date: Wed, 22 May 2024 18:46:49 +0200 Subject: [PATCH 1/2] Firmware: Add initial QMK firmware files --- Makefile | 46 +++++++++ README.md | 23 +++++ qmk_keyboards/binarydiv/eepypad/v1/config.h | 20 ++++ qmk_keyboards/binarydiv/eepypad/v1/info.json | 99 +++++++++++++++++++ .../eepypad/v1/keymaps/default/keymap.c | 37 +++++++ .../binarydiv/eepypad/v1/rgb_matrix_user.inc | 32 ++++++ qmk_keyboards/binarydiv/eepypad/v1/rules.mk | 2 + 7 files changed, 259 insertions(+) create mode 100644 Makefile create mode 100644 qmk_keyboards/binarydiv/eepypad/v1/config.h create mode 100644 qmk_keyboards/binarydiv/eepypad/v1/info.json create mode 100644 qmk_keyboards/binarydiv/eepypad/v1/keymaps/default/keymap.c create mode 100644 qmk_keyboards/binarydiv/eepypad/v1/rgb_matrix_user.inc create mode 100644 qmk_keyboards/binarydiv/eepypad/v1/rules.mk diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f88854a --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +# Set QMK_HOME in your environment variables to adjust the path of the firmware +QMK_HOME ?= ${HOME}/qmk_firmware + +# Directories for QMK keyboard files (author, keyboard, revision) +QMK_KEYBOARD_AUTHOR_DIR := binarydiv +QMK_KEYBOARD_BASE_DIR := ${QMK_KEYBOARD_AUTHOR_DIR}/eepypad +QMK_KEYBOARD_REV_DIR := ${QMK_KEYBOARD_BASE_DIR}/v1 + +# Keymap to use when compiling QMK firmware +QMK_KEYMAP := default + + +# -- QMK commands + +# Prerequisite: Check if QMK is installed +.PHONY: _qmk-check-firmware-installed +_qmk-check-firmware-installed: + @test -d "${QMK_HOME}" || { \ + echo "QMK firmware not found! (QMK_HOME=${QMK_HOME})"; \ + echo "Please install QMK using 'qmk setup' first or set QMK_HOME in environment."; \ + exit 1; \ + } + +# Create symlink in QMK firmware directory to the keyboard files in qmk_keyboards/ +.PHONY: _qmk-create-symlink +_qmk-create-symlink: _qmk-check-firmware-installed ${QMK_HOME}/keyboards/${QMK_KEYBOARD_BASE_DIR} + +# Only create symlink if it doesn't exist already +${QMK_HOME}/keyboards/${QMK_KEYBOARD_BASE_DIR}: + mkdir -p "${QMK_HOME}/keyboards/${QMK_KEYBOARD_AUTHOR_DIR}" + ln -s "$$(realpath qmk_keyboards/${QMK_KEYBOARD_BASE_DIR})" "${QMK_HOME}/keyboards/${QMK_KEYBOARD_BASE_DIR}" + +# Compile QMK firmware +.PHONY: qmk-compile +qmk-compile: _qmk-create-symlink + qmk compile -kb ${QMK_KEYBOARD_REV_DIR} -km ${QMK_KEYMAP} + +# Compile and flash QMK firmware to keyboard +.PHONY: qmk-flash +qmk-flash: _qmk-create-symlink + qmk flash -kb ${QMK_KEYBOARD_REV_DIR} -km ${QMK_KEYMAP} + +# Run "qmk config" to set this keyboard as the default (to simplify running qmk commands manually) +.PHONY: qmk-activate +qmk-activate: _qmk-create-symlink + qmk config user.keyboard=${QMK_KEYBOARD_REV_DIR} user.keymap=${QMK_KEYMAP} diff --git a/README.md b/README.md index 9aad828..5b7e707 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Custom macro key pad with mechanical low-profile (Choc) switches. - `/layouts`: Keyboard layouts created with the [Keyboard Layout Editor](http://www.keyboard-layout-editor.com) - `/ergogen`: [Ergogen](https://docs.ergogen.xyz/) files to generate outlines, cases and PCBs +- `/qmk_keyboards`: [QMK](https://qmk.fm/) keyboard files to compile and flash the QMK firmware ## How-to @@ -75,6 +76,26 @@ Now you can generate the gerber, drill and map files. 4. Upload zip file to manufacturer and make sure everything is correct. 5. Add all generated files to version control (the zip should be on gitignore). +### Compile and flash QMK firmware + +To compile the QMK firmware, you first need the `qmk` CLI and a local copy of the QMK firmware. + +1. [Install](https://docs.qmk.fm/#/cli) the `qmk` CLI using your favorite package manager. +2. Run `qmk setup` to clone a local copy of the QMK firmware. (By default in `~/qmk_firmware`, feel free to adjust.) + +The firmware for this keyboard is compiled using the local copy of QMK and the keyboard definitions in `qmk_keyboards` +which are automatically symlinked to your installed QMK firmware directory (defaults to `~/qmk_firmware`, can be +overridden by setting `QMK_HOME` in your environment). A Makefile is provided to simplify compiling and flashing. + +To compile and flash the firmware, run `make qmk-flash`. + +After compiling the firmware, you will be asked to put your keyboard into bootloader mode. This can be done either by +pressing the reset button on the backside of the keyboard, or by using the `QK_BOOTLOADER` keycode which is mapped to +the key combination `0,4 (hold) + 0,0` (these are the matrix coordinates). + +You can also run `make qmk-activate` which will run `qmk config` to set `user.keyboard` and `user.keymap` to this +keyboard. This allows you to use the `qmk` CLI directly without specifying the keyboard and keymap everytime. + ## Used software - [Keyboard Layout Editor](http://www.keyboard-layout-editor.com) @@ -82,7 +103,9 @@ Now you can generate the gerber, drill and map files. - [KiCad](https://www.kicad.org/) - [FreeCAD](https://www.freecad.org/) - [UltiMaker Cura](https://ultimaker.com/software/ultimaker-cura/) +- [QMK](https://qmk.fm/) ## Resources - [FlatFootFox's Ergogen tutorial](https://flatfootfox.com/ergogen-introduction/) +- [QMK documentation](https://docs.qmk.fm/) diff --git a/qmk_keyboards/binarydiv/eepypad/v1/config.h b/qmk_keyboards/binarydiv/eepypad/v1/config.h new file mode 100644 index 0000000..428a0c4 --- /dev/null +++ b/qmk_keyboards/binarydiv/eepypad/v1/config.h @@ -0,0 +1,20 @@ +// Copyright 2024 binaryDiv (@binaryDiv) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +//#define NO_DEBUG + +/* disable print */ +//#define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT diff --git a/qmk_keyboards/binarydiv/eepypad/v1/info.json b/qmk_keyboards/binarydiv/eepypad/v1/info.json new file mode 100644 index 0000000..7652fbd --- /dev/null +++ b/qmk_keyboards/binarydiv/eepypad/v1/info.json @@ -0,0 +1,99 @@ +{ + "keyboard_name": "eepyPad v1.0", + "maintainer": "binaryDiv", + "manufacturer": "binaryDiv", + "url": "https://git.0xbd.space/binaryDiv/eepyPad/", + "processor": "atmega32u4", + "bootloader": "caterina", + "usb": { + "device_version": "1.0.0", + "vid": "0x1337", + "pid": "0xBD30" + }, + "features": { + "bootmagic": true, + "command": false, + "console": false, + "extrakey": true, + "mousekey": true, + "nkro": true, + "rgb_matrix": true + }, + "diode_direction": "ROW2COL", + "matrix_pins": { + "cols": ["F7", "B1", "B3", "B2", "B6"], + "rows": ["B5", "B4", "E6", "D7", "C6"] + }, + "layouts": { + "LAYOUT_ortho_5x5": { + "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": [1, 0], "x": 0, "y": 1}, + {"matrix": [1, 1], "x": 1, "y": 1}, + {"matrix": [1, 2], "x": 2, "y": 1}, + {"matrix": [1, 3], "x": 3, "y": 1}, + {"matrix": [1, 4], "x": 4, "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": 2}, + {"matrix": [2, 4], "x": 4, "y": 2}, + {"matrix": [3, 0], "x": 0, "y": 3}, + {"matrix": [3, 1], "x": 1, "y": 3}, + {"matrix": [3, 2], "x": 2, "y": 3}, + {"matrix": [3, 3], "x": 3, "y": 3}, + {"matrix": [3, 4], "x": 4, "y": 3}, + {"matrix": [4, 0], "x": 0, "y": 4}, + {"matrix": [4, 1], "x": 1, "y": 4}, + {"matrix": [4, 2], "x": 2, "y": 4}, + {"matrix": [4, 3], "x": 3, "y": 4}, + {"matrix": [4, 4], "x": 4, "y": 4} + ] + } + }, + "rgb_matrix": { + "driver": "ws2812", + "default": { + "animation": "trans_pride", + "speed": 32 + }, + "center_point": [2, 2], + "animations": { + "cycle_pinwheel": true, + "trans_pride": true + }, + "layout": [ + {"matrix": [0, 3], "x": 3, "y": 0, "flags": 4}, + {"matrix": [0, 2], "x": 2, "y": 0, "flags": 4}, + {"matrix": [0, 1], "x": 1, "y": 0, "flags": 4}, + {"matrix": [0, 0], "x": 0, "y": 0, "flags": 4}, + {"matrix": [1, 0], "x": 0, "y": 1, "flags": 4}, + {"matrix": [1, 1], "x": 1, "y": 1, "flags": 4}, + {"matrix": [1, 2], "x": 2, "y": 1, "flags": 4}, + {"matrix": [1, 3], "x": 3, "y": 1, "flags": 4}, + {"matrix": [1, 4], "x": 4, "y": 1, "flags": 4}, + {"matrix": [2, 4], "x": 4, "y": 2, "flags": 4}, + {"matrix": [2, 3], "x": 3, "y": 2, "flags": 4}, + {"matrix": [2, 2], "x": 2, "y": 2, "flags": 4}, + {"matrix": [2, 1], "x": 1, "y": 2, "flags": 4}, + {"matrix": [2, 0], "x": 0, "y": 2, "flags": 4}, + {"matrix": [3, 0], "x": 0, "y": 3, "flags": 4}, + {"matrix": [3, 1], "x": 1, "y": 3, "flags": 4}, + {"matrix": [3, 2], "x": 2, "y": 3, "flags": 4}, + {"matrix": [3, 3], "x": 3, "y": 3, "flags": 4}, + {"matrix": [3, 4], "x": 4, "y": 3, "flags": 4}, + {"matrix": [4, 4], "x": 4, "y": 4, "flags": 4}, + {"matrix": [4, 3], "x": 3, "y": 4, "flags": 4}, + {"matrix": [4, 2], "x": 2, "y": 4, "flags": 4}, + {"matrix": [4, 1], "x": 1, "y": 4, "flags": 4}, + {"matrix": [4, 0], "x": 0, "y": 4, "flags": 4} + ] + }, + "ws2812": { + "pin": "F6" + } +} diff --git a/qmk_keyboards/binarydiv/eepypad/v1/keymaps/default/keymap.c b/qmk_keyboards/binarydiv/eepypad/v1/keymaps/default/keymap.c new file mode 100644 index 0000000..30d95c5 --- /dev/null +++ b/qmk_keyboards/binarydiv/eepypad/v1/keymaps/default/keymap.c @@ -0,0 +1,37 @@ +// Copyright 2024 binaryDiv (@binaryDiv) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* + * ┌────────┬────────┬────────┬────────┬────────┐ + * │ │ │ │ Kbd-Fn │ │ + * ├────────┼────────┼────────┼────────┼────────┤ + * │ Alt+6 │ Alt+7 │ Alt+8 │ Alt+9 │ Alt+0 │ + * ├────────┼────────┼────────┼────────┼────────┤ + * │ Alt+1 │ Alt+2 │ Alt+3 │ Alt+4 │ Alt+5 │ + * ├────────┼────────┼────────┼────────┼────────┤ + * │ Ctrl+6 │ Ctrl+7 │ Ctrl+8 │ Ctrl+9 │ Ctrl+0 │ + * ├────────┼────────┼────────┼────────┼────────┤ + * │ Ctrl+1 │ Ctrl+2 │ Ctrl+3 │ Ctrl+4 │ Ctrl+5 │ + * └────────┴────────┴────────┴────────┴────────┘ + */ + // Default layer for Factorio tertiary/quarternary quick bars + [0] = LAYOUT_ortho_5x5( + _______, _______, _______, MO(1), _______, + LALT(KC_6), LALT(KC_7), LALT(KC_8), LALT(KC_9), LALT(KC_0), + LALT(KC_1), LALT(KC_2), LALT(KC_3), LALT(KC_4), LALT(KC_5), + LCTL(KC_6), LCTL(KC_7), LCTL(KC_8), LCTL(KC_9), LCTL(KC_0), + LCTL(KC_1), LCTL(KC_2), LCTL(KC_3), LCTL(KC_4), LCTL(KC_5) + ), + + // Keyboard control layer for entering bootloader and controlling the RGB light (hold 0,4) + [1] = LAYOUT_ortho_5x5( + QK_BOOTLOADER, QK_REBOOT, _______, _______, QK_CLEAR_EEPROM, + RGB_TOG, RGB_MODE_REVERSE, RGB_MODE_FORWARD, _______, _______, + RGB_VAI, RGB_SAI, RGB_HUI, RGB_SPI, _______, + RGB_VAD, RGB_SAD, RGB_HUD, RGB_SPD, _______, + RGB_MODE_PLAIN, RGB_MODE_BREATHE, RGB_MODE_RAINBOW, RGB_MODE_SWIRL, _______ + ), +}; diff --git a/qmk_keyboards/binarydiv/eepypad/v1/rgb_matrix_user.inc b/qmk_keyboards/binarydiv/eepypad/v1/rgb_matrix_user.inc new file mode 100644 index 0000000..465abe8 --- /dev/null +++ b/qmk_keyboards/binarydiv/eepypad/v1/rgb_matrix_user.inc @@ -0,0 +1,32 @@ +RGB_MATRIX_EFFECT(trans_pride) + +#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +bool trans_pride(effect_params_t* params) { + RGB_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t total_rows = 5; + uint8_t total_cols = 5; + + uint8_t rgb_rows[][3] = { + {RGB_CYAN}, + {RGB_MAGENTA}, + {RGB_WHITE}, + {RGB_MAGENTA}, + {RGB_CYAN} + }; + + for (uint8_t row = 0; row < total_rows; row++) { + for (uint8_t col = 0; col < total_cols; col++) { + rgb_matrix_set_color( + g_led_config.matrix_co[row][col], + (uint8_t) scale8(rgb_rows[row][0], rgb_matrix_config.hsv.v), + (uint8_t) scale8(rgb_rows[row][1], rgb_matrix_config.hsv.v), + (uint8_t) scale8(rgb_rows[row][2], rgb_matrix_config.hsv.v) + ); + } + } + return rgb_matrix_check_finished_leds(led_max); +} + +#endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/qmk_keyboards/binarydiv/eepypad/v1/rules.mk b/qmk_keyboards/binarydiv/eepypad/v1/rules.mk new file mode 100644 index 0000000..2f730fb --- /dev/null +++ b/qmk_keyboards/binarydiv/eepypad/v1/rules.mk @@ -0,0 +1,2 @@ +# Add custom RGB LED effects +RGB_MATRIX_CUSTOM_USER = yes From ad40075688ccb9aec0341e2a6905a0b38b3b4b01 Mon Sep 17 00:00:00 2001 From: binaryDiv Date: Wed, 22 May 2024 18:50:58 +0200 Subject: [PATCH 2/2] Enclosure: Add enclosure rev2 3D model --- 3d_prints/eepypad_v1_enclosure_rev2.stl | Bin 0 -> 107784 bytes README.md | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 3d_prints/eepypad_v1_enclosure_rev2.stl diff --git a/3d_prints/eepypad_v1_enclosure_rev2.stl b/3d_prints/eepypad_v1_enclosure_rev2.stl new file mode 100644 index 0000000000000000000000000000000000000000..92f74237a72e2fab2574c3587636b33704eaae03 GIT binary patch literal 107784 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 F_&@Nar@R0F literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 5b7e707..127bc27 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Custom macro key pad with mechanical low-profile (Choc) switches. - `/layouts`: Keyboard layouts created with the [Keyboard Layout Editor](http://www.keyboard-layout-editor.com) - `/ergogen`: [Ergogen](https://docs.ergogen.xyz/) files to generate outlines, cases and PCBs +- `/kicad`: KiCad PCBs and generated files +- `/3d_prints`: 3D models for the enclosure - `/qmk_keyboards`: [QMK](https://qmk.fm/) keyboard files to compile and flash the QMK firmware ## How-to @@ -101,7 +103,7 @@ keyboard. This allows you to use the `qmk` CLI directly without specifying the k - [Keyboard Layout Editor](http://www.keyboard-layout-editor.com) - [Ergogen](https://docs.ergogen.xyz/), [unofficial Ergogen web UI](https://ergogen.cache.works/) - [KiCad](https://www.kicad.org/) -- [FreeCAD](https://www.freecad.org/) +- [Onshape](https://www.onshape.com/) - [UltiMaker Cura](https://ultimaker.com/software/ultimaker-cura/) - [QMK](https://qmk.fm/)