Compare commits

...

73 Commits

Author SHA1 Message Date
Thomas Haukland
26f5a784bc homerow_mods_fixed_for_everybody_cheapino2 2024-09-01 16:32:12 +02:00
Thomas Haukland
ef5c9248d9 Moved info.json to keyboard.json 2024-08-31 11:50:18 +02:00
Thomas Haukland
eb17259123 Merge branch 'master' into cheapinov2 2024-08-31 11:43:32 +02:00
Thomas Haukland
44c360e306 Add NKRO support 2024-06-28 10:07:46 +02:00
Thomas Haukland
57cb971c41 Blacktyl_lars 2024-06-18 19:41:39 +02:00
Thomas Haukland
a51b65854b keymap: grave 2024-06-15 09:45:16 +02:00
Thomas Haukland
1f86bf03fe Merge branch 'master' into cheapinov2 2024-05-30 22:11:30 +02:00
Thomas Haukland
7041eadcbf Use unsigned short instead of macro ushort
Ref: https://github.com/tompi/cheapino/issues/38
2024-05-18 09:55:30 +02:00
Thomas Haukland
2b0a045409 Merge branch 'master' into cheapinov2
# Conflicts:
#	keyboards/bastardkb/blacktyl/rules.mk
2024-05-18 09:41:24 +02:00
Thomas Haukland
766ef32a47 Fix more ghosting: https://github.com/tompi/cheapino/issues/33 2024-05-07 21:56:12 +02:00
Thomas Haukland
605daf9597 Fix silly bit alignment error 2024-05-06 22:01:15 +02:00
Thomas Haukland
4cfdc10412 Fix observed ghosts: https://github.com/tompi/cheapino/issues/33 2024-05-06 21:40:34 +02:00
Thomas Haukland
f66d8439a7 Disable debug output by default 2024-04-09 08:13:25 +02:00
Thomas Haukland
1e0fd1ac55 Fix error in default keymap 2024-04-06 13:03:16 +02:00
Thomas Haukland
31928517ce Merge branch 'master' into cheapinov2 2024-04-06 10:37:02 +02:00
Thomas Haukland
e6851f7ae9 Update to latest qmk 2024-03-26 21:21:36 +01:00
Thomas Haukland
6cc3169c16 Merge branch 'master' into cheapinov2 2024-03-26 19:07:10 +01:00
Thomas Haukland
181976a4fc Fixed encoder logic and some mappings 2023-12-10 13:58:30 +01:00
Thomas Haukland
0671e5f95c Merge pull request #3 from fauh45/cheapinov2
Fix Cheapino v2 Code
2023-12-10 12:21:29 +01:00
Fauzan Lubis
d5b6ce4aa8 fix encoder not recognized
encoder code now only checks for certain bits
2023-12-09 22:39:25 +07:00
Fauzan Lubis
af6f1b5d70 fix pin & key mapping
tested out with current design
2023-12-09 22:38:39 +07:00
Thomas Haukland
f0892a027c Cheapino v2 wip 2023-12-05 16:31:50 +01:00
Thomas Haukland
9d538fc75a Merge branch 'master' into cheapino 2023-11-30 20:19:24 +01:00
Thomas Haukland
da9c2971c2 Make default keymap json and more usable 2023-09-10 12:30:59 +02:00
Thomas Haukland
b7dec6480b Update config.h to latest format 2023-07-24 23:27:01 +02:00
Thomas Haukland
0f0e1dab49 Merge branch 'master' into cheapino 2023-07-24 23:13:09 +02:00
Thomas Haukland
6bfbcd8ca0 Added community layout support: https://lemmy.world/post/2042497
Also removed some warnings
2023-07-24 22:59:52 +02:00
Thomas Haukland
e908f86835 LED: double steps in init animation 2023-05-11 23:55:25 +02:00
Thomas Haukland
9b9040430e Merge branch 'cheapino' of github.com:tompi/qmk_firmware into cheapino 2023-05-11 23:38:14 +02:00
Thomas Haukland
c27677b504 Second attempt at ghosting issue: more specific fix 2023-05-11 23:37:27 +02:00
Thomas Haukland
e51adc4a56 Fix reversed ghosting correction 2023-05-11 08:41:44 +02:00
Thomas Haukland
e67f3c1bc7 Merge branch 'cheapino' of github.com:tompi/qmk_firmware into cheapino
# Conflicts:
#	keyboards/cheapino/cheapino.c
#	keyboards/cheapino/config.h
#	keyboards/cheapino/info.json
#	keyboards/cheapino/keymaps/default/keymap.c
#	keyboards/cheapino/matrix.c
#	keyboards/cheapino/readme.md
#	keyboards/cheapino/rules.mk
#	keyboards/ferris/sweep/rules.mk
2023-05-11 08:40:00 +02:00
Thomas Haukland
42193e0123 Fix a ghosting issue, and introduce longer wait in scanning 2023-05-11 07:14:10 +02:00
Thomas Haukland
c6cca1c013 Cheapino: support onboard LED, and a small init flash 2023-04-28 21:26:18 +02:00
Thomas Haukland
47a116e13f Merge branch 'cheapino' of github.com:tompi/qmk_firmware into cheapino 2023-04-27 23:05:39 +02:00
Thomas Haukland
d8203067c6 Merge pull request #1 from DeBasti/cheapino
Removed duplicate definition of keyboard_post_init_user in default keymap causing build to fail
2023-04-24 15:01:28 +02:00
DeBasti
358a00f8b8 removed since build fails otherwise 2023-04-24 14:34:12 +02:00
Thomas Haukland
ca8ab1dcf6 RGB matrix works 2023-04-23 15:12:47 +02:00
Thomas Haukland
892afe5e36 Fix encoding actions and add Lars keymap 2023-03-31 23:00:54 +02:00
Thomas Haukland
a7f3742dc1 Cheapino: encoder abstractions 2023-03-25 22:41:05 +01:00
Thomas Haukland
76b3490f10 Cheapino: encoder works 2023-03-25 15:29:34 +01:00
Thomas Haukland
ff202e2274 Merge branch 'master' into cheapino 2023-03-24 23:23:42 +01:00
Thomas Haukland
2fa3131f76 The cheapino works, except for the encoder 2023-03-22 22:47:54 +01:00
Thomas Haukland
3e94864262 Cheapino: it compiles 2023-03-12 13:24:06 +01:00
Thomas Haukland
17852c1866 2x2 matrix scan works 2022-10-16 19:05:46 +02:00
Thomas Haukland
94435a48ed Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-10-14 13:14:37 +02:00
Thomas Haukland
1e8f58d73e ferris: remap mouse buttons 2022-10-01 12:05:56 +02:00
Thomas Haukland
30120b4e5b mouse buttons on ferris 2022-10-01 11:03:09 +02:00
Thomas Haukland
e1337cc928 CAPS WORD for zompi 2022-09-25 20:33:42 +02:00
Thomas Haukland
08b55ef037 Zompi: per key led works 2022-09-25 20:31:49 +02:00
Thomas Haukland
b72b00f7c7 CAPS WORD for blacktyl 2022-09-25 20:30:16 +02:00
Thomas Haukland
733d2245d8 Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-09-25 13:49:36 +02:00
Thomas Haukland
bf0a78149d Ferris: enabling caps word 2022-09-25 13:48:29 +02:00
Thomas Haukland
b292324586 Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-09-25 10:07:07 +02:00
Thomas Haukland
f785d092bc Merge branch 'master' of github.com:tompi/qmk_firmware into develop 2022-09-17 18:43:05 +02:00
Thomas Haukland
449b6b7e05 Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-09-17 18:42:10 +02:00
Thomas Haukland
23405481a0 Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-09-03 08:54:12 +02:00
Thomas Haukland
886bd2946b zompi: leds work 2022-09-03 08:52:40 +02:00
Thomas Haukland
ac7864d2b8 Merge branch 'develop' of github.com:tompi/qmk_firmware into develop 2022-08-28 09:43:46 +02:00
Thomas Haukland
0c18526ada zompi: split works, no external pullup needed 2022-08-28 09:42:11 +02:00
Thomas Haukland
78a00d66ea Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-08-28 09:24:44 +02:00
Thomas Haukland
fa67bef4ec change 0 position and add mouse clicks 2022-08-22 18:26:43 +02:00
Thomas Haukland
e224ec4fc6 Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-08-21 10:03:29 +02:00
Thomas Haukland
68eaa2ea99 Merge branch 'master' into develop 2022-08-18 08:12:41 +02:00
Thomas Haukland
0a4c3ec63a Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-08-18 08:09:19 +02:00
Thomas Haukland
d43884affe Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-08-07 19:52:13 +02:00
Thomas Haukland
50dffc477f Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-07-29 11:39:40 +02:00
Thomas Haukland
cc703c1004 custom oled logo 2022-07-05 20:34:26 +02:00
Thomas Haukland
22ffbeb99b encoder works 2022-07-05 20:06:11 +02:00
Thomas Haukland
78c2197d15 Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-07-05 20:02:39 +02:00
Thomas Haukland
d9bbbebad8 zompi: oled works 2022-07-05 20:00:42 +02:00
Thomas Haukland
2feae0ab52 Merge branch 'develop' of github.com:qmk/qmk_firmware into develop 2022-07-02 16:06:55 +02:00
Thomas Haukland
3fac02d691 Zompi compiles and flashes! 2022-07-02 16:05:48 +02:00
34 changed files with 2653 additions and 32 deletions

View File

@@ -26,6 +26,7 @@ SPLIT_KEYBOARD = yes
MOUSEKEY_ENABLE = yes
EXTRAKEY_ENABLE = yes
CAPS_WORD_ENABLE = yes
RGB_MATRIX_SUPPORTED = yes # RGB matrix is supported and enabled by default
RGBLIGHT_SUPPORTED = no # RGB underglow is supported, but not enabled by default
RGB_MATRIX_ENABLE = yes # Enable keyboard RGB matrix functionality

View File

@@ -35,7 +35,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Pick good defaults for enabling homerow modifiers
#define TAPPING_TERM 200
// #define PERMISSIVE_HOLD
#define IGNORE_MOD_TAP_INTERRUPT
//#define IGNORE_MOD_TAP_INTERRUPT
#define TAPPING_FORCE_HOLD
//#define RETRO_TAPPING

View File

@@ -0,0 +1,75 @@
#include "wait.h"
#include "quantum.h"
// This is to keep state between callbacks, when it is 0 the
// initial RGB flash is finished
uint8_t _hue_countdown = 50;
// These are to keep track of user selected color, so we
// can restore it after RGB flash
uint8_t _hue;
uint8_t _saturation;
uint8_t _value;
// Do a little 2.5 seconds display of the different colors
// Use the deferred executor so the LED flash dance does not
// stop us from using the keyboard.
// https://docs.qmk.fm/#/custom_quantum_functions?id=deferred-executor-registration
uint32_t flash_led(uint32_t next_trigger_time, void *cb_arg) {
rgblight_sethsv(_hue_countdown * 5, 230, 70);
_hue_countdown--;
if (_hue_countdown == 0) {
// Finished, reset to user chosen led color
rgblight_sethsv(_hue, _saturation, _value);
return 0;
} else {
return 50;
}
}
void keyboard_post_init_user(void) {
//debug_enable=true;
//debug_matrix=true;
//debug_keyboard=true;
//debug_mouse=true;
// Store user selected rgb hsv:
_hue = rgblight_get_hue();
_saturation = rgblight_get_sat();
_value = rgblight_get_val();
// Flash a little on start
defer_exec(50, flash_led, NULL);
}
// Make the builtin RGB led show different colors per layer:
// This seemed like a good idea but turned out pretty annoying,
// to me at least... Uncomment the lines below to enable
/*
uint8_t get_hue(uint8_t layer) {
switch (layer) {
case 6:
return 169;
case 5:
return 43;
case 4:
return 85;
case 3:
return 120;
case 2:
return 180;
case 1:
return 220;
default:
return 0;
}
}
layer_state_t layer_state_set_user(layer_state_t state) {
uint8_t sat = rgblight_get_sat();
uint8_t val = rgblight_get_val();
uint8_t hue = get_hue(get_highest_layer(state));
rgblight_sethsv(hue, sat, val);
return state;
}
*/

View File

@@ -0,0 +1,40 @@
// Copyright 2023 Thomas Haukland (@tompi)
// 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
#define BOTH_SHIFTS_TURNS_ON_CAPS_WORD
#define WS2812_PIO_USE_PIO1 // Force the usage of PIO1 peripheral, by default the WS2812 implementation uses the PIO0 peripheral
//#define WS2812_TRST_US 80
#define WS2812_BYTE_ORDER WS2812_BYTE_ORDER_RGB
#define RGB_MATRIX_DEFAULT_VAL 32
// Pick good defaults for enabling homerow modifiers
#define TAPPING_TERM 230
#define WS2812_DI_PIN GP16 // The pin connected to the data pin of the LEDs
#define RGBLIGHT_LED_COUNT 1 // The number of LEDs connected
#define MAX_DEFERRED_EXECUTORS 42
// #define DEBUG_MATRIX_SCAN_RATE

View File

@@ -0,0 +1,63 @@
#include "matrix.h"
#include "quantum.h"
#define COL_SHIFTER ((uint16_t)1)
#define ENC_ROW 3
#define ENC_A_COL 2
#define ENC_B_COL 4
#define ENC_BUTTON_COL 0
static bool colABPressed = false;
static bool encoderPressed = false;
void clicked(void) {
tap_code(KC_MPLY);
}
void turned(bool clockwise) {
if (IS_LAYER_ON(6)) {
tap_code(clockwise ? KC_VOLU : KC_VOLD);
} else if (IS_LAYER_ON(3)) {
tap_code16(clockwise ? LCTL(KC_TAB) : LCTL(LSFT(KC_TAB)));
} else if (IS_LAYER_ON(5)) {
tap_code16(clockwise ? LGUI(KC_Y) : LGUI(KC_Z));
} else {
tap_code16(clockwise ? KC_PGDN : KC_PGUP);
}
}
void fix_encoder_action(matrix_row_t current_matrix[]) {
matrix_row_t encoder_row = current_matrix[ENC_ROW];
if (encoder_row & (COL_SHIFTER << ENC_BUTTON_COL)) {
encoderPressed = true;
} else {
// Only trigger click on release
if (encoderPressed) {
encoderPressed = false;
clicked();
}
}
// Check which way the encoder is turned:
bool colA = encoder_row & (COL_SHIFTER << ENC_A_COL);
bool colB = encoder_row & (COL_SHIFTER << ENC_B_COL);
if (colA && colB) {
colABPressed = true;
} else if (colA) {
if (colABPressed) {
// A+B followed by A means clockwise
colABPressed = false;
turned(true);
}
} else if (colB) {
if (colABPressed) {
// A+B followed by B means counter-clockwise
colABPressed = false;
turned(false);
}
}
current_matrix[ENC_ROW] = 0;
}

View File

@@ -0,0 +1,5 @@
//
// Created by Thomas Haukland on 25/03/2023.
//
void fix_encoder_action(matrix_row_t current_matrix[]);

View File

@@ -0,0 +1,128 @@
//
// Created by Thomas Haukland on 2024-05-05.
//
#include "matrix.h"
#include "quantum.h"
#include "print.h"
// This is just to be able to declare constants as they appear in the qmk console
#define rev(b) \
((b & 1) << 15) | \
((b & (1 << 1)) << 13) | \
((b & (1 << 2)) << 11) | \
((b & (1 << 3)) << 9) | \
((b & (1 << 4)) << 7) | \
((b & (1 << 5)) << 5) | \
((b & (1 << 6)) << 3) | \
((b & (1 << 7)) << 1) | \
((b & (1 << 8)) >> 1) | \
((b & (1 << 9)) >> 3) | \
((b & (1 << 10)) >> 5) | \
((b & (1 << 11)) >> 7) | \
((b & (1 << 12)) >> 9) | \
((b & (1 << 13)) >> 11) | \
((b & (1 << 14)) >> 13) | \
b >> 15
/* This is for debugging the matrix rows
void printBits(uint16_t n)
{
long i;
for (i = 15; i >= 0; i--) {
if ((n & (1 << i)) != 0) {
printf("1");
}
else {
printf("0");
}
}
printf("\n");
}
*/
bool bit_pattern_set(uint16_t number, uint16_t bitPattern) {
return !(~number & bitPattern);
}
void fix_ghosting_instance(
matrix_row_t current_matrix[],
unsigned short row_num_with_possible_error_cause,
uint16_t possible_error_cause,
unsigned short row_num_with_possible_error,
uint16_t possible_error,
uint16_t error_fix) {
if (bit_pattern_set(current_matrix[row_num_with_possible_error_cause], possible_error_cause)) {
if (bit_pattern_set(current_matrix[row_num_with_possible_error], possible_error)) {
current_matrix[row_num_with_possible_error] = current_matrix[row_num_with_possible_error] ^ error_fix;
}
}
}
void fix_ghosting_column(
matrix_row_t matrix[],
uint16_t possible_error_cause,
uint16_t possible_error,
uint16_t error_fix) {
// First the right side
for (short i = 0; i<3; i++) {
fix_ghosting_instance(matrix, i, possible_error_cause, (i+1)%3, possible_error, error_fix);
fix_ghosting_instance(matrix, i, possible_error_cause, (i+2)%3, possible_error, error_fix);
}
// Then exactly same procedure on the left side
for (short i = 0; i<3; i++) {
fix_ghosting_instance(matrix, i+4, possible_error_cause<<6, 4+((i+1)%3), possible_error<<6, error_fix<<6);
fix_ghosting_instance(matrix, i+4, possible_error_cause<<6, 4+((i+2)%3), possible_error<<6, error_fix<<6);
}
}
// For QWERTY layout, key combo a+s+e also outputs q. This suppresses the q, and other similar ghosts
// These are observed ghosts(following a pattern). TODO: need to fix this for v3
// Might need to add 2 diodes(one in each direction) for every row, to increase voltage drop.
void fix_ghosting(matrix_row_t matrix[]) {
fix_ghosting_column(matrix,
rev(0B0110000000000000),
rev(0B1010000000000000),
rev(0B0010000000000000));
fix_ghosting_column(matrix,
rev(0B0110000000000000),
rev(0B0101000000000000),
rev(0B0100000000000000));
fix_ghosting_column(matrix,
rev(0B0001100000000000),
rev(0B0010100000000000),
rev(0B0000100000000000));
fix_ghosting_column(matrix,
rev(0B0001100000000000),
rev(0B0001010000000000),
rev(0B0001000000000000));
fix_ghosting_column(matrix,
rev(0B1000010000000000),
rev(0B1000100000000000),
rev(0B1000000000000000));
fix_ghosting_column(matrix,
rev(0B1000010000000000),
rev(0B0100010000000000),
rev(0B0000010000000000));
fix_ghosting_column(matrix,
rev(0B1001000000000000),
rev(0B0101000000000000),
rev(0B0001000000000000));
fix_ghosting_column(matrix,
rev(0B1001000000000000),
rev(0B1010000000000000),
rev(0B1000000000000000));
fix_ghosting_column(matrix,
rev(0B0100100000000000),
rev(0B0100010000000000),
rev(0B0100000000000000));
fix_ghosting_column(matrix,
rev(0B0100100000000000),
rev(0B1000100000000000),
rev(0B0000100000000000));
}

View File

@@ -0,0 +1,5 @@
//
// Created by Thomas Haukland on 2024-05-05.
//
void fix_ghosting(matrix_row_t current_matrix[]);

View File

@@ -0,0 +1,8 @@
#pragma once
#define HAL_USE_PWM TRUE
#define HAL_USE_PAL TRUE
#define HAL_USE_I2C TRUE
#include_next <halconf.h>

View File

@@ -0,0 +1,94 @@
{
"manufacturer": "Thomas Haukland",
"keyboard_name": "cheapino2",
"maintainer": "tompi",
"bootloader": "rp2040",
"diode_direction": "ROW2COL",
"features": {
"bootmagic": true,
"command": false,
"console": false,
"extrakey": true,
"mousekey": true,
"nkro": true
},
"community_layouts": ["split_3x5_3"],
"matrix_pins": {
"cols": [
"GP6",
"GP6",
"GP5",
"GP5",
"GP4",
"GP4",
"GP14",
"GP14",
"GP15",
"GP15",
"GP26",
"GP26"
],
"rows": ["GP3", "GP1", "GP2", "GP0", "GP27", "GP28", "GP29", "GP8"]
},
"processor": "RP2040",
"url": "",
"usb": {
"device_version": "1.0.0",
"pid": "0x0000",
"vid": "0xFEE3",
"force_nkro": true
},
"layouts": {
"LAYOUT_split_3x5_3": {
"layout": [
{ "matrix": [4, 10], "x": 0, "y": 0.25 },
{ "matrix": [4, 9], "x": 1, "y": 0.125 },
{ "matrix": [4, 8], "x": 2, "y": 0 },
{ "matrix": [4, 7], "x": 3, "y": 0.125 },
{ "matrix": [4, 6], "x": 4, "y": 0.25 },
{ "matrix": [0, 0], "x": 7, "y": 0.25 },
{ "matrix": [0, 1], "x": 8, "y": 0.125 },
{ "matrix": [0, 2], "x": 9, "y": 0 },
{ "matrix": [0, 3], "x": 10, "y": 0.125 },
{ "matrix": [0, 4], "x": 11, "y": 0.25 },
{ "matrix": [5, 10], "x": 0, "y": 1.25 },
{ "matrix": [5, 9], "x": 1, "y": 1.125 },
{ "matrix": [5, 8], "x": 2, "y": 1 },
{ "matrix": [5, 7], "x": 3, "y": 1.125 },
{ "matrix": [5, 6], "x": 4, "y": 1.25 },
{ "matrix": [1, 0], "x": 7, "y": 1.25 },
{ "matrix": [1, 1], "x": 8, "y": 1.125 },
{ "matrix": [1, 2], "x": 9, "y": 1 },
{ "matrix": [1, 3], "x": 10, "y": 1.125 },
{ "matrix": [1, 4], "x": 11, "y": 1.25 },
{ "matrix": [6, 10], "x": 0, "y": 2.25 },
{ "matrix": [6, 9], "x": 1, "y": 2.125 },
{ "matrix": [6, 8], "x": 2, "y": 2 },
{ "matrix": [6, 7], "x": 3, "y": 2.125 },
{ "matrix": [6, 6], "x": 4, "y": 2.25 },
{ "matrix": [2, 0], "x": 7, "y": 2.25 },
{ "matrix": [2, 1], "x": 8, "y": 2.125 },
{ "matrix": [2, 2], "x": 9, "y": 2 },
{ "matrix": [2, 3], "x": 10, "y": 2.125 },
{ "matrix": [2, 4], "x": 11, "y": 2.25 },
{ "matrix": [6, 11], "x": 2.5, "y": 3.25 },
{ "matrix": [5, 11], "x": 3.5, "y": 3.5 },
{ "matrix": [4, 11], "x": 4.5, "y": 3.75 },
{ "matrix": [0, 5], "x": 6.5, "y": 3.75 },
{ "matrix": [1, 5], "x": 7.5, "y": 3.5 },
{ "matrix": [2, 5], "x": 8.5, "y": 3.25 }
]
}
}
}

View File

@@ -0,0 +1,277 @@
{
"version": 1,
"notes": "Cheapino default keymap",
"documentation": "\"This file is a QMK Configurator export. You can import this at <https://config.qmk.fm>. It can also be used directly with QMK's source code.\n\nTo setup your QMK environment check out the tutorial: <https://docs.qmk.fm/#/newbs>\n\nYou can convert this file to a keymap.c using this command: `qmk json2c {keymap}`\n\nYou can compile this keymap using this command: `qmk compile {keymap}`\"\n",
"keyboard": "bastardkb/skeletyl/blackpill",
"keymap": "default",
"layout": "LAYOUT_split_3x5_3",
"layers": [
[
"KC_Q",
"KC_W",
"KC_E",
"KC_R",
"KC_T",
"KC_Y",
"KC_U",
"KC_I",
"KC_O",
"KC_P",
"LGUI_T(KC_A)",
"LALT_T(KC_S)",
"LCTL_T(KC_D)",
"LSFT_T(KC_F)",
"KC_G",
"KC_H",
"RSFT_T(KC_J)",
"LCTL_T(KC_K)",
"LALT_T(KC_L)",
"LGUI_T(KC_SCLN)",
"KC_Z",
"KC_X",
"KC_C",
"KC_V",
"LT(5,KC_B)",
"LT(1,KC_N)",
"KC_M",
"KC_COMM",
"KC_DOT",
"KC_SLSH",
"LT(6,KC_ESC)",
"LT(3,KC_SPC)",
"LT(5,KC_TAB)",
"LT(1,KC_DEL)",
"LT(2,KC_BSPC)",
"LT(4,KC_ENT)"
],
[
"KC_VOLU",
"KC_WH_L",
"KC_MS_U",
"KC_WH_U",
"KC_WH_R",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"ANY(QK_RBT)",
"KC_MS_L",
"KC_BTN2",
"KC_BTN1",
"KC_MS_R",
"KC_MUTE",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_VOLD",
"KC_MNXT",
"KC_MS_D",
"KC_WH_D",
"KC_MPLY",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_NO",
"KC_NO"
],
[
"KC_NO",
"KC_HOME",
"KC_DEL",
"KC_PGUP",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_LEFT",
"KC_UP",
"KC_RGHT",
"KC_NO",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_END",
"KC_DOWN",
"KC_PGDN",
"KC_NO",
"KC_NO",
"KC_BTN1",
"KC_BTN2",
"KC_BTN3",
"KC_BTN4",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_NO",
"KC_NO"
],
[
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_WH_U",
"KC_AT",
"KC_UNDS",
"KC_PIPE",
"KC_GRV",
"KC_PERC",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"RGB_TOG",
"KC_HASH",
"KC_TAB",
"KC_EXLM",
"KC_DQUO",
"KC_DLR",
"KC_BTN4",
"KC_BTN3",
"KC_BTN2",
"KC_BTN1",
"KC_WH_D",
"KC_TILD",
"KC_QUOT",
"KC_BSLS",
"KC_SLSH",
"KC_AMPR",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_NO"
],
[
"KC_EQL",
"KC_CIRC",
"KC_LT",
"KC_GT",
"KC_SCLN",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_LCBR",
"KC_RCBR",
"KC_LPRN",
"KC_RPRN",
"KC_AT",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_MINS",
"KC_EXLM",
"KC_LBRC",
"KC_RBRC",
"KC_TRNS",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_NO"
],
[
"ANY(QK_RBT)",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_F7",
"KC_F8",
"KC_F9",
"KC_F10",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_NO",
"KC_F4",
"KC_F5",
"KC_F6",
"KC_F11",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_F1",
"KC_F2",
"KC_F3",
"KC_F12",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS"
],
[
"RGB_SPI",
"RGB_VAI",
"RGB_SAI",
"RGB_HUI",
"RGB_MOD",
"KC_PPLS",
"KC_P7",
"KC_P8",
"KC_P9",
"KC_PAST",
"EE_CLR",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"RGB_TOG",
"KC_PMNS",
"KC_P4",
"KC_P5",
"KC_P6",
"KC_PSLS",
"RGB_SPD",
"RGB_VAD",
"RGB_SAD",
"RGB_HUD",
"RGB_RMOD",
"KC_PDOT",
"KC_P1",
"KC_P2",
"KC_P3",
"KC_PEQL",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_0",
"KC_COMM",
"KC_P0"
]
],
"author": "thomas.haukland@gmail.com"
}

View File

@@ -0,0 +1,51 @@
/*
Copyright 2020 Pierre Chevalier <pierrechevalier83@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// Set the mouse settings to a comfortable speed/accuracy trade-off,
// assuming a screen refresh rate of 60 Htz or higher
// The default is 50. This makes the mouse ~3 times faster and more accurate
#define MOUSEKEY_INTERVAL 16
// The default is 20. Since we made the mouse about 3 times faster with the previous setting,
// give it more time to accelerate to max speed to retain precise control over short distances.
#define MOUSEKEY_TIME_TO_MAX 40
// The default is 300. Let's try and make this as low as possible while keeping the cursor responsive
#define MOUSEKEY_DELAY 100
// It makes sense to use the same delay for the mouseweel
#define MOUSEKEY_WHEEL_DELAY 100
// The default is 100
#define MOUSEKEY_WHEEL_INTERVAL 50
// The default is 40
#define MOUSEKEY_WHEEL_TIME_TO_MAX 100
// Pick good defaults for enabling homerow modifiers
#undef TAPPING_TERM
#define TAPPING_TERM 200
// #define PERMISSIVE_HOLD
#define TAPPING_FORCE_HOLD
//#define RETRO_TAPPING
// Underglow configuration
#ifdef RGBLIGHT_ENABLE
#define RGBLIGHT_ANIMATIONS
#define RGBLIGHT_HUE_STEP 8
#define RGBLIGHT_SAT_STEP 8
#define RGBLIGHT_VAL_STEP 8
#endif
//#define UNICODE_SELECTED_MODES UC_MAC

View File

@@ -0,0 +1,125 @@
{
"version": 1,
"notes": "My awesome keymap",
"documentation": "\"This file is a QMK Configurator export. You can import this at <https://config.qmk.fm>. It can also be used directly with QMK's source code.\n\nTo setup your QMK environment check out the tutorial: <https://docs.qmk.fm/#/newbs>\n\nYou can convert this file to a keymap.c using this command: `qmk json2c {keymap}`\n\nYou can compile this keymap using this command: `qmk compile {keymap}`\"\n",
"keyboard": "bastardkb/skeletyl/blackpill",
"keymap": "default",
"layout": "LAYOUT_split_3x5_3",
"layers": [
[
"KC_Q",
"KC_W",
"KC_F",
"KC_P",
"KC_B",
"KC_J",
"KC_L",
"KC_U",
"KC_Y",
"KC_SCLN",
"KC_A",
"KC_R",
"KC_S",
"KC_T",
"KC_G",
"KC_M",
"KC_N",
"KC_E",
"KC_I",
"KC_O",
"LSFT_T(KC_Z)",
"LCTL_T(KC_X)",
"RALT_T(KC_C)",
"KC_D",
"KC_V",
"KC_K",
"KC_H",
"RALT_T(KC_COMM)",
"LCTL_T(KC_DOT)",
"LSFT_T(KC_SLSH)",
"TO(1)",
"KC_BSPC",
"KC_TAB",
"KC_LGUI",
"KC_SPC",
"KC_ENT"
],
[
"KC_TRNS",
"KC_7",
"KC_8",
"KC_9",
"KC_TRNS",
"KC_QUOT",
"KC_MINS",
"KC_EQL",
"KC_ASTR",
"KC_CIRC",
"KC_TRNS",
"KC_4",
"KC_5",
"KC_6",
"KC_0",
"KC_BSLS",
"KC_LPRN",
"KC_RPRN",
"KC_LBRC",
"KC_RBRC",
"KC_LSFT",
"KC_1",
"KC_2",
"KC_3",
"KC_TRNS",
"KC_PIPE",
"KC_GRV",
"KC_LALT",
"KC_LCTL",
"KC_RSFT",
"TO(2)",
"KC_BSPC",
"KC_TAB",
"KC_DEL",
"TO(0)",
"KC_ENT"
],
[
"KC_TRNS",
"KC_TRNS",
"KC_PGUP",
"KC_TRNS",
"KC_TRNS",
"ANY(UC(0xE6))",
"ANY(UC(0xF8))",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_LEFT",
"KC_UP",
"KC_DOWN",
"KC_RGHT",
"KC_TRNS",
"KC_TRNS",
"KC_LGUI",
"ANY(UC(0xE5))",
"LCTL(KC_LALT)",
"LCA(KC_LSFT)",
"KC_TRNS",
"KC_HOME",
"KC_PGDN",
"KC_END",
"KC_TRNS",
"KC_TRNS",
"KC_RBRC",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TAB",
"KC_DEL",
"TO(0)",
"KC_TRNS"
]
],
"author": "thomas.haukland@gmail.com"
}

View File

@@ -0,0 +1,63 @@
#include QMK_KEYBOARD_H
#if __has_include("keymap.h")
# include "keymap.h"
#endif
enum custom_keycodes {
SMTD_KEYCODES_BEGIN = SAFE_RANGE,
CKC_A, // reads as C(ustom) + KC_A, but you may give any name here
CKC_R,
CKC_S,
CKC_T,
CKC_N,
CKC_E,
CKC_I,
CKC_O,
SMTD_KEYCODES_END
};
#include "sm_td.h"
uint32_t get_smtd_timeout(uint16_t keycode, smtd_timeout timeout) {
if (keycode == CKC_N && timeout == SMTD_TIMEOUT_RELEASE) return 35;
return get_smtd_timeout_default(timeout);
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (!process_smtd(keycode, record)) {
return false;
}
return true;
}
void on_smtd_action(uint16_t keycode, smtd_action action, uint8_t tap_count) {
switch (keycode) {
SMTD_MT(CKC_A, KC_A, KC_LEFT_GUI)
SMTD_MT(CKC_R, KC_R, KC_LEFT_ALT)
SMTD_MT(CKC_S, KC_S, KC_LEFT_CTRL)
SMTD_MT(CKC_T, KC_T, KC_LSFT)
SMTD_MT(CKC_N, KC_N, KC_RSFT)
SMTD_MT(CKC_E, KC_E, KC_RIGHT_CTRL)
SMTD_MT(CKC_I, KC_I, KC_RIGHT_ALT)
SMTD_MT(CKC_O, KC_O, KC_RIGHT_GUI)
}
}
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_split_3x5_3(KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, CKC_A, CKC_R, CKC_S, CKC_T, KC_G, KC_M, CKC_N, CKC_E, CKC_I, CKC_O, KC_Z, KC_X, KC_C, KC_D, LT(5,KC_V), LT(1,KC_K), KC_H, KC_COMM, KC_DOT, KC_SLSH, LT(6,KC_ESC), LT(3,KC_SPC), LT(5,KC_TAB), LT(1,KC_DEL), LT(2,KC_BSPC), LT(4,KC_ENT)),
[1] = LAYOUT_split_3x5_3(KC_VOLU, KC_WH_L, KC_MS_U, KC_WH_U, KC_WH_R, KC_NO, KC_NO, KC_NO, KC_NO, QK_RBT, KC_MS_L, KC_BTN2, KC_BTN1, KC_MS_R, KC_MUTE, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLD, KC_MNXT, KC_MS_D, KC_WH_D, KC_MPLY, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO),
[2] = LAYOUT_split_3x5_3(NK_TOGG, KC_HOME, KC_DEL, KC_PGUP, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_UP, KC_RGHT, KC_NO, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_END, KC_DOWN, KC_PGDN, KC_NO, KC_NO, KC_BTN1, KC_BTN2, KC_BTN3, KC_BTN4, KC_NO, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO),
[3] = LAYOUT_split_3x5_3(KC_NO, KC_NO, KC_NO, KC_NO, KC_WH_U, KC_AT, KC_UNDS, KC_PIPE, KC_GRV, KC_PERC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, KC_HASH, KC_TAB, KC_EXLM, KC_DQUO, KC_DLR, KC_BTN4, KC_BTN3, KC_BTN2, KC_BTN1, KC_WH_D, KC_TILD, KC_QUOT, KC_BSLS, KC_SLSH, KC_AMPR, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_TRNS, KC_NO),
[4] = LAYOUT_split_3x5_3(KC_GRV, KC_CIRC, KC_LT, KC_GT, KC_SCLN, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LCBR, KC_RCBR, KC_LPRN, KC_RPRN, KC_AT, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, KC_EXLM, KC_LBRC, KC_RBRC, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_NO),
[5] = LAYOUT_split_3x5_3(QK_RBT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_F4, KC_F5, KC_F6, KC_F11, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_F1, KC_F2, KC_F3, KC_F12, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
[6] = LAYOUT_split_3x5_3(RGB_SPI, RGB_VAI, RGB_SAI, RGB_HUI, RGB_MOD, KC_PPLS, KC_P7, KC_P8, KC_P9, KC_PAST, EE_CLR, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, KC_PMNS, KC_P4, KC_P5, KC_P6, KC_PSLS, RGB_SPD, RGB_VAD, RGB_SAD, RGB_HUD, RGB_RMOD, KC_PDOT, KC_P1, KC_P2, KC_P3, KC_PEQL, KC_NO, KC_NO, KC_NO, KC_0, KC_COMM, KC_P0)
};
#if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
};
#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE)

View File

@@ -0,0 +1,834 @@
/* Copyright 2024 Stanislav Markin (https://github.com/stasmarkin)
*
* 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/>.
*
*
* Version: 0.4.0
* Date: 2024-03-07
*/
#pragma once
#include QMK_KEYBOARD_H
#include "deferred_exec.h"
#ifdef SMTD_DEBUG_ENABLED
#include "print.h"
#endif
#ifdef SMTD_GLOBAL_SIMULTANEOUS_PRESSES_DELAY_MS
#include "timer.h"
#endif
/* ************************************* *
* GLOBAL CONFIGURATION *
* ************************************* */
#ifndef SMTD_GLOBAL_SIMULTANEOUS_PRESSES_DELAY_MS
#define SMTD_GLOBAL_SIMULTANEOUS_PRESSES_DELAY_MS 0
#endif
#if SMTD_GLOBAL_SIMULTANEOUS_PRESSES_DELAY_MS > 0
#define SMTD_SIMULTANEOUS_PRESSES_DELAY wait_ms(SMTD_GLOBAL_SIMULTANEOUS_PRESSES_DELAY_MS);
#else
#define SMTD_SIMULTANEOUS_PRESSES_DELAY
#endif
#ifndef SMTD_GLOBAL_TAP_TERM
#define SMTD_GLOBAL_TAP_TERM TAPPING_TERM
#endif
#ifndef SMTD_GLOBAL_SEQUENCE_TERM
#define SMTD_GLOBAL_SEQUENCE_TERM TAPPING_TERM / 2
#endif
#ifndef SMTD_GLOBAL_FOLLOWING_TAP_TERM
#define SMTD_GLOBAL_FOLLOWING_TAP_TERM TAPPING_TERM
#endif
#ifndef SMTD_GLOBAL_RELEASE_TERM
#define SMTD_GLOBAL_RELEASE_TERM TAPPING_TERM / 4
#endif
#ifndef SMTD_GLOBAL_MODS_RECALL
#define SMTD_GLOBAL_MODS_RECALL true
#endif
#ifndef SMTD_GLOBAL_AGGREGATE_TAPS
#define SMTD_GLOBAL_AGGREGATE_TAPS false
#endif
/* ************************************* *
* DEBUG CONFIGURATION *
* ************************************* */
#ifdef SMTD_DEBUG_ENABLED
__attribute__((weak)) char* keycode_to_string_user(uint16_t keycode);
char* keycode_to_string(uint16_t keycode) {
if (keycode_to_string_user) {
char* result = keycode_to_string_user(keycode);
if (result) {
return result;
}
}
static char buffer[16];
snprintf(buffer, sizeof(buffer), "KC_%d", keycode);
return buffer;
}
#endif
/* ************************************* *
* USER TIMEOUT DEFINITIONS *
* ************************************* */
typedef enum {
SMTD_TIMEOUT_TAP,
SMTD_TIMEOUT_SEQUENCE,
SMTD_TIMEOUT_FOLLOWING_TAP,
SMTD_TIMEOUT_RELEASE
} smtd_timeout;
__attribute__((weak)) uint32_t get_smtd_timeout(uint16_t keycode, smtd_timeout timeout);
uint32_t get_smtd_timeout_default(smtd_timeout timeout) {
switch (timeout) {
case SMTD_TIMEOUT_TAP:
return SMTD_GLOBAL_TAP_TERM;
case SMTD_TIMEOUT_SEQUENCE:
return SMTD_GLOBAL_SEQUENCE_TERM;
case SMTD_TIMEOUT_FOLLOWING_TAP:
return SMTD_GLOBAL_FOLLOWING_TAP_TERM;
case SMTD_TIMEOUT_RELEASE:
return SMTD_GLOBAL_RELEASE_TERM;
}
return 0;
}
uint32_t get_smtd_timeout_or_default(uint16_t keycode, smtd_timeout timeout) {
if (get_smtd_timeout) {
return get_smtd_timeout(keycode, timeout);
}
return get_smtd_timeout_default(timeout);
}
/* ************************************* *
* USER FEATURE FLAGS DEFINITIONS *
* ************************************* */
typedef enum {
SMTD_FEATURE_MODS_RECALL,
SMTD_FEATURE_AGGREGATE_TAPS,
} smtd_feature;
__attribute__((weak)) bool smtd_feature_enabled(uint16_t keycode, smtd_feature feature);
bool smtd_feature_enabled_default(smtd_feature feature) {
switch (feature) {
case SMTD_FEATURE_MODS_RECALL:
return SMTD_GLOBAL_MODS_RECALL;
case SMTD_FEATURE_AGGREGATE_TAPS:
return SMTD_GLOBAL_AGGREGATE_TAPS;
}
return false;
}
bool smtd_feature_enabled_or_default(uint16_t keycode, smtd_feature feature) {
if (smtd_feature_enabled) {
return smtd_feature_enabled(keycode, feature);
}
return smtd_feature_enabled_default(feature);
}
/* ************************************* *
* USER ACTION DEFINITIONS *
* ************************************* */
typedef enum {
SMTD_ACTION_TOUCH,
SMTD_ACTION_TAP,
SMTD_ACTION_HOLD,
SMTD_ACTION_RELEASE,
} smtd_action;
#ifdef SMTD_DEBUG_ENABLED
char *smtd_action_to_string(smtd_action action) {
switch (action) {
case SMTD_ACTION_TOUCH:
return "ACT_TOUCH";
case SMTD_ACTION_TAP:
return "ACT_TAP";
case SMTD_ACTION_HOLD:
return "ACT_HOLD";
case SMTD_ACTION_RELEASE:
return "ACT_RELEASE";
}
return "ACT_UNKNOWN";
}
#endif
void on_smtd_action(uint16_t keycode, smtd_action action, uint8_t sequence_len);
#ifdef SMTD_DEBUG_ENABLED
#define SMTD_ACTION(action, state) printf("%s by %s in %s\n", \
smtd_action_to_string(action), keycode_to_string(state->macro_keycode), smtd_stage_to_string(state->stage)); \
on_smtd_action(state->macro_keycode, action, state->sequence_len);
#else
#define SMTD_ACTION(action, state) on_smtd_action(state->macro_keycode, action, state->sequence_len);
#endif
/* ************************************* *
* USER STATES DEFINITIONS *
* ************************************* */
typedef enum {
SMTD_STAGE_NONE,
SMTD_STAGE_TOUCH,
SMTD_STAGE_SEQUENCE,
SMTD_STAGE_FOLLOWING_TOUCH,
SMTD_STAGE_HOLD,
SMTD_STAGE_RELEASE,
} smtd_stage;
#ifdef SMTD_DEBUG_ENABLED
char *smtd_stage_to_string(smtd_stage stage) {
switch (stage) {
case SMTD_STAGE_NONE:
return "STAGE_NONE";
case SMTD_STAGE_TOUCH:
return "STAGE_TOUCH";
case SMTD_STAGE_SEQUENCE:
return "STAGE_SEQUENCE";
case SMTD_STAGE_FOLLOWING_TOUCH:
return "STAGE_FOL_TOUCH";
case SMTD_STAGE_HOLD:
return "STAGE_HOLD";
case SMTD_STAGE_RELEASE:
return "STAGE_RELEASE";
}
return "STAGE_UNKNOWN";
}
#endif
typedef struct {
/** The keycode of the macro key */
uint16_t macro_keycode;
/** The mods before the touch action performed. Required for mod_recall feature */
uint8_t modes_before_touch;
/** Since touch can modify global mods, we need to save them separately to correctly restore a state before touch */
uint8_t modes_with_touch;
/** The length of the sequence of same key taps */
uint8_t sequence_len;
/** The position of key that was pressed after macro was pressed */
keypos_t following_key;
/** The keycode of the key that was pressed after macro was pressed */
uint16_t following_keycode;
/** The timeout of current stage */
deferred_token timeout;
/** The current stage of the state */
smtd_stage stage;
/** The flag that indicates that the state is frozen, so it won't handle any events */
bool freeze;
} smtd_state;
#define EMPTY_STATE { \
.macro_keycode = 0, \
.modes_before_touch = 0, \
.modes_with_touch = 0, \
.sequence_len = 0, \
.following_key = MAKE_KEYPOS(0, 0), \
.following_keycode = 0, \
.timeout = INVALID_DEFERRED_TOKEN, \
.stage = SMTD_STAGE_NONE, \
.freeze = false \
}
/* ************************************* *
* LAYER UTILS *
* ************************************* */
#define RETURN_LAYER_NOT_SET 15
static uint8_t return_layer = RETURN_LAYER_NOT_SET;
static uint8_t return_layer_cnt = 0;
void avoid_unused_variable_on_compile(void* ptr) {
// just touch them, so compiler won't throw "defined but not used" error
// that variables are used in macros that user may not use
if (return_layer == RETURN_LAYER_NOT_SET) return_layer = RETURN_LAYER_NOT_SET;
if (return_layer_cnt == 0) return_layer_cnt = 0;
}
#define LAYER_PUSH(layer) \
return_layer_cnt++; \
if (return_layer == RETURN_LAYER_NOT_SET) { \
return_layer = get_highest_layer(layer_state); \
} \
layer_move(layer);
#define LAYER_RESTORE() \
if (return_layer_cnt > 0) { \
return_layer_cnt--; \
if (return_layer_cnt == 0) { \
layer_move(return_layer); \
return_layer = RETURN_LAYER_NOT_SET; \
} \
}
/* ************************************* *
* CORE LOGIC IMPLEMENTATION *
* ************************************* */
smtd_state smtd_active_states[10] = {EMPTY_STATE, EMPTY_STATE, EMPTY_STATE, EMPTY_STATE, EMPTY_STATE,
EMPTY_STATE, EMPTY_STATE, EMPTY_STATE, EMPTY_STATE, EMPTY_STATE};
uint8_t smtd_active_states_size = 0;
#define DO_ACTION_TAP(state) \
uint8_t current_mods = get_mods(); \
if ( \
smtd_feature_enabled_or_default(state->macro_keycode, SMTD_FEATURE_MODS_RECALL) \
&& state->modes_before_touch != current_mods \
) { \
set_mods(state->modes_before_touch); \
send_keyboard_report(); \
\
SMTD_SIMULTANEOUS_PRESSES_DELAY \
SMTD_ACTION(SMTD_ACTION_TAP, state) \
uint8_t mods_diff = get_mods() ^ state->modes_before_touch; \
\
SMTD_SIMULTANEOUS_PRESSES_DELAY \
set_mods(current_mods ^ mods_diff); \
del_mods(state->modes_with_touch); \
send_keyboard_report(); \
\
state->modes_before_touch = 0; \
state->modes_with_touch = 0; \
} else { \
SMTD_ACTION(SMTD_ACTION_TAP, state) \
}
void smtd_press_following_key(smtd_state *state, bool release) {
state->freeze = true;
keyevent_t event_press = MAKE_KEYEVENT(state->following_key.row, state->following_key.col, true);
keyrecord_t record_press = {.event = event_press};
#ifdef SMTD_DEBUG_ENABLED
if (release) {
printf("FOLLOWING_TAP(%s) by %s in %s\n", keycode_to_string(state->following_keycode),
keycode_to_string(state->macro_keycode), smtd_stage_to_string(state->stage));
} else {
printf("FOLLOWING_PRESS(%s) by %s in %s\n", keycode_to_string(state->following_keycode),
keycode_to_string(state->macro_keycode), smtd_stage_to_string(state->stage));
}
#endif
process_record(&record_press);
if (release) {
keyevent_t event_release = MAKE_KEYEVENT(state->following_key.row, state->following_key.col, false);
keyrecord_t record_release = {.event = event_release};
SMTD_SIMULTANEOUS_PRESSES_DELAY
process_record(&record_release);
}
state->freeze = false;
}
void smtd_next_stage(smtd_state *state, smtd_stage next_stage);
uint32_t timeout_reset_seq(uint32_t trigger_time, void *cb_arg) {
smtd_state *state = (smtd_state *) cb_arg;
state->sequence_len = 0;
return 0;
}
uint32_t timeout_touch(uint32_t trigger_time, void *cb_arg) {
smtd_state *state = (smtd_state *) cb_arg;
smtd_next_stage(state, SMTD_STAGE_HOLD);
return 0;
}
uint32_t timeout_sequence(uint32_t trigger_time, void *cb_arg) {
smtd_state *state = (smtd_state *) cb_arg;
if (smtd_feature_enabled_or_default(state->macro_keycode, SMTD_FEATURE_AGGREGATE_TAPS)) {
DO_ACTION_TAP(state);
}
smtd_next_stage(state, SMTD_STAGE_NONE);
return 0;
}
uint32_t timeout_following_touch(uint32_t trigger_time, void *cb_arg) {
smtd_state *state = (smtd_state *) cb_arg;
smtd_next_stage(state, SMTD_STAGE_HOLD);
SMTD_SIMULTANEOUS_PRESSES_DELAY
smtd_press_following_key(state, false);
return 0;
}
uint32_t timeout_release(uint32_t trigger_time, void *cb_arg) {
smtd_state *state = (smtd_state *) cb_arg;
DO_ACTION_TAP(state);
SMTD_SIMULTANEOUS_PRESSES_DELAY
smtd_press_following_key(state, false);
smtd_next_stage(state, SMTD_STAGE_NONE);
return 0;
}
void smtd_next_stage(smtd_state *state, smtd_stage next_stage) {
#ifdef SMTD_DEBUG_ENABLED
printf("STAGE by %s, %s -> %s\n", keycode_to_string(state->macro_keycode),
smtd_stage_to_string(state->stage),smtd_stage_to_string(next_stage));
#endif
deferred_token prev_token = state->timeout;
state->timeout = INVALID_DEFERRED_TOKEN;
state->stage = next_stage;
switch (state->stage) {
case SMTD_STAGE_NONE:
for (uint8_t i = 0; i < smtd_active_states_size; i++) {
if (&smtd_active_states[i] != state) continue;
for (uint8_t j = i; j < smtd_active_states_size - 1; j++) {
smtd_active_states[j].macro_keycode = smtd_active_states[j + 1].macro_keycode;
smtd_active_states[j].modes_before_touch = smtd_active_states[j + 1].modes_before_touch;
smtd_active_states[j].modes_with_touch = smtd_active_states[j + 1].modes_with_touch;
smtd_active_states[j].sequence_len = smtd_active_states[j + 1].sequence_len;
smtd_active_states[j].following_key = smtd_active_states[j + 1].following_key;
smtd_active_states[j].following_keycode = smtd_active_states[j + 1].following_keycode;
smtd_active_states[j].timeout = smtd_active_states[j + 1].timeout;
smtd_active_states[j].stage = smtd_active_states[j + 1].stage;
smtd_active_states[j].freeze = smtd_active_states[j + 1].freeze;
}
smtd_active_states_size--;
smtd_state *last_state = &smtd_active_states[smtd_active_states_size];
last_state->macro_keycode = 0;
last_state->modes_before_touch = 0;
last_state->modes_with_touch = 0;
last_state->sequence_len = 0;
last_state->following_key = MAKE_KEYPOS(0, 0);
last_state->following_keycode = 0;
last_state->timeout = INVALID_DEFERRED_TOKEN;
last_state->stage = SMTD_STAGE_NONE;
last_state->freeze = false;
break;
}
break;
case SMTD_STAGE_TOUCH:
state->modes_before_touch = get_mods();
SMTD_ACTION(SMTD_ACTION_TOUCH, state)
state->modes_with_touch = get_mods() & ~state->modes_before_touch;
state->timeout = defer_exec(get_smtd_timeout_or_default(state->macro_keycode, SMTD_TIMEOUT_TAP),
timeout_touch, state);
break;
case SMTD_STAGE_SEQUENCE:
state->timeout = defer_exec(get_smtd_timeout_or_default(state->macro_keycode, SMTD_TIMEOUT_SEQUENCE),
timeout_sequence, state);
break;
case SMTD_STAGE_HOLD:
SMTD_ACTION(SMTD_ACTION_HOLD, state)
break;
case SMTD_STAGE_FOLLOWING_TOUCH:
state->timeout = defer_exec(get_smtd_timeout_or_default(state->macro_keycode, SMTD_TIMEOUT_FOLLOWING_TAP),
timeout_following_touch, state);
break;
case SMTD_STAGE_RELEASE:
state->timeout = defer_exec(get_smtd_timeout_or_default(state->macro_keycode, SMTD_TIMEOUT_RELEASE),
timeout_release, state);
break;
}
// need to cancel after creating new timeout. There is a bug in QMK scheduling
cancel_deferred_exec(prev_token);
}
bool process_smtd_state(uint16_t keycode, keyrecord_t *record, smtd_state *state) {
if (state->freeze) {
return true;
}
switch (state->stage) {
case SMTD_STAGE_NONE:
if (keycode == state->macro_keycode && record->event.pressed) {
smtd_next_stage(state, SMTD_STAGE_TOUCH);
return false;
}
return true;
case SMTD_STAGE_TOUCH:
if (keycode == state->macro_keycode && !record->event.pressed) {
smtd_next_stage(state, SMTD_STAGE_SEQUENCE);
if (!smtd_feature_enabled_or_default(state->macro_keycode, SMTD_FEATURE_AGGREGATE_TAPS)) {
DO_ACTION_TAP(state);
}
return false;
}
if (keycode != state->macro_keycode && record->event.pressed) {
state->following_key = record->event.key;
state->following_keycode = keycode;
smtd_next_stage(state, SMTD_STAGE_FOLLOWING_TOUCH);
return false;
}
return true;
case SMTD_STAGE_SEQUENCE:
if (keycode == state->macro_keycode && record->event.pressed) {
state->sequence_len++;
smtd_next_stage(state, SMTD_STAGE_TOUCH);
return false;
}
if (record->event.pressed) {
if (smtd_feature_enabled_or_default(state->macro_keycode, SMTD_FEATURE_AGGREGATE_TAPS)) {
DO_ACTION_TAP(state);
}
smtd_next_stage(state, SMTD_STAGE_NONE);
return true;
}
return true;
case SMTD_STAGE_FOLLOWING_TOUCH:
// At this stage, we have already pressed the macro key and the following key
// none of them is assumed to be held yet
if (keycode == state->macro_keycode && !record->event.pressed) {
// Macro key is released, moving to the next stage
smtd_next_stage(state, SMTD_STAGE_RELEASE);
return false;
}
if (
keycode != state->macro_keycode
&& (state->following_key.row == record->event.key.row &&
state->following_key.col == record->event.key.col)
&& !record->event.pressed
) {
// Following key is released. Now we definitely know that macro key is held
// we need to execute hold the macro key and execute hold the following key
// and then press move to next stage
smtd_next_stage(state, SMTD_STAGE_HOLD);
SMTD_SIMULTANEOUS_PRESSES_DELAY
smtd_press_following_key(state, true);
return false;
}
if (
keycode != state->macro_keycode
&& !(state->following_key.row == record->event.key.row &&
state->following_key.col == record->event.key.col)
&& record->event.pressed
) {
// so, now we have 3rd key pressed
// we assume this to be hold macro key, hold following key and press the 3rd key
// need to put first key state into HOLD stage
smtd_next_stage(state, SMTD_STAGE_HOLD);
// then press and hold (without releasing) the following key
SMTD_SIMULTANEOUS_PRESSES_DELAY
smtd_press_following_key(state, false);
// then rerun the 3rd key press
// since we have just started hold stage, we need to simulate the press of the 3rd key again
// because by holding first two keys we might have changed a layer, so current keycode might be not actual
// if we don't do this, we might continue processing the wrong key
SMTD_SIMULTANEOUS_PRESSES_DELAY
state->freeze = true;
keyevent_t event_press = MAKE_KEYEVENT(record->event.key.row, record->event.key.col, true);
keyrecord_t record_press = {.event = event_press};
process_record(&record_press);
state->freeze = false;
// we have processed the 3rd key, so we intentionally return false to stop further processing
return false;
}
return true;
case SMTD_STAGE_HOLD:
if (keycode == state->macro_keycode && !record->event.pressed) {
SMTD_ACTION(SMTD_ACTION_RELEASE, state)
smtd_next_stage(state, SMTD_STAGE_NONE);
return false;
}
return true;
case SMTD_STAGE_RELEASE:
// At this stage we have just released the macro key and still holding the following key
if (keycode == state->macro_keycode && record->event.pressed) {
DO_ACTION_TAP(state);
SMTD_SIMULTANEOUS_PRESSES_DELAY
smtd_press_following_key(state, false);
//todo need to go to NONE stage and from NONE jump to TOUCH stage
SMTD_SIMULTANEOUS_PRESSES_DELAY
smtd_next_stage(state, SMTD_STAGE_TOUCH);
state->sequence_len = 0;
return false;
}
if (
keycode != state->macro_keycode
&& (state->following_key.row == record->event.key.row &&
state->following_key.col == record->event.key.col)
&& !record->event.pressed
) {
// Following key is released. Now we definitely know that macro key is held
// we need to execute hold the macro key and execute tap the following key
// then close the state
SMTD_ACTION(SMTD_ACTION_HOLD, state)
SMTD_SIMULTANEOUS_PRESSES_DELAY
smtd_press_following_key(state, true);
SMTD_SIMULTANEOUS_PRESSES_DELAY
SMTD_ACTION(SMTD_ACTION_RELEASE, state)
smtd_next_stage(state, SMTD_STAGE_NONE);
return false;
}
if (
keycode != state->macro_keycode
&& (state->following_key.row != record->event.key.row ||
state->following_key.col != record->event.key.col)
&& record->event.pressed
) {
// at this point we have already released the macro key and still holding the following key
// and we get 3rd key pressed
// we assume this to be tap macro key, press (w/o release) following key and press (w/o release) the 3rd key
// so we need to tap the macro key first
DO_ACTION_TAP(state)
// then press and hold (without releasing) the following key
SMTD_SIMULTANEOUS_PRESSES_DELAY
smtd_press_following_key(state, false);
// release current state, because the first key is already processed
smtd_next_stage(state, SMTD_STAGE_NONE);
// then rerun the 3rd key press
// since we have just press following state, we need to simulate the press of the 3rd key again
// because by pressing second key we might have changed a layer, so current keycode might be not actual
// if we don't do this, we might continue processing the wrong key
SMTD_SIMULTANEOUS_PRESSES_DELAY
// we also don't need to freeze the state here, because we are already put in NONE stage
keyevent_t event_press = MAKE_KEYEVENT(record->event.key.row, record->event.key.col, true);
keyrecord_t record_press = {.event = event_press};
process_record(&record_press);
// we have processed the 3rd key, so we intentionally return false to stop further processing
return false;
}
return true;
}
return true;
}
/* ************************************* *
* ENTRY POINT IMPLEMENTATION *
* ************************************* */
bool process_smtd(uint16_t keycode, keyrecord_t *record) {
#ifdef SMTD_DEBUG_ENABLED
printf("\n>> GOT KEY %s %s\n", keycode_to_string(keycode), record->event.pressed ? "PRESSED" : "RELEASED");
#endif
// check if any active state may process an event
for (uint8_t i = 0; i < smtd_active_states_size; i++) {
smtd_state *state = &smtd_active_states[i];
if (!process_smtd_state(keycode, record, state)) {
#ifdef SMTD_DEBUG_ENABLED
printf("<< HANDLE KEY %s %s by %s\n", keycode_to_string(keycode),
record->event.pressed ? "PRESSED" : "RELEASED", keycode_to_string(state->macro_keycode));
#endif
return false;
}
}
// may be start a new state? A key must be just pressed
if (!record->event.pressed) {
#ifdef SMTD_DEBUG_ENABLED
printf("<< BYPASS KEY %s %s\n", keycode_to_string(keycode), record->event.pressed ? "PRESSED" : "RELEASED");
#endif
return true;
}
// check if the key is a macro key
if (keycode <= SMTD_KEYCODES_BEGIN || SMTD_KEYCODES_END <= keycode) {
#ifdef SMTD_DEBUG_ENABLED
printf("<< BYPASS KEY %s %s\n", keycode_to_string(keycode), record->event.pressed ? "PRESSED" : "RELEASED");
#endif
return true;
}
// check if the key is already handled
for (uint8_t i = 0; i < smtd_active_states_size; i++) {
if (smtd_active_states[i].macro_keycode == keycode) {
#ifdef SMTD_DEBUG_ENABLED
printf("<< ALREADY HANDELED KEY %s %s\n", keycode_to_string(keycode), record->event.pressed ? "PRESSED" : "RELEASED");
#endif
return true;
}
}
// create a new state and process the event
smtd_state *state = &smtd_active_states[smtd_active_states_size];
state->macro_keycode = keycode;
smtd_active_states_size++;
#ifdef SMTD_DEBUG_ENABLED
printf("<< CREATE STATE %s %s\n", keycode_to_string(keycode), record->event.pressed ? "PRESSED" : "RELEASED");
#endif
return process_smtd_state(keycode, record, state);
}
/* ************************************* *
* CUSTOMIZATION MACROS *
* ************************************* */
#ifdef CAPS_WORD_ENABLE
#define SMTD_TAP_16(use_cl, key) tap_code16(use_cl && is_caps_word_on() ? LSFT(key) : key)
#define SMTD_REGISTER_16(use_cl, key) register_code16(use_cl && is_caps_word_on() ? LSFT(key) : key)
#define SMTD_UNREGISTER_16(use_cl, key) unregister_code16(use_cl && is_caps_word_on() ? LSFT(key) : key)
#else
#define SMTD_TAP_16(use_cl, key) tap_code16(key)
#define SMTD_REGISTER_16(use_cl, key) register_code16(key)
#define SMTD_UNREGISTER_16(use_cl, key) unregister_code16(key)
#endif
#define SMTD_GET_MACRO(_1, _2, _3, _4, _5, NAME, ...) NAME
#define SMTD_MT(...) SMTD_GET_MACRO(__VA_ARGS__, SMTD_MT5, SMTD_MT4, SMTD_MT3)(__VA_ARGS__)
#define SMTD_MTE(...) SMTD_GET_MACRO(__VA_ARGS__, SMTD_MTE5, SMTD_MTE4, SMTD_MTE3)(__VA_ARGS__)
#define SMTD_LT(...) SMTD_GET_MACRO(__VA_ARGS__, SMTD_LT5, SMTD_LT4, SMTD_LT3)(__VA_ARGS__)
#define SMTD_MT3(macro_key, tap_key, mod) SMTD_MT4(macro_key, tap_key, mod, 1000)
#define SMTD_MTE3(macro_key, tap_key, mod) SMTD_MTE4(macro_key, tap_key, mod, 1000)
#define SMTD_LT3(macro_key, tap_key, layer) SMTD_LT4(macro_key, tap_key, layer, 1000)
#define SMTD_MT4(macro_key, tap_key, mod, threshold) SMTD_MT5(macro_key, tap_key, mod, threshold, true)
#define SMTD_MTE4(macro_key, tap_key, mod, threshold) SMTD_MTE5(macro_key, tap_key, mod, threshold, true)
#define SMTD_LT4(macro_key, tap_key, layer, threshold) SMTD_LT5(macro_key, tap_key, layer, threshold, true)
#define SMTD_MT5(macro_key, tap_key, mod, threshold, use_cl) \
case macro_key: { \
switch (action) { \
case SMTD_ACTION_TOUCH: \
break; \
case SMTD_ACTION_TAP: \
SMTD_TAP_16(use_cl, tap_key); \
break; \
case SMTD_ACTION_HOLD: \
if (tap_count < threshold) { \
register_mods(MOD_BIT(mod)); \
} else { \
SMTD_REGISTER_16(use_cl, tap_key); \
} \
break; \
case SMTD_ACTION_RELEASE: \
if (tap_count < threshold) { \
unregister_mods(MOD_BIT(mod)); \
} else { \
SMTD_UNREGISTER_16(use_cl, tap_key); \
send_keyboard_report(); \
} \
break; \
} \
break; \
}
#define SMTD_MTE5(macro_key, tap_key, mod, threshold, use_cl) \
case macro_key: { \
switch (action) { \
case SMTD_ACTION_TOUCH: \
register_mods(MOD_BIT(mod)); \
break; \
case SMTD_ACTION_TAP: \
unregister_mods(MOD_BIT(mod)); \
SMTD_TAP_16(use_cl, tap_key); \
break; \
case SMTD_ACTION_HOLD: \
if (!(tap_count < threshold)) { \
unregister_mods(MOD_BIT(mod)); \
SMTD_REGISTER_16(use_cl, tap_key); \
} \
break; \
case SMTD_ACTION_RELEASE: \
if (tap_count < threshold) { \
unregister_mods(MOD_BIT(mod)); \
send_keyboard_report(); \
} else { \
SMTD_UNREGISTER_16(use_cl, tap_key); \
} \
break; \
} \
break; \
}
#define SMTD_LT5(macro_key, tap_key, layer, threshold, use_cl)\
case macro_key: { \
switch (action) { \
case SMTD_ACTION_TOUCH: \
break; \
case SMTD_ACTION_TAP: \
SMTD_TAP_16(use_cl, tap_key); \
break; \
case SMTD_ACTION_HOLD: \
if (tap_count < threshold) { \
LAYER_PUSH(layer); \
} else { \
SMTD_REGISTER_16(use_cl, tap_key); \
} \
break; \
case SMTD_ACTION_RELEASE: \
if (tap_count < threshold) { \
LAYER_RESTORE(); \
} \
SMTD_UNREGISTER_16(use_cl, tap_key); \
break; \
} \
break; \
}

View File

@@ -0,0 +1,163 @@
{
"version": 1,
"notes": "Cheapino default keymap",
"documentation": "\"This file is a QMK Configurator export. You can import this at <https://config.qmk.fm>. It can also be used directly with QMK's source code.\n\nTo setup your QMK environment check out the tutorial: <https://docs.qmk.fm/#/newbs>\n\nYou can convert this file to a keymap.c using this command: `qmk json2c {keymap}`\n\nYou can compile this keymap using this command: `qmk compile {keymap}`\"\n",
"keyboard": "bastardkb/skeletyl/blackpill",
"keymap": "via",
"layout": "LAYOUT_split_3x5_3",
"layers": [
[
"KC_Q",
"KC_W",
"KC_E",
"KC_R",
"KC_T",
"KC_Y",
"KC_U",
"KC_I",
"KC_O",
"KC_P",
"LGUI_T(KC_A)",
"LALT_T(KC_S)",
"LCTL_T(KC_D)",
"LSFT_T(KC_F)",
"KC_G",
"KC_H",
"RSFT_T(KC_J)",
"LCTL_T(KC_K)",
"LALT_T(KC_L)",
"LGUI_T(KC_SCLN)",
"KC_Z",
"KC_X",
"KC_C",
"KC_V",
"LT(5,KC_B)",
"LT(1,KC_N)",
"KC_M",
"KC_COMM",
"KC_DOT",
"KC_SLSH",
"LT(6,KC_ESC)",
"LT(3,KC_SPC)",
"LT(5,KC_TAB)",
"LT(1,KC_DEL)",
"LT(2,KC_BSPC)",
"LT(4,KC_ENT)"
],
[
"KC_VOLU",
"KC_WH_L",
"KC_MS_U",
"KC_WH_U",
"KC_WH_R",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"ANY(QK_RBT)",
"KC_MS_L",
"KC_BTN2",
"KC_BTN1",
"KC_MS_R",
"KC_MUTE",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_VOLD",
"KC_MNXT",
"KC_MS_D",
"KC_WH_D",
"KC_MPLY",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_NO",
"KC_NO"
],
[
"KC_NO",
"KC_HOME",
"KC_DEL",
"KC_PGUP",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_LEFT",
"KC_UP",
"KC_RGHT",
"KC_NO",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_END",
"KC_DOWN",
"KC_PGDN",
"KC_NO",
"KC_NO",
"KC_BTN1",
"KC_BTN2",
"KC_BTN3",
"KC_BTN4",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_NO",
"KC_NO"
],
[
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_WH_U",
"KC_AT",
"KC_UNDS",
"KC_PIPE",
"KC_GRV",
"KC_PERC",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"RGB_TOG",
"KC_HASH",
"KC_TAB",
"KC_EXLM",
"KC_DQUO",
"KC_DLR",
"KC_BTN4",
"KC_BTN3",
"KC_BTN2",
"KC_BTN1",
"KC_WH_D",
"KC_TILD",
"KC_QUOT",
"KC_BSLS",
"KC_SLSH",
"KC_AMPR",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_NO"
]
],
"author": "thomas.haukland@gmail.com"
}

152
keyboards/cheapino/matrix.c Normal file
View File

@@ -0,0 +1,152 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Copied from here: https://github.com/e3w2q/qmk_firmware/blob/762fe3e0a7cbea768245a75520f06ff5a2f00b9f/keyboards/2x3test/matrix.c
*/
/*
* scan matrix
*/
#include <stdint.h>
#include <stdbool.h>
#include "wait.h"
#include "util.h"
#include "matrix.h"
#include "config.h"
#include "quantum.h"
#include "debounce.h"
#include "encoder.h"
#include "ghosting.h"
#include "print.h"
// How long the scanning code waits for changed io to settle.
// Adjust from default 30 to weigh up for increased time spent ghost-hunting.
// (the rp2040 does not seem to have any problems with this value...)
#define MATRIX_IO_DELAY 25
#define COL_SHIFTER ((uint16_t)1)
static const pin_t row_pins[] = MATRIX_ROW_PINS;
static const pin_t col_pins[] = MATRIX_COL_PINS;
static matrix_row_t previous_matrix[MATRIX_ROWS];
static void select_row(uint8_t row) {
setPinOutput(row_pins[row]);
writePinLow(row_pins[row]);
}
static void unselect_row(uint8_t row) { setPinInputHigh(row_pins[row]); }
static void unselect_rows(void) {
for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
setPinInputHigh(row_pins[x]);
}
}
static void select_col(uint8_t col) {
setPinOutput(col_pins[col]);
writePinLow(col_pins[col]);
}
static void unselect_col(uint8_t col) {
setPinInputHigh(col_pins[col]);
}
static void unselect_cols(void) {
for (uint8_t x = 0; x < MATRIX_COLS/2; x++) {
setPinInputHigh(col_pins[x*2]);
}
}
static void read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
// Select row and wait for row selection to stabilize
select_row(current_row);
wait_us(MATRIX_IO_DELAY);
// For each col...
for (uint8_t col_index = 0; col_index < MATRIX_COLS / 2; col_index++) {
uint16_t column_index_bitmask = COL_SHIFTER << ((col_index * 2) + 1);
// Check row pin state
if (readPin(col_pins[col_index*2])) {
// Pin HI, clear col bit
current_matrix[current_row] &= ~column_index_bitmask;
} else {
// Pin LO, set col bit
current_matrix[current_row] |= column_index_bitmask;
}
}
// Unselect row
unselect_row(current_row);
}
static void read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
// Select col and wait for col selection to stabilize
select_col(current_col*2);
wait_us(MATRIX_IO_DELAY);
uint16_t column_index_bitmask = COL_SHIFTER << (current_col * 2);
// For each row...
for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
// Check row pin state
if (readPin(row_pins[row_index])) {
// Pin HI, clear col bit
current_matrix[row_index] &= ~column_index_bitmask;
} else {
// Pin LO, set col bit
current_matrix[row_index] |= column_index_bitmask;
}
}
// Unselect col
unselect_col(current_col*2);
}
void matrix_init_custom(void) {
// initialize key pins
unselect_cols();
unselect_rows();
debounce_init(MATRIX_ROWS);
}
void store_old_matrix(matrix_row_t current_matrix[]) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
previous_matrix[i] = current_matrix[i];
}
}
bool has_matrix_changed(matrix_row_t current_matrix[]) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
if (previous_matrix[i] != current_matrix[i]) return true;
}
return false;
}
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
store_old_matrix(current_matrix);
// Set row, read cols
for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
read_cols_on_row(current_matrix, current_row);
}
// Set col, read rows
for (uint8_t current_col = 0; current_col < MATRIX_COLS/2; current_col++) {
read_rows_on_col(current_matrix, current_col);
}
fix_encoder_action(current_matrix);
fix_ghosting(current_matrix);
return has_matrix_changed(current_matrix);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include_next <mcuconf.h>
#undef RP_I2C_USE_I2C1
#define RP_I2C_USE_I2C1 TRUE

View File

@@ -0,0 +1,27 @@
# cheapino
![cheapino](imgur.com image replace me!)
*A short description of the keyboard/project*
* Keyboard Maintainer: [Thomas Haukland](https://github.com/tompi)
* Hardware Supported: *The PCBs, controllers supported*
* Hardware Availability: *Links to where you can find this hardware*
Make example for this keyboard (after setting up your build environment):
make cheapino:default
Flashing example for this keyboard:
make cheapino: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,8 @@
CAPS_WORD_ENABLE = yes
CUSTOM_MATRIX = lite
WS2812_DRIVER = vendor
RGBLIGHT_ENABLE = yes
DEFERRED_EXEC_ENABLE = yes
SRC += encoder.c
SRC += ghosting.c
SRC += matrix.c

View File

@@ -16,6 +16,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#define BOTH_SHIFTS_TURNS_ON_CAPS_WORD
// Set the mouse settings to a comfortable speed/accuracy trade-off,
// assuming a screen refresh rate of 60 Htz or higher
// The default is 50. This makes the mouse ~3 times faster and more accurate

View File

@@ -23,7 +23,7 @@
"LSFT_T(KC_T)",
"KC_G",
"KC_M",
"LSFT_T(KC_N)",
"RSFT_T(KC_N)",
"LCTL_T(KC_E)",
"LALT_T(KC_I)",
"LGUI_T(KC_O)",
@@ -59,10 +59,10 @@
"KC_MS_R",
"KC_MUTE",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_VOLD",
"KC_MNXT",
"KC_MS_D",
@@ -85,9 +85,9 @@
"KC_PGUP",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_BTN1",
"KC_BTN2",
"KC_BTN3",
"KC_NO",
"KC_NO",
"KC_LEFT",
@@ -151,8 +151,8 @@
"KC_TRNS"
],
[
"KC_EQL",
"KC_COLN",
"KC_TILD",
"KC_EXLM",
"KC_LT",
"KC_GT",
"KC_SCLN",
@@ -165,7 +165,7 @@
"KC_RCBR",
"KC_LPRN",
"KC_RPRN",
"KC_AT",
"KC_PEQL",
"KC_NO",
"KC_TRNS",
"KC_TRNS",
@@ -197,10 +197,10 @@
"KC_F8",
"KC_F9",
"KC_F10",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_TRNS",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_NO",
"KC_F4",
@@ -229,9 +229,9 @@
"KC_NO",
"KC_NO",
"KC_PPLS",
"KC_7",
"KC_8",
"KC_9",
"KC_P7",
"KC_P8",
"KC_P9",
"KC_PAST",
"KC_TRNS",
"KC_TRNS",
@@ -239,9 +239,9 @@
"KC_TRNS",
"KC_NO",
"KC_PMNS",
"KC_4",
"KC_5",
"KC_6",
"KC_P4",
"KC_P5",
"KC_P6",
"KC_PSLS",
"KC_NO",
"KC_NO",
@@ -249,9 +249,9 @@
"KC_NO",
"KC_NO",
"KC_PDOT",
"KC_1",
"KC_2",
"KC_3",
"KC_P1",
"KC_P2",
"KC_P3",
"KC_PEQL",
"KC_NO",
"KC_NO",

View File

@@ -20,7 +20,7 @@
//#define SERIAL_USART_TX_PIN B6 // USART TX pin
//#define SERIAL_USART_RX_PIN B7 // USART RX pin
#define EE_HANDS
//#define EE_HANDS
#define SOFT_SERIAL_PIN B14 // D0 or D1, D2, D3, E6
#define SELECT_SOFT_SERIAL_SPEED 2 // or 0, 2, 3, 4, 5
@@ -31,7 +31,8 @@
// 4: about 26kbps
// 5: about 20kbps
#define CRC8_USE_TABLE
#define CRC8_OPTIMIZE_SPEED
/* Top left key on left half */
#define BOOTMAGIC_LITE_ROW 0
#define BOOTMAGIC_LITE_COLUMN 0
@@ -40,6 +41,6 @@
#define BOOTMAGIC_LITE_COLUMN_RIGHT 4
#define DEVICE_VER 0x0001
#define AUDIO_PIN A1
//#define AUDIO_PIN A1
//#define AUDIO_PWM_DRIVER PWMD1
//#define AUDIO_PWM_CHANNEL 1

View File

@@ -2,7 +2,7 @@
"version": 1,
"notes": "My awesome keymap",
"documentation": "\"This file is a QMK Configurator export. You can import this at <https://config.qmk.fm>. It can also be used directly with QMK's source code.\n\nTo setup your QMK environment check out the tutorial: <https://docs.qmk.fm/#/newbs>\n\nYou can convert this file to a keymap.c using this command: `qmk json2c {keymap}`\n\nYou can compile this keymap using this command: `qmk compile {keymap}`\"\n",
"keyboard": "bastardkb/skeletyl",
"keyboard": "bastardkb/skeletyl/blackpill",
"keymap": "default",
"layout": "LAYOUT_split_3x5_3",
"layers": [
@@ -23,7 +23,7 @@
"LSFT_T(KC_T)",
"KC_G",
"KC_M",
"LSFT_T(KC_N)",
"RSFT_T(KC_N)",
"LCTL_T(KC_E)",
"LALT_T(KC_I)",
"LGUI_T(KC_O)",

View File

@@ -2,8 +2,8 @@ BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
SPLIT_KEYBOARD = yes
SERIAL_DRIVER = bitbang
AUDIO_ENABLE = yes
AUDIO_DRIVER = pwm_software
#AUDIO_ENABLE = yes
#AUDIO_DRIVER = pwm_software
# Bootloader selection
BOOTLOADER = stm32-dfu
@@ -11,3 +11,4 @@ BOOTLOADER = stm32-dfu
CONSOLE_ENABLE = yes
DEBOUNCE_TYPE = asym_eager_defer_pk
CAPS_WORD_ENABLE = yes

79
keyboards/zompi/config.h Normal file
View File

@@ -0,0 +1,79 @@
/*
* Copyright 2022 Thomas.Haukland@gmail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "config_common.h"
#define VENDOR_ID 0xA8F8
#define PRODUCT_ID 0x1830
#define DEVICE_VER 0x0001
#define MANUFACTURER "tompi"
#define PRODUCT "Zompi"
#define SOFT_SERIAL_PIN GP0
#define CRC8_USE_TABLE
#define CRC8_OPTIMIZE_SPEED
//#define MASTER_RIGHT
#define MATRIX_ROWS 8
#define MATRIX_COLS 5
#define MATRIX_ROW_PINS { GP9, GP10, GP4, GP5 }
#define MATRIX_COL_PINS { GP6, GP7, GP8, GP11, GP12 }
#ifdef OLED_ENABLE
# define OLED_DISPLAY_128X32
#define I2C1_SCL_PIN GP3
#define I2C1_SDA_PIN GP2
#define I2C_DRIVER I2CD2
#define OLED_BRIGHTNESS 128
//#define OLED_FONT_H "keyboards/mlego/m65/lib/glcdfont.c"
#endif
#ifdef RGB_MATRIX_ENABLE
# define RGBLED_NUM 6
# define RGBLED_SPLIT { 3,3 }
# define RGB_DI_PIN GP14
# define DRIVER_LED_TOTAL 6
/* Enable Framebuffer and keypress effects */
# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
# define RGB_MATRIX_KEYPRESSES
# define ENABLE_RGB_MATRIX_ALPHAS_MODS
# define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
# define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
# define ENABLE_RGB_MATRIX_BREATHING
# define ENABLE_RGB_MATRIX_HUE_BREATHING
# define ENABLE_RGB_MATRIX_PIXEL_RAIN
# define ENABLE_RGB_MATRIX_PIXEL_FLOW
# define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
# define ENABLE_RGB_MATRIX_TYPING_HEATMAP
# define ENABLE_RGB_MATRIX_DIGITAL_RAIN
# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
# define ENABLE_RGB_MATRIX_SOLID_REACTIVE
# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
# define ENABLE_RGB_MATRIX_SPLASH
# define ENABLE_RGB_MATRIX_MULTISPLASH
# define ENABLE_RGB_MATRIX_SOLID_SPLASH
# define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
#endif

27
keyboards/zompi/halconf.h Normal file
View File

@@ -0,0 +1,27 @@
/* Copyright 2020 QMK
*
* 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/>.
*/
/*
* This file was auto-generated by:
* `qmk chibios-confmigrate -i keyboards/handwired/onekey/blackpill_f401/halconf.h -r platforms/chibios/common/configs/halconf.h`
*/
#pragma once
#define HAL_USE_I2C TRUE
#include_next <halconf.h>

73
keyboards/zompi/info.json Normal file
View File

@@ -0,0 +1,73 @@
{
"keyboard_name": "Zompi",
"url": "https://github.com/tompi/qmk_firmware/tree/develop",
"maintainer": "Thomas Haukland",
"bootloader": "rp2040",
"debounce": 5,
"diode_direction": "COL2ROW",
"encoder": {
"enabled": true,
"rotary": [
{
"pin_a": "GP24",
"pin_b": "GP25",
"resolution": 4
}
]
},
"features": {
"audio": false,
"backlight": false,
"bootmagic": true,
"command": false,
"console": true,
"encoder": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
"oled": true,
"wpm": true
},
"layouts": {
"LAYOUT_split_3x5_3": {
"layout": [
{"label":"L00", "x":0, "y":0},
{"label":"L01", "x":1, "y":0},
{"label":"L02", "x":2, "y":0},
{"label":"L03", "x":3, "y":0},
{"label":"L04", "x":4, "y":0},
{"label":"R00", "x":11, "y":0},
{"label":"R01", "x":12, "y":0},
{"label":"R02", "x":13, "y":0},
{"label":"R03", "x":14, "y":0},
{"label":"R04", "x":15, "y":0},
{"label":"L10", "x":0, "y":1},
{"label":"L11", "x":1, "y":1},
{"label":"L12", "x":2, "y":1},
{"label":"L13", "x":3, "y":1},
{"label":"L14", "x":4, "y":1},
{"label":"R10", "x":11, "y":1},
{"label":"R11", "x":12, "y":1},
{"label":"R12", "x":13, "y":1},
{"label":"R13", "x":14, "y":1},
{"label":"R14", "x":15, "y":1},
{"label":"L20", "x":0, "y":2},
{"label":"L21", "x":1, "y":2},
{"label":"L22", "x":2, "y":2},
{"label":"L23", "x":3, "y":2},
{"label":"L24", "x":4, "y":2},
{"label":"R20", "x":11, "y":2},
{"label":"R21", "x":12, "y":2},
{"label":"R22", "x":13, "y":2},
{"label":"R23", "x":14, "y":2},
{"label":"R24", "x":15, "y":2},
{"label":"L33", "x":4, "y":3},
{"label":"L34", "x":5, "y":3},
{"label":"L31", "x":6, "y":3},
{"label":"R33", "x":9, "y":3},
{"label":"R34", "x":10, "y":3},
{"label":"R31", "x":11, "y":3}
]
}
}
}

View File

@@ -0,0 +1,72 @@
/*
*
* 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
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_split_3x5_3(
//,-----------------------------------------------------. ,-----------------------------------------------------.
KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
// KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH,
RGB_MOD, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, RGB_MOD,
//|--------+--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------+--------|
KC_LGUI, KC_SPC , MO(1), MO(2), KC_ENT , KC_RALT
//`--------------------------' `--------------------------'
),
[1] = LAYOUT_split_3x5_3(
//,-----------------------------------------------------. ,-----------------------------------------------------.
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_LEFT, KC_DOWN, KC_UP,KC_RIGHT, XXXXXXX,
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
//|--------+--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------+--------|
KC_LGUI, KC_SPC, _______, MO(3), KC_ENT, KC_RALT
//`--------------------------' `--------------------------'
),
[2] = LAYOUT_split_3x5_3(
//,-----------------------------------------------------. ,-----------------------------------------------------.
KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN,
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS,
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE,
//|--------+--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------+--------|
KC_LGUI, KC_SPC, MO(3), _______, KC_ENT, KC_RALT
//`--------------------------' `--------------------------'
),
[3] = LAYOUT_split_3x5_3(
//,-----------------------------------------------------. ,-----------------------------------------------------.
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
RGB_HUI, RGB_SAI, RGB_VAI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
RGB_HUD, RGB_SAD, RGB_VAD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
//|--------+--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------+--------|
KC_LGUI, KC_SPC, _______, _______, KC_ENT, KC_RALT
//`--------------------------' `--------------------------'
)
};

View File

@@ -0,0 +1,6 @@
#pragma once
#include_next "mcuconf.h"
#undef RP_I2C_USE_I2C1
#define RP_I2C_USE_I2C1 TRUE

11
keyboards/zompi/readme.md Normal file
View File

@@ -0,0 +1,11 @@
# Zompi
My experiment with qmk and the rp2040-zero.
Blingy split keyboard using audio, leds and rotary encoders, because these
things are essentials, right?
Make example for this keyboard (after setting up your build environment):
make zompi:default

26
keyboards/zompi/rules.mk Normal file
View File

@@ -0,0 +1,26 @@
# MCU name
MCU = RP2040
# Bootloader selection
BOOTLOADER = rp2040
# Build Options
# change yes to no to disable
#
RGB_MATRIX_ENABLE = yes # Enable keyboard RGB matrix (do not use together with RGBLIGHT_ENABLE)
RGB_MATRIX_DRIVER = WS2812 # RGB matrix driver support
WS2812_DRIVER = vendor
SPLIT_KEYBOARD = yes
LTO_ENABLE = yes
AUDIO_SUPPORTED = no
RGB_MATRIX_SUPPORTED = yes
#RGBLIGHT_ENABLE = yes
##BACKLIGHT_ENABLE = yes
SERIAL_DRIVER = vendor
LAYOUTS = split_3x5_3
OLED_DRIVER = SSD1306
# Project specific files
#QUANTUM_LIB_SRC += spi_master.c

158
keyboards/zompi/zompi.c Normal file
View File

@@ -0,0 +1,158 @@
/*
* Copyright 2022 Thomas.Haukland@gmail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "zompi.h"
#ifdef RGB_MATRIX
led_config_t g_led_config = { {
{ 1, 2, 1, 1, 1 },
{ 1, 2, 1, 1, 1 },
{ 1, 2, 1, 1, 1 },
{ 1, 2, 1, 1, 1 },
{ 1, 2, 1, 1, 1 },
{ 1, 2, 1, 1, 1 },
{ 1, 2, 1, 1, 1 },
{ 1, 2, 1, 1, 1 }
}, {
{ 85, 16 }, { 50, 13 }, { 16, 20 }, { 16, 38 }, { 50, 48 }, { 85, 52 }
}, {
4, 4, 4, 4, 4, 4
} };
#endif
#ifdef OLED_ENABLE
static void render_logo(void) {
static const char PROGMEM raw_logo[] = {
0x00, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x7c, 0xfe, 0xfe, 0xfe, 0xfc, 0x7c, 0x38, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xc1, 0xe1, 0xf1, 0xf9, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x7f,
0x3f, 0x1f, 0x0f, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfc,
0xfc, 0xfe, 0x7e, 0x7e, 0x7e, 0x3e, 0x7e, 0x7e, 0x7e, 0xfe, 0xfc, 0xfc, 0xfc, 0xf8, 0xf0, 0xe0,
0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xf8, 0x7c, 0x7c, 0x3e,
0x3e, 0x7e, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8, 0xf8, 0xf8, 0x7c, 0x7c, 0x3e, 0x3e, 0x7e,
0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfc, 0x7c, 0x7e, 0x7e, 0x3e, 0x7e, 0x7e, 0x7e, 0xfe, 0xfe, 0xfc, 0xfc, 0xf8,
0xf8, 0xf0, 0xe0, 0x80, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0x00,
0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xf3, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x02, 0x1f, 0x3f, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf0, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f,
0x1f, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf8, 0xff, 0xff, 0xff, 0xff,
0xff, 0x7f, 0x3f, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00
};
oled_write_raw_P(raw_logo, sizeof(raw_logo));
}
enum layers {
_QWERTY = 0,
_LOWER,
_RAISE,
_ADJUST,
};
static void render_status(void) {
render_logo();
return;
// Host Keyboard Layer Status
oled_write_P(PSTR("Layer: "), false);
switch (get_highest_layer(layer_state)) {
case _QWERTY:
oled_write_P(PSTR("Default\n"), false);
break;
case _LOWER:
oled_write_P(PSTR("Lower\n"), false);
break;
case _RAISE:
oled_write_P(PSTR("Raise\n"), false);
break;
case _ADJUST:
oled_write_P(PSTR("Adjust\n"), false);
break;
default:
oled_write_P(PSTR("Undefined\n"), false);
}
// Host Keyboard LED Status
led_t led_state = host_keyboard_led_state();
oled_write_P(led_state.num_lock ? PSTR("NUMLCK ") : PSTR(" "), false);
oled_write_P(led_state.caps_lock ? PSTR("CAPLCK ") : PSTR(" "), false);
oled_write_P(led_state.scroll_lock ? PSTR("SCRLCK ") : PSTR(" "), false);
}
bool oled_task_kb(void) {
if (!oled_task_user()) { return false; }
if (is_keyboard_left()) {
render_status(); // Renders the current keyboard state (layer, lock, caps, scroll, etc)
} else {
render_logo();
}
return true;
}
#endif
/* The encoder_update_user is a function.
* It'll be called by QMK every time you turn the encoder.
*
* The index parameter tells you which encoder was turned. If you only have
* one encoder, the index will always be zero.
*
* The clockwise parameter tells you the direction of the encoder. It'll be
* true when you turned the encoder clockwise, and false otherwise.
*/
bool encoder_update_user(uint8_t index, bool clockwise) {
/* With an if statement we can check which encoder was turned. */
if (index == 0) { /* First encoder */
/* And with another if statement we can check the direction. */
if (clockwise) {
/* This is where the actual magic happens: this bit of code taps on the
Page Down key. You can do anything QMK allows you to do here.
You'll want to replace these lines with the things you want your
encoders to do. */
tap_code(KC_PGDN);
} else {
/* And likewise for the other direction, this time Page Down is pressed. */
tap_code(KC_PGUP);
}
/* You can copy the code and change the index for every encoder you have. Most
keyboards will only have two, so this piece of code will suffice. */
} else if (index == 1) { /* Second encoder */
if (clockwise) {
tap_code(KC_UP);
} else {
tap_code(KC_DOWN);
}
}
return false;
}

39
keyboards/zompi/zompi.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* Copyright 2022 Thomas.Haukland@gmail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "quantum.h"
// clang-format off
#define LAYOUT_split_3x5_3( \
k00, k01, k02, k03, k04, k44, k43, k42, k41, k40, \
k10, k11, k12, k13, k14, k54, k53, k52, k51, k50, \
k20, k21, k22, k23, k24, k64, k63, k62, k61, k60, \
k32, k33, k30, k70, k73, k72 \
) \
{ \
{ k00, k01, k02, k03, k04 }, \
{ k10, k11, k12, k13, k14 }, \
{ k20, k21, k22, k23, k24 }, \
{ k30, KC_NO, k32, k33, KC_NO }, \
{ k40, k41, k42, k43, k44 }, \
{ k50, k51, k52, k53, k54 }, \
{ k60, k61, k62, k63, k64 }, \
{ k70, KC_NO, k72, k73, KC_NO }, \
}
// clang-format on
//