diff options
Diffstat (limited to 'quantum')
29 files changed, 513 insertions, 743 deletions
diff --git a/quantum/action.c b/quantum/action.c index 4e81a5466f..83f6e2a970 100644 --- a/quantum/action.c +++ b/quantum/action.c @@ -844,7 +844,7 @@ __attribute__((weak)) void register_code(uint8_t code) { # endif add_key(KC_CAPS_LOCK); send_keyboard_report(); - wait_ms(100); + wait_ms(TAP_HOLD_CAPS_DELAY); del_key(KC_CAPS_LOCK); send_keyboard_report(); } diff --git a/quantum/action_layer.h b/quantum/action_layer.h index b87d096eed..bd1085a70f 100644 --- a/quantum/action_layer.h +++ b/quantum/action_layer.h @@ -41,7 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #endif #if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT) -# define LAYER_STATE_32BIT +# define LAYER_STATE_16BIT #endif #if defined(LAYER_STATE_8BIT) diff --git a/quantum/action_tapping.c b/quantum/action_tapping.c index 3c8b5678b7..df3317ac05 100644 --- a/quantum/action_tapping.c +++ b/quantum/action_tapping.c @@ -125,7 +125,7 @@ void action_tapping_process(keyrecord_t record) { /* return true when key event is processed or consumed. */ bool process_tapping(keyrecord_t *keyp) { keyevent_t event = keyp->event; -# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(TAPPING_TERM_PER_KEY) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) +# if (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) || defined(PERMISSIVE_HOLD_PER_KEY) || defined(TAPPING_FORCE_HOLD_PER_KEY) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY) uint16_t tapping_keycode = get_record_keycode(&tapping_key, false); # endif @@ -164,17 +164,15 @@ bool process_tapping(keyrecord_t *keyp) { * useful for long TAPPING_TERM but may prevent fast typing. */ // clang-format off -# if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) +# if defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) else if ( ( - ( - GET_TAPPING_TERM(tapping_keycode, &tapping_key) >= 500 + IS_RELEASED(event) && waiting_buffer_typed(event) # ifdef PERMISSIVE_HOLD_PER_KEY - || get_permissive_hold(tapping_keycode, &tapping_key) + && get_permissive_hold(tapping_keycode, &tapping_key) # elif defined(PERMISSIVE_HOLD) - || true + && true # endif - ) && IS_RELEASED(event) && waiting_buffer_typed(event) ) // Causes nested taps to not wait past TAPPING_TERM/RETRO_SHIFT // unnecessarily and fixes them for Layer Taps. diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h index 3e425abb47..ff22e6fe95 100644 --- a/quantum/audio/song_list.h +++ b/quantum/audio/song_list.h @@ -144,6 +144,12 @@ */ #define USSR_ANTHEM B__NOTE(_G6), B__NOTE(_C7), W__NOTE(_G6), H__NOTE(_A6), B__NOTE(_B6), W__NOTE(_E6), W__NOTE(_E6), B__NOTE(_A6), W__NOTE(_G6), H__NOTE(_F6), B__NOTE(_G6), W__NOTE(_C6), W__NOTE(_C6), B__NOTE(_D6), W__NOTE(_D6), W__NOTE(_E6), B__NOTE(_D6), W__NOTE(_D6), W__NOTE(_G6), B__NOTE(_F6), W__NOTE(_G6), W__NOTE(_A6), B__NOTE(_B6), +/* Title: Hymn Risen + * Author/Composer: Terrance Andrew Davis + * License: Public Domain + */ +#define TOS_HYMN_RISEN H__NOTE(_D5), H__NOTE(_E5), HD_NOTE(_F5), HD_NOTE(_F5), H__NOTE(_F5), HD_NOTE(_D5), E__NOTE(_E5), E__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_D5), Q__NOTE(_D5), H__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_G5), Q__NOTE(_F5), H__NOTE(_D5), H__NOTE(_E5), HD_NOTE(_F5), HD_NOTE(_F5), H__NOTE(_F5), HD_NOTE(_D5), E__NOTE(_E5), E__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_D5), Q__NOTE(_D5), H__NOTE(_E5), H__NOTE(_C5), Q__NOTE(_G5), Q__NOTE(_F5), H__NOTE(_D5), H__NOTE(_C5), W__NOTE(_D5), W__NOTE(_E5), Q__NOTE(_A4), H__NOTE(_A4), Q__NOTE(_E5), Q__NOTE(_E5), Q__NOTE(_F5), Q__NOTE(_E5), Q__NOTE(_D5), Q__NOTE(_G5), Q__NOTE(_B4), Q__NOTE(_D5), Q__NOTE(_C5), M__NOTE(_F5, 80), H__NOTE(_D5), H__NOTE(_C5), W__NOTE(_D5), W__NOTE(_E5), Q__NOTE(_A4), H__NOTE(_A4), Q__NOTE(_E5), Q__NOTE(_E5), Q__NOTE(_F5), Q__NOTE(_E5), Q__NOTE(_D5), Q__NOTE(_G5), Q__NOTE(_B4), Q__NOTE(_D5), Q__NOTE(_C5), M__NOTE(_F5, 80) + /* Removed sounds + This list is here solely for compatibility, so that removed songs don't just break things * If you think that any of these songs were wrongfully removed, let us know and provide diff --git a/quantum/keyboard.c b/quantum/keyboard.c index a65f9d6d18..8273299a9a 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -381,7 +381,7 @@ void keyboard_init(void) { #ifdef ENCODER_ENABLE encoder_init(); #endif -#ifdef STENO_ENABLE +#ifdef STENO_ENABLE_ALL steno_init(); #endif #ifdef POINTING_DEVICE_ENABLE diff --git a/quantum/keymap.h b/quantum/keymap.h index d64b271efb..081bc54ebe 100644 --- a/quantum/keymap.h +++ b/quantum/keymap.h @@ -55,3 +55,5 @@ extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; // Ensure we have a forward declaration for the encoder map # include "encoder.h" #endif + +#include "keymap_introspection.h" diff --git a/quantum/keymap_extras/keymap_steno.h b/quantum/keymap_extras/keymap_steno.h index e888ccd643..07d96b7465 100644 --- a/quantum/keymap_extras/keymap_steno.h +++ b/quantum/keymap_extras/keymap_steno.h @@ -89,3 +89,31 @@ enum steno_combined_keycodes { STN_COMB_MAX = STN_EU, }; #endif + +#ifdef STENO_ENABLE_BOLT +// TxBolt Codes +# define TXB_NUL 0 +# define TXB_S_L 0b00000001 +# define TXB_T_L 0b00000010 +# define TXB_K_L 0b00000100 +# define TXB_P_L 0b00001000 +# define TXB_W_L 0b00010000 +# define TXB_H_L 0b00100000 +# define TXB_R_L 0b01000001 +# define TXB_A_L 0b01000010 +# define TXB_O_L 0b01000100 +# define TXB_STR 0b01001000 +# define TXB_E_R 0b01010000 +# define TXB_U_R 0b01100000 +# define TXB_F_R 0b10000001 +# define TXB_R_R 0b10000010 +# define TXB_P_R 0b10000100 +# define TXB_B_R 0b10001000 +# define TXB_L_R 0b10010000 +# define TXB_G_R 0b10100000 +# define TXB_T_R 0b11000001 +# define TXB_S_R 0b11000010 +# define TXB_D_R 0b11000100 +# define TXB_Z_R 0b11001000 +# define TXB_NUM 0b11010000 +#endif // STENO_ENABLE_BOLT diff --git a/quantum/keymap_introspection.c b/quantum/keymap_introspection.c new file mode 100644 index 0000000000..9628b41eef --- /dev/null +++ b/quantum/keymap_introspection.c @@ -0,0 +1,25 @@ +// Copyright 2022 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later + +// Pull the actual keymap code so that we can inspect stuff from it +#include KEYMAP_C + +#include "keymap_introspection.h" + +#define NUM_KEYMAP_LAYERS ((uint8_t)(sizeof(keymaps) / ((MATRIX_ROWS) * (MATRIX_COLS) * sizeof(uint16_t)))) + +uint8_t keymap_layer_count(void) { + return NUM_KEYMAP_LAYERS; +} + +#if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) + +# define NUM_ENCODERMAP_LAYERS ((uint8_t)(sizeof(encoder_map) / ((NUM_ENCODERS) * (2) * sizeof(uint16_t)))) + +uint8_t encodermap_layer_count(void) { + return NUM_ENCODERMAP_LAYERS; +} + +_Static_assert(NUM_KEYMAP_LAYERS == NUM_ENCODERMAP_LAYERS, "Number of encoder_map layers doesn't match the number of keymap layers"); + +#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) diff --git a/quantum/keymap_introspection.h b/quantum/keymap_introspection.h new file mode 100644 index 0000000000..23f6f2016f --- /dev/null +++ b/quantum/keymap_introspection.h @@ -0,0 +1,15 @@ +// Copyright 2022 Nick Brassel (@tzarc) +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include <stdint.h> + +// Get the number of layers defined in the keymap +uint8_t keymap_layer_count(void); + +#if defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) + +// Get the number of layers defined in the encoder map +uint8_t encodermap_layer_count(void); + +#endif // defined(ENCODER_ENABLE) && defined(ENCODER_MAP_ENABLE) diff --git a/quantum/mousekey.c b/quantum/mousekey.c index 64d0e66682..81e887d529 100644 --- a/quantum/mousekey.c +++ b/quantum/mousekey.c @@ -66,11 +66,18 @@ uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX; /* milliseconds between the initial key press and first repeated motion event (0-2550) */ uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10; /* milliseconds between repeated motion events (0-255) */ -uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL; +# ifdef MK_KINETIC_SPEED +float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; +# else +uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL; +# endif uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED; uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; # ifndef MK_COMBINED +# ifndef MK_KINETIC_SPEED + +/* Default accelerated mode */ static uint8_t move_unit(void) { uint16_t unit; @@ -108,8 +115,7 @@ static uint8_t wheel_unit(void) { return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); } -# else /* #ifndef MK_COMBINED */ -# ifdef MK_KINETIC_SPEED +# else /* #ifndef MK_KINETIC_SPEED */ /* * Kinetic movement acceleration algorithm @@ -147,27 +153,27 @@ static uint8_t move_unit(void) { return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed; } -float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; - static uint8_t wheel_unit(void) { float speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS; if (mousekey_accel & ((1 << 0) | (1 << 2))) { speed = mousekey_accel & (1 << 2) ? MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS : MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS; - } else if (mousekey_repeat && mouse_timer) { + } else if (mousekey_wheel_repeat && mouse_timer) { if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) { const float time_elapsed = timer_elapsed(mouse_timer) / 50; speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + 1 * 0.5 * time_elapsed * time_elapsed; } speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed; } - mk_wheel_interval = 1000.0f / speed; - return 1; + return (uint8_t)speed > MOUSEKEY_WHEEL_INITIAL_MOVEMENTS ? 2 : 1; } -# else /* #ifndef MK_KINETIC_SPEED */ +# endif /* #ifndef MK_KINETIC_SPEED */ +# else /* #ifndef MK_COMBINED */ + +/* Combined mode */ static uint8_t move_unit(void) { uint16_t unit; @@ -205,8 +211,7 @@ static uint8_t wheel_unit(void) { return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); } -# endif /* #ifndef MK_KINETIC_SPEED */ -# endif /* #ifndef MK_COMBINED */ +# endif /* #ifndef MK_COMBINED */ void mousekey_task(void) { // report cursor and scroll movement independently diff --git a/quantum/mousekey.h b/quantum/mousekey.h index 03da5f282a..d44f47fc1f 100644 --- a/quantum/mousekey.h +++ b/quantum/mousekey.h @@ -39,7 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # ifndef MK_KINETIC_SPEED # define MOUSEKEY_MOVE_DELTA 8 # else -# define MOUSEKEY_MOVE_DELTA 5 +# define MOUSEKEY_MOVE_DELTA 16 # endif # endif # ifndef MOUSEKEY_WHEEL_DELTA @@ -82,7 +82,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # define MOUSEKEY_INITIAL_SPEED 100 # endif # ifndef MOUSEKEY_BASE_SPEED -# define MOUSEKEY_BASE_SPEED 1000 +# define MOUSEKEY_BASE_SPEED 5000 # endif # ifndef MOUSEKEY_DECELERATED_SPEED # define MOUSEKEY_DECELERATED_SPEED 400 diff --git a/quantum/pointing_device.c b/quantum/pointing_device.c index a160647890..3c2e2bc09d 100644 --- a/quantum/pointing_device.c +++ b/quantum/pointing_device.c @@ -177,7 +177,8 @@ __attribute__((weak)) void pointing_device_send(void) { report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report) { // Support rotation of the sensor data #if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270) - int8_t x = mouse_report.x, y = mouse_report.y; + mouse_xy_report_t x = mouse_report.x; + mouse_xy_report_t y = mouse_report.y; # if defined(POINTING_DEVICE_ROTATION_90) mouse_report.x = y; mouse_report.y = -x; @@ -347,7 +348,7 @@ void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) { * @param[in] int16_t value * @return int8_t clamped value */ -static inline int8_t pointing_device_movement_clamp(int16_t value) { +static inline int8_t pointing_device_hv_clamp(int16_t value) { if (value < INT8_MIN) { return INT8_MIN; } else if (value > INT8_MAX) { @@ -358,6 +359,21 @@ static inline int8_t pointing_device_movement_clamp(int16_t value) { } /** + * @brief clamps int16_t to int8_t + * + * @param[in] clamp_range_t value + * @return mouse_xy_report_t clamped value + */ +static inline mouse_xy_report_t pointing_device_xy_clamp(clamp_range_t value) { + if (value < XY_REPORT_MIN) { + return XY_REPORT_MIN; + } else if (value > XY_REPORT_MAX) { + return XY_REPORT_MAX; + } else { + return value; + } +} +/** * @brief combines 2 mouse reports and returns 2 * * Combines 2 report_mouse_t structs, clamping movement values to int8_t and ignores report_id then returns the resulting report_mouse_t struct. @@ -369,10 +385,10 @@ static inline int8_t pointing_device_movement_clamp(int16_t value) { * @return combined report_mouse_t of left_report and right_report */ report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report) { - left_report.x = pointing_device_movement_clamp((int16_t)left_report.x + right_report.x); - left_report.y = pointing_device_movement_clamp((int16_t)left_report.y + right_report.y); - left_report.h = pointing_device_movement_clamp((int16_t)left_report.h + right_report.h); - left_report.v = pointing_device_movement_clamp((int16_t)left_report.v + right_report.v); + left_report.x = pointing_device_xy_clamp((clamp_range_t)left_report.x + right_report.x); + left_report.y = pointing_device_xy_clamp((clamp_range_t)left_report.y + right_report.y); + left_report.h = pointing_device_hv_clamp((int16_t)left_report.h + right_report.h); + left_report.v = pointing_device_hv_clamp((int16_t)left_report.v + right_report.v); left_report.buttons |= right_report.buttons; return left_report; } @@ -390,7 +406,8 @@ report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, repor report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report) { // Support rotation of the sensor data # if defined(POINTING_DEVICE_ROTATION_90_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT) - int8_t x = mouse_report.x, y = mouse_report.y; + mouse_xy_report_t x = mouse_report.x; + mouse_xy_report_t y = mouse_report.y; # if defined(POINTING_DEVICE_ROTATION_90_RIGHT) mouse_report.x = y; mouse_report.y = -x; diff --git a/quantum/pointing_device.h b/quantum/pointing_device.h index 5c0eaeaf34..1e5ef9590c 100644 --- a/quantum/pointing_device.h +++ b/quantum/pointing_device.h @@ -75,6 +75,16 @@ typedef enum { POINTING_DEVICE_BUTTON8, } pointing_device_buttons_t; +#ifdef MOUSE_EXTENDED_REPORT +# define XY_REPORT_MIN INT16_MIN +# define XY_REPORT_MAX INT16_MAX +typedef int32_t clamp_range_t; +#else +# define XY_REPORT_MIN INT8_MIN +# define XY_REPORT_MAX INT8_MAX +typedef int16_t clamp_range_t; +#endif + void pointing_device_init(void); void pointing_device_task(void); void pointing_device_send(void); diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c index 56363c7ac6..41d7018c86 100644 --- a/quantum/pointing_device_drivers.c +++ b/quantum/pointing_device_drivers.c @@ -22,8 +22,8 @@ #include "timer.h" #include <stddef.h> -// hid mouse reports cannot exceed -127 to 127, so constrain to that value -#define constrain_hid(amt) ((amt) < -127 ? -127 : ((amt) > 127 ? 127 : (amt))) +#define CONSTRAIN_HID(amt) ((amt) < INT8_MIN ? INT8_MIN : ((amt) > INT8_MAX ? INT8_MAX : (amt))) +#define CONSTRAIN_HID_XY(amt) ((amt) < XY_REPORT_MIN ? XY_REPORT_MIN : ((amt) > XY_REPORT_MAX ? XY_REPORT_MAX : (amt))) // get_report functions should probably be moved to their respective drivers. #if defined(POINTING_DEVICE_DRIVER_adns5050) @@ -35,8 +35,8 @@ report_mouse_t adns5050_get_report(report_mouse_t mouse_report) { if (debug_mouse) dprintf("Raw ] X: %d, Y: %d\n", data.dx, data.dy); # endif - mouse_report.x = data.dx; - mouse_report.y = data.dy; + mouse_report.x = (mouse_xy_report_t)data.dx; + mouse_report.y = (mouse_xy_report_t)data.dy; } return mouse_report; @@ -55,11 +55,8 @@ const pointing_device_driver_t pointing_device_driver = { report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) { report_adns9800_t sensor_report = adns9800_get_report(); - int8_t clamped_x = constrain_hid(sensor_report.x); - int8_t clamped_y = constrain_hid(sensor_report.y); - - mouse_report.x = clamped_x; - mouse_report.y = clamped_y; + mouse_report.x = CONSTRAIN_HID_XY(sensor_report.x); + mouse_report.y = CONSTRAIN_HID_XY(sensor_report.y); return mouse_report; } @@ -107,16 +104,16 @@ const pointing_device_driver_t pointing_device_driver = { # endif report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { - pinnacle_data_t touchData = cirque_pinnacle_read_data(); - static uint16_t x = 0, y = 0, mouse_timer = 0; - int8_t report_x = 0, report_y = 0; - static bool is_z_down = false; + pinnacle_data_t touchData = cirque_pinnacle_read_data(); + static uint16_t x = 0, y = 0, mouse_timer = 0; + mouse_xy_report_t report_x = 0, report_y = 0; + static bool is_z_down = false; cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); // Scale coordinates to arbitrary X, Y resolution if (x && y && touchData.xValue && touchData.yValue) { - report_x = (int8_t)(touchData.xValue - x); - report_y = (int8_t)(touchData.yValue - y); + report_x = (mouse_xy_report_t)(touchData.xValue - x); + report_y = (mouse_xy_report_t)(touchData.yValue - y); } x = touchData.xValue; y = touchData.yValue; @@ -157,11 +154,26 @@ const pointing_device_driver_t pointing_device_driver = { // clang-format on #elif defined(POINTING_DEVICE_DRIVER_pimoroni_trackball) + +mouse_xy_report_t pimoroni_trackball_adapt_values(clamp_range_t* offset) { + if (*offset > XY_REPORT_MAX) { + *offset -= XY_REPORT_MAX; + return (mouse_xy_report_t)XY_REPORT_MAX; + } else if (*offset < XY_REPORT_MIN) { + *offset += XY_REPORT_MAX; + return (mouse_xy_report_t)XY_REPORT_MIN; + } else { + mouse_xy_report_t temp_return = *offset; + *offset = 0; + return temp_return; + } +} + report_mouse_t pimoroni_trackball_get_report(report_mouse_t mouse_report) { - static uint16_t debounce = 0; - static uint8_t error_count = 0; - pimoroni_data_t pimoroni_data = {0}; - static int16_t x_offset = 0, y_offset = 0; + static uint16_t debounce = 0; + static uint8_t error_count = 0; + pimoroni_data_t pimoroni_data = {0}; + static clamp_range_t x_offset = 0, y_offset = 0; if (error_count < PIMORONI_TRACKBALL_ERROR_COUNT) { i2c_status_t status = read_pimoroni_trackball(&pimoroni_data); @@ -174,8 +186,8 @@ report_mouse_t pimoroni_trackball_get_report(report_mouse_t mouse_report) { if (!debounce) { x_offset += pimoroni_trackball_get_offsets(pimoroni_data.right, pimoroni_data.left, PIMORONI_TRACKBALL_SCALE); y_offset += pimoroni_trackball_get_offsets(pimoroni_data.down, pimoroni_data.up, PIMORONI_TRACKBALL_SCALE); - pimoroni_trackball_adapt_values(&mouse_report.x, &x_offset); - pimoroni_trackball_adapt_values(&mouse_report.y, &y_offset); + mouse_report.x = pimoroni_trackball_adapt_values(&x_offset); + mouse_report.y = pimoroni_trackball_adapt_values(&y_offset); } else { debounce--; } @@ -221,8 +233,8 @@ report_mouse_t pmw3360_get_report(report_mouse_t mouse_report) { # endif MotionStart = timer_read(); } - mouse_report.x = constrain_hid(data.dx); - mouse_report.y = constrain_hid(data.dy); + mouse_report.x = CONSTRAIN_HID_XY(data.dx); + mouse_report.y = CONSTRAIN_HID_XY(data.dy); } return mouse_report; @@ -259,8 +271,8 @@ report_mouse_t pmw3389_get_report(report_mouse_t mouse_report) { # endif MotionStart = timer_read(); } - mouse_report.x = constrain_hid(data.dx); - mouse_report.y = constrain_hid(data.dy); + mouse_report.x = CONSTRAIN_HID_XY(data.dx); + mouse_report.y = CONSTRAIN_HID_XY(data.dy); } return mouse_report; diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c index 12ee898212..20b8b9db4b 100644 --- a/quantum/process_keycode/process_steno.c +++ b/quantum/process_keycode/process_steno.c @@ -1,4 +1,4 @@ -/* Copyright 2017 Joseph Wasson +/* Copyright 2017, 2022 Joseph Wasson, Vladislav Kucheriavykh * * 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 @@ -15,77 +15,118 @@ */ #include "process_steno.h" #include "quantum_keycodes.h" -#include "eeprom.h" #include "keymap_steno.h" -#include "virtser.h" #include <string.h> +#ifdef VIRTSER_ENABLE +# include "virtser.h" +#endif +#ifdef STENO_ENABLE_ALL +# include "eeprom.h" +#endif -// TxBolt Codes -#define TXB_NUL 0 -#define TXB_S_L 0b00000001 -#define TXB_T_L 0b00000010 -#define TXB_K_L 0b00000100 -#define TXB_P_L 0b00001000 -#define TXB_W_L 0b00010000 -#define TXB_H_L 0b00100000 -#define TXB_R_L 0b01000001 -#define TXB_A_L 0b01000010 -#define TXB_O_L 0b01000100 -#define TXB_STR 0b01001000 -#define TXB_E_R 0b01010000 -#define TXB_U_R 0b01100000 -#define TXB_F_R 0b10000001 -#define TXB_R_R 0b10000010 -#define TXB_P_R 0b10000100 -#define TXB_B_R 0b10001000 -#define TXB_L_R 0b10010000 -#define TXB_G_R 0b10100000 -#define TXB_T_R 0b11000001 -#define TXB_S_R 0b11000010 -#define TXB_D_R 0b11000100 -#define TXB_Z_R 0b11001000 -#define TXB_NUM 0b11010000 - -#define TXB_GRP0 0b00000000 -#define TXB_GRP1 0b01000000 -#define TXB_GRP2 0b10000000 -#define TXB_GRP3 0b11000000 -#define TXB_GRPMASK 0b11000000 - -#define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6) - -#define BOLT_STATE_SIZE 4 -#define GEMINI_STATE_SIZE 6 -#define MAX_STATE_SIZE GEMINI_STATE_SIZE - -static uint8_t state[MAX_STATE_SIZE] = {0}; -static uint8_t chord[MAX_STATE_SIZE] = {0}; -static int8_t pressed = 0; +// All steno keys that have been pressed to form this chord, +// stored in MAX_STROKE_SIZE groups of 8-bit arrays. +static uint8_t chord[MAX_STROKE_SIZE] = {0}; +// The number of physical keys actually being held down. +// This is not always equal to the number of 1 bits in `chord` because it is possible to +// simultaneously press down four keys, then release three of those four keys and then press yet +// another key while the fourth finger is still holding down its key. +// At the end of this scenario given as an example, `chord` would have five bits set to 1 but +// `n_pressed_keys` would be set to 2 because there are only two keys currently being pressed down. +static int8_t n_pressed_keys = 0; + +#ifdef STENO_ENABLE_ALL static steno_mode_t mode; - -static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R}; - -#ifdef STENO_COMBINEDMAP -/* Used to look up when pressing the middle row key to combine two consonant or vowel keys */ -static const uint16_t combinedmap_first[] PROGMEM = {STN_S1, STN_TL, STN_PL, STN_HL, STN_FR, STN_PR, STN_LR, STN_TR, STN_DR, STN_A, STN_E}; -static const uint16_t combinedmap_second[] PROGMEM = {STN_S2, STN_KL, STN_WL, STN_RL, STN_RR, STN_BR, STN_GR, STN_SR, STN_ZR, STN_O, STN_U}; +#elif defined(STENO_ENABLE_GEMINI) +static const steno_mode_t mode = STENO_MODE_GEMINI; +#elif defined(STENO_ENABLE_BOLT) +static const steno_mode_t mode = STENO_MODE_BOLT; #endif -static void steno_clear_state(void) { - memset(state, 0, sizeof(state)); +static inline void steno_clear_chord(void) { memset(chord, 0, sizeof(chord)); } -static void send_steno_state(uint8_t size, bool send_empty) { - for (uint8_t i = 0; i < size; ++i) { - if (chord[i] || send_empty) { -#ifdef VIRTSER_ENABLE +#ifdef STENO_ENABLE_GEMINI + +# ifdef VIRTSER_ENABLE +void send_steno_chord_gemini(void) { + // Set MSB to 1 to indicate the start of packet + chord[0] |= 0x80; + for (uint8_t i = 0; i < GEMINI_STROKE_SIZE; ++i) { + virtser_send(chord[i]); + } +} +# else +# pragma message "VIRTSER_ENABLE = yes is required for Gemini PR to work properly out of the box!" +# endif // VIRTSER_ENABLE + +/** + * @precondition: `key` is pressed + */ +bool add_gemini_key_to_chord(uint8_t key) { + // Although each group of the packet is 8 bits long, the MSB is reserved + // to indicate whether that byte is the first byte of the packet (MSB=1) + // or one of the remaining five bytes of the packet (MSB=0). + // As a consequence, only 7 out of the 8 bits are left to be used as a bit array + // for the steno keys of that group. + const int group_idx = key / 7; + const int intra_group_idx = key - group_idx * 7; + // The 0th steno key of the group has bit=0b01000000, the 1st has bit=0b00100000, etc. + const uint8_t bit = 1 << (6 - intra_group_idx); + chord[group_idx] |= bit; + return false; +} +#endif // STENO_ENABLE_GEMINI + +#ifdef STENO_ENABLE_BOLT + +# define TXB_GRP0 0b00000000 +# define TXB_GRP1 0b01000000 +# define TXB_GRP2 0b10000000 +# define TXB_GRP3 0b11000000 +# define TXB_GRPMASK 0b11000000 + +# define TXB_GET_GROUP(code) ((code & TXB_GRPMASK) >> 6) + +static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R}; + +# ifdef VIRTSER_ENABLE +static void send_steno_chord_bolt(void) { + for (uint8_t i = 0; i < BOLT_STROKE_SIZE; ++i) { + // TX Bolt uses variable length packets where each byte corresponds to a bit array of certain keys. + // If a user chorded the keys of the first group with keys of the last group, for example, there + // would be bytes of 0x00 in `chord` for the middle groups which we mustn't send. + if (chord[i]) { virtser_send(chord[i]); -#endif } } + // Sending a null packet is not always necessary, but it is simpler and more reliable + // to unconditionally send it every time instead of keeping track of more states and + // creating more branches in the execution of the program. + virtser_send(0); } +# else +# pragma message "VIRTSER_ENABLE = yes is required for TX Bolt to work properly out of the box!" +# endif // VIRTSER_ENABLE + +/** + * @precondition: `key` is pressed + */ +static bool add_bolt_key_to_chord(uint8_t key) { + uint8_t boltcode = pgm_read_byte(boltmap + key); + chord[TXB_GET_GROUP(boltcode)] |= boltcode; + return false; +} +#endif // STENO_ENABLE_BOLT |