1
0
Fork 0

[Keymap] Unicode and Pointing Device and Autocorect for drashna keymaps (#15415)

This commit is contained in:
Drashna Jaelre 2021-12-14 20:53:36 -08:00 committed by GitHub
parent c10bc9f91e
commit 3fa592a402
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 815 additions and 187 deletions

View file

@ -16,7 +16,7 @@
#include "f411.h" #include "f411.h"
void matrix_init_sub_kb(void) { setPinInputHigh(A0); } void keyboard_pre_init_sub(void) { setPinInputHigh(A0); }
void matrix_scan_sub_kb(void) { void matrix_scan_sub_kb(void) {
if (!readPin(A0)) { if (!readPin(A0)) {
@ -24,6 +24,33 @@ void matrix_scan_sub_kb(void) {
} }
} }
void bootmagic_lite(void) {
// We need multiple scans because debouncing can't be turned off.
matrix_scan();
#if defined(DEBOUNCE) && DEBOUNCE > 0
wait_ms(DEBOUNCE * 2);
#else
wait_ms(30);
#endif
matrix_scan();
uint8_t row = BOOTMAGIC_LITE_ROW;
uint8_t col = BOOTMAGIC_LITE_COLUMN;
#if defined(SPLIT_KEYBOARD) && defined(BOOTMAGIC_LITE_ROW_RIGHT) && defined(BOOTMAGIC_LITE_COLUMN_RIGHT)
if (!is_keyboard_left()) {
row = BOOTMAGIC_LITE_ROW_RIGHT;
col = BOOTMAGIC_LITE_COLUMN_RIGHT;
}
#endif
if (matrix_get_row(row) & (1 << col) || !readPin(A0)) {
eeconfig_disable();
bootloader_jump();
}
}
#ifdef USB_VBUS_PIN #ifdef USB_VBUS_PIN
bool usb_vbus_state(void) { bool usb_vbus_state(void) {
setPinInputLow(USB_VBUS_PIN); setPinInputLow(USB_VBUS_PIN);

View file

@ -1,7 +1,7 @@
# Drashna's Blackpill Tractyl Manuform (5x6) with a right side trackball # Drashna's Blackpill Tractyl Manuform (5x6) with a right side trackball
* System Timer on TIM5 * System Timer on TIM5
* ~~VBUS mod, using PB10~~ (*doesn't seem to work for me*) * VBUS mod, using PB10 -- does work, but not on my tractyl... bad soldering probably
* Split Hand Pin, using PC14 * Split Hand Pin, using PC14
* Full Duplex Serial/USART using PA2 and PA3 on USART2 * Full Duplex Serial/USART using PA2 and PA3 on USART2
* PWM Audio using PB1 and TIM3 and GPT on TIM4 * PWM Audio using PB1 and TIM3 and GPT on TIM4
@ -12,7 +12,8 @@
* SSD1306 OLED display (128x64) using PB8-PB9 on I2C1 * SSD1306 OLED display (128x64) using PB8-PB9 on I2C1
* Pull-up resistor (22k) on PA10 to fix reset issue. * Pull-up resistor (22k) on PA10 to fix reset issue.
* Pull-up resistor (5.1k) on PA1 for WS2812 LED support, and wire it's VCC to the 5V pin. * Pull-up resistor (5.1k) on PA1 for WS2812 LED support, and wire it's VCC to the 5V pin.
* Pins PA9, PA11, A12 are not useable because they're used for USB connection, and can't be shared. * Pins PA9 is meant for VBUS sense, and has an internal pulldown resistor. A 5.1k pullup resistor can work (but should be avoided)
* Pins PA11 and A12 are not useable because they're used for USB connection, and can't be shared.
* Pin PB2 is used by BOOT1, and is unusable * Pin PB2 is used by BOOT1, and is unusable
## Keyboard Info ## Keyboard Info

View file

@ -16,11 +16,6 @@
#include "drashna.h" #include "drashna.h"
enum tractyl_keycodes {
KC_ACCEL = NEW_SAFE_RANGE,
};
bool enable_acceleration = false;
// clang-format off // clang-format off
#define LAYOUT_5x6_right_wrapper(...) LAYOUT_5x6_right(__VA_ARGS__) #define LAYOUT_5x6_right_wrapper(...) LAYOUT_5x6_right(__VA_ARGS__)
#define LAYOUT_5x6_right_base( \ #define LAYOUT_5x6_right_base( \
@ -129,10 +124,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EEP_RST, VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EEP_RST,
KEYLOCK, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS, KEYLOCK, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY, UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY,
HPT_DWLI, HPT_DWLD, TG_GAME, TG_DBLO, TG(_DIABLOII), AUTO_CTN, TG_GAME, TG_DBLO,
HPT_TOG, HPT_BUZ, KC_NUKE, _______, _______, KC_NUKE,
_______, _______, _______, _______, _______, _______,
_______, TG(_DIABLOII),KC_NUKE, _______ _______, _______, KC_NUKE, _______
), ),
}; };
@ -169,116 +164,6 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
} }
#endif #endif
#ifdef POINTING_DEVICE_ENABLE
static uint16_t mouse_timer = 0;
static uint16_t mouse_debounce_timer = 0;
static uint8_t mouse_keycode_tracker = 0;
bool tap_toggling = false;
# ifdef TAPPING_TERM_PER_KEY
# define TAP_CHECK get_tapping_term(KC_BTN1, NULL)
# else
# ifndef TAPPING_TERM
# define TAPPING_TERM 200
# endif
# define TAP_CHECK TAPPING_TERM
# endif
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
int8_t x = mouse_report.x, y = mouse_report.y;
mouse_report.x = 0;
mouse_report.y = 0;
if (x != 0 && y != 0) {
mouse_timer = timer_read();
# ifdef OLED_ENABLE
oled_timer = timer_read32();
# endif
if (timer_elapsed(mouse_debounce_timer) > TAP_CHECK) {
if (enable_acceleration) {
x = (x > 0 ? x * x / 16 + x : -x * x / 16 + x);
y = (y > 0 ? y * y / 16 + y : -y * y / 16 + y);
}
mouse_report.x = x;
mouse_report.y = y;
if (!layer_state_is(_MOUSE)) {
layer_on(_MOUSE);
}
}
}
return mouse_report;
}
void matrix_scan_keymap(void) {
if (timer_elapsed(mouse_timer) > 650 && layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) {
layer_off(_MOUSE);
}
if (tap_toggling) {
if (!layer_state_is(_MOUSE)) {
layer_on(_MOUSE);
}
}
}
bool process_record_keymap(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case TT(_MOUSE):
if (record->event.pressed) {
mouse_keycode_tracker++;
} else {
# if TAPPING_TOGGLE != 0
if (record->tap.count == TAPPING_TOGGLE) {
tap_toggling ^= 1;
# if TAPPING_TOGGLE == 1
if (!tap_toggling) mouse_keycode_tracker -= record->tap.count + 1;
# else
if (!tap_toggling) mouse_keycode_tracker -= record->tap.count;
# endif
} else {
mouse_keycode_tracker--;
}
# endif
}
mouse_timer = timer_read();
break;
case TG(_MOUSE):
if (record->event.pressed) {
tap_toggling ^= 1;
}
break;
case MO(_MOUSE):
case DPI_CONFIG:
case KC_MS_UP ... KC_MS_WH_RIGHT:
record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
mouse_timer = timer_read();
case KC_ACCEL:
enable_acceleration = record->event.pressed;
break;
default:
if (IS_NOEVENT(record->event)) break;
if ((keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) && (((keycode >> 0x8) & 0xF) == _MOUSE)) {
record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
mouse_timer = timer_read();
break;
}
if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) {
layer_off(_MOUSE);
}
mouse_keycode_tracker = 0;
mouse_debounce_timer = timer_read();
break;
}
return true;
}
layer_state_t layer_state_set_keymap(layer_state_t state) {
if (layer_state_cmp(state, _GAMEPAD) || layer_state_cmp(state, _DIABLO)) {
state |= ((layer_state_t)1 << _MOUSE);
}
return state;
}
#endif
#ifdef OLED_ENABLE #ifdef OLED_ENABLE
// WPM-responsive animation stuff here // WPM-responsive animation stuff here
# define SLEEP_FRAMES 2 # define SLEEP_FRAMES 2

View file

@ -1,5 +1,6 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* * Copyright 2021 Dasky (@daskygit)
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or

View file

@ -70,6 +70,7 @@ bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
return true; return true;
} }
__attribute__((weak)) void keyboard_pre_init_sync(void) {} __attribute__((weak)) void keyboard_pre_init_sync(void) {}
__attribute__((weak)) void keyboard_pre_init_sub(void) {}
void keyboard_pre_init_kb(void) { void keyboard_pre_init_kb(void) {
// debug_enable = true; // debug_enable = true;
// debug_matrix = true; // debug_matrix = true;
@ -82,6 +83,7 @@ void keyboard_pre_init_kb(void) {
writePin(DEBUG_LED_PIN, !debug_enable); writePin(DEBUG_LED_PIN, !debug_enable);
#endif #endif
keyboard_pre_init_sub();
keyboard_pre_init_sync(); keyboard_pre_init_sync();
keyboard_pre_init_user(); keyboard_pre_init_user();
} }

View file

@ -1,7 +1,7 @@
BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
MOUSEKEY_ENABLE = no # Mouse keys(+4700) MOUSEKEY_ENABLE = no # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control(+450) EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug(+400) CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration COMMAND_ENABLE = no # Commands for debug and configuration
TAP_DANCE_ENABLE = no TAP_DANCE_ENABLE = no
RGBLIGHT_ENABLE = yes RGBLIGHT_ENABLE = yes
@ -9,9 +9,9 @@ AUDIO_ENABLE = no
NKRO_ENABLE = yes NKRO_ENABLE = yes
BACKLIGHT_ENABLE = no BACKLIGHT_ENABLE = no
SWAP_HANDS_ENABLE = no SWAP_HANDS_ENABLE = no
SPACE_CADET_ENABLE = no BOOTLOADER = qmk-dfu
INDICATOR_LIGHTS = no INDICATOR_LIGHTS = no
RGBLIGHT_STARTUP_ANIMATION = no RGBLIGHT_STARTUP_ANIMATION = no
CUSTOM_UNICODE_ENABLE = no
BOOTLOADER = qmk-dfu CUSTOM_SPLIT_TRANSPORT_SYNC = no

View file

@ -110,7 +110,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
VRSN, _________________ADJUST_L1_________________, TG(_DIABLOII), _______, _________________ADJUST_R1_________________, EEP_RST, VRSN, _________________ADJUST_L1_________________, TG(_DIABLOII), _______, _________________ADJUST_R1_________________, EEP_RST,
KEYLOCK, _________________ADJUST_L2_________________, _______, _______, _________________ADJUST_R2_________________, RGB_IDL, KEYLOCK, _________________ADJUST_L2_________________, _______, _______, _________________ADJUST_R2_________________, RGB_IDL,
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS, UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PAUS, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, AUTO_CTN,
_______, _______, _______, _______, _______, _______ _______, _______, _______, _______, _______, _______
), ),
}; };

View file

@ -11,6 +11,6 @@ SPACE_CADET_ENABLE = no
INDICATOR_LIGHTS = yes INDICATOR_LIGHTS = yes
RGBLIGHT_STARTUP_ANIMATION = yes RGBLIGHT_STARTUP_ANIMATION = yes
CUSTOM_UNICODE_ENABLE = no
BOOTLOADER = qmk-dfu BOOTLOADER = qmk-dfu

View file

@ -17,7 +17,7 @@
#pragma once #pragma once
#define OLED_FONT_H "users/drashna/drashna_font.h" #define OLED_FONT_H "users/drashna/oled/drashna_font.h"
#define OLED_UPDATE_INTERVAL 15 #define OLED_UPDATE_INTERVAL 15
#define OLED_DISABLE_TIMEOUT #define OLED_DISABLE_TIMEOUT
#define OLED_FONT_END 255 #define OLED_FONT_END 255

View file

@ -9,12 +9,12 @@ ifeq ($(strip $(KEYBOARD)), ergodox_ez)
RGB_MATRIX_ENABLE = yes RGB_MATRIX_ENABLE = yes
INDICATOR_LIGHTS = no INDICATOR_LIGHTS = no
RGBLIGHT_STARTUP_ANIMATION = yes RGBLIGHT_STARTUP_ANIMATION = yes
PIMORONI_TRACKBALL_ENABLE = yes PIMORONI_TRACKBALL_ENABLE = no
MOUSEKEY_ENABLE = no MOUSEKEY_ENABLE = no
endif endif
UNICODE_ENABLE = no UNICODE_ENABLE = no
UNICDOEMAP_ENABLE = no UNICDOEMAP_ENABLE = no
CUSTOM_UNICODE_ENABLE = no
DEBOUNCE_TYPE = sym_eager_pr DEBOUNCE_TYPE = sym_eager_pr

View file

@ -14,4 +14,5 @@ ifeq ($(strip $(KEYBOARD)), fractal)
RGBLIGHT_ENABLE = yes RGBLIGHT_ENABLE = yes
RGBLIGHT_STARTUP_ANIMATION = yes RGBLIGHT_STARTUP_ANIMATION = yes
BOOTLOADER = qmk-dfu BOOTLOADER = qmk-dfu
CUSTOM_UNICODE_ENABLE = no
endif endif

View file

@ -32,6 +32,7 @@ ifeq ($(strip $(CTPC)), yes)
SWAP_HANDS_ENABLE = yes SWAP_HANDS_ENABLE = yes
WPM_ENABLE = yes WPM_ENABLE = yes
else else
CUSTOM_UNICODE_ENABLE = no
BOOTLOADER = qmk-hid BOOTLOADER = qmk-hid
BOOTLOADER_SIZE = 512 BOOTLOADER_SIZE = 512
endif endif

View file

@ -77,7 +77,7 @@
# endif # endif
#endif // !AUDIO_ENABLE #endif // !AUDIO_ENABLE
#define UNICODE_SELECTED_MODES UC_WIN, UC_MAC #define UNICODE_SELECTED_MODES UC_WINC, UC_MAC
#ifdef RGBLIGHT_ENABLE #ifdef RGBLIGHT_ENABLE
# define RGBLIGHT_SLEEP # define RGBLIGHT_SLEEP
@ -200,7 +200,7 @@
# ifdef OLED_FONT_H # ifdef OLED_FONT_H
# undef OLED_FONT_H # undef OLED_FONT_H
# endif # endif
# define OLED_FONT_H "drashna_font.h" # define OLED_FONT_H "oled/drashna_font.h"
# define OLED_FONT_END 255 # define OLED_FONT_END 255
// # define OLED_FONT_5X5 // # define OLED_FONT_5X5
// # define OLED_FONT_AZTECH // # define OLED_FONT_AZTECH

View file

@ -70,7 +70,9 @@ void matrix_init_user(void) {
DDRB &= ~(1 << 0); DDRB &= ~(1 << 0);
PORTB &= ~(1 << 0); PORTB &= ~(1 << 0);
#endif #endif
#ifdef CUSTOM_UNICODE_ENABLE
matrix_init_unicode();
#endif
matrix_init_secret(); matrix_init_secret();
matrix_init_keymap(); matrix_init_keymap();
} }
@ -152,6 +154,9 @@ void matrix_scan_user(void) {
#if defined(RGB_MATRIX_ENABLE) #if defined(RGB_MATRIX_ENABLE)
matrix_scan_rgb_matrix(); matrix_scan_rgb_matrix();
#endif #endif
#if defined(POINTING_DEVICE_ENABLE)
matrix_scan_pointing();
#endif
matrix_scan_secret(); matrix_scan_secret();
@ -171,6 +176,9 @@ layer_state_t layer_state_set_user(layer_state_t state) {
} }
state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST); state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST);
#if defined(POINTING_DEVICE_ENABLE)
state = layer_state_set_pointing(state);
#endif
#if defined(RGBLIGHT_ENABLE) #if defined(RGBLIGHT_ENABLE)
state = layer_state_set_rgb_light(state); state = layer_state_set_rgb_light(state);
#endif // RGBLIGHT_ENABLE #endif // RGBLIGHT_ENABLE

View file

@ -18,25 +18,25 @@
#include QMK_KEYBOARD_H #include QMK_KEYBOARD_H
#include "eeprom.h" #include "eeprom.h"
#include "wrappers.h" #include "keyrecords/wrappers.h"
#include "process_records.h" #include "keyrecords/process_records.h"
#ifdef TAP_DANCE_ENABLE #ifdef TAP_DANCE_ENABLE
# include "tap_dances.h" # include "keyrecords/tap_dances.h"
#endif // TAP_DANCE_ENABLE #endif // TAP_DANCE_ENABLE
#if defined(RGBLIGHT_ENABLE) #if defined(RGBLIGHT_ENABLE)
# include "rgb_stuff.h" # include "rgb/rgb_stuff.h"
#endif #endif
#if defined(RGB_MATRIX_ENABLE) #if defined(RGB_MATRIX_ENABLE)
# include "rgb_matrix_stuff.h" # include "rgb/rgb_matrix_stuff.h"
#endif #endif
#if defined(OLED_ENABLE) #if defined(OLED_ENABLE)
# include "oled_stuff.h" # include "oled/oled_stuff.h"
#endif
#if defined(PIMORONI_TRACKBALL_ENABLE)
# include "drivers/sensors/pimoroni_trackball.h"
#endif #endif
#ifdef SPLIT_KEYBOARD #ifdef SPLIT_KEYBOARD
# include "transport_sync.h" # include "split/transport_sync.h"
#endif
#ifdef POINTING_DEVICE_ENABLE
# include "pointing/pointing.h"
#endif #endif
/* Define layer names */ /* Define layer names */
@ -113,6 +113,7 @@ typedef union {
bool nuke_switch :1; bool nuke_switch :1;
bool swapped_numbers :1; bool swapped_numbers :1;
bool rgb_matrix_idle_anim :1; bool rgb_matrix_idle_anim :1;
bool autocorrection :1;
}; };
} userspace_config_t; } userspace_config_t;
// clang-format on // clang-format on

View file

@ -0,0 +1,143 @@
// Copyright 2021 Google LLC
// Copyright 2022 @filterpaper
// SPDX-License-Identifier: Apache-2.0
// Original source: https://getreuer.info/posts/keyboards/autocorrection
#include "autocorrection.h"
#include <string.h>
#if __has_include("autocorrection_data.h")
# include "autocorrection_data.h"
# if AUTOCORRECTION_MIN_LENGTH < 4
# error Minimum Length is too short and may cause overflows
# endif
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;
if (keycode == AUTO_CTN) {
if (record->event.pressed) {
typo_buffer_size = 0;
userspace_config.autocorrection ^= 1;
eeconfig_update_user(userspace_config.raw);
}
return false;
}
if (!userspace_config.autocorrection) {
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
# ifndef NO_ACTION_ONESHOT
case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
if ((keycode & 0xF) == MOD_LSFT) {
return true;
}
# endif
default:
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) {
// 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) {
typo_buffer_size = 0;
}
keycode = KC_SPC;
} else {
// 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;
}
// 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) {
return true;
}
// Check for typo in buffer using a trie stored in `autocorrection_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 const key_i = typo_buffer[i];
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))) {
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);
// Check for match in node with single child.
} else if (code != key_i) {
return true;
} else if (!(code = pgm_read_byte(autocorrection_data + (++state)))) {
++state;
}
code = pgm_read_byte(autocorrection_data + state);
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);
}
send_string_P((char const*)(autocorrection_data + state + 1));
if (keycode == KC_SPC) {
typo_buffer[0] = KC_SPC;
typo_buffer_size = 1;
return true;
} else {
typo_buffer_size = 0;
return false;
}
}
}
return true;
}
#else
# pragma message "Warning!!! Autocorrect is not corretly setup!"
bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { return true; }
#endif

View file

@ -0,0 +1,10 @@
// Copyright 2021 Google LLC
// Copyright 2022 @filterpaper
// SPDX-License-Identifier: Apache-2.0
// Original source: https://getreuer.info/posts/keyboards/autocorrection
#pragma once
#include "drashna.h"
bool process_autocorrection(uint16_t keycode, keyrecord_t* record);

View file

@ -0,0 +1,273 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Python program to make autocorrection_data.h.
This program reads "autocorrection_dict.txt" and generates a C source file
"autocorrection_data.h" with a serialized trie embedded as an array. Run this
program without arguments like
$ python3 make_autocorrection_data.py
Or to read from a different typo dict file, pass it as the first argument like
$ python3 make_autocorrection_data.py dict.txt
Each line of the dict file defines one typo and its correction with the syntax
"typo -> correction". Blank lines or lines starting with '#' are ignored.
Example:
:thier -> their
fitler -> filter
lenght -> length
ouput -> output
widht -> width
See autocorrection_dict_extra.txt for a larger example.
For full documentation, see
https://getreuer.info/posts/keyboards/autocorrection
"""
import sys
import textwrap
from typing import Any, Dict, List, Tuple
try:
from english_words import english_words_lower_alpha_set as CORRECT_WORDS
except ImportError:
print('Autocorrection will falsely trigger when a typo is a substring of a '
'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')
KC_A = 4
KC_SPC = 0x2c
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.
Args:
file_name: String, path of the autocorrections dictionary.
Returns:
List of (typo, correction) tuples.
"""
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}"')
sys.exit(1)
typo, correction = tokens
typo = typo.lower() # Force typos to lowercase.
typo = typo.replace(' ', ':')
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)
return autocorrections
def make_trie(autocorrections: List[Tuple[str, str]]) -> Dict[str, Any]:
"""Makes a trie from the the typos, writing in reverse.
Args:
autocorrections: List of (typo, correction) tuples.
Returns:
Dict of dict, representing the trie.
"""
trie = {}
for typo, correction in autocorrections:
node = trie
for letter in typo[::-1]:
node = node.setdefault(letter, {})
node['LEAF'] = (typo, correction)
return trie
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.
Args:
autocorrections: List of (typo, correction) tuples.
trie: Dict of dicts.
Returns:
List of ints in the range 0-255.
"""
table = []
# Traverse trie in depth first order.
def traverse(trie_node):
if 'LEAF' in trie_node: # Handle a leaf trie node.
typo, correction = trie_node['LEAF']
word_boundary_ending = typo[-1] == ':'
typo = typo.strip(':')
i = 0 # Make the autocorrection data for this entry and serialize it.
while i < min(len(typo), len(correction)) and typo[i] == correction[i]:
i += 1
backspaces = len(typo) - i - 1 + word_boundary_ending
assert 0 <= backspaces <= 63
correction = correction[i:]
data = [backspaces + 128] + list(bytes(correction, 'ascii')) + [0]
entry = {'data': data, 'links': [], 'byte_offset': 0}
table.append(entry)
elif len(trie_node) == 1: # Handle trie node with a single child.
c, trie_node = next(iter(trie_node.items()))
entry = {'chars': c, 'byte_offset': 0}
# It's common for a trie to have long chains of single-child nodes. We
# find the whole chain so that we can serialize it more efficiently.
while len(trie_node) == 1 and 'LEAF' not in trie_node:
c, trie_node = next(iter(trie_node.items()))
entry['chars'] += c
table.append(entry)
entry['links'] = [traverse(trie_node)]
else: # Handle trie node with multiple children.
entry = {'chars': ''.join(sorted(trie_node.keys())), 'byte_offset': 0}
table.append(entry)
entry['links'] = [traverse(trie_node[c]) for c in entry['chars']]
return entry
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]
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]))
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)
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 write_generated_code(autocorrections: List[Tuple[str, str]],
data: List[int],
file_name: str) -> None:
"""Writes autocorrection data as generated C code to `file_name`.
Args:
autocorrections: List of (typo, correction) tuples.
data: List of ints in 0-255, the serialized trie.
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])
min_typo = min(autocorrections, key=typo_len)[0]
max_typo = max(autocorrections, key=typo_len)[0]
generated_code = ''.join([
'// Generated code.\n\n',
f'// Autocorrection dictionary ({len(autocorrections)} entries):\n',
''.join(sorted(f'// {typo:<{len(max_typo)}} -> {correction}\n'
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',
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:
f.write(generated_code)
def main(argv):
dict_file = argv[1] if len(argv) > 1 else 'autocorrection_dict.txt'
autocorrections = parse_file(dict_file)
trie = make_trie(autocorrections)
data = serialize_trie(autocorrections, trie)
print(f'Processed %d autocorrection entries to table with %d bytes.'
% (len(autocorrections), len(data)))
write_generated_code(autocorrections, data, 'autocorrection_data.h')
if __name__ == '__main__':
main(sys.argv)

View file

@ -0,0 +1,69 @@
// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0
#include "caps_word.h"
bool caps_word_enabled = false;
bool caps_word_shifted = false;
bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
if (!caps_word_enabled) {
// Pressing both shift keys at the same time enables caps word.
if (((get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) {
clear_mods();
clear_oneshot_mods();
caps_word_shifted = false;
caps_word_enabled = true;
return false;
}
return true;
}
if (!record->event.pressed) {
return true;
}
if (!((get_mods() | get_oneshot_mods()) & ~MOD_MASK_SHIFT)) {
switch (keycode) {
case QK_MOD_TAP ... QK_MOD_TAP_MAX:
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
// Earlier return if this has not been considered tapped yet.
if (record->tap.count == 0) {
return true;
}
// Get the base tapping keycode of a mod- or layer-tap key.
keycode &= 0xff;
}
switch (keycode) {
// Letter keys should be shifted.
case KC_A ... KC_Z:
if (!caps_word_shifted) {
register_code(KC_LSFT);
}
caps_word_shifted = true;
return true;
// Keycodes that continue caps word but shouldn't get shifted.
case KC_1 ... KC_0:
case KC_BSPC:
case KC_MINS:
case KC_UNDS:
if (caps_word_shifted) {
unregister_code(KC_LSFT);
}
caps_word_shifted = false;
return true;
// Any other keycode disables caps word.
}
}
// Disable caps word.
caps_word_enabled = false;
if (caps_word_shifted) {
unregister_code(KC_LSFT);
}
caps_word_shifted = false;
return true;
}

View file

@ -0,0 +1,8 @@
// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "drashna.h"
bool process_caps_word(uint16_t keycode, keyrecord_t* record);

View file

@ -16,6 +16,12 @@
#include "drashna.h" #include "drashna.h"
#include "version.h" #include "version.h"
#ifdef CAPS_WORD_ENABLE
# include "caps_word.h"
#endif
#ifdef AUTOCORRECTION_ENABLE
# include "autocorrection/autocorrection.h"
#endif
uint16_t copy_paste_timer; uint16_t copy_paste_timer;
bool host_driver_disabled = false; bool host_driver_disabled = false;
@ -42,6 +48,15 @@ bool process_record_user(uint16_t keycode, keyrecord_t *re
#endif #endif
#ifdef CUSTOM_UNICODE_ENABLE #ifdef CUSTOM_UNICODE_ENABLE
&& process_record_unicode(keycode, record) && process_record_unicode(keycode, record)
#endif
#if defined(POINTING_DEVICE_ENABLE)
&& process_record_pointing(keycode, record)
#endif
#ifdef CAPS_WORD_ENABLE
&& process_caps_word(keycode, record)
#endif
#ifdef AUTOCORRECTION_ENABLE
&& process_autocorrection(keycode, record)
#endif #endif
&& true)) { && true)) {
return false; return false;

View file

@ -17,7 +17,7 @@
#pragma once #pragma once
#include "drashna.h" #include "drashna.h"
#if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right) #if defined(KEYBOARD_handwired_tractyl_manuform)
# define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE # define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE
#else #else
# define PLACEHOLDER_SAFE_RANGE SAFE_RANGE # define PLACEHOLDER_SAFE_RANGE SAFE_RANGE
@ -56,6 +56,8 @@ enum userspace_custom_keycodes {
KC_REGIONAL, KC_REGIONAL,
KC_AUSSIE, KC_AUSSIE,
KC_ZALGO, KC_ZALGO,
KC_ACCEL,
AUTO_CTN, // Toggle Autocorrect status
NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes
}; };
@ -64,6 +66,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record);
void post_process_record_keymap(uint16_t keycode, keyrecord_t *record); void post_process_record_keymap(uint16_t keycode, keyrecord_t *record);
#ifdef CUSTOM_UNICODE_ENABLE #ifdef CUSTOM_UNICODE_ENABLE
bool process_record_unicode(uint16_t keycode, keyrecord_t *record); bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
void matrix_init_unicode(void);
#endif #endif
#define LOWER MO(_LOWER) #define LOWER MO(_LOWER)

View file

@ -1,5 +1,6 @@
/* Copyright 2020 @tzarc /* Copyright 2020 @ridingqwerty
* 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com> * Copyright 2020 @tzarc
* Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -278,5 +279,9 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
} else if (typing_mode == KC_ZALGO) { } else if (typing_mode == KC_ZALGO) {
return process_record_zalgo(keycode, record); return process_record_zalgo(keycode, record);
} }
return true; return process_unicode_common(keycode, record);
}
void matrix_init_unicode(void) {
unicode_input_mode_init();
} }

View file

@ -234,7 +234,11 @@ void render_bootmagic_status(void) {
oled_write_P(PSTR(" "), false); oled_write_P(PSTR(" "), false);
oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NKRO), keymap_config.nkro); oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NKRO), keymap_config.nkro);
oled_write_P(PSTR(" "), false); oled_write_P(PSTR(" "), false);
#ifdef AUTOCORRECTION_ENABLE
oled_write_P(PSTR("CRCT"), userspace_config.autocorrection);
#else
oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui); oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui);
#endif
#ifdef OLED_DISPLAY_128X64 #ifdef OLED_DISPLAY_128X64
oled_advance_page(true); oled_advance_page(true);
oled_write_P(PSTR("Magic"), false); oled_write_P(PSTR("Magic"), false);
@ -344,7 +348,7 @@ void render_wpm(uint8_t padding) {
#endif #endif
} }
#if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right) #if defined(KEYBOARD_handwired_tractyl_manuform) || defined(KEYBOARD_bastardkb_charybdis)
extern kb_config_data_t kb_config; extern kb_config_data_t kb_config;
void render_pointing_dpi_status(uint8_t padding) { void render_pointing_dpi_status(uint8_t padding) {
oled_write_P(PSTR("CPI:"), false); oled_write_P(PSTR("CPI:"), false);
@ -377,7 +381,7 @@ __attribute__((weak)) void oled_driver_render_logo_left(void) {
render_wpm(0); render_wpm(0);
# endif # endif
oled_write_P(PSTR(" "), false); oled_write_P(PSTR(" "), false);
# if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right) # if defined(KEYBOARD_handwired_tractyl_manuform) || defined(KEYBOARD_bastardkb_charybdis)
render_pointing_dpi_status(1); render_pointing_dpi_status(1);
# endif # endif
oled_set_cursor(0, 4); oled_set_cursor(0, 4);

View file

@ -0,0 +1,136 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.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 "pointing.h"
static uint16_t mouse_timer = 0;
static uint16_t mouse_debounce_timer = 0;
static uint8_t mouse_keycode_tracker = 0;
bool tap_toggling = false, enable_acceleration = false;
#ifdef TAPPING_TERM_PER_KEY
# define TAP_CHECK get_tapping_term(KC_BTN1, NULL)
#else
# ifndef TAPPING_TERM
# define TAPPING_TERM 200
# endif
# define TAP_CHECK TAPPING_TERM
#endif
__attribute__((weak)) report_mouse_t pointing_device_task_keymap(report_mouse_t mouse_report) {
return mouse_report;
}
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
int8_t x = mouse_report.x, y = mouse_report.y;
mouse_report.x = 0;
mouse_report.y = 0;
if (x != 0 && y != 0) {
mouse_timer = timer_read();
#ifdef OLED_ENABLE
oled_timer = timer_read32();
#endif
if (timer_elapsed(mouse_debounce_timer) > TAP_CHECK) {
if (enable_acceleration) {
x = (x > 0 ? x * x / 16 + x : -x * x / 16 + x);
y = (y > 0 ? y * y / 16 + y : -y * y / 16 + y);
}
mouse_report.x = x;
mouse_report.y = y;
if (!layer_state_is(_MOUSE)) {
layer_on(_MOUSE);
}
}
}
return pointing_device_task_keymap(mouse_report);
}
void matrix_scan_pointing(void) {
if (timer_elapsed(mouse_timer) > 650 && layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) {
layer_off(_MOUSE);
}
if (tap_toggling) {
if (!layer_state_is(_MOUSE)) {
layer_on(_MOUSE);
}
}
}
bool process_record_pointing(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case TT(_MOUSE):
if (record->event.pressed) {
mouse_keycode_tracker++;
} else {
#if TAPPING_TOGGLE != 0
if (record->tap.count == TAPPING_TOGGLE) {
tap_toggling ^= 1;
# if TAPPING_TOGGLE == 1
if (!tap_toggling) mouse_keycode_tracker -= record->tap.count + 1;
# else
if (!tap_toggling) mouse_keycode_tracker -= record->tap.count;
# endif
} else {
mouse_keycode_tracker--;
}
#endif
}
mouse_timer = timer_read();
break;
case TG(_MOUSE):
if (record->event.pressed) {
tap_toggling ^= 1;
}
break;
case MO(_MOUSE):
#if defined(KEYBOARD_ploopy) || defined(KEYBOARD_handwired_tractyl_manuform)
case DPI_CONFIG:
#elif defined(KEYBOARD_bastardkb_charybdis)
case SAFE_RANGE ... (CHARYBDIS_SAFE_RANGE-1):
#endif
case KC_MS_UP ... KC_MS_WH_RIGHT:
record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
mouse_timer = timer_read();
break;
case KC_ACCEL:
enable_acceleration = record->event.pressed;
record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
mouse_timer = timer_read();
break;
default:
if (IS_NOEVENT(record->event)) break;
if ((keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) && (((keycode >> 0x8) & 0xF) == _MOUSE)) {
record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
mouse_timer = timer_read();
break;
}
if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) {
layer_off(_MOUSE);
}
mouse_keycode_tracker = 0;
mouse_debounce_timer = timer_read();
break;
}
return true;
}
layer_state_t layer_state_set_pointing(layer_state_t state) {
if (layer_state_cmp(state, _GAMEPAD) || layer_state_cmp(state, _DIABLO)) {
state |= ((layer_state_t)1 << _MOUSE);
}
return state;
}

View file

@ -0,0 +1,23 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.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 "drashna.h"
report_mouse_t pointing_device_task_keymap(report_mouse_t mouse_report);
void matrix_scan_pointing(void);
bool process_record_pointing(uint16_t keycode, keyrecord_t* record);
layer_state_t layer_state_set_pointing(layer_state_t state);
extern bool tap_toggling, enable_acceleration;

View file

@ -2,12 +2,12 @@
This is my personal userspace file. Most of my code exists here, as it's heavily shared. This is my personal userspace file. Most of my code exists here, as it's heavily shared.
* [RGB Customization](readme_rgb.md) * [RGB Customization](readme/rgb.md)
* [Diablo Tap Dancing](readme_tap_dance.md) * [Diablo Tap Dancing](readme/tap_dance.md)
* [Keymap Wrappers](readme_wrappers.md) * [Keymap Wrappers](readme/wrappers.md)
* [Custom Function Handlers](readme_handlers.md) * [Custom Function Handlers](readme/handlers.md)
* [Secret Macros](readme_secrets.md) * [Secret Macros](readme/secrets.md)
* [Custom Keycodes](readme_keycodes.md) * [Custom Keycodes](readme/keycodes.md)
## Pro Micro Hacking ## Pro Micro Hacking

View file

@ -1,5 +1,5 @@
SRC += $(USER_PATH)/drashna.c \ SRC += $(USER_PATH)/drashna.c \
$(USER_PATH)/process_records.c $(USER_PATH)/keyrecords/process_records.c
ifneq ($(PLATFORM),CHIBIOS) ifneq ($(PLATFORM),CHIBIOS)
ifneq ($(strip $(LTO_SUPPORTED)), no) ifneq ($(strip $(LTO_SUPPORTED)), no)
@ -10,8 +10,8 @@ SPACE_CADET_ENABLE = no
GRAVE_ESC_ENABLE = no GRAVE_ESC_ENABLE = no
ifneq ($(strip $(NO_SECRETS)), yes) ifneq ($(strip $(NO_SECRETS)), yes)
ifneq ("$(wildcard $(USER_PATH)/secrets.c)","") ifneq ("$(wildcard $(USER_PATH)/keyrecords/secrets.c)","")
SRC += $(USER_PATH)/secrets.c SRC += $(USER_PATH)/keyrecords/secrets.c
endif endif
ifeq ($(strip $(NO_SECRETS)), lite) ifeq ($(strip $(NO_SECRETS)), lite)
OPT_DEFS += -DNO_SECRETS OPT_DEFS += -DNO_SECRETS
@ -25,20 +25,20 @@ ifeq ($(strip $(CUSTOM_UNICODE_ENABLE)), yes)
UCIS_ENABLE = no UCIS_ENABLE = no
UNICODE_COMMON = yes UNICODE_COMMON = yes
OPT_DEFS += -DCUSTOM_UNICODE_ENABLE OPT_DEFS += -DCUSTOM_UNICODE_ENABLE
SRC += unicoooode.c SRC += $(USER_PATH)/keyrecords/unicode.c
endif endif
CUSTOM_TAP_DANCE ?= yes CUSTOM_TAP_DANCE ?= yes
ifeq ($(strip $(CUSTOM_TAP_DANCE)), yes) ifeq ($(strip $(CUSTOM_TAP_DANCE)), yes)
ifeq ($(strip $(TAP_DANCE_ENABLE)), yes) ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
SRC += $(USER_PATH)/tap_dances.c SRC += $(USER_PATH)/keyrecords/tap_dances.c
endif endif
endif endif
CUSTOM_RGBLIGHT ?= yes CUSTOM_RGBLIGHT ?= yes
ifeq ($(strip $(RGBLIGHT_ENABLE)), yes) ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
ifeq ($(strip $(CUSTOM_RGBLIGHT)), yes) ifeq ($(strip $(CUSTOM_RGBLIGHT)), yes)
SRC += $(USER_PATH)/rgb_stuff.c SRC += $(USER_PATH)/rgb/rgb_stuff.c
ifeq ($(strip $(RGBLIGHT_NOEEPROM)), yes) ifeq ($(strip $(RGBLIGHT_NOEEPROM)), yes)
OPT_DEFS += -DRGBLIGHT_NOEEPROM OPT_DEFS += -DRGBLIGHT_NOEEPROM
endif endif
@ -51,7 +51,7 @@ endif
CUSTOM_RGB_MATRIX ?= yes CUSTOM_RGB_MATRIX ?= yes
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
ifeq ($(strip $(CUSTOM_RGB_MATRIX)), yes) ifeq ($(strip $(CUSTOM_RGB_MATRIX)), yes)
SRC += $(USER_PATH)/rgb_matrix_stuff.c SRC += $(USER_PATH)/rgb/rgb_matrix_stuff.c
endif endif
endif endif
@ -76,24 +76,36 @@ endif
CUSTOM_OLED_DRIVER ?= yes CUSTOM_OLED_DRIVER ?= yes
ifeq ($(strip $(OLED_ENABLE)), yes) ifeq ($(strip $(OLED_ENABLE)), yes)
ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes) ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes)
SRC += $(USER_PATH)/oled_stuff.c SRC += $(USER_PATH)/oled/oled_stuff.c
OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE
endif endif
endif endif
ifeq ($(strip $(PIMORONI_TRACKBALL_ENABLE)), yes) CUSTOM_POINTING_DEVICE ?= yes
POINTING_DEVICE_ENABLE := yes ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
OPT_DEFS += -DPIMORONI_TRACKBALL_ENABLE ifeq ($(strip $(CUSTOM_POINTING_DEVICE)), yes)
SRC += drivers/sensors/pimoroni_trackball.c SRC += $(USER_PATH)/pointing/pointing.c
QUANTUM_LIB_SRC += i2c_master.c endif
endif endif
CUSTOM_SPLIT_TRANSPORT_SYNC ?= yes CUSTOM_SPLIT_TRANSPORT_SYNC ?= yes
ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes) ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes)
ifeq ($(strip $(SPLIT_KEYBOARD)), yes) ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
QUANTUM_LIB_SRC += $(USER_PATH)/transport_sync.c QUANTUM_LIB_SRC += $(USER_PATH)/split/transport_sync.c
OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC
endif endif
endif endif
# DEBUG_MATRIX_SCAN_RATE_ENABLE = api # DEBUG_MATRIX_SCAN_RATE_ENABLE = api
AUTOCORRECTION_ENABLE ?= yes
ifeq ($(strip $(AUTOCORRECTION_ENABLE)), yes)
SRC += $(USER_PATH)/keyrecords/autocorrection/autocorrection.c
OPT_DEFS += -DAUTOCORRECTION_ENABLE
endif
CAPS_WORD_ENABLE ?= yes
ifeq ($(strip $(CAPS_WORD_ENABLE)), yes)
SRC += $(USER_PATH)/keyrecords/caps_word.c
OPT_DEFS += -DCAPS_WORD_ENABLE
endif