Merge remote-tracking branch 'origin/master' into develop
This commit is contained in:
commit
c0bb153151
45 files changed
+815
-187
No files matched your search
@@ -16,7 +16,7 @@
|
||||
|
||||
#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) {
|
||||
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
|
||||
bool usb_vbus_state(void) {
|
||||
setPinInputLow(USB_VBUS_PIN);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Drashna's Blackpill Tractyl Manuform (5x6) with a right side trackball
|
||||
|
||||
* 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
|
||||
* Full Duplex Serial/USART using PA2 and PA3 on USART2
|
||||
* PWM Audio using PB1 and TIM3 and GPT on TIM4
|
||||
@@ -12,7 +12,8 @@
|
||||
* SSD1306 OLED display (128x64) using PB8-PB9 on I2C1
|
||||
* 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.
|
||||
* 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
|
||||
|
||||
## Keyboard Info
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
|
||||
#include "drashna.h"
|
||||
|
||||
enum tractyl_keycodes {
|
||||
KC_ACCEL = NEW_SAFE_RANGE,
|
||||
};
|
||||
|
||||
bool enable_acceleration = false;
|
||||
// clang-format off
|
||||
#define LAYOUT_5x6_right_wrapper(...) LAYOUT_5x6_right(__VA_ARGS__)
|
||||
#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,
|
||||
KEYLOCK, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
|
||||
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY,
|
||||
HPT_DWLI, HPT_DWLD, TG_GAME, TG_DBLO,
|
||||
HPT_TOG, HPT_BUZ, KC_NUKE,
|
||||
TG(_DIABLOII), AUTO_CTN, TG_GAME, TG_DBLO,
|
||||
_______, _______, KC_NUKE,
|
||||
_______, _______, _______,
|
||||
_______, TG(_DIABLOII),KC_NUKE, _______
|
||||
_______, _______, KC_NUKE, _______
|
||||
),
|
||||
};
|
||||
|
||||
@@ -169,116 +164,6 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
|
||||
}
|
||||
#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
|
||||
// WPM-responsive animation stuff here
|
||||
# define SLEEP_FRAMES 2
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <[email protected]>
|
||||
*
|
||||
* Copyright 2021 Dasky (@daskygit)
|
||||
|
||||
* 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
|
||||
|
||||
@@ -70,6 +70,7 @@ bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
|
||||
return true;
|
||||
}
|
||||
__attribute__((weak)) void keyboard_pre_init_sync(void) {}
|
||||
__attribute__((weak)) void keyboard_pre_init_sub(void) {}
|
||||
void keyboard_pre_init_kb(void) {
|
||||
// debug_enable = true;
|
||||
// debug_matrix = true;
|
||||
@@ -82,6 +83,7 @@ void keyboard_pre_init_kb(void) {
|
||||
writePin(DEBUG_LED_PIN, !debug_enable);
|
||||
#endif
|
||||
|
||||
keyboard_pre_init_sub();
|
||||
keyboard_pre_init_sync();
|
||||
keyboard_pre_init_user();
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
|
||||
MOUSEKEY_ENABLE = no # Mouse keys(+4700)
|
||||
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
|
||||
CONSOLE_ENABLE = no # Console for debug(+400)
|
||||
COMMAND_ENABLE = no # Commands for debug and configuration
|
||||
TAP_DANCE_ENABLE = no
|
||||
RGBLIGHT_ENABLE = yes
|
||||
AUDIO_ENABLE = no
|
||||
NKRO_ENABLE = yes
|
||||
BACKLIGHT_ENABLE = no
|
||||
SWAP_HANDS_ENABLE = no
|
||||
SPACE_CADET_ENABLE = no
|
||||
|
||||
INDICATOR_LIGHTS = no
|
||||
RGBLIGHT_STARTUP_ANIMATION = no
|
||||
|
||||
BOOTMAGIC_ENABLE = no # Enable Bootmagic Lite
|
||||
MOUSEKEY_ENABLE = no # Mouse keys
|
||||
EXTRAKEY_ENABLE = yes # Audio control and System control
|
||||
CONSOLE_ENABLE = no # Console for debug
|
||||
COMMAND_ENABLE = no # Commands for debug and configuration
|
||||
TAP_DANCE_ENABLE = no
|
||||
RGBLIGHT_ENABLE = yes
|
||||
AUDIO_ENABLE = no
|
||||
NKRO_ENABLE = yes
|
||||
BACKLIGHT_ENABLE = no
|
||||
SWAP_HANDS_ENABLE = no
|
||||
BOOTLOADER = qmk-dfu
|
||||
|
||||
INDICATOR_LIGHTS = no
|
||||
RGBLIGHT_STARTUP_ANIMATION = no
|
||||
CUSTOM_UNICODE_ENABLE = no
|
||||
CUSTOM_SPLIT_TRANSPORT_SYNC = no
|
||||
@@ -110,7 +110,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
VRSN, _________________ADJUST_L1_________________, TG(_DIABLOII), _______, _________________ADJUST_R1_________________, EEP_RST,
|
||||
KEYLOCK, _________________ADJUST_L2_________________, _______, _______, _________________ADJUST_R2_________________, RGB_IDL,
|
||||
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PAUS,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, AUTO_CTN,
|
||||
_______, _______, _______, _______, _______, _______
|
||||
),
|
||||
};
|
||||
|
||||
@@ -11,6 +11,6 @@ SPACE_CADET_ENABLE = no
|
||||
|
||||
INDICATOR_LIGHTS = yes
|
||||
RGBLIGHT_STARTUP_ANIMATION = yes
|
||||
|
||||
CUSTOM_UNICODE_ENABLE = no
|
||||
|
||||
BOOTLOADER = qmk-dfu
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#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_DISABLE_TIMEOUT
|
||||
#define OLED_FONT_END 255
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
|
||||
BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite
|
||||
TAP_DANCE_ENABLE = no
|
||||
COMMAND_ENABLE = no # Commands for debug and configuration
|
||||
CONSOLE_ENABLE = no
|
||||
@@ -9,12 +9,12 @@ ifeq ($(strip $(KEYBOARD)), ergodox_ez)
|
||||
RGB_MATRIX_ENABLE = yes
|
||||
INDICATOR_LIGHTS = no
|
||||
RGBLIGHT_STARTUP_ANIMATION = yes
|
||||
PIMORONI_TRACKBALL_ENABLE = yes
|
||||
PIMORONI_TRACKBALL_ENABLE = no
|
||||
MOUSEKEY_ENABLE = no
|
||||
endif
|
||||
|
||||
UNICODE_ENABLE = no
|
||||
UNICDOEMAP_ENABLE = no
|
||||
|
||||
UNICODE_ENABLE = no
|
||||
UNICDOEMAP_ENABLE = no
|
||||
CUSTOM_UNICODE_ENABLE = no
|
||||
|
||||
DEBOUNCE_TYPE = sym_eager_pr
|
||||
@@ -14,4 +14,5 @@ ifeq ($(strip $(KEYBOARD)), fractal)
|
||||
RGBLIGHT_ENABLE = yes
|
||||
RGBLIGHT_STARTUP_ANIMATION = yes
|
||||
BOOTLOADER = qmk-dfu
|
||||
CUSTOM_UNICODE_ENABLE = no
|
||||
endif
|
||||
@@ -32,6 +32,7 @@ ifeq ($(strip $(CTPC)), yes)
|
||||
SWAP_HANDS_ENABLE = yes
|
||||
WPM_ENABLE = yes
|
||||
else
|
||||
CUSTOM_UNICODE_ENABLE = no
|
||||
BOOTLOADER = qmk-hid
|
||||
BOOTLOADER_SIZE = 512
|
||||
endif
|
||||
@@ -77,7 +77,7 @@
|
||||
# endif
|
||||
#endif // !AUDIO_ENABLE
|
||||
|
||||
#define UNICODE_SELECTED_MODES UC_WIN, UC_MAC
|
||||
#define UNICODE_SELECTED_MODES UC_WINC, UC_MAC
|
||||
|
||||
#ifdef RGBLIGHT_ENABLE
|
||||
# define RGBLIGHT_SLEEP
|
||||
@@ -200,7 +200,7 @@
|
||||
# ifdef OLED_FONT_H
|
||||
# undef OLED_FONT_H
|
||||
# endif
|
||||
# define OLED_FONT_H "drashna_font.h"
|
||||
# define OLED_FONT_H "oled/drashna_font.h"
|
||||
# define OLED_FONT_END 255
|
||||
// # define OLED_FONT_5X5
|
||||
// # define OLED_FONT_AZTECH
|
||||
|
||||
@@ -70,7 +70,9 @@ void matrix_init_user(void) {
|
||||
DDRB &= ~(1 << 0);
|
||||
PORTB &= ~(1 << 0);
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_UNICODE_ENABLE
|
||||
matrix_init_unicode();
|
||||
#endif
|
||||
matrix_init_secret();
|
||||
matrix_init_keymap();
|
||||
}
|
||||
@@ -152,6 +154,9 @@ void matrix_scan_user(void) {
|
||||
#if defined(RGB_MATRIX_ENABLE)
|
||||
matrix_scan_rgb_matrix();
|
||||
#endif
|
||||
#if defined(POINTING_DEVICE_ENABLE)
|
||||
matrix_scan_pointing();
|
||||
#endif
|
||||
|
||||
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);
|
||||
#if defined(POINTING_DEVICE_ENABLE)
|
||||
state = layer_state_set_pointing(state);
|
||||
#endif
|
||||
#if defined(RGBLIGHT_ENABLE)
|
||||
state = layer_state_set_rgb_light(state);
|
||||
#endif // RGBLIGHT_ENABLE
|
||||
|
||||
+11
-10
@@ -18,25 +18,25 @@
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
#include "eeprom.h"
|
||||
#include "wrappers.h"
|
||||
#include "process_records.h"
|
||||
#include "keyrecords/wrappers.h"
|
||||
#include "keyrecords/process_records.h"
|
||||
#ifdef TAP_DANCE_ENABLE
|
||||
# include "tap_dances.h"
|
||||
# include "keyrecords/tap_dances.h"
|
||||
#endif // TAP_DANCE_ENABLE
|
||||
#if defined(RGBLIGHT_ENABLE)
|
||||
# include "rgb_stuff.h"
|
||||
# include "rgb/rgb_stuff.h"
|
||||
#endif
|
||||
#if defined(RGB_MATRIX_ENABLE)
|
||||
# include "rgb_matrix_stuff.h"
|
||||
# include "rgb/rgb_matrix_stuff.h"
|
||||
#endif
|
||||
#if defined(OLED_ENABLE)
|
||||
# include "oled_stuff.h"
|
||||
#endif
|
||||
#if defined(PIMORONI_TRACKBALL_ENABLE)
|
||||
# include "drivers/sensors/pimoroni_trackball.h"
|
||||
# include "oled/oled_stuff.h"
|
||||
#endif
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
# include "transport_sync.h"
|
||||
# include "split/transport_sync.h"
|
||||
#endif
|
||||
#ifdef POINTING_DEVICE_ENABLE
|
||||
# include "pointing/pointing.h"
|
||||
#endif
|
||||
|
||||
/* Define layer names */
|
||||
@@ -113,6 +113,7 @@ typedef union {
|
||||
bool nuke_switch :1;
|
||||
bool swapped_numbers :1;
|
||||
bool rgb_matrix_idle_anim :1;
|
||||
bool autocorrection :1;
|
||||
};
|
||||
} userspace_config_t;
|
||||
// clang-format on
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -16,6 +16,12 @@
|
||||
|
||||
#include "drashna.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;
|
||||
bool host_driver_disabled = false;
|
||||
@@ -42,6 +48,15 @@ bool process_record_user(uint16_t keycode, keyrecord_t *re
|
||||
#endif
|
||||
#ifdef CUSTOM_UNICODE_ENABLE
|
||||
&& 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
|
||||
&& true)) {
|
||||
return false;
|
||||
@@ -196,7 +211,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *re
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
#pragma once
|
||||
#include "drashna.h"
|
||||
|
||||
#if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
|
||||
#if defined(KEYBOARD_handwired_tractyl_manuform)
|
||||
# define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE
|
||||
#else
|
||||
# define PLACEHOLDER_SAFE_RANGE SAFE_RANGE
|
||||
@@ -56,7 +56,9 @@ enum userspace_custom_keycodes {
|
||||
KC_REGIONAL,
|
||||
KC_AUSSIE,
|
||||
KC_ZALGO,
|
||||
NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes
|
||||
KC_ACCEL,
|
||||
AUTO_CTN, // Toggle Autocorrect status
|
||||
NEW_SAFE_RANGE // use "NEWPLACEHOLDER for keymap specific codes
|
||||
};
|
||||
|
||||
bool process_record_secrets(uint16_t keycode, keyrecord_t *record);
|
||||
@@ -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);
|
||||
#ifdef CUSTOM_UNICODE_ENABLE
|
||||
bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
|
||||
void matrix_init_unicode(void);
|
||||
#endif
|
||||
|
||||
#define LOWER MO(_LOWER)
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,5 +1,6 @@
|
||||
/* Copyright 2020 @tzarc
|
||||
* 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
/* Copyright 2020 @ridingqwerty
|
||||
* 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
|
||||
* 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) {
|
||||
return process_record_zalgo(keycode, record);
|
||||
}
|
||||
return true;
|
||||
return process_unicode_common(keycode, record);
|
||||
}
|
||||
|
||||
void matrix_init_unicode(void) {
|
||||
unicode_input_mode_init();
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -234,7 +234,11 @@ void render_bootmagic_status(void) {
|
||||
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);
|
||||
#else
|
||||
oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui);
|
||||
#endif
|
||||
#ifdef OLED_DISPLAY_128X64
|
||||
oled_advance_page(true);
|
||||
oled_write_P(PSTR("Magic"), false);
|
||||
@@ -344,7 +348,7 @@ void render_wpm(uint8_t padding) {
|
||||
#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;
|
||||
void render_pointing_dpi_status(uint8_t padding) {
|
||||
oled_write_P(PSTR("CPI:"), false);
|
||||
@@ -377,7 +381,7 @@ __attribute__((weak)) void oled_driver_render_logo_left(void) {
|
||||
render_wpm(0);
|
||||
# endif
|
||||
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);
|
||||
# endif
|
||||
oled_set_cursor(0, 4);
|
||||
File renamed without changes.
@@ -0,0 +1,136 @@
|
||||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <[email protected]>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <[email protected]>
|
||||
*
|
||||
* 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;
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
This is my personal userspace file. Most of my code exists here, as it's heavily shared.
|
||||
|
||||
* [RGB Customization](readme_rgb.md)
|
||||
* [Diablo Tap Dancing](readme_tap_dance.md)
|
||||
* [Keymap Wrappers](readme_wrappers.md)
|
||||
* [Custom Function Handlers](readme_handlers.md)
|
||||
* [Secret Macros](readme_secrets.md)
|
||||
* [Custom Keycodes](readme_keycodes.md)
|
||||
* [RGB Customization](readme/rgb.md)
|
||||
* [Diablo Tap Dancing](readme/tap_dance.md)
|
||||
* [Keymap Wrappers](readme/wrappers.md)
|
||||
* [Custom Function Handlers](readme/handlers.md)
|
||||
* [Secret Macros](readme/secrets.md)
|
||||
* [Custom Keycodes](readme/keycodes.md)
|
||||
|
||||
|
||||
## Pro Micro Hacking
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+26
-14
@@ -1,5 +1,5 @@
|
||||
SRC += $(USER_PATH)/drashna.c \
|
||||
$(USER_PATH)/process_records.c
|
||||
$(USER_PATH)/keyrecords/process_records.c
|
||||
|
||||
ifneq ($(PLATFORM),CHIBIOS)
|
||||
ifneq ($(strip $(LTO_SUPPORTED)), no)
|
||||
@@ -10,8 +10,8 @@ SPACE_CADET_ENABLE = no
|
||||
GRAVE_ESC_ENABLE = no
|
||||
|
||||
ifneq ($(strip $(NO_SECRETS)), yes)
|
||||
ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
|
||||
SRC += $(USER_PATH)/secrets.c
|
||||
ifneq ("$(wildcard $(USER_PATH)/keyrecords/secrets.c)","")
|
||||
SRC += $(USER_PATH)/keyrecords/secrets.c
|
||||
endif
|
||||
ifeq ($(strip $(NO_SECRETS)), lite)
|
||||
OPT_DEFS += -DNO_SECRETS
|
||||
@@ -25,20 +25,20 @@ ifeq ($(strip $(CUSTOM_UNICODE_ENABLE)), yes)
|
||||
UCIS_ENABLE = no
|
||||
UNICODE_COMMON = yes
|
||||
OPT_DEFS += -DCUSTOM_UNICODE_ENABLE
|
||||
SRC += unicoooode.c
|
||||
SRC += $(USER_PATH)/keyrecords/unicode.c
|
||||
endif
|
||||
|
||||
CUSTOM_TAP_DANCE ?= yes
|
||||
ifeq ($(strip $(CUSTOM_TAP_DANCE)), yes)
|
||||
ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
|
||||
SRC += $(USER_PATH)/tap_dances.c
|
||||
SRC += $(USER_PATH)/keyrecords/tap_dances.c
|
||||
endif
|
||||
endif
|
||||
|
||||
CUSTOM_RGBLIGHT ?= yes
|
||||
ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
|
||||
ifeq ($(strip $(CUSTOM_RGBLIGHT)), yes)
|
||||
SRC += $(USER_PATH)/rgb_stuff.c
|
||||
SRC += $(USER_PATH)/rgb/rgb_stuff.c
|
||||
ifeq ($(strip $(RGBLIGHT_NOEEPROM)), yes)
|
||||
OPT_DEFS += -DRGBLIGHT_NOEEPROM
|
||||
endif
|
||||
@@ -51,7 +51,7 @@ endif
|
||||
CUSTOM_RGB_MATRIX ?= yes
|
||||
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
|
||||
ifeq ($(strip $(CUSTOM_RGB_MATRIX)), yes)
|
||||
SRC += $(USER_PATH)/rgb_matrix_stuff.c
|
||||
SRC += $(USER_PATH)/rgb/rgb_matrix_stuff.c
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -76,24 +76,36 @@ endif
|
||||
CUSTOM_OLED_DRIVER ?= yes
|
||||
ifeq ($(strip $(OLED_ENABLE)), 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
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(PIMORONI_TRACKBALL_ENABLE)), yes)
|
||||
POINTING_DEVICE_ENABLE := yes
|
||||
OPT_DEFS += -DPIMORONI_TRACKBALL_ENABLE
|
||||
SRC += drivers/sensors/pimoroni_trackball.c
|
||||
QUANTUM_LIB_SRC += i2c_master.c
|
||||
CUSTOM_POINTING_DEVICE ?= yes
|
||||
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
|
||||
ifeq ($(strip $(CUSTOM_POINTING_DEVICE)), yes)
|
||||
SRC += $(USER_PATH)/pointing/pointing.c
|
||||
endif
|
||||
endif
|
||||
|
||||
CUSTOM_SPLIT_TRANSPORT_SYNC ?= yes
|
||||
ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), 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
|
||||
endif
|
||||
endif
|
||||
|
||||
# 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
|
||||
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user