[Keymap] Drashna update for post Q2 merge (#17241)

master
Drashna Jaelre 2022-05-30 22:02:55 -07:00 committed by GitHub
parent b554e4b612
commit cda343acbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 672 additions and 769 deletions

View File

@ -23,8 +23,8 @@
// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT(
KC_VOLU, KC_MPLY, KC_MPRV, RESET,
KC_VOLD, KC_MUTE, KC_MNXT, RESET
KC_VOLU, KC_MPLY, KC_MPRV, QK_BOOT,
KC_VOLD, KC_MUTE, KC_MNXT, QK_BOOT
),
};

View File

@ -1,38 +0,0 @@
/* 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_f411/chconf.h -r platforms/chibios/common/configs/chconf.h`
*/
#pragma once
#define CH_CFG_ST_FREQUENCY 10000
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
#define CH_CFG_FACTORY_SEMAPHORES TRUE
#define CH_CFG_FACTORY_MAILBOXES TRUE
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
#define CH_CFG_FACTORY_PIPES TRUE
#include_next <chconf.h>

View File

@ -71,6 +71,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SERIAL_USART_TX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
#define SERIAL_USART_RX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
#define SERIAL_USART_TIMEOUT 100 // USART driver timeout. default 100
#define SERIAL_USART_SPEED 921600
// #define SERIAL_USART_PIN_SWAP // swap RX and TX pins on master
// To use the highest possible baudrate (3.75Mbit/s) uncomment the following
// line, this can result in dropped communications so lower the speed if there
@ -102,8 +103,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define PMW3360_SPI_MODE 3
#define PMW3360_SPI_DIVISOR 64
# define CHARYBDIS_MINIMUM_DEFAULT_DPI 1200
# define CHARYBDIS_DEFAULT_DPI_CONFIG_STEP 400
# define CHARYBDIS_MINIMUM_SNIPING_DPI 200
# define CHARYBDIS_SNIPING_DPI_CONFIG_STEP 100
#define CHARYBDIS_MINIMUM_DEFAULT_DPI 1200
#define CHARYBDIS_DEFAULT_DPI_CONFIG_STEP 400
#define CHARYBDIS_MINIMUM_SNIPING_DPI 200
#define CHARYBDIS_SNIPING_DPI_CONFIG_STEP 100

View File

@ -73,13 +73,13 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_________________RAISE_L1__________________, _________________RAISE_R1__________________,
_________________RAISE_L2__________________, _________________RAISE_R2__________________,
_________________RAISE_L3__________________, _________________RAISE_R3__________________,
REBOOT, KEYLOCK, _______, _______, _______
QK_RBT, _______, _______, _______, _______
),
[_ADJUST] = LAYOUT_charybdis_3x5_wrapper(
_________________ADJUST_L1_________________, _________________ADJUST_R1_________________,
_________________ADJUST_L2_________________, _________________ADJUST_R2_________________,
_________________ADJUST_L3_________________, _________________ADJUST_R3_________________,
EEP_RST, KC_NUKE, _______, _______, RESET
EE_CLR, KC_NUKE, _______, _______, QK_BOOT
),
};
@ -98,3 +98,9 @@ bool usb_vbus_state(void) {
return readPin(USB_VBUS_PIN);
}
#endif
void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
for (int32_t i = 0; i < 40; i++) {
__asm__ volatile("nop" ::: "memory");
}
}

View File

@ -1,38 +0,0 @@
/* 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_f411/chconf.h -r platforms/chibios/common/configs/chconf.h`
*/
#pragma once
#define CH_CFG_ST_FREQUENCY 10000
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
#define CH_CFG_FACTORY_SEMAPHORES TRUE
#define CH_CFG_FACTORY_MAILBOXES TRUE
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
#define CH_CFG_FACTORY_PIPES TRUE
#include_next <chconf.h>

View File

@ -59,6 +59,7 @@
// // line, this can result in dropped communications so lower the speed if there
// // are many timeouts.
// // #define SERIAL_USART_SPEED (STM32_PCLK2 >> 4)
#define SERIAL_USART_SPEED 921600
#define CRC8_USE_TABLE
#define CRC8_OPTIMIZE_SPEED

View File

@ -100,7 +100,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _________________LOWER_L3__________________, _________________LOWER_R3__________________, _______,
_______, _______, _______, _______, _______,
_______, _______, _______
),
),
[_RAISE] = LAYOUT_charybdis_4x6_wrapper(
KC_F12, _________________FUNC_LEFT_________________, _________________FUNC_RIGHT________________, KC_F11,
@ -109,8 +109,16 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _________________RAISE_L3__________________, _________________RAISE_R3__________________, _______,
_______, _______, _______, _______, _______,
_______, _______, _______
)
),
[_ADJUST] = LAYOUT_charybdis_4x6_wrapper(
QK_MAKE, KC_WIDE,KC_AUSSIE,KC_SCRIPT,KC_ZALGO,KC_NOMODE, KC_NOMODE,KC_BLOCKS,KC_REGIONAL,_______,_______, QK_BOOT,
VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EE_CLR,
KEYLOCK, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY,
QK_RBT, AUTO_CTN, _______, KC_NUKE, _______,
_______, _______, _______
)
};
// clang-format on
@ -130,3 +138,9 @@ bool usb_vbus_state(void) {
return readPin(USB_VBUS_PIN);
}
#endif
void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
for (int32_t i = 0; i < 40; i++) {
__asm__ volatile("nop" ::: "memory");
}
}

View File

@ -78,8 +78,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_gergo_wrapper(
KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET,
VRSN, _________________ADJUST_L2_________________, _______, KC_NUKE, _________________ADJUST_R2_________________, EEP_RST,
QK_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L2_________________, _______, KC_NUKE, _________________ADJUST_R2_________________, EE_CLR,
_______, _________________ADJUST_L3_________________, _______, _______, _______, _______, _________________ADJUST_R3_________________, TG_MODS,
_______, _______, _______, _______, _______, _______, _______, _______
),

View File

@ -105,8 +105,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______, _______
),
[_ADJUST] = LAYOUT_4x6_right_wrapper(
KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RST,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
QK_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EE_CLR,
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS,
HPT_DWLI, HPT_DWLD, TG_GAME, TG_DBLO,
HPT_TOG, HPT_BUZ, KC_NUKE,

View File

@ -68,7 +68,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SERIAL_USART_TX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
#define SERIAL_USART_RX_PAL_MODE 7 // Pin "alternate function", see the respective datasheet for the appropriate values for your MCU. default: 7
#define SERIAL_USART_TIMEOUT 100 // USART driver timeout. default 100
#define SERIAL_USART_SPEED 921600
#define CRC8_USE_TABLE
#define CRC8_OPTIMIZE_SPEED

View File

@ -58,3 +58,9 @@ bool usb_vbus_state(void) {
return readPin(USB_VBUS_PIN);
}
#endif
void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
for (int32_t i = 0; i < 40; i++) {
__asm__ volatile("nop" ::: "memory");
}
}

View File

@ -17,13 +17,19 @@
#pragma once
#define DEBOUNCE 45
#define ENCODER_DEFAULT_POS 0x3
#ifdef OLED_DRIVER_SH1107
# undef OLED_DISPLAY_128X64
#endif
# define CHARYBDIS_MINIMUM_DEFAULT_DPI 1200
# define CHARYBDIS_DEFAULT_DPI_CONFIG_STEP 200
# define CHARYBDIS_MINIMUM_SNIPING_DPI 400
# define CHARYBDIS_SNIPING_DPI_CONFIG_STEP 200
#define CHARYBDIS_MINIMUM_DEFAULT_DPI 1200
#define CHARYBDIS_DEFAULT_DPI_CONFIG_STEP 200
#define CHARYBDIS_MINIMUM_SNIPING_DPI 400
#define CHARYBDIS_SNIPING_DPI_CONFIG_STEP 200
#define ENCODER_DEFAULT_POS 0x3
#define SECURE_UNLOCK_SEQUENCE \
{ \
{ 2, 1 }, { 2, 2 }, { 2, 3 }, { 2, 4 } \
}

View File

@ -120,25 +120,24 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______, _______
),
[_ADJUST] = LAYOUT_5x6_right_wrapper(
KC_MAKE, KC_WIDE,KC_AUSSIE,KC_SCRIPT,KC_ZALGO,KC_NOMODE, KC_NOMODE,KC_BLOCKS,KC_REGIONAL,_______,_______, KC_RST,
VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EEP_RST,
QK_MAKE, KC_WIDE,KC_AUSSIE,KC_SCRIPT,KC_ZALGO,KC_NOMODE, KC_NOMODE,KC_BLOCKS,KC_REGIONAL,_______,_______, QK_BOOT,
VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EE_CLR,
KEYLOCK, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY,
TG(_DIABLOII), AUTO_CTN, TG_GAME, TG_DBLO,
_______, REBOOT, KC_NUKE,
_______, QK_RBT, KC_NUKE,
_______, _______, _______,
_______, _______, KC_NUKE, _______
),
};
#define BASE_ENCODERS { { KC_VOLD, KC_VOLU }, { KC_WH_D, KC_WH_U } }
#ifdef ENCODER_MAP_ENABLE
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[_DEFAULT_LAYER_1] = BASE_ENCODERS,
[_DEFAULT_LAYER_2] = BASE_ENCODERS,
[_DEFAULT_LAYER_3] = BASE_ENCODERS,
[_DEFAULT_LAYER_4] = BASE_ENCODERS,
[_DEFAULT_LAYER_1] = { { KC_VOLD, KC_VOLU }, { KC_WH_D, KC_WH_U } },
[_DEFAULT_LAYER_2] = { { _______, _______ }, { _______, _______ } },
[_DEFAULT_LAYER_3] = { { _______, _______ }, { _______, _______ } },
[_DEFAULT_LAYER_4] = { { _______, _______ }, { _______, _______ } },
[_GAMEPAD] = { { _______, _______ }, { _______, _______ } },
[_DIABLO] = { { _______, _______ }, { _______, _______ } },
[_MOUSE] = { { _______, _______ }, { KC_WH_D, KC_WH_U } },
@ -188,15 +187,15 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
#endif
#ifdef OLED_ENABLE
extern uint16_t typing_mode;
# include "keyrecords/unicode.h"
oled_rotation_t oled_init_keymap(oled_rotation_t rotation) {
return OLED_ROTATION_180;
}
void oled_render_large_display(void) {
if (is_keyboard_left()) {
render_wpm_graph(54, 64);
void oled_render_large_display(bool side) {
if (side) {
render_wpm_graph(56, 64);
} else {
oled_advance_page(true);
oled_advance_page(true);
@ -214,25 +213,25 @@ void oled_render_large_display(void) {
oled_set_cursor(1, 14);
oled_write_ln_P(PSTR("Unicode:"), false);
switch (typing_mode) {
case KC_WIDE:
case UCTM_WIDE:
oled_write_P(PSTR(" Wide"), false);
break;
case KC_SCRIPT:
case UCTM_SCRIPT:
oled_write_P(PSTR(" Script"), false);
break;
case KC_BLOCKS:
case UCTM_BLOCKS:
oled_write_P(PSTR(" Blocks"), false);
break;
case KC_REGIONAL:
case UCTM_REGIONAL:
oled_write_P(PSTR(" Regional"), false);
break;
case KC_AUSSIE:
case UCTM_AUSSIE:
oled_write_P(PSTR(" Aussie"), false);
break;
case KC_ZALGO:
case UCTM_ZALGO:
oled_write_P(PSTR(" Zalgo"), false);
break;
case KC_NOMODE:
case UCTM_NO_MODE:
oled_write_P(PSTR(" Normal"), false);
break;
default:

View File

@ -32,6 +32,9 @@ ifeq ($(strip $(KEYBOARD)), handwired/tractyl_manuform/5x6_right/teensy2pp)
AUTOCORRECTION_ENABLE = no
CAPS_WORD_ENABLE = yes
endif
ifeq ($(strip $(KEYBOARD)), handwired/tractyl_manuform/5x6_right/f411)
BOOTLOADER = tinyuf2
endif
# DEBOUNCE_TYPE = sym_eager_pk
OLED_DRIVER = custom

View File

@ -91,8 +91,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_wrapper(
KC_MAKE, _______, _______, _______, _______, _______, _________________ADJUST_R1_________________, KC_RST,
VRSN, _________________ADJUST_L1_________________, KC_NUKE, _______, _______, _______, _______, EEP_RST,
QK_MAKE, _______, _______, _______, _______, _______, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L1_________________, KC_NUKE, _______, _______, _______, _______, EE_CLR,
_______, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
_______, _________________ADJUST_L3_________________, TG_GAME, _______, _________________ADJUST_R3_________________, KC_MPLY,
_______, _______, _______, _______, _______, _______

View File

@ -51,8 +51,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_MEDIA] = LAYOUT_ortho_5x7(
KC_MAKE, RESET, MU_TOG, AU_ON, AU_OFF, CK_TOGG, RGB_SAD,
_______, EEP_RST, KC_RGB_T,RGB_M_P, RGB_M_B, RGB_M_R, RGB_SAI,
QK_MAKE, QK_BOOT, MU_TOG, AU_ON, AU_OFF, CK_TOGG, RGB_SAD,
_______, EE_CLR, KC_RGB_T,RGB_M_P, RGB_M_B, RGB_M_R, RGB_SAI,
RGB_TOG, RGB_MOD, RGB_RMOD,RGB_M_SW,RGB_M_SN,RGB_M_K, RGB_HUD,
KC_MPLY, KC_MPRV, KC_MNXT, RGB_M_X, RGB_M_G, RGB_M_P, RGB_HUI,
KC_MUTE, KC_VOLD, KC_VOLU, XXXXXXX, XXXXXXX, RGB_VAD, RGB_VAI

View File

@ -75,8 +75,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_wrapper(
KC_MAKE, _________________ADJUST_L1_________________, KC_NUKE, _________________ADJUST_R1_________________, KC_RST,
VRSN, _________________ADJUST_L2_________________, MG_NKRO, _________________ADJUST_R2_________________, EEP_RST,
QK_MAKE, _________________ADJUST_L1_________________, KC_NUKE, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L2_________________, MG_NKRO, _________________ADJUST_R2_________________, EE_CLR,
TG_MODS, _________________ADJUST_L3_________________, KC_RGB_T,_________________ADJUST_R3_________________, RGB_IDL
)
};

View File

@ -79,7 +79,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_Q, CALTDEL, \
KC_A, TSKMGR, \
KC_Z, KC_X, \
_______, RESET \
_______, QK_BOOT \
)
};

View File

@ -18,5 +18,10 @@
#pragma once
#define TAPPING_TERM_PER_KEY
#define WAIT_FOR_USB
// #define WAIT_FOR_USB
// #define NO_USB_STARTUP_CHECK
#define SECURE_UNLOCK_SEQUENCE \
{ \
{ 2, 1 }, { 2, 2 }, { 2, 3 }, { 2, 4 } \
}

View File

@ -106,12 +106,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_moonlander_wrapper(
KC_MAKE, KC_WIDE,KC_AUSSIE,KC_SCRIPT,KC_ZALGO,KC_NOMODE,_______, KC_NUKE,KC_NOMODE,KC_BLOCKS,KC_REGIONAL,_______,_______, KC_RST,
VRSN, _________________ADJUST_L1_________________, TG(_DIABLOII), _______, _________________ADJUST_R1_________________, EEP_RST,
QK_MAKE, KC_WIDE,KC_AUSSIE,KC_SCRIPT,KC_ZALGO,KC_NOMODE,_______, KC_NUKE,KC_NOMODE,KC_BLOCKS,KC_REGIONAL,_______,_______, QK_BOOT,
VRSN, _________________ADJUST_L1_________________, TG(_DIABLOII), _______, _________________ADJUST_R1_________________, EE_CLR,
KEYLOCK, _________________ADJUST_L2_________________, _______, _______, _________________ADJUST_R2_________________, RGB_IDL,
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, AUTO_CTN,
REBOOT, _______, _______, _______, _______, _______
QK_RBT, _______, _______, _______, _______, _______
),
};

View File

@ -61,8 +61,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_wrapper(\
KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET,
VRSN, _________________ADJUST_L2_________________, _______, _______, _______, KC_NUKE, _________________ADJUST_R2_________________, EEP_RST,
QK_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L2_________________, _______, _______, _______, KC_NUKE, _________________ADJUST_R2_________________, EE_CLR,
TG_MODS, _________________ADJUST_L3_________________, _______, _______, _______, _______, _______, _______, _________________ADJUST_R3_________________, KC_MPLY
)

View File

@ -27,3 +27,5 @@
#define RGBLIGHT_EFFECT_KNIGHT
#define RGBLIGHT_EFFECT_TWINKLE
#define RGBLIGHT_SLEEP
#define MOUSE_EXT_REPORT

View File

@ -23,7 +23,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(/* Base */
C(KC_C), KC_BTN1, KC_BTN3, KC_BTN2, MO(1), KC_BTN4, KC_BTN5, DPI_CONFIG),
[1] = LAYOUT(/* Base */
RGB_HUI, RGB_MOD, RGB_TOG, RGB_RMOD, MO(1), KC_VOLU, KC_VOLD, RESET)
RGB_HUI, RGB_MOD, RGB_TOG, RGB_RMOD, MO(1), KC_VOLU, KC_VOLD, QK_BOOT)
};

View File

@ -46,5 +46,4 @@
#define BOOTMAGIC_LITE_ROW_RIGHT 4
#define BOOTMAGIC_LITE_COLUMN_RIGHT 7
#define I2C1_CLOCK_SPEED 400000
#define I2C1_DUTY_CYCLE FAST_DUTY_CYCLE_2
#define SERIAL_USART_SPEED 921600

View File

@ -90,10 +90,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
[_ADJUST] = LAYOUT_wrapper(
KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
QK_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EE_CLR,
UC_MOD, _________________ADJUST_L3_________________, HPT_TOG, HPT_FBK, MG_NKRO, UC_MOD, _________________ADJUST_R3_________________, TG_MODS,
REBOOT, _______, KEYLOCK, KC_NUKE, _______, _______, _______, _______, _______, AUTO_CTN
QK_RBT, _______, KEYLOCK, KC_NUKE, _______, _______, _______, _______, _______, AUTO_CTN
),
// [_LAYERINDEX] = LAYOUT_wrapper(
// _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
@ -105,7 +105,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
#ifdef ENCODER_MAP_ENABLE
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = {
[_DEFAULT_LAYER_1] = { { KC_DOWN, KC_UP }, { KC_VOLD, KC_VOLU } },
[_DEFAULT_LAYER_1] = { { KC_VOLD, KC_VOLU }, { KC_WH_D, KC_WH_U } },
[_DEFAULT_LAYER_2] = { { _______, _______ }, { _______, _______ } },
[_DEFAULT_LAYER_3] = { { _______, _______ }, { _______, _______ } },
[_DEFAULT_LAYER_4] = { { _______, _______ }, { _______, _______ } },
@ -129,9 +129,9 @@ oled_rotation_t oled_init_keymap(oled_rotation_t rotation) {
#endif
}
void oled_render_large_display(void) {
if (is_keyboard_left()) {
render_wpm_graph(54, 64);
void oled_render_large_display(bool side) {
if (side) {
render_wpm_graph(56, 64);
} else {
static const char PROGMEM kyria_logo[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,128,192,224,240,112,120, 56, 60, 28, 30, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 30, 28, 60, 56,120,112,240,224,192,128,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -149,27 +149,6 @@ void oled_render_large_display(void) {
}
#endif
#ifdef ENCODER_ENABLE
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) {
// Volume control
if (clockwise) {
tap_code(KC_VOLU);
} else {
tap_code(KC_VOLD);
}
} else if (index == 1) {
// Page up/Page down
if (clockwise) {
tap_code(KC_PGDN);
} else {
tap_code(KC_PGUP);
}
}
return true;
}
#endif
#ifdef RGBLIGHT_LAYERS
const rgblight_segment_t PROGMEM shift_layers[] = RGBLIGHT_LAYER_SEGMENTS({8, 1, 120, 255, 255}, {18, 1, 120, 255, 255});
const rgblight_segment_t PROGMEM control_layers[] = RGBLIGHT_LAYER_SEGMENTS({6, 1, 0, 255, 255}, {16, 1, 0, 255, 255});
@ -188,3 +167,12 @@ void matrix_scan_keymap(void) {
rgblight_set_layer_state(3, mods & MOD_MASK_GUI);
}
#endif
#ifdef KEYBOARD_splitkb_kyria_rev1_proton_c
void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
for (int32_t i = 0; i < 40; i++) {
__asm__ volatile("nop" ::: "memory");
}
}
#endif

View File

@ -17,11 +17,10 @@ ifeq ($(strip $(KEYBOARD)), splitkb/kyria/rev1/proton_c)
TAP_DANCE_ENABLE = yes
SWAP_HANDS_ENABLE = yes
LTO_ENABLE = no
CTPC = yes
ENCODER_MAP_ENABLE = yes
AUTOCORRECTION_ENABLE = yes
CAPS_WORD_ENABLE = yes
OLED_DRIVER = custom
DEBUG_MATRIX_SCAN_RATE_ENABLE = api
else
LTO_ENABLE = yes
BOOTLOADER = qmk-hid

View File

@ -30,7 +30,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_P1, KC_P2, KC_P3
),
[1] = LAYOUT_ortho_4x3( /* Layer 1 */
RESET, _______, XXXXXXX,
QK_BOOT, _______, XXXXXXX,
AU_ON, AU_OFF, XXXXXXX,
CK_TOGG, XXXXXXX, CK_UP,
CK_RST, XXXXXXX, CK_DOWN

View File

@ -83,8 +83,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_wrapper(
KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RST, _______,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
QK_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, QK_BOOT, _______,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EE_CLR,
_______, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL,
KEYLOCK, _______, _______, _______, _______, KC_NUKE, _______, _______, _______, _______, _______, TG_MODS
)

View File

@ -167,8 +167,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_ergodox_pretty_wrapper(
KC_MAKE, _______, _______, _______, _______, _______, UC_MOD, KC_NUKE, _________________ADJUST_R1_________________, KC_RST,
VRSN, _________________ADJUST_L1_________________, _______, _______, _________________ADJUST_R1_________________, EEP_RST,
QK_MAKE, _______, _______, _______, _______, _______, UC_MOD, KC_NUKE, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L1_________________, _______, _______, _________________ADJUST_R1_________________, EE_CLR,
_______, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, RGB_IDL,
KEYLOCK, _________________ADJUST_L3_________________, _______, _______, _________________ADJUST_R3_________________, TG_MODS,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______,

View File

@ -29,7 +29,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_GAMEPAD] = LAYOUT_numpad_5x6(
RGB_TOG, _______, _______, EEP_RST, KC_MAKE, RESET,
RGB_TOG, _______, _______, EE_CLR, QK_MAKE, QK_BOOT,
RGB_MOD, RGB_RMOD, _______, _______, _______,
RGB_HUI, RGB_HUD, _______, _______, _______, _______,
RGB_SAI, RGB_SAD, _______, _______, _______,

View File

@ -103,10 +103,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_ortho_4x12_wrapper(
KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RST,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
QK_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EE_CLR,
TH_LVL, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL,
KEYLOCK, _______, _______, REBOOT, _______, KC_NUKE, _______, _______, AUTO_CTN,_______, _______, TG_MODS
KEYLOCK, _______, _______, QK_RBT, _______, KC_NUKE, _______, _______, AUTO_CTN,_______, _______, TG_MODS
)
};

View File

@ -121,8 +121,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
* `-----------------------------------------------------------------------------------'
*/
[_ADJUST] = LAYOUT_ortho_5x12_wrapper( \
KC_MAKE, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_RST,
VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EEP_RST,
QK_MAKE, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, QK_BOOT,
VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EE_CLR,
_______, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, RGB_IDL,
KEYLOCK, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______

View File

@ -87,10 +87,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
),
[_ADJUST] = LAYOUT_split_3x6_3_wrapper( \
KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RESET,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
QK_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, QK_BOOT,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EE_CLR,
KEYLOCK, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, RGB_IDL,
REBOOT, KC_NUKE, _______, _______, TG_MODS, AUTO_CTN
QK_RBT, KC_NUKE, _______, _______, TG_MODS, AUTO_CTN
)
};
// clang-format on
@ -120,7 +120,9 @@ uint32_t anim_frame_duration = 500;
uint8_t current_sleep_frame = 0;
uint8_t current_wake_frame = 0; // uncomment if WAKE_FRAMES >1
uint8_t current_kaki_frame = 0;
#ifdef SWAP_HANDS_ENABLE
uint8_t current_rtogi_frame = 0;
#endif
// uint8_t current_ltogi_frame = 0;
// clang-format off
void render_small_kitty(void) {
@ -171,6 +173,7 @@ void render_small_kitty(void) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0d, 0x8d, 0x55, 0x50, 0x94, 0xf0, 0x10, 0x0a, 0x0e, 0x1d, 0x95, 0x24, 0x24, 0x27, 0x13, 0xe1, 0x01, 0x01, 0x01, 0x01, 0x02, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1f, 0x14, 0x14, 0x10, 0x10, 0x11, 0x1f, 0x10, 0x10, 0x18, 0x0f, 0x18, 0x10, 0x10, 0x1f, 0x19, 0x18, 0x1c, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14, 0x14, 0x08,
}};
#ifdef SWAP_HANDS_ENABLE
static const char PROGMEM rtogi[KAKI_FRAMES][ANIM_SIZE] = {{
// 'rtogi1', 32x32px
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x0f, 0x90, 0x10, 0x20, 0xf0, 0xf8, 0xf8,
@ -184,15 +187,20 @@ void render_small_kitty(void) {
0x0f, 0x11, 0x22, 0x44, 0x48, 0x4c, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x80, 0x80, 0xc0, 0xe1, 0xfe, 0xb8, 0x88, 0x0c, 0x04, 0x06, 0x06, 0x06, 0x0e, 0x0e, 0x06, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x06, 0x04, 0x04, 0x04, 0x04, 0x05, 0x04, 0x04, 0x04, 0x07, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}};
#endif
// assumes 1 frame prep stage
#ifdef SWAP_HANDS_ENABLE
extern bool swap_hands;
#endif
void animation_phase(void) {
#ifdef SWAP_HANDS_ENABLE
if (swap_hands) {
anim_frame_duration = 300;
current_rtogi_frame = (current_rtogi_frame + 1) % RTOGI_FRAMES;
oled_write_raw_P(rtogi[abs((RTOGI_FRAMES - 1) - current_rtogi_frame)], ANIM_SIZE);
} else {
} else
#endif
{
if (get_current_wpm() <= SLEEP_SPEED) {
anim_frame_duration = 500;
current_sleep_frame = (current_sleep_frame + 1) % SLEEP_FRAMES;

View File

@ -14,13 +14,21 @@ UNICODE_ENABLE = no # Unicode
RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight.
SWAP_HANDS_ENABLE = no # Enable one-hand typing
ifeq ($(strip $(KEYBOARD)), crkbd/rev1)
OLED_ENABLE = yes
RGB_MATRIX_ENABLE = yes
HAPTIC_ENABLE = no
USE_ARM_CONFIG ?= no
ifeq ($(strip $(CONVERT_TO)), proton_c)
USE_ARM_CONFIG = yes
endif
ifeq ($(strip $(CTPC)), yes)
USE_ARM_CONFIG = yes
endif
ifeq ($(strip $(MCU)), STM32F303)
USE_ARM_CONFIG = yes
endif
ifeq ($(strip $(MCU)), STM32F401)
USE_ARM_CONFIG = yes
endif
ifeq ($(strip $(CTPC)), yes)
ifeq ($(strip $(USE_ARM_CONFIG)), yes)
HAPTIC_ENABLE = no
WS2812_DRIVER = pwm # won't work without a patch to the ctpc mk file
SERIAL_DRIVER = usart
@ -33,3 +41,13 @@ else
BOOTLOADER = qmk-hid
BOOTLOADER_SIZE = 512
endif
ifeq ($(strip $(KEYBOARD)), crkbd/rev1)
OLED_ENABLE = yes
RGB_MATRIX_ENABLE = yes
HAPTIC_ENABLE = no
endif
ifeq ($(strip $(KEYBOARD)), cantor)
SWAP_HANDS_ENABLE = no
endif

View File

@ -0,0 +1,5 @@
#if __has_include("../qmk_secrets/autocorrection_data.h")
# include "../qmk_secrets/autocorrection_data.h"
#else
# include "autocorrect_data_default.h"
#endif

View File

@ -87,6 +87,9 @@ void suspend_power_down_user(void) {
__attribute__((weak)) void suspend_wakeup_init_keymap(void) {}
void suspend_wakeup_init_user(void) {
#ifdef OLED_ENABLE
oled_timer_reset();
#endif
suspend_wakeup_init_keymap();
}

View File

@ -23,6 +23,3 @@ void matrix_init_unicode(void);
#ifdef SPLIT_KEYBOARD
void matrix_slave_scan_keymap(void);
#endif
#ifdef CAPS_WORD_ENABLE
# include "keyrecords/caps_word.h"
#endif

View File

@ -37,9 +37,9 @@
// # define WPM_LAUNCH_CONTROL
// # define WPM_ALLOW_COUNT_REGRESSOIN
// # define WPM_UNFILTERED
# define WPM_SAMPLE_SECONDS 6
# define WPM_SAMPLE_SECONDS 10
# define WPM_SAMPLE_PERIODS 50
# define WPM_ESTIMATED_WORD_SIZE 6
# define WPM_ESTIMATED_WORD_SIZE 5
#endif
#ifdef AUDIO_ENABLE
@ -291,6 +291,12 @@
# ifndef OLED_BRIGHTNESS
# define OLED_BRIGHTNESS 50
# endif
# undef OLED_UPDATE_INTERVAL
# define OLED_UPDATE_INTERVAL 100
# if !defined(STM32F4XX)
# undef OLED_UPDATE_INTERVAL
# define OLED_UPDATE_INTERVAL 75
# endif
#endif
#define ENABLE_COMPILE_KEYCODE
#define BOTH_SHIFTS_TURNS_ON_CAPS_WORD

View File

@ -10,6 +10,13 @@
# pragma GCC push_options
# pragma GCC optimize("O0")
# include "autocorrection_data.h"
# ifndef AUTOCORRECTION_MIN_LENGTH
# define AUTOCORRECTION_MIN_LENGTH AUTOCORRECT_MIN_LENGTH
# endif
# ifndef AUTOCORRECTION_MAX_LENGTH
# define AUTOCORRECTION_MAX_LENGTH AUTOCORRECT_MAX_LENGTH
# endif
# define autocorrection_data autocorrect_data
# if AUTOCORRECTION_MIN_LENGTH < 4
# error Minimum Length is too short and may cause overflows
# endif
@ -17,6 +24,138 @@
# error Dictionary size excees maximum size permitted
# endif
static uint8_t typo_buffer[AUTOCORRECT_MAX_LENGTH] = {KC_SPC};
static uint8_t typo_buffer_size = 1;
/**
* @brief function for querying the enabled state of autocorrect
*
* @return true if enabled
* @return false if disabled
*/
bool autocorrect_is_enabled(void) {
return userspace_config.autocorrection;
}
/**
* @brief Enables autocorrect and saves state to eeprom
*
*/
void autocorrect_enable(void) {
userspace_config.autocorrection = true;
eeconfig_update_user(userspace_config.raw);
}
/**
* @brief Disables autocorrect and saves state to eeprom
*
*/
void autocorrect_disable(void) {
userspace_config.autocorrection = false;
typo_buffer_size = 0;
eeconfig_update_user(userspace_config.raw);
}
/**
* @brief Toggles autocorrect's status and save state to eeprom
*
*/
void autocorrect_toggle(void) {
userspace_config.autocorrection = !userspace_config.autocorrection;
typo_buffer_size = 0;
eeconfig_update_user(userspace_config.raw);
}
/**
* @brief handler for determining if autocorrect should process keypress
*
* @param keycode Keycode registered by matrix press, per keymap
* @param record keyrecord_t structure
* @param typo_buffer_size passed along to allow resetting of autocorrect buffer
* @param mods allow processing of mod status
* @return true Allow autocorection
* @return false Stop processing and escape from autocorrect.
*/
__attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) {
// See quantum_keycodes.h for reference on these matched ranges.
switch (*keycode) {
// Exclude these keycodes from processing.
case KC_LSFT:
case KC_RSFT:
case KC_CAPS:
case QK_TO ... QK_ONE_SHOT_LAYER_MAX:
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_MOD_MAX:
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
return false;
// Mask for base keycode from shifted keys.
case QK_LSFT ... QK_LSFT + 255:
case QK_RSFT ... QK_RSFT + 255:
if (*keycode >= QK_LSFT && *keycode <= (QK_LSFT + 255)) {
*mods |= MOD_LSFT;
} else {
*mods |= MOD_RSFT;
}
*keycode &= 0xFF; // Get the basic keycode.
return true;
#ifndef NO_ACTION_TAPPING
// Exclude tap-hold keys when they are held down
// and mask for base keycode when they are tapped.
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
# ifdef NO_ACTION_LAYER
// Exclude Layer Tap, if layers are disabled
// but action tapping is still enabled.
return false;
# endif
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
// Exclude hold keycode
if (!record->tap.count) {
return false;
}
*keycode &= 0xFF;
break;
#else
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
// Exclude if disabled
return false;
#endif
// Exclude swap hands keys when they are held down
// and mask for base keycode when they are tapped.
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
#ifdef SWAP_HANDS_ENABLE
if (*keycode >= 0x56F0 || !record->tap.count) {
return false;
}
*keycode &= 0xFF;
break;
#else
// Exclude if disabled
return false;
#endif
}
// Disable autocorrect while a mod other than shift is active.
if ((*mods & ~MOD_MASK_SHIFT) != 0) {
*typo_buffer_size = 0;
return false;
}
return true;
}
/**
* @brief handling for when autocorrection has been triggered
*
* @param backspaces number of characters to remove
* @param str pointer to PROGMEM string to replace mistyped seletion with
* @return true apply correction
* @return false user handled replacement
*/
__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) {
return true;
}
/**
* @brief Process handler for autocorrect feature
*
@ -25,131 +164,124 @@
* @return true Continue processing keycodes, and send to host
* @return false Stop processing keycodes, and don't send to host
*/
bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {KC_SPC};
static uint8_t typo_buffer_size = 1;
bool process_autocorrection(uint16_t keycode, keyrecord_t *record) {
uint8_t mods = get_mods();
#ifndef NO_ACTION_ONESHOT
mods |= get_oneshot_mods();
#endif
if (keycode == AUTO_CTN) {
if (record->event.pressed) {
typo_buffer_size = 0;
userspace_config.autocorrection ^= 1;
eeconfig_update_user(userspace_config.raw);
if ((keycode >= AUTOCORRECT_ON && keycode <= AUTOCORRECT_TOGGLE) && record->event.pressed) {
if (keycode == AUTOCORRECT_ON) {
autocorrect_enable();
} else if (keycode == AUTOCORRECT_OFF) {
autocorrect_disable();
} else if (keycode == AUTOCORRECT_TOGGLE) {
autocorrect_toggle();
} else {
return true;
}
return false;
}
if (!userspace_config.autocorrection) {
if (!autocorrect_is_enabled()) {
typo_buffer_size = 0;
return true;
}
switch (keycode) {
case KC_LSFT:
case KC_RSFT:
return true;
# ifndef NO_ACTION_TAPPING
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
if (((keycode >> 8) & 0xF) == MOD_LSFT) {
return true;
}
# ifndef NO_ACTION_LAYER
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
# endif
if (record->event.pressed || !record->tap.count) {
return true;
}
keycode &= 0xFF;
break;
# endif
# ifdef SWAP_HANDS_ENABLE
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
if (keycode >= 0x56F0 || record->event.pressed || !record->tap.count) {
return true;
}
keycode &= 0xFF;
break;
# endif
# ifndef NO_ACTION_ONESHOT
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
if ((keycode & 0xF) == MOD_LSFT) {
return true;
}
# endif
default:
// Disable autocorrection while a mod other than shift is active.
if (((get_mods() | get_oneshot_mods()) & ~MOD_MASK_SHIFT) != 0) {
typo_buffer_size = 0;
return true;
}
if (!record->event.pressed) {
return true;
}
if (!record->event.pressed) {
return true;
}
// Subtract buffer for Backspace key, reset for other non-alpha.
if (!(KC_A <= keycode && keycode <= KC_Z)) {
if (keycode == KC_BSPC) {
// autocorrect keycode verification and extraction
if (!process_autocorrect_user(&keycode, record, &typo_buffer_size, &mods)) {
return true;
}
// keycode buffer check
switch (keycode) {
case KC_A ... KC_Z:
// process normally
break;
case KC_1 ... KC_0:
case KC_TAB ... KC_SEMICOLON:
case KC_GRAVE ... KC_SLASH:
// Set a word boundary if space, period, digit, etc. is pressed.
keycode = KC_SPC;
break;
case KC_ENTER:
// Behave more conservatively for the enter key. Reset, so that enter
// can't be used on a word ending.
typo_buffer_size = 0;
keycode = KC_SPC;
break;
case KC_BSPC:
// Remove last character from the buffer.
if (typo_buffer_size > 0) {
--typo_buffer_size;
}
return true;
} else if (KC_1 <= keycode && keycode <= KC_SLSH && keycode != KC_ESC) {
// Set a word boundary if space, period, digit, etc. is pressed.
// Behave more conservatively for the enter key. Reset, so that enter
// can't be used on a word ending.
if (keycode == KC_ENT || (keycode == KC_MINUS && (get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT)) {
typo_buffer_size = 0;
case KC_QUOTE:
// Treat " (shifted ') as a word boundary.
if ((mods & MOD_MASK_SHIFT) != 0) {
keycode = KC_SPC;
}
keycode = KC_SPC;
} else {
break;
default:
// Clear state if some other non-alpha key is pressed.
typo_buffer_size = 0;
return true;
}
}
// Rotate oldest character if buffer is full.
if (typo_buffer_size >= AUTOCORRECTION_MAX_LENGTH) {
memmove(typo_buffer, typo_buffer + 1, AUTOCORRECTION_MAX_LENGTH - 1);
typo_buffer_size = AUTOCORRECTION_MAX_LENGTH - 1;
if (typo_buffer_size >= AUTOCORRECT_MAX_LENGTH) {
memmove(typo_buffer, typo_buffer + 1, AUTOCORRECT_MAX_LENGTH - 1);
typo_buffer_size = AUTOCORRECT_MAX_LENGTH - 1;
}
// Append `keycode` to buffer.
typo_buffer[typo_buffer_size++] = keycode;
// Return if buffer is smaller than the shortest word.
if (typo_buffer_size < AUTOCORRECTION_MIN_LENGTH) {
if (typo_buffer_size < AUTOCORRECT_MIN_LENGTH) {
return true;
}
// Check for typo in buffer using a trie stored in `autocorrection_data`.
// Check for typo in buffer using a trie stored in `autocorrect_data`.
uint16_t state = 0;
uint8_t code = pgm_read_byte(autocorrection_data + state);
for (uint8_t i = typo_buffer_size - 1; i >= 0; --i) {
uint8_t code = pgm_read_byte(autocorrect_data + state);
for (int8_t i = typo_buffer_size - 1; i >= 0; --i) {
uint8_t const key_i = typo_buffer[i];
if (code & 64) { // Check for match in node with multiple children.
if (code & 64) { // Check for match in node with multiple children.
code &= 63;
for (; code != key_i; code = pgm_read_byte(autocorrection_data + (state += 3))) {
for (; code != key_i; code = pgm_read_byte(autocorrect_data + (state += 3))) {
if (!code) return true;
}
// Follow link to child node.
state = (pgm_read_byte(autocorrection_data + state + 1) | pgm_read_byte(autocorrection_data + state + 2) << 8);
state = (pgm_read_byte(autocorrect_data + state + 1) | pgm_read_byte(autocorrect_data + state + 2) << 8);
// Check for match in node with single child.
} else if (code != key_i) {
return true;
} else if (!(code = pgm_read_byte(autocorrection_data + (++state)))) {
} else if (!(code = pgm_read_byte(autocorrect_data + (++state)))) {
++state;
}
code = pgm_read_byte(autocorrection_data + state);
// Stop if `state` becomes an invalid index. This should not normally
// happen, it is a safeguard in case of a bug, data corruption, etc.
if (state >= DICTIONARY_SIZE) {
return true;
}
if (code & 128) { // A typo was found! Apply autocorrection.
const uint8_t backspaces = code & 63;
for (uint8_t i = 0; i < backspaces; ++i) {
tap_code(KC_BSPC);
code = pgm_read_byte(autocorrect_data + state);
if (code & 128) { // A typo was found! Apply autocorrect.
const uint8_t backspaces = (code & 63) + !record->event.pressed;
if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) {
for (uint8_t i = 0; i < backspaces; ++i) {
tap_code(KC_BSPC);
}
send_string_P((char const *)(autocorrect_data + state + 1));
}
send_string_P((char const*)(autocorrection_data + state + 1));
if (keycode == KC_SPC) {
typo_buffer[0] = KC_SPC;
@ -166,5 +298,7 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
# pragma GCC pop_options
#else
# pragma message "Warning!!! Autocorrect is not corretly setup!"
bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { return true; }
bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
return true;
}
#endif

View File

@ -7,4 +7,11 @@
#include "drashna.h"
bool process_autocorrection(uint16_t keycode, keyrecord_t* record);
bool process_autocorrection(uint16_t keycode, keyrecord_t *record);
bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods);
bool apply_autocorrect(uint8_t backspaces, const char *str);
bool autocorrect_is_enabled(void);
void autocorrect_enable(void);
void autocorrect_disable(void);
void autocorrect_toggle(void);

View File

@ -1,4 +1,4 @@
# Copyright 2021 Google LLC
# Copyright 2021-2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -29,6 +29,7 @@ Each line of the dict file defines one typo and its correction with the syntax
Example:
:thier -> their
dosen't -> doesn't
fitler -> filter
lenght -> length
ouput -> output
@ -42,7 +43,7 @@ https://getreuer.info/posts/keyboards/autocorrection
import sys
import textwrap
from typing import Any, Dict, List, Tuple
from typing import Any, Dict, Iterator, List, Tuple
try:
from english_words import english_words_lower_alpha_set as CORRECT_WORDS
@ -51,85 +52,67 @@ except ImportError:
'correctly spelled word. To check for this, install the english_words '
'package and rerun this script:\n\n pip install english_words\n')
# Use a minimal word list as a fallback.
CORRECT_WORDS = ('information', 'available', 'international', 'language',
'loosest', 'reference', 'wealthier', 'entertainment',
'association', 'provides', 'technology', 'statehood')
CORRECT_WORDS = ('apparent', 'association', 'available', 'classification',
'effect', 'entertainment', 'fantastic', 'information',
'integrate', 'international', 'language', 'loosest',
'manual', 'nothing', 'provides', 'reference', 'statehood',
'technology', 'virtually', 'wealthier', 'wonderful')
KC_A = 4
KC_SPC = 0x2c
KC_QUOT = 0x34
TYPO_CHARS = dict(
[
("'", KC_QUOT),
(':', KC_SPC), # "Word break" character.
] +
# Characters a-z.
[(chr(c), c + KC_A - ord('a')) for c in range(ord('a'), ord('z') + 1)]
)
def parse_file(file_name: str) -> List[Tuple[str, str]]:
"""Parses autocorrections dictionary file.
Each line of the file defines one typo and its correction with the syntax
"typo -> correction". Blank lines or lines starting with '#' are ignored. The
function validates that typos only have characters a-z and that typos are not
substrings of other typos, otherwise the longer typo would never trigger.
function validates that typos only have characters in TYPO_CHARS, that
typos are not substrings of other typos, and checking that typos don't trigger
on CORRECT_WORDS.
Args:
file_name: String, path of the autocorrections dictionary.
Returns:
List of (typo, correction) tuples.
"""
correct_words = ('information', 'available', 'international', 'language', 'loosest', 'reference', 'wealthier', 'entertainment', 'association', 'provides', 'technology', 'statehood')
autocorrections = []
typos = set()
line_number = 0
for line in open(file_name, 'rt'):
line_number += 1
line = line.strip()
if line and line[0] != '#':
# Parse syntax "typo -> correction", using strip to ignore indenting.
tokens = [token.strip() for token in line.split('->', 1)]
if len(tokens) != 2 or not tokens[0]:
print(f'Error:{line_number}: Invalid syntax: "{line}"')
for line_number, typo, correction in parse_file_lines(file_name):
if typo in typos:
print(f'Warning:{line_number}: Ignoring duplicate typo: "{typo}"')
continue
# Check that `typo` is valid.
if not(all([c in TYPO_CHARS for c in typo])):
print(f'Error:{line_number}: Typo "{typo}" has '
'characters other than ' + ''.join(TYPO_CHARS.keys()))
sys.exit(1)
for other_typo in typos:
if typo in other_typo or other_typo in typo:
print(f'Error:{line_number}: Typos may not be substrings of one '
f'another, otherwise the longer typo would never trigger: '
f'"{typo}" vs. "{other_typo}".')
sys.exit(1)
if len(typo) < 5:
print(f'Warning:{line_number}: It is suggested that typos are at '
f'least 5 characters long to avoid false triggers: "{typo}"')
typo, correction = tokens
typo = typo.lower() # Force typos to lowercase.
typo = typo.replace(' ', ':')
check_typo_against_dictionary(typo, line_number, correct_words)
if typo in typos:
print(f'Warning:{line_number}: Ignoring duplicate typo: "{typo}"')
continue
# Check that `typo` is valid.
if not(all([ord('a') <= ord(c) <= ord('z') or c == ':' for c in typo])):
print(f'Error:{line_number}: Typo "{typo}" has '
'characters other than a-z and :.')
sys.exit(1)
for other_typo in typos:
if typo in other_typo or other_typo in typo:
print(f'Error:{line_number}: Typos may not be substrings of one '
f'another, otherwise the longer typo would never trigger: '
f'"{typo}" vs. "{other_typo}".')
sys.exit(1)
if len(typo) < 5:
print(f'Warning:{line_number}: It is suggested that typos are at '
f'least 5 characters long to avoid false triggers: "{typo}"')
if typo.startswith(':') and typo.endswith(':'):
if typo[1:-1] in CORRECT_WORDS:
print(f'Warning:{line_number}: Typo "{typo}" is a correctly spelled '
'dictionary word.')
elif typo.startswith(':') and not typo.endswith(':'):
for word in CORRECT_WORDS:
if word.startswith(typo[1:]):
print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
f'on correctly spelled word "{word}".')
elif not typo.startswith(':') and typo.endswith(':'):
for word in CORRECT_WORDS:
if word.endswith(typo[:-1]):
print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
f'on correctly spelled word "{word}".')
elif not typo.startswith(':') and not typo.endswith(':'):
for word in CORRECT_WORDS:
if typo in word:
print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
f'on correctly spelled word "{word}".')
autocorrections.append((typo, correction))
typos.add(typo)
autocorrections.append((typo, correction))
typos.add(typo)
return autocorrections
@ -152,6 +135,47 @@ def make_trie(autocorrections: List[Tuple[str, str]]) -> Dict[str, Any]:
return trie
def parse_file_lines(file_name: str) -> Iterator[Tuple[int, str, str]]:
"""Parses lines read from `file_name` into typo-correction pairs."""
line_number = 0
for line in open(file_name, 'rt'):
line_number += 1
line = line.strip()
if line and line[0] != '#':
# Parse syntax "typo -> correction", using strip to ignore indenting.
tokens = [token.strip() for token in line.split('->', 1)]
if len(tokens) != 2 or not tokens[0]:
print(f'Error:{line_number}: Invalid syntax: "{line}"')
sys.exit(1)
typo, correction = tokens
typo = typo.lower() # Force typos to lowercase.
typo = typo.replace(' ', ':')
yield line_number, typo, correction
def check_typo_against_dictionary(typo: str, line_number: int, correct_words) -> None:
"""Checks `typo` against English dictionary words."""
if typo.startswith(':') and typo.endswith(':'):
if typo[1:-1] in correct_words:
print(f'Warning:{line_number}: Typo "{typo}" is a correctly spelled dictionary word.')
elif typo.startswith(':') and not typo.endswith(':'):
for word in correct_words:
if word.startswith(typo[1:]):
print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger on correctly spelled word "{word}".')
elif not typo.startswith(':') and typo.endswith(':'):
for word in correct_words:
if word.endswith(typo[:-1]):
print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger on correctly spelled word "{word}".')
elif not typo.startswith(':') and not typo.endswith(':'):
for word in correct_words:
if typo in word:
print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger on correctly spelled word "{word}".')
def serialize_trie(autocorrections: List[Tuple[str, str]],
trie: Dict[str, Any]) -> List[int]:
"""Serializes trie and correction data in a form readable by the C code.
@ -165,7 +189,7 @@ def serialize_trie(autocorrections: List[Tuple[str, str]],
table = []
# Traverse trie in depth first order.
def traverse(trie_node):
def traverse(trie_node: Dict[str, Any]) -> Dict[str, Any]:
if 'LEAF' in trie_node: # Handle a leaf trie node.
typo, correction = trie_node['LEAF']
word_boundary_ending = typo[-1] == ':'
@ -200,37 +224,35 @@ def serialize_trie(autocorrections: List[Tuple[str, str]],
traverse(trie)
def serialize(e):
def kc_code(c):
if ord('a') <= ord(c) <= ord('z'):
return ord(c) - ord('a') + KC_A
elif c == ':':
return KC_SPC
else:
raise ValueError(f'Invalid character: {c}')
encode_link = lambda link: [link['byte_offset'] & 255,
link['byte_offset'] >> 8]
def serialize(e: Dict[str, Any]) -> List[int]:
if not e['links']: # Handle a leaf table entry.
return e['data']
elif len(e['links']) == 1: # Handle a chain table entry.
return list(map(kc_code, e['chars'])) + [0] #+ encode_link(e['links'][0]))
return [TYPO_CHARS[c] for c in e['chars']] + [0]
else: # Handle a branch table entry.
data = []
for c, link in zip(e['chars'], e['links']):
data += [kc_code(c) | (0 if data else 64)] + encode_link(link)
data += [TYPO_CHARS[c] | (0 if data else 64)] + encode_link(link)
return data + [0]
byte_offset = 0
for e in table: # To encode links, first compute byte offset of each entry.
e['byte_offset'] = byte_offset
byte_offset += len(serialize(e))
assert 0 <= byte_offset <= 0xffff
return [b for e in table for b in serialize(e)] # Serialize final table.
def encode_link(link: Dict[str, Any]) -> List[int]:
"""Encodes a node link as two bytes."""
byte_offset = link['byte_offset']
if not (0 <= byte_offset <= 0xffff):
print('Error: The autocorrection table is too large, a node link exceeds '
'64KB limit. Try reducing the autocorrection dict to fewer entries.')
sys.exit(1)
return [byte_offset & 255, byte_offset >> 8]
def write_generated_code(autocorrections: List[Tuple[str, str]],
data: List[int],
file_name: str) -> None:
@ -242,7 +264,10 @@ def write_generated_code(autocorrections: List[Tuple[str, str]],
file_name: String, path of the output C file.
"""
assert all(0 <= b <= 255 for b in data)
typo_len = lambda e: len(e[0])
def typo_len(e: Tuple[str, str]) -> int:
return len(e[0])
min_typo = min(autocorrections, key=typo_len)[0]
max_typo = max(autocorrections, key=typo_len)[0]
generated_code = ''.join([
@ -252,9 +277,8 @@ def write_generated_code(autocorrections: List[Tuple[str, str]],
for typo, correction in autocorrections)),
f'\n#define AUTOCORRECTION_MIN_LENGTH {len(min_typo)} // "{min_typo}"\n',
f'#define AUTOCORRECTION_MAX_LENGTH {len(max_typo)} // "{max_typo}"\n\n',
f'#define DICTIONARY_SIZE {len(data)}\n\n',
textwrap.fill('static const uint8_t autocorrection_data[DICTIONARY_SIZE] PROGMEM = {%s};' % (
', '.join(map(str, data))), width=120, subsequent_indent=' '),
textwrap.fill('static const uint8_t autocorrection_data[%d] PROGMEM = {%s};' % (
len(data), ', '.join(map(str, data))), width=80, subsequent_indent=' '),
'\n\n'])
with open(file_name, 'wt') as f:

View File

@ -1,139 +0,0 @@
#include "caps_word.h"
static bool caps_word_active = false;
#if CAPS_WORD_IDLE_TIMEOUT > 0
# if CAPS_WORD_IDLE_TIMEOUT < 100 || CAPS_WORD_IDLE_TIMEOUT > 30000
// Constrain timeout to a sensible range. With the 16-bit timer, the longest
// representable timeout is 32768 ms, rounded here to 30000 ms = half a minute.
# error "caps_word: CAPS_WORD_IDLE_TIMEOUT must be between 100 and 30000 ms"
# endif
static uint16_t idle_timer = 0;
void caps_word_task(void) {
if (caps_word_active && timer_expired(timer_read(), idle_timer)) {
caps_word_set(false);
}
}
#endif // CAPS_WORD_IDLE_TIMEOUT > 0
bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
#ifndef NO_ACTION_ONESHOT
const uint8_t mods = get_mods() | get_oneshot_mods();
#else
const uint8_t mods = get_mods();
#endif // NO_ACTION_ONESHOT
if (!caps_word_active) {
// Pressing both shift keys at the same time enables caps word.
if ((mods & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) {
caps_word_set(true); // Activate Caps Word.
return false;
}
return true;
} else {
#if CAPS_WORD_IDLE_TIMEOUT > 0
idle_timer = record->event.time + CAPS_WORD_IDLE_TIMEOUT;
#endif // CAPS_WORD_IDLE_TIMEOUT > 0
}
if (!record->event.pressed) {
return true;
}
if (!(mods & ~MOD_MASK_SHIFT)) {
switch (keycode) {
// Ignore MO, TO, TG, TT, and OSL layer switch keys.
case QK_MOMENTARY ... QK_MOMENTARY_MAX:
case QK_TO ... QK_TO_MAX:
case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
return true;
#ifndef NO_ACTION_TAPPING
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
if (record->tap.count == 0) {
// Deactivate if a mod becomes active through holding a mod-tap key.
caps_word_set(false);
return true;
}
keycode &= 0xff;
break;
# ifndef NO_ACTION_LAYER
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
# endif // NO_ACTION_LAYER
if (record->tap.count == 0) {
return true;
}
keycode &= 0xff;
break;
#endif // NO_ACTION_TAPPING
#ifdef SWAP_HANDS_ENABLE
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
if (keycode > 0x56F0 || record->tap.count == 0) {
return true;
}
keycode &= 0xff;
break;
#endif // SWAP_HANDS_ENABLE
}
if (caps_word_press_user(keycode)) {
return true;
}
}
caps_word_set(false); // Deactivate Caps Word.
return true;
}
void caps_word_set(bool active) {
if (active != caps_word_active) {
if (active) {
clear_mods();
#ifndef NO_ACTION_ONESHOT
clear_oneshot_mods();
#endif // NO_ACTION_ONESHOT
#if CAPS_WORD_IDLE_TIMEOUT > 0
idle_timer = timer_read() + CAPS_WORD_IDLE_TIMEOUT;
#endif // CAPS_WORD_IDLE_TIMEOUT > 0
} else if ((get_weak_mods() & MOD_BIT(KC_LSFT)) != 0) {
// If the weak shift mod is still on, turn it off and send an update to
// the host computer.
del_weak_mods(MOD_BIT(KC_LSFT));
send_keyboard_report();
}
caps_word_active = active;
caps_word_set_user(active);
}
}
bool caps_word_get(void) {
return caps_word_active;
}
__attribute__((weak)) void caps_word_set_user(bool active) {}
__attribute__((weak)) bool caps_word_press_user(uint16_t keycode) {
switch (keycode) {
// Keycodes that continue Caps Word, with shift applied.
case KC_A ... KC_Z:
add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to the next key.
return true;
// Keycodes that continue Caps Word, without shifting.
case KC_1 ... KC_0:
case KC_BSPC:
case KC_MINS:
case KC_UNDS:
return true;
default:
return false; // Deactivate Caps Word.
}
}

View File

@ -1,85 +0,0 @@
// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "drashna.h"
// Call this function from `process_record_user()` to implement Caps Word.
bool process_caps_word(uint16_t keycode, keyrecord_t* record);
// If CAPS_WORD_IDLE_TIMEOUT is set, call `caps_word_task()` from
// `matrix_scan_user()` as described above.
//
// If CAPS_WORD_IDLE_TIMEOUT isn't set, calling this function has no effect (but
// will still compile).
#if CAPS_WORD_IDLE_TIMEOUT > 0
void caps_word_task(void);
#else
static inline void caps_word_task(void) {}
#endif
// Activates or deactivates Caps Word. For instance activate Caps Word with a
// combo by defining a `COMBO_ACTION` that calls `caps_word_set(true)`:
//
// void process_combo_event(uint16_t combo_index, bool pressed) {
// switch(combo_index) {
// case CAPS_COMBO:
// if (pressed) {
// caps_word_set(true); // Activate Caps Word.
// }
// break;
//
// // Other combos...
// }
// }
void caps_word_set(bool active);
// Returns whether Caps Word is currently active.
bool caps_word_get(void);
// An optional callback that gets called when Caps Word turns on or off. This is
// useful to represent the current Caps Word state, e.g. by setting an LED or
// playing a sound. In your keymap, define
//
// void caps_word_set_user(bool active) {
// if (active) {
// // Do something when Caps Word activates.
// } else {
// // Do something when Caps Word deactivates.
// }
// }
void caps_word_set_user(bool active);
// An optional callback which is called on every key press while Caps Word is
// active. When the key should be shifted (that is, a letter key), the callback
// should call `add_weak_mods(MOD_BIT(KC_LSFT))` to shift the key. The callback
// also determines whether the key should continue Caps Word. Returning true
// continues the current "word", while returning false is "word breaking" and
// deactivates Caps Word. The default callback is
//
// bool caps_word_press_user(uint16_t keycode) {
// switch (keycode) {
// // Keycodes that continue Caps Word, with shift applied.
// case KC_A ... KC_Z:
// add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to the next key.
// return true;
//
// // Keycodes that continue Caps Word, without shifting.
// case KC_1 ... KC_0:
// case KC_BSPC:
// case KC_MINS:
// case KC_UNDS:
// return true;
//
// default:
// return false; // Deactivate Caps Word.
// }
// }
//
// To customize, copy the above function into your keymap and add/remove
// keycodes to the above cases.
//
// NOTE: Outside of this callback, you can use `caps_word_set(false)` to
// deactivate Caps Word.
bool caps_word_press_user(uint16_t keycode);

View File

@ -5,14 +5,9 @@ Keycodes are defined in the `process_record.h` file and need to be included in t
A bunch of macros are present and are only included on boards that are not the Ergodox EZ or Orthodox, as they are not needed for those boards.
* `KC_MAKE` - outputs `qmk compile -kb (keyboard) -km (keymap)` and enter, to start compiling the currenct keyboard. This uses generated variables to always use the current keyboard and keymap. Will work with any keyboard and any keymap.
* If you are holding shift, it will use `qmk flash` instead of `qmk compile`.
* If `MAKE_BOOTLOADER` is defined, it will always use `qmk flash` instead of `qmk compile`.
* `DEFAULT_LAYER_1` ... `DEFAULT_LAYER_4` - This sets layer 0-3 as the default layer, and writes that to eeprom, and plays a chime.
* `VRSN`, outputs the keyboard, keymap, commit and date info. Eg:
* `handwired/tractyl_manuform/5x6_right/f411/drashna @ 0.15.9-162-g087d08, Built on: 2021-12-19-21:10:26`
* `KC_DIABLO_CLEAR` - clears the diablo tapdance status.
* `KC_CCCV` - Copy on hold, paste on tap.
* `KEYLOCK` - This unloads the host driver, and prevents any data from being sent to the host. Hitting it again loads the driver, back.
* `REBOOT` - Uses watchdog timer on AVR, and `NVIC_SystemReset()` on ChibiOS to reset the board, without jumping to the bootloader.
* `EEP_RST` - Overrides the default behavior, disables EEPROM (which will trigger a reset on init), and reboots the keyboard as per `REBOOT` keycode.

View File

@ -3,9 +3,6 @@
#include "drashna.h"
#include "version.h"
#ifdef CAPS_WORD_ENABLE
# include "caps_word.h"
#endif
#ifdef AUTOCORRECTION_ENABLE
# include "autocorrection/autocorrection.h"
#endif
@ -37,6 +34,15 @@ __attribute__((weak)) bool process_record_secrets(uint16_t keycode, keyrecord_t
* @return false Stop process keycode and do not send to host
*/
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#ifdef ENCODER_ENABLE // some debouncing for weird issues
if (IS_ENCODEREVENT(record->event)) {
static bool ignore_first = true;
if (ignore_first) {
ignore_first = false;
return false;
}
}
#endif
// If console is enabled, it will print the matrix position and status of each key pressed
#ifdef KEYLOGGER_ENABLE
uprintf("KL: kc: 0x%04X, col: %2u, row: %2u, pressed: %b, time: %5u, int: %b, count: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed, record->event.time, record->tap.interrupted, record->tap.count);
@ -58,9 +64,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
#if defined(CUSTOM_POINTING_DEVICE)
&& process_record_pointing(keycode, record)
#endif
#ifdef CAPS_WORD_ENABLE
&& process_caps_word(keycode, record)
#endif
#ifdef AUTOCORRECTION_ENABLE
&& process_autocorrection(keycode, record)
#endif
@ -87,33 +90,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
break;
case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader
if (!record->event.pressed) {
#ifndef MAKE_BOOTLOADER
uint8_t temp_mod = mod_config(get_mods());
uint8_t temp_osm = mod_config(get_oneshot_mods());
clear_mods();
clear_oneshot_mods();
#endif
send_string_with_delay_P(PSTR("qmk"), TAP_CODE_DELAY);
#ifndef MAKE_BOOTLOADER
if ((temp_mod | temp_osm) & MOD_MASK_SHIFT)
#endif
{
send_string_with_delay_P(PSTR(" flash "), TAP_CODE_DELAY);
#ifndef MAKE_BOOTLOADER
} else {
send_string_with_delay_P(PSTR(" compile "), TAP_CODE_DELAY);
#endif
}
send_string_with_delay_P(PSTR("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP), TAP_CODE_DELAY);
#ifdef CONVERT_TO_PROTON_C
send_string_with_delay_P(PSTR(" -e CTPC=yes"), TAP_CODE_DELAY);
#endif
send_string_with_delay_P(PSTR(SS_TAP(X_ENTER)), TAP_CODE_DELAY);
}
break;
case VRSN: // Prints firmware version
if (record->event.pressed) {
send_string_with_delay_P(PSTR(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE), TAP_CODE_DELAY);
@ -148,13 +124,19 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
dprintf("rgblight layer change [EEPROM]: %u\n", userspace_config.rgb_layer_change);
eeconfig_update_user(userspace_config.raw);
if (userspace_config.rgb_layer_change) {
# if defined(CUSTOM_RGBLIGHT) && defined(CUSTOM_RGB_MATRIX)
# if defined(CUSTOM_RGB_MATRIX)
rgb_matrix_set_flags(LED_FLAG_UNDERGLOW | LED_FLAG_KEYLIGHT | LED_FLAG_INDICATOR);
# if defined(CUSTOM_RGBLIGHT)
rgblight_enable_noeeprom();
# endif
# endif
layer_state_set(layer_state); // This is needed to immediately set the layer color (looks better)
# if defined(CUSTOM_RGBLIGHT) && defined(CUSTOM_RGB_MATRIX)
layer_state_set(layer_state); // This is needed to immediately set the layer color (looks better)
# if defined(CUSTOM_RGB_MATRIX)
} else {
rgb_matrix_set_flags(LED_FLAG_ALL);
# if defined(CUSTOM_RGBLIGHT)
rgblight_disable_noeeprom();
# endif
# endif
}
}
@ -218,23 +200,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
}
break;
}
case EEP_RST:
if (record->event.pressed) {
eeconfig_disable();
shutdown_user();
#ifdef __AVR__
wdt_enable(WDTO_250MS);
#else
NVIC_SystemReset();
#endif
}
return false;
case REBOOT:
if (record->event.pressed) {
software_reset();
}
return false;
}
}
return true;
}

View File

@ -21,7 +21,6 @@ enum userspace_custom_keycodes {
KC_DVORAK, // Sets default layer to DVORAK
LAST_DEFAULT_LAYER_KEYCODE = KC_DVORAK, // Sets default layer to WORKMAN
KC_DIABLO_CLEAR, // Clears all Diablo Timers
KC_MAKE, // Run keyboard's customized make command
KC_RGB_T, // Toggles RGB Layer Indication mode
RGB_IDL, // RGB Idling animations
KC_SECRET_1, // test1
@ -46,8 +45,9 @@ enum userspace_custom_keycodes {
KC_AUSSIE,
KC_ZALGO,
KC_ACCEL,
AUTO_CTN, // Toggle Autocorrect status
REBOOT,
AUTOCORRECT_ON,
AUTOCORRECT_OFF,
AUTOCORRECT_TOGGLE,
NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes
};
@ -95,9 +95,6 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
# endif
#endif
#define KC_RESET RESET
#define KC_RST KC_RESET
#ifdef SWAP_HANDS_ENABLE
# define KC_C1R3 SH_T(KC_TAB)
#elif defined(DRASHNA_LP)
@ -130,7 +127,7 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
#define MG_NKRO MAGIC_TOGGLE_NKRO
#define AUTO_CTN AUTOCORRECT_TOGGLE
/*
Custom Keycodes for Diablo 3 layer
But since TD() doesn't work when tap dance is disabled

View File

@ -24,14 +24,12 @@ secrets.h
Here is the magic. This handles including the "secrets", and adding the custom macros to send them.
```c
#include "drashna.h" // replace with your keymap's "h" file, or whatever file stores the keycodes
#include QMK_KEYBOARD_H
#if (__has_include("secrets.h") && !defined(NO_SECRETS))
#include "secrets.h"
#else
// `PROGMEM const char secret[][x]` may work better, but it takes up more space in the firmware
// And I'm not familiar enough to know which is better or why...
static const char * const secret[] = {
static const char * const secrets[] = {
"test1",
"test2",
"test3",
@ -43,9 +41,10 @@ static const char * const secret[] = {
bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_SECRET_1 ... KC_SECRET_5: // Secrets! Externally defined strings, not stored in repo
if (!record->event.pressed) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
send_string_with_delay(secret[keycode - KC_SECRET_1], MACRO_TIMER);
if (record->event.pressed) {
clear_mods();
clear_oneshot_mods();
send_string_with_delay(secrets[keycode - KC_SECRET_1], MACRO_TIMER);
}
return false;
break;
@ -59,7 +58,7 @@ bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
Now, for the actual secrets! The file needs to look like
```c
static const char * secrets[] = {
static const char * secrets[] = {
"secret1",
"secret2",
"secret3",
@ -96,7 +95,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
Here, you want your `/users/<name>/rules.mk` file to "detect" the existence of the `secrets.c` file, and only add it if the file exists.
Additionally, to ensure that it's not added or processed in any way, it checks to see if `NO_SECRETS` is set. This way, if you run `make keyboard:name NO_SECRETS=yes`, it will remove the feature altogether.
Additionally, to ensure that it's not added or processed in any way, it checks to see if `NO_SECRETS` is set. This way, if you run `qmk compile -kb keyboard -km name -e NO_SECRETS=yes`, it will remove the feature altogether.
```make
ifneq ($(strip $(NO_SECRETS)), yes)

View File

@ -4,9 +4,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "drashna.h"
#include "unicode.h"
#include "process_unicode_common.h"
uint16_t typing_mode = KC_NOMODE;
uint8_t typing_mode = UCTM_NO_MODE;
/**
* @brief Registers the unicode keystrokes based on desired unicode
@ -242,10 +243,10 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
break;
case KC_NOMODE ... KC_ZALGO:
if (record->event.pressed) {
if (typing_mode != keycode) {
typing_mode = keycode;
if (typing_mode != keycode - KC_NOMODE) {
typing_mode = keycode - KC_NOMODE;
} else {
typing_mode = KC_NOMODE;
typing_mode = UCTM_NO_MODE;
}
}
break;
@ -259,19 +260,19 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
keycode &= 0xFF;
}
if (typing_mode == KC_WIDE) {
if (typing_mode == UCTM_WIDE) {
if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
return process_record_glyph_replacement(keycode, record, unicode_range_translator_wide);
}
} else if (typing_mode == KC_SCRIPT) {
} else if (typing_mode == UCTM_SCRIPT) {
if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
return process_record_glyph_replacement(keycode, record, unicode_range_translator_script);
}
} else if (typing_mode == KC_BLOCKS) {
} else if (typing_mode == UCTM_BLOCKS) {
if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
return process_record_glyph_replacement(keycode, record, unicode_range_translator_boxes);
}
} else if (typing_mode == KC_REGIONAL) {
} else if (typing_mode == UCTM_REGIONAL) {
if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
if (!process_record_glyph_replacement(keycode, record, unicode_range_translator_regional)) {
wait_us(500);
@ -279,9 +280,9 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
return false;
}
}
} else if (typing_mode == KC_AUSSIE) {
} else if (typing_mode == UCTM_AUSSIE) {
return process_record_aussie(keycode, record);
} else if (typing_mode == KC_ZALGO) {
} else if (typing_mode == UCTM_ZALGO) {
return process_record_zalgo(keycode, record);
}
return true;

View File

@ -0,0 +1,16 @@
// Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
enum unicode_typing_mode {
UCTM_NO_MODE,
UCTM_WIDE,
UCTM_SCRIPT,
UCTM_BLOCKS,
UCTM_REGIONAL,
UCTM_AUSSIE,
UCTM_ZALGO,
};
extern uint8_t typing_mode;

View File

@ -18,19 +18,23 @@
#include "drashna.h"
#ifdef UNICODE_COMMON_ENABLE
# include "process_unicode_common.h"
# include "keyrecords/unicode.h"
#endif
#ifdef AUDIO_CLICKY
# include "process_clicky.h"
#endif
#if defined(AUTOCORRECTION_ENABLE)
# include "keyrecords/autocorrection/autocorrection.h"
#endif
# ifdef AUDIO_CLICKY
# include "process_clicky.h"
# endif
#include <string.h>
extern bool host_driver_disabled;
uint32_t oled_timer = 0;
char keylog_str[OLED_KEYLOGGER_LENGTH] = {0};
static uint16_t log_timer = 0;
uint32_t oled_timer = 0;
char keylog_str[OLED_KEYLOGGER_LENGTH] = {0};
static uint16_t log_timer = 0;
#ifdef OLED_DISPLAY_VERBOSE
static const char PROGMEM display_border[3] = {0x0, 0xFF, 0x0};
static const char PROGMEM display_border[3] = {0x0, 0xFF, 0x0};
#endif
deferred_token kittoken;
@ -100,12 +104,15 @@ void add_keylog(uint16_t keycode, keyrecord_t *record) {
*/
bool process_record_user_oled(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
oled_timer = timer_read32();
oled_timer_reset();
add_keylog(keycode, record);
}
return true;
}
void oled_timer_reset(void) {
oled_timer = timer_read32();
}
/**
* @brief Renders keylogger buffer to oled
*
@ -262,9 +269,8 @@ void render_layer_state(void) {
}
};
// clang-format on
uint8_t layer_is[4] = { 0, 4, 4, 4};
uint8_t layer_is[4] = {0, 4, 4, 4};
if (layer_state_is(_ADJUST)) {
layer_is[0] = 3;
} else if (layer_state_is(_RAISE)) {
@ -280,7 +286,6 @@ void render_layer_state(void) {
layer_is[2] = 5;
}
oled_set_cursor(1, 2);
oled_write_raw_P(tri_layer_image[layer_is[0]][0], sizeof(tri_layer_image[0][0]));
oled_set_cursor(5, 2);
@ -322,7 +327,7 @@ void render_layer_state(void) {
*
* @param led_usb_state Current keyboard led state
*/
void render_keylock_status(uint8_t led_usb_state) {
void render_keylock_status(led_t led_usb_state) {
#if defined(OLED_DISPLAY_VERBOSE)
oled_set_cursor(1, 6);
#endif
@ -330,12 +335,12 @@ void render_keylock_status(uint8_t led_usb_state) {
#if !defined(OLED_DISPLAY_VERBOSE)
oled_write_P(PSTR(" "), false);
#endif
oled_write_P(PSTR(OLED_RENDER_LOCK_NUML), led_usb_state & (1 << USB_LED_NUM_LOCK));
oled_write_P(PSTR(OLED_RENDER_LOCK_NUML), led_usb_state.num_lock);
oled_write_P(PSTR(" "), false);
oled_write_P(PSTR(OLED_RENDER_LOCK_CAPS), led_usb_state & (1 << USB_LED_CAPS_LOCK));
oled_write_P(PSTR(OLED_RENDER_LOCK_CAPS), led_usb_state.caps_lock);
#if defined(OLED_DISPLAY_VERBOSE)
oled_write_P(PSTR(" "), false);
oled_write_P(PSTR(OLED_RENDER_LOCK_SCLK), led_usb_state & (1 << USB_LED_SCROLL_LOCK));
oled_write_P(PSTR(OLED_RENDER_LOCK_SCLK), led_usb_state.scroll_lock);
#endif
}
@ -417,15 +422,14 @@ void render_bootmagic_status(void) {
oled_write_P(logo[0][0], !is_bootmagic_on);
}
#ifndef OLED_DISPLAY_VERBOSE
oled_write_P(PSTR(" "), false);
oled_write_P(logo[1][1], is_bootmagic_on);
oled_write_P(logo[0][1], !is_bootmagic_on);
#endif
oled_write_P(PSTR(" "), false);
oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NKRO), keymap_config.nkro);
oled_write_P(PSTR(" "), false);
#ifdef AUTOCORRECTION_ENABLE
oled_write_P(PSTR("CRCT"), userspace_config.autocorrection);
#if defined(AUTOCORRECTION_ENABLE) || defined(AUTOCORRECT_ENABLE)
oled_write_P(PSTR("CRCT"), autocorrect_is_enabled());
oled_write_P(PSTR(" "), false);
#else
oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui);
@ -439,7 +443,7 @@ void render_bootmagic_status(void) {
}
#endif
oled_write_P(PSTR(" "), false);
oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_ONESHOT), !is_oneshot_enabled());
oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_ONESHOT), is_oneshot_enabled());
#ifdef SWAP_HANDS_ENABLE
oled_write_P(PSTR(" "), false);
oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_SWAP), swap_hands);
@ -461,7 +465,7 @@ void render_user_status(void) {
l_is_clicky_on = user_state.audio_clicky_enable;
# endif
# else
is_audio_on = is_audio_on();
is_audio_on = is_audio_on();
# ifdef AUDIO_CLICKY
l_is_clicky_on = is_clicky_on();
# endif
@ -501,7 +505,7 @@ void render_user_status(void) {
static const char PROGMEM cat_mode[2][3] = {{0xF8, 0xF9, 0}, {0xF6, 0xF7, 0}};
oled_write_P(cat_mode[0], host_driver_disabled);
#if defined(UNICODE_COMMON_ENABLE)
static const char PROGMEM uc_mod_status[5][3] = {{0xEC, 0xED, 0}, {0x20, 0x20, 0}, {0x20, 0x20, 0}, {0x20, 0x20, 0}, {0xEA, 0xEB, 0}};
static const char PROGMEM uc_mod_status[5][3] = {{0xEC, 0xED, 0}, {0x20, 0x20, 0}, {0x20, 0x20, 0}, {0x20, 0x20, 0}, {0xEA, 0xEB, 0}};
oled_write_P(uc_mod_status[get_unicode_input_mode()], false);
#endif
if (userspace_config.nuke_switch) {
@ -549,9 +553,9 @@ void render_wpm_graph(uint8_t max_lines_graph, uint8_t vertical_offset) {
uint8_t currwpm = get_current_wpm();
float max_wpm = OLED_WPM_GRAPH_MAX_WPM;
if (timer_elapsed(timer) > OLED_WPM_GRAPH_REFRESH_INTERVAL) { // check if it's been long enough before refreshing graph
x = (max_lines_graph - 1) - ((currwpm / max_wpm) * (max_lines_graph - 1)); // main calculation to plot graph line
for (uint8_t i = 0; i <= OLED_WPM_GRAPH_GRAPH_LINE_THICKNESS - 1; i++) { // first draw actual value line
if (timer_elapsed(timer) > OLED_WPM_GRAPH_REFRESH_INTERVAL) { // check if it's been long enough before refreshing graph
x = (max_lines_graph - 1) - ((currwpm / max_wpm) * (max_lines_graph - 1)); // main calculation to plot graph line
for (uint8_t i = 0; i <= OLED_WPM_GRAPH_GRAPH_LINE_THICKNESS - 1; i++) { // first draw actual value line
oled_write_pixel(3, x + i + vertical_offset, true);
}
# ifdef OLED_WPM_GRAPH_VERTICAL_LINE
@ -577,20 +581,11 @@ void render_wpm_graph(uint8_t max_lines_graph, uint8_t vertical_offset) {
}
}
# endif
oled_pan(false); // then move the entire graph one pixel to the right
static const char PROGMEM display_border[3] = {0x0, 0xFF, 0x0};
for (uint8_t i = 0; i < 7; i++) {
oled_set_cursor(0, i + 8);
oled_write_raw_P(display_border, sizeof(display_border));
oled_set_cursor(21, i + 8);
oled_write_raw_P(display_border, sizeof(display_border));
}
static const char PROGMEM footer_image[] = {0, 3, 4, 8, 16, 32, 64, 128, 128, 128, 128, 128, 128, 128, 192, 224, 240, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 240, 224, 192, 128, 128, 128, 128, 128, 128, 128, 64, 32, 16, 8, 4, 3, 0};
oled_set_cursor(0, 15);
oled_write_raw_P(footer_image, sizeof(footer_image));
timer = timer_read(); // refresh the timer for the next iteration
# include <math.h>
uint8_t y_start = ceil(vertical_offset / 8);
uint8_t y_length = y_start + ceil(max_lines_graph / 8);
oled_pan_section(false, y_start, y_length, 3, 125); // then move the entire graph one pixel to the right
timer = timer_read(); // refresh the timer for the next iteration
}
#endif
}
@ -617,13 +612,13 @@ __attribute__((weak)) void oled_driver_render_logo_right(void) {
// WPM-responsive animation stuff here
#define OLED_SLEEP_FRAMES 2
#define OLED_SLEEP_SPEED 10 // below this wpm value your animation will idle
#define OLED_SLEEP_SPEED 10 // below this wpm value your animation will idle
#define OLED_WAKE_FRAMES 2 // uncomment if >1
#define OLED_WAKE_SPEED OLED_SLEEP_SPEED // below this wpm value your animation will idle
#define OLED_WAKE_FRAMES 2 // uncomment if >1
#define OLED_WAKE_SPEED OLED_SLEEP_SPEED // below this wpm value your animation will idle
#define OLED_KAKI_FRAMES 3
#define OLED_KAKI_SPEED 40 // above this wpm value typing animation to triggere
#define OLED_KAKI_SPEED 40 // above this wpm value typing animation to triggere
#define OLED_RTOGI_FRAMES 2
//#define OLED_LTOGI_FRAMES 2
@ -781,25 +776,13 @@ void oled_driver_render_logo_left(void) {
# if (defined(KEYBOARD_bastardkb_charybdis) || defined(KEYBOARD_handwired_tractyl_manuform)) && defined(POINTING_DEVICE_ENABLE)
render_pointing_dpi_status(charybdis_get_pointer_sniping_enabled() ? charybdis_get_pointer_sniping_dpi() : charybdis_get_pointer_default_dpi(), 1);
// credit and thanks to jaspertandy on discord for these images
static const char PROGMEM mouse_logo[3][2][16] = {
// mouse icon
{
{ 0, 0, 0, 252, 2, 2, 2, 58, 2, 2, 2, 252, 0, 0, 0, 0 },
{ 0, 0, 63, 96, 64, 64, 64, 64, 64, 64, 64, 96, 63, 0, 0, 0 }
},
// crosshair icon
{
{ 128, 240, 136, 228, 146, 138, 202, 127, 202, 138, 146, 228, 136, 240, 128, 0 },
{ 0, 7, 8, 19, 36, 40, 41, 127, 41, 40, 36, 19, 8, 7, 0, 0 }
},
// dragscroll icon
{
{ 0, 0, 112, 136, 156, 2, 15, 1, 15, 2, 140, 68, 56, 0, 0, 0 },
{ 0, 0, 2, 6, 15, 28, 60, 124, 60, 28, 15, 6, 2, 0, 0, 0 }
}
};
// credit and thanks to jaspertandy on discord for these images
static const char PROGMEM mouse_logo[3][2][16] = {// mouse icon
{{0, 0, 0, 252, 2, 2, 2, 58, 2, 2, 2, 252, 0, 0, 0, 0}, {0, 0, 63, 96, 64, 64, 64, 64, 64, 64, 64, 96, 63, 0, 0, 0}},
// crosshair icon
{{128, 240, 136, 228, 146, 138, 202, 127, 202, 138, 146, 228, 136, 240, 128, 0}, {0, 7, 8, 19, 36, 40, 41, 127, 41, 40, 36, 19, 8, 7, 0, 0}},
// dragscroll icon
{{0, 0, 112, 136, 156, 2, 15, 1, 15, 2, 140, 68, 56, 0, 0, 0}, {0, 0, 2, 6, 15, 28, 60, 124, 60, 28, 15, 6, 2, 0, 0, 0}}};
uint8_t image_index = 0;
# ifdef OLED_DISPLAY_TEST
@ -847,7 +830,7 @@ void render_status_right(void) {
#if !defined(OLED_DISPLAY_VERBOSE) && defined(WPM_ENABLE) && !defined(CONVERT_TO_PROTON_C)
render_wpm(2);
#endif
render_keylock_status(host_keyboard_leds());
render_keylock_status(host_keyboard_led_state());
}
void render_status_left(void) {
@ -860,9 +843,11 @@ void render_status_left(void) {
render_keylogger_status();
}
__attribute__((weak)) void oled_render_large_display(void) {}
__attribute__((weak)) void oled_render_large_display(bool side) {}
__attribute__((weak)) oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return rotation; }
__attribute__((weak)) oled_rotation_t oled_init_keymap(oled_rotation_t rotation) {
return rotation;
}
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
if (is_keyboard_master()) {
@ -876,10 +861,11 @@ oled_rotation_t oled_init_user(oled_rotation_t rotation) {
return oled_init_keymap(rotation);
}
__attribute__((weak)) bool oled_task_keymap(void) { return true; }
__attribute__((weak)) bool oled_task_keymap(void) {
return true;
}
bool oled_task_user(void) {
if (is_keyboard_master()) {
#ifndef OLED_DISPLAY_TEST
if (timer_elapsed32(oled_timer) > 60000) {
@ -896,29 +882,29 @@ bool oled_task_user(void) {
return false;
}
#if defined(OLED_DISPLAY_128X128)
oled_set_cursor(0, 7);
oled_render_large_display();
#endif
#if defined(OLED_DISPLAY_VERBOSE)
static const char PROGMEM header_image[] = {
0, 192, 32, 16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 7, 15, 31, 63, 127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 63, 31, 15, 7, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 192, 0,
// 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0
};
static const char PROGMEM footer_image[] = {0, 3, 4, 8, 16, 32, 64, 128, 128, 128, 128, 128, 128, 128, 192, 224, 240, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 240, 224, 192, 128, 128, 128, 128, 128, 128, 128, 64, 32, 16, 8, 4, 3, 0};
oled_set_cursor(0, 0);
oled_write_raw_P(header_image, sizeof(header_image));
oled_set_cursor(0, 1);
#endif
#ifndef OLED_DISPLAY_TEST
if (is_keyboard_left()) {
#endif
render_status_left();
#if defined(OLED_DISPLAY_128X128)
oled_set_cursor(0, 7);
oled_render_large_display(true);
#endif
#ifndef OLED_DISPLAY_TEST
} else {
render_status_right();
# if defined(OLED_DISPLAY_128X128)
oled_set_cursor(0, 7);
oled_render_large_display(false);
# endif
}
#endif
@ -936,6 +922,7 @@ bool oled_task_user(void) {
oled_write_raw_P(display_border, sizeof(display_border));
}
static const char PROGMEM footer_image[] = {0, 3, 4, 8, 16, 32, 64, 128, 128, 128, 128, 128, 128, 128, 192, 224, 240, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 240, 224, 192, 128, 128, 128, 128, 128, 128, 128, 64, 32, 16, 8, 4, 3, 0};
oled_set_cursor(0, num_of_rows);
oled_write_raw_P(footer_image, sizeof(footer_image));
#endif

View File

@ -23,11 +23,11 @@ extern deferred_token kittoken;
void oled_driver_render_logo(void);
bool process_record_user_oled(uint16_t keycode, keyrecord_t *record);
oled_rotation_t oled_init_keymap(oled_rotation_t rotation);
extern uint32_t oled_timer;
void oled_timer_reset(void);
void render_keylogger_status(void);
void render_default_layer_state(void);
void render_layer_state(void);
void render_keylock_status(uint8_t led_usb_state);
void render_keylock_status(led_t led_usb_state);
void render_matrix_scan_rate(uint8_t padding);
void render_mod_status(uint8_t modifiers);
void render_bootmagic_status(void);
@ -37,9 +37,12 @@ void render_wpm(uint8_t padding);
void render_pointing_dpi_status(uint16_t cpi, uint8_t padding);
void oled_driver_render_logo_left(void);
void oled_driver_render_logo_right(void);
void oled_render_large_display(void);
void oled_render_large_display(bool side);
void render_wpm_graph(uint8_t max_lines_graph, uint8_t vertical_offset);
void oled_pan_section(bool left, uint16_t y_start, uint16_t y_end, uint16_t x_start, uint16_t x_end);
#if defined(OLED_DISPLAY_128X128) || defined(OLED_DISPLAY_128X64)
# define OLED_DISPLAY_VERBOSE

View File

@ -521,6 +521,25 @@ void oled_pan(bool left) {
oled_dirty = OLED_ALL_BLOCKS_MASK;
}
void oled_pan_section(bool left, uint16_t y_start, uint16_t y_end, uint16_t x_start, uint16_t x_end) {
uint16_t i = 0;
for (uint16_t y = y_start; y < y_end; y++) {
if (left) {
for (uint16_t x = x_start; x < x_end - 1; x++) {
i = y * OLED_DISPLAY_WIDTH + x;
oled_buffer[i] = oled_buffer[i + 1];
oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE));
}
} else {
for (uint16_t x = x_end - 1; x > 0; x--) {
i = y * OLED_DISPLAY_WIDTH + x;
oled_buffer[i] = oled_buffer[i - 1];
oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE));
}
}
}
}
oled_buffer_reader_t oled_read_raw(uint16_t start_index) {
if (start_index > OLED_MATRIX_SIZE) start_index = OLED_MATRIX_SIZE;
oled_buffer_reader_t ret_reader;

View File

@ -29,7 +29,7 @@ report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
if (x != 0 && y != 0) {
mouse_timer = timer_read();
#ifdef OLED_ENABLE
oled_timer = timer_read32();
oled_timer_reset();
#endif
if (timer_elapsed(mouse_debounce_timer) > TAP_CHECK) {
if (enable_acceleration) {
@ -94,8 +94,10 @@ bool process_record_pointing(uint16_t keycode, keyrecord_t* record) {
record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
mouse_timer = timer_read();
break;
#if 0
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
break;
#endif
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
if (record->event.pressed || !record->tap.count) {
break;

View File

@ -57,6 +57,9 @@ void keyboard_post_init_rgb_matrix(void) {
rgb_matrix_mode_noeeprom(RGB_MATRIX_REST_MODE);
}
#endif
if (userspace_config.rgb_layer_change) {
rgb_matrix_set_flags(LED_FLAG_UNDERGLOW | LED_FLAG_KEYLIGHT | LED_FLAG_INDICATOR);
}
}
bool process_record_user_rgb_matrix(uint16_t keycode, keyrecord_t *record) {

View File

@ -13,8 +13,9 @@ GRAVE_ESC_ENABLE = no
# DEBUG_MATRIX_SCAN_RATE_ENABLE = api
ifneq ($(strip $(NO_SECRETS)), yes)
ifneq ("$(wildcard $(USER_PATH)/keyrecords/secrets.c)","")
SRC += $(USER_PATH)/keyrecords/secrets.c
ifneq ("$(wildcard $(USER_PATH)/../../../qmk_secrets/secrets.c)","")
SRC += $(USER_PATH)/../../../qmk_secrets/secrets.c
SECURE_ENABLE = yes
endif
ifeq ($(strip $(NO_SECRETS)), lite)
OPT_DEFS += -DNO_SECRETS
@ -102,6 +103,7 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
ifeq ($(strip $(CUSTOM_POINTING_DEVICE)), yes)
SRC += $(USER_PATH)/pointing/pointing.c
OPT_DEFS += -DCUSTOM_POINTING_DEVICE
OPT_DEFS += -DMOUSE_EXT_REPORT
endif
endif
@ -119,9 +121,3 @@ ifeq ($(strip $(AUTOCORRECTION_ENABLE)), yes)
SRC += $(USER_PATH)/keyrecords/autocorrection/autocorrection.c
OPT_DEFS += -DAUTOCORRECTION_ENABLE
endif
CAPS_WORD_ENABLE ?= no
ifeq ($(strip $(CAPS_WORD_ENABLE)), yes)
SRC += $(USER_PATH)/keyrecords/caps_word.c
OPT_DEFS += -DCAPS_WORD_ENABLE
endif

View File

@ -11,6 +11,7 @@
#ifdef UNICODE_COMMON_ENABLE
# include "process_unicode_common.h"
extern unicode_config_t unicode_config;
# include "keyrecords/unicode.h"
#endif
#ifdef AUDIO_ENABLE
# include "audio.h"
@ -97,6 +98,7 @@ void user_transport_update(void) {
#endif
#ifdef UNICODE_COMMON_ENABLE
user_state.unicode_mode = unicode_config.input_mode;
user_state.unicode_typing_mode = typing_mode;
#endif
#ifdef SWAP_HANDS_ENABLE
user_state.swap_hands = swap_hands;
@ -110,6 +112,7 @@ void user_transport_update(void) {
user_state.raw = transport_user_state;
#ifdef UNICODE_COMMON_ENABLE
unicode_config.input_mode = user_state.unicode_mode;
typing_mode = user_state.unicode_typing_mode;
#endif
#if defined(CUSTOM_POINTING_DEVICE)
tap_toggling = user_state.tap_toggling;

View File

@ -12,12 +12,13 @@ extern char keylog_str[OLED_KEYLOGGER_LENGTH];
typedef union {
uint32_t raw;
struct {
bool audio_enable :1;
bool audio_clicky_enable :1;
bool tap_toggling :1;
uint8_t unicode_mode :3;
bool swap_hands :1;
bool host_driver_disabled :1;
bool audio_enable :1;
bool audio_clicky_enable :1;
bool tap_toggling :1;
uint8_t unicode_mode :3;
bool swap_hands :1;
bool host_driver_disabled :1;
uint8_t unicode_typing_mode :3;
};
} user_runtime_config_t;

View File

@ -25,21 +25,6 @@ __attribute__((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *
// And use "NEWPLACEHOLDER" for new safe range
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_MAKE:
if (!record->event.pressed) {
SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP
#if (defined(BOOTLOADER_DFU) || defined(BOOTLOADER_LUFA_DFU) || defined(BOOTLOADER_QMK_DFU))
":dfu"
#elif defined(BOOTLOADER_HALFKAY)
":teensy"
#elif defined(BOOTLOADER_CATERINA)
":avrdude"
#endif
SS_TAP(X_ENTER));
}
return false;
break;
case VRSN:
if (record->event.pressed) {
SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);

View File

@ -12,7 +12,7 @@
enum custom_keycodes {
VRSN = SAFE_RANGE, // can always be here
KC_MAKE,
KC_RESET,
QK_MAKE,
QK_BOOT,
NEWPLACEHOLDER // use "NEWPLACEHOLDER for keymap specific codes
};