merge from master

This commit is contained in:
Jack Humbert 2021-02-07 21:01:30 -05:00
commit 3996250d81
11279 changed files with 499671 additions and 99678 deletions

View file

@ -1,5 +1,4 @@
#ifndef PROCESS_AUDIO_H
#define PROCESS_AUDIO_H
#pragma once
float compute_freq_for_midi_note(uint8_t note);
@ -9,5 +8,3 @@ void process_audio_noteoff(uint8_t note);
void process_audio_all_notes_off(void);
void audio_on_user(void);
#endif

View file

@ -16,15 +16,152 @@
#ifdef AUTO_SHIFT_ENABLE
# include <stdbool.h>
# include <stdio.h>
# include "process_auto_shift.h"
static bool autoshift_enabled = true;
static uint16_t autoshift_time = 0;
static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
static uint16_t autoshift_lastkey = KC_NO;
static struct {
// Whether autoshift is enabled.
bool enabled : 1;
// Whether the last auto-shifted key was released after the timeout. This
// is used to replicate the last key for a tap-then-hold.
bool lastshifted : 1;
// Whether an auto-shiftable key has been pressed but not processed.
bool in_progress : 1;
// Whether the auto-shifted keypress has been registered.
bool holding_shift : 1;
} autoshift_flags = {true, false, false, false};
/** \brief Record the press of an autoshiftable key
*
* \return Whether the record should be further processed.
*/
static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) {
if (!autoshift_flags.enabled) {
return true;
}
# ifndef AUTO_SHIFT_MODIFIERS
if (get_mods() & (~MOD_BIT(KC_LSFT))) {
return true;
}
# endif
# ifdef AUTO_SHIFT_REPEAT
const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
if (!autoshift_flags.lastshifted) {
# endif
if (elapsed < TAPPING_TERM && keycode == autoshift_lastkey) {
// Allow a tap-then-hold for keyrepeat.
if (!autoshift_flags.lastshifted) {
register_code(autoshift_lastkey);
} else {
// Simulate pressing the shift key.
add_weak_mods(MOD_BIT(KC_LSFT));
register_code(autoshift_lastkey);
}
return false;
}
# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
}
# endif
# endif
// Record the keycode so we can simulate it later.
autoshift_lastkey = keycode;
autoshift_time = now;
autoshift_flags.in_progress = true;
# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
# endif
return false;
}
/** \brief Registers an autoshiftable key under the right conditions
*
* If the autoshift delay has elapsed, register a shift and the key.
*
* If the autoshift key is released before the delay has elapsed, register the
* key without a shift.
*/
static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) {
// Called on key down with KC_NO, auto-shifted key up, and timeout.
if (autoshift_flags.in_progress) {
// Process the auto-shiftable key.
autoshift_flags.in_progress = false;
// Time since the initial press was recorded.
const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
if (elapsed < autoshift_timeout) {
register_code(autoshift_lastkey);
autoshift_flags.lastshifted = false;
} else {
// Simulate pressing the shift key.
add_weak_mods(MOD_BIT(KC_LSFT));
register_code(autoshift_lastkey);
autoshift_flags.lastshifted = true;
# if defined(AUTO_SHIFT_REPEAT) && !defined(AUTO_SHIFT_NO_AUTO_REPEAT)
if (matrix_trigger) {
// Prevents release.
return;
}
# endif
}
# if TAP_CODE_DELAY > 0
wait_ms(TAP_CODE_DELAY);
# endif
unregister_code(autoshift_lastkey);
del_weak_mods(MOD_BIT(KC_LSFT));
} else {
// Release after keyrepeat.
unregister_code(keycode);
if (keycode == autoshift_lastkey) {
// This will only fire when the key was the last auto-shiftable
// pressed. That prevents aaaaBBBB then releasing a from unshifting
// later Bs (if B wasn't auto-shiftable).
del_weak_mods(MOD_BIT(KC_LSFT));
}
}
send_keyboard_report(); // del_weak_mods doesn't send one.
// Roll the autoshift_time forward for detecting tap-and-hold.
autoshift_time = now;
}
/** \brief Simulates auto-shifted key releases when timeout is hit
*
* Can be called from \c matrix_scan_user so that auto-shifted keys are sent
* immediately after the timeout has expired, rather than waiting for the key
* to be released.
*/
void autoshift_matrix_scan(void) {
if (autoshift_flags.in_progress) {
const uint16_t now = timer_read();
const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
if (elapsed >= autoshift_timeout) {
autoshift_end(autoshift_lastkey, now, true);
}
}
}
void autoshift_toggle(void) {
autoshift_flags.enabled = !autoshift_flags.enabled;
del_weak_mods(MOD_BIT(KC_LSFT));
}
void autoshift_enable(void) { autoshift_flags.enabled = true; }
void autoshift_disable(void) {
autoshift_flags.enabled = false;
del_weak_mods(MOD_BIT(KC_LSFT));
}
# ifndef AUTO_SHIFT_NO_SETUP
void autoshift_timer_report(void) {
char display[8];
@ -32,63 +169,29 @@ void autoshift_timer_report(void) {
send_string((const char *)display);
}
# endif
void autoshift_on(uint16_t keycode) {
autoshift_time = timer_read();
autoshift_lastkey = keycode;
}
void autoshift_flush(void) {
if (autoshift_lastkey != KC_NO) {
uint16_t elapsed = timer_elapsed(autoshift_time);
if (elapsed > autoshift_timeout) {
tap_code16(LSFT(autoshift_lastkey));
} else {
tap_code(autoshift_lastkey);
}
autoshift_time = 0;
autoshift_lastkey = KC_NO;
}
}
void autoshift_enable(void) { autoshift_enabled = true; }
void autoshift_disable(void) {
autoshift_enabled = false;
autoshift_flush();
}
void autoshift_toggle(void) {
if (autoshift_enabled) {
autoshift_enabled = false;
autoshift_flush();
} else {
autoshift_enabled = true;
}
}
bool get_autoshift_state(void) { return autoshift_enabled; }
bool get_autoshift_state(void) { return autoshift_flags.enabled; }
uint16_t get_autoshift_timeout(void) { return autoshift_timeout; }
void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; }
bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
// Note that record->event.time isn't reliable, see:
// https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550
const uint16_t now = timer_read();
if (record->event.pressed) {
if (autoshift_flags.in_progress) {
// Evaluate previous key if there is one. Doing this elsewhere is
// more complicated and easier to break.
autoshift_end(KC_NO, now, false);
}
// For pressing another key while keyrepeating shifted autoshift.
del_weak_mods(MOD_BIT(KC_LSFT));
switch (keycode) {
case KC_ASUP:
autoshift_timeout += 5;
return true;
case KC_ASDN:
autoshift_timeout -= 5;
return true;
case KC_ASRP:
autoshift_timer_report();
return true;
case KC_ASTG:
autoshift_toggle();
return true;
@ -99,41 +202,40 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
autoshift_disable();
return true;
# ifndef NO_AUTO_SHIFT_ALPHA
case KC_A ... KC_Z:
# endif
# ifndef NO_AUTO_SHIFT_NUMERIC
case KC_1 ... KC_0:
# endif
# ifndef NO_AUTO_SHIFT_SPECIAL
case KC_TAB:
case KC_MINUS ... KC_SLASH:
case KC_NONUS_BSLASH:
# endif
autoshift_flush();
if (!autoshift_enabled) return true;
# ifndef AUTO_SHIFT_MODIFIERS
if (get_mods()) {
return true;
}
# endif
autoshift_on(keycode);
// We need some extra handling here for OSL edge cases
# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
# endif
return false;
default:
autoshift_flush();
# ifndef AUTO_SHIFT_NO_SETUP
case KC_ASUP:
autoshift_timeout += 5;
return true;
case KC_ASDN:
autoshift_timeout -= 5;
return true;
case KC_ASRP:
autoshift_timer_report();
return true;
# endif
}
} else {
autoshift_flush();
}
switch (keycode) {
# ifndef NO_AUTO_SHIFT_ALPHA
case KC_A ... KC_Z:
# endif
# ifndef NO_AUTO_SHIFT_NUMERIC
case KC_1 ... KC_0:
# endif
# ifndef NO_AUTO_SHIFT_SPECIAL
case KC_TAB:
case KC_MINUS ... KC_SLASH:
case KC_NONUS_BSLASH:
# endif
if (record->event.pressed) {
return autoshift_press(keycode, now, record);
} else {
autoshift_end(keycode, now, false);
return false;
}
}
return true;
}

View file

@ -30,3 +30,4 @@ void autoshift_toggle(void);
bool get_autoshift_state(void);
uint16_t get_autoshift_timeout(void);
void set_autoshift_timeout(uint16_t timeout);
void autoshift_matrix_scan(void);

View file

@ -1,5 +1,4 @@
#ifndef PROCESS_CLICKY_H
#define PROCESS_CLICKY_H
#pragma once
void clicky_play(void);
bool process_clicky(uint16_t keycode, keyrecord_t *record);
@ -13,5 +12,3 @@ void clicky_on(void);
void clicky_off(void);
bool is_clicky_on(void);
#endif

View file

@ -24,10 +24,10 @@ extern combo_t key_combos[];
extern int COMBO_LEN;
#endif
__attribute__((weak)) void process_combo_event(uint8_t combo_index, bool pressed) {}
__attribute__((weak)) void process_combo_event(uint16_t combo_index, bool pressed) {}
static uint16_t timer = 0;
static uint8_t current_combo_index = 0;
static uint16_t current_combo_index = 0;
static bool drop_buffer = false;
static bool is_active = false;
static bool b_combo_enable = true; // defaults to enabled
@ -82,8 +82,8 @@ static inline void dump_key_buffer(bool emit) {
} while (0)
static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) {
uint8_t count = 0;
uint8_t index = -1;
uint8_t count = 0;
uint16_t index = -1;
/* Find index of keycode and number of combo keys */
for (const uint16_t *keys = combo->keys;; ++count) {
uint16_t key = pgm_read_word(&keys[count]);

View file

@ -14,8 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_COMBO_H
#define PROCESS_COMBO_H
#pragma once
#include "progmem.h"
#include "quantum.h"
@ -56,11 +55,9 @@ typedef struct {
bool process_combo(uint16_t keycode, keyrecord_t *record);
void matrix_scan_combo(void);
void process_combo_event(uint8_t combo_index, bool pressed);
void process_combo_event(uint16_t combo_index, bool pressed);
void combo_enable(void);
void combo_disable(void);
void combo_toggle(void);
bool is_combo_enabled(void);
#endif

View file

@ -216,11 +216,13 @@ bool process_dynamic_macro(uint16_t keycode, keyrecord_t *record) {
} else {
/* A macro is being recorded right now. */
switch (keycode) {
case DYN_REC_START1:
case DYN_REC_START2:
case DYN_REC_STOP:
/* Stop the macro recording. */
if (record->event.pressed) { /* Ignore the initial release
* just after the recoding
* starts. */
if (record->event.pressed ^ (keycode != DYN_REC_STOP)) { /* Ignore the initial release
* just after the recording
* starts for DYN_REC_STOP. */
switch (macro_id) {
case 1:
dynamic_macro_record_end(macro_buffer, macro_pointer, +1, &macro_end);

View file

@ -17,8 +17,8 @@ bool process_joystick(uint16_t keycode, keyrecord_t *record) {
return true;
}
__attribute__((weak))
void joystick_task(void) {
__attribute__((weak)) void joystick_task(void) {
if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)) {
send_joystick_packet(&joystick_status);
joystick_status.status &= ~JS_UPDATED;
@ -47,16 +47,11 @@ uint16_t savePinState(pin_t pin) {
return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1);
#elif defined(PROTOCOL_CHIBIOS)
/*
The pin configuration is backed up in the following format :
The pin configuration is backed up in the following format :
bit 15 9 8 7 6 5 4 3 2 1 0
|unused|ODR|IDR|PUPDR|OSPEEDR|OTYPER|MODER|
*/
return (( PAL_PORT(pin)->MODER >> (2*PAL_PAD(pin))) & 0x3)
| (((PAL_PORT(pin)->OTYPER >> (1*PAL_PAD(pin))) & 0x1) << 2)
| (((PAL_PORT(pin)->OSPEEDR >> (2*PAL_PAD(pin))) & 0x3) << 3)
| (((PAL_PORT(pin)->PUPDR >> (2*PAL_PAD(pin))) & 0x3) << 5)
| (((PAL_PORT(pin)->IDR >> (1*PAL_PAD(pin))) & 0x1) << 7)
| (((PAL_PORT(pin)->ODR >> (1*PAL_PAD(pin))) & 0x1) << 8);
return ((PAL_PORT(pin)->MODER >> (2 * PAL_PAD(pin))) & 0x3) | (((PAL_PORT(pin)->OTYPER >> (1 * PAL_PAD(pin))) & 0x1) << 2) | (((PAL_PORT(pin)->OSPEEDR >> (2 * PAL_PAD(pin))) & 0x3) << 3) | (((PAL_PORT(pin)->PUPDR >> (2 * PAL_PAD(pin))) & 0x3) << 5) | (((PAL_PORT(pin)->IDR >> (1 * PAL_PAD(pin))) & 0x1) << 7) | (((PAL_PORT(pin)->ODR >> (1 * PAL_PAD(pin))) & 0x1) << 8);
#else
return 0;
#endif
@ -68,12 +63,12 @@ void restorePinState(pin_t pin, uint16_t restoreState) {
PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber);
DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber);
#elif defined(PROTOCOL_CHIBIOS)
PAL_PORT(pin)->MODER = (PAL_PORT(pin)->MODER & ~(0x3<< (2*PAL_PAD(pin)))) | (restoreState & 0x3) << (2*PAL_PAD(pin));
PAL_PORT(pin)->OTYPER = (PAL_PORT(pin)->OTYPER & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>2) & 0x1) << (1*PAL_PAD(pin));
PAL_PORT(pin)->OSPEEDR= (PAL_PORT(pin)->OSPEEDR & ~(0x3<< (2*PAL_PAD(pin)))) | ((restoreState>>3) & 0x3) << (2*PAL_PAD(pin));
PAL_PORT(pin)->PUPDR = (PAL_PORT(pin)->PUPDR & ~(0x3<< (2*PAL_PAD(pin)))) | ((restoreState>>5) & 0x3) << (2*PAL_PAD(pin));
PAL_PORT(pin)->IDR = (PAL_PORT(pin)->IDR & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>7) & 0x1) << (1*PAL_PAD(pin));
PAL_PORT(pin)->ODR = (PAL_PORT(pin)->ODR & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>8) & 0x1) << (1*PAL_PAD(pin));
PAL_PORT(pin)->MODER = (PAL_PORT(pin)->MODER & ~(0x3 << (2 * PAL_PAD(pin)))) | (restoreState & 0x3) << (2 * PAL_PAD(pin));
PAL_PORT(pin)->OTYPER = (PAL_PORT(pin)->OTYPER & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 2) & 0x1) << (1 * PAL_PAD(pin));
PAL_PORT(pin)->OSPEEDR = (PAL_PORT(pin)->OSPEEDR & ~(0x3 << (2 * PAL_PAD(pin)))) | ((restoreState >> 3) & 0x3) << (2 * PAL_PAD(pin));
PAL_PORT(pin)->PUPDR = (PAL_PORT(pin)->PUPDR & ~(0x3 << (2 * PAL_PAD(pin)))) | ((restoreState >> 5) & 0x3) << (2 * PAL_PAD(pin));
PAL_PORT(pin)->IDR = (PAL_PORT(pin)->IDR & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 7) & 0x1) << (1 * PAL_PAD(pin));
PAL_PORT(pin)->ODR = (PAL_PORT(pin)->ODR & ~(0x1 << (1 * PAL_PAD(pin)))) | ((restoreState >> 8) & 0x1) << (1 * PAL_PAD(pin));
#else
return;
#endif
@ -132,21 +127,21 @@ bool process_joystick_analogread_quantum() {
int16_t axis_val = joystick_axes[axis_index].mid_digit;
# endif
//test the converted value against the lower range
int32_t ref = joystick_axes[axis_index].mid_digit;
int32_t range = joystick_axes[axis_index].min_digit;
int32_t ranged_val = ((axis_val - ref) * -127) / (range - ref) ;
// test the converted value against the lower range
int32_t ref = joystick_axes[axis_index].mid_digit;
int32_t range = joystick_axes[axis_index].min_digit;
int32_t ranged_val = ((axis_val - ref) * -JOYSTICK_RESOLUTION) / (range - ref);
if (ranged_val > 0) {
//the value is in the higher range
range = joystick_axes[axis_index].max_digit;
ranged_val = ((axis_val - ref) * 127) / (range - ref);
// the value is in the higher range
range = joystick_axes[axis_index].max_digit;
ranged_val = ((axis_val - ref) * JOYSTICK_RESOLUTION) / (range - ref);
}
//clamp the result in the valid range
ranged_val = ranged_val < -127 ? -127 : ranged_val;
ranged_val = ranged_val > 127 ? 127 : ranged_val;
// clamp the result in the valid range
ranged_val = ranged_val < -JOYSTICK_RESOLUTION ? -JOYSTICK_RESOLUTION : ranged_val;
ranged_val = ranged_val > JOYSTICK_RESOLUTION ? JOYSTICK_RESOLUTION : ranged_val;
if (ranged_val != joystick_status.axes[axis_index]) {
joystick_status.axes[axis_index] = ranged_val;
joystick_status.status |= JS_UPDATED;

View file

@ -14,8 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "inttypes.h"
#include "stdint.h"
#include <inttypes.h>
#include <stdint.h>
#include "process_key_lock.h"
#define BV_64(shift) (((uint64_t)1) << (shift))

View file

@ -14,11 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_KEY_LOCK_H
#define PROCESS_KEY_LOCK_H
#pragma once
#include "quantum.h"
bool process_key_lock(uint16_t *keycode, keyrecord_t *record);
#endif // PROCESS_KEY_LOCK_H

View file

@ -14,8 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_LEADER_H
#define PROCESS_LEADER_H
#pragma once
#include "quantum.h"
@ -37,5 +36,3 @@ void qk_leader_start(void);
extern uint16_t leader_sequence[5]; \
extern uint8_t leader_sequence_size
#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT)
#endif

View file

@ -41,12 +41,12 @@ static int8_t midi_modulation_step;
static uint16_t midi_modulation_timer;
midi_config_t midi_config;
inline uint8_t compute_velocity(uint8_t setting) { return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); }
inline uint8_t compute_velocity(uint8_t setting) { return setting * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN)); }
void midi_init(void) {
midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN;
midi_config.transpose = 0;
midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN);
midi_config.velocity = 127;
midi_config.channel = 0;
midi_config.modulation_interval = 8;
@ -66,12 +66,14 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
case MIDI_TONE_MIN ... MIDI_TONE_MAX: {
uint8_t channel = midi_config.channel;
uint8_t tone = keycode - MIDI_TONE_MIN;
uint8_t velocity = compute_velocity(midi_config.velocity);
uint8_t velocity = midi_config.velocity;
if (record->event.pressed) {
uint8_t note = midi_compute_note(keycode);
midi_send_noteon(&midi_device, channel, note, velocity);
dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
tone_status[tone] = note;
if (tone_status[tone] == MIDI_INVALID_NOTE) {
uint8_t note = midi_compute_note(keycode);
midi_send_noteon(&midi_device, channel, note, velocity);
dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
tone_status[tone] = note;
}
} else {
uint8_t note = tone_status[tone];
if (note != MIDI_INVALID_NOTE) {
@ -122,19 +124,30 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
return false;
case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX:
if (record->event.pressed) {
midi_config.velocity = keycode - MIDI_VELOCITY_MIN;
midi_config.velocity = compute_velocity(keycode - MIDI_VELOCITY_MIN);
dprintf("midi velocity %d\n", midi_config.velocity);
}
return false;
case MI_VELD:
if (record->event.pressed && midi_config.velocity > 0) {
midi_config.velocity--;
if (midi_config.velocity == 127) {
midi_config.velocity -= 10;
} else if (midi_config.velocity > 12) {
midi_config.velocity -= 13;
} else {
midi_config.velocity = 0;
}
dprintf("midi velocity %d\n", midi_config.velocity);
}
return false;
case MI_VELU:
if (record->event.pressed) {
midi_config.velocity++;
if (record->event.pressed && midi_config.velocity < 127) {
if (midi_config.velocity < 115) {
midi_config.velocity += 13;
} else {
midi_config.velocity = 127;
}
dprintf("midi velocity %d\n", midi_config.velocity);
}
return false;

View file

@ -14,8 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_MIDI_H
#define PROCESS_MIDI_H
#pragma once
#include "quantum.h"
@ -35,7 +34,7 @@ typedef union {
struct {
uint8_t octave : 4;
int8_t transpose : 4;
uint8_t velocity : 4;
uint8_t velocity : 7;
uint8_t channel : 4;
uint8_t modulation_interval : 4;
};
@ -53,5 +52,3 @@ uint8_t midi_compute_note(uint16_t keycode);
# endif // MIDI_ADVANCED
#endif // MIDI_ENABLE
#endif

View file

@ -191,7 +191,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
note = music_starting_note + music_offset + 36 + music_map[record->event.key.row][record->event.key.col];
} else {
uint8_t position = music_map[record->event.key.row][record->event.key.col];
note = music_starting_note + music_offset + 36 + SCALE[position % 12] + (position / 12) * 12;
note = music_starting_note + music_offset + 36 + SCALE[position % 7] + (position / 7) * 12;
}
# else
if (music_mode == MUSIC_MODE_CHROMATIC)

View file

@ -14,8 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_MUSIC_H
#define PROCESS_MUSIC_H
#pragma once
#include "quantum.h"
@ -57,5 +56,3 @@ bool music_mask_user(uint16_t keycode);
# endif
#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
#endif

View file

@ -14,13 +14,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_PRINTER_H
#define PROCESS_PRINTER_H
#pragma once
#include "quantum.h"
#include "protocol/serial.h"
bool process_printer(uint16_t keycode, keyrecord_t *record);
#endif

View file

@ -23,6 +23,7 @@ typedef void (*rgb_func_pointer)(void);
*
* noinline to optimise for firmware size not speed (not in hot path)
*/
#if (defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)) || (defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES))
static void __attribute__((noinline)) handleKeycodeRGB(const uint8_t is_shifted, const rgb_func_pointer inc_func, const rgb_func_pointer dec_func) {
if (is_shifted) {
dec_func();
@ -30,6 +31,7 @@ static void __attribute__((noinline)) handleKeycodeRGB(const uint8_t is_shifted,
inc_func();
}
}
#endif
/**
* Wrapper for animation mode
@ -56,81 +58,152 @@ bool process_rgb(const uint16_t keycode, const keyrecord_t *record) {
// Split keyboards need to trigger on key-up for edge-case issue
if (!record->event.pressed) {
#endif
uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT));
#if (defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)) || (defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES))
uint8_t shifted = get_mods() & MOD_MASK_SHIFT;
#endif
switch (keycode) {
case RGB_TOG:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
rgblight_toggle();
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
rgb_matrix_toggle();
#endif
return false;
case RGB_MODE_FORWARD:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_step, rgblight_step_reverse);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_step, rgb_matrix_step_reverse);
#endif
return false;
case RGB_MODE_REVERSE:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_step_reverse, rgblight_step);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_step_reverse, rgb_matrix_step);
#endif
return false;
case RGB_HUI:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_increase_hue, rgblight_decrease_hue);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_increase_hue, rgb_matrix_decrease_hue);
#endif
return false;
case RGB_HUD:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_decrease_hue, rgblight_increase_hue);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_decrease_hue, rgb_matrix_increase_hue);
#endif
return false;
case RGB_SAI:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_increase_sat, rgblight_decrease_sat);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_increase_sat, rgb_matrix_decrease_sat);
#endif
return false;
case RGB_SAD:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_decrease_sat, rgblight_increase_sat);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_decrease_sat, rgb_matrix_increase_sat);
#endif
return false;
case RGB_VAI:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_increase_val, rgblight_decrease_val);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_increase_val, rgb_matrix_decrease_val);
#endif
return false;
case RGB_VAD:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_decrease_val, rgblight_increase_val);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_decrease_val, rgb_matrix_increase_val);
#endif
return false;
case RGB_SPI:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_increase_speed, rgblight_decrease_speed);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_increase_speed, rgb_matrix_decrease_speed);
#endif
return false;
case RGB_SPD:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgblight_decrease_speed, rgblight_increase_speed);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
handleKeycodeRGB(shifted, rgb_matrix_decrease_speed, rgb_matrix_increase_speed);
#endif
return false;
case RGB_MODE_PLAIN:
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES)
rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES)
rgb_matrix_mode(RGB_MATRIX_SOLID_COLOR);
#endif
return false;
case RGB_MODE_BREATHE:
#ifdef RGBLIGHT_EFFECT_BREATHING
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_BREATHING)
handleKeycodeRGBMode(RGBLIGHT_MODE_BREATHING, RGBLIGHT_MODE_BREATHING_end);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES) && !defined(DISABLE_RGB_MATRIX_BREATHING)
rgb_matrix_mode(RGB_MATRIX_BREATHING);
#endif
return false;
case RGB_MODE_RAINBOW:
#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_RAINBOW_MOOD)
handleKeycodeRGBMode(RGBLIGHT_MODE_RAINBOW_MOOD, RGBLIGHT_MODE_RAINBOW_MOOD_end);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES) && !defined(DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT)
rgb_matrix_mode(RGB_MATRIX_CYCLE_LEFT_RIGHT);
#endif
return false;
case RGB_MODE_SWIRL:
#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL)
handleKeycodeRGBMode(RGBLIGHT_MODE_RAINBOW_SWIRL, RGBLIGHT_MODE_RAINBOW_SWIRL_end);
#endif
#if defined(RGB_MATRIX_ENABLE) && !defined(RGB_MATRIX_DISABLE_KEYCODES) && !defined(DISABLE_RGB_MATRIX_CYCLE_PINWHEEL)
rgb_matrix_mode(RGB_MATRIX_CYCLE_PINWHEEL);
#endif
return false;
case RGB_MODE_SNAKE:
#ifdef RGBLIGHT_EFFECT_SNAKE
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_SNAKE)
handleKeycodeRGBMode(RGBLIGHT_MODE_SNAKE, RGBLIGHT_MODE_SNAKE_end);
#endif
return false;
case RGB_MODE_KNIGHT:
#ifdef RGBLIGHT_EFFECT_KNIGHT
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_KNIGHT)
handleKeycodeRGBMode(RGBLIGHT_MODE_KNIGHT, RGBLIGHT_MODE_KNIGHT_end);
#endif
return false;
case RGB_MODE_XMAS:
#ifdef RGBLIGHT_EFFECT_CHRISTMAS
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_CHRISTMAS)
rgblight_mode(RGBLIGHT_MODE_CHRISTMAS);
#endif
return false;
case RGB_MODE_GRADIENT:
#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_STATIC_GRADIENT)
handleKeycodeRGBMode(RGBLIGHT_MODE_STATIC_GRADIENT, RGBLIGHT_MODE_STATIC_GRADIENT_end);
#endif
return false;
case RGB_MODE_RGBTEST:
#ifdef RGBLIGHT_EFFECT_RGB_TEST
#if defined(RGBLIGHT_ENABLE) && !defined(RGBLIGHT_DISABLE_KEYCODES) && defined(RGBLIGHT_EFFECT_RGB_TEST)
rgblight_mode(RGBLIGHT_MODE_RGB_TEST);
#endif
return false;

View file

@ -0,0 +1,62 @@
/* Copyright 2020 Rodolphe Belouin
*
* 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 "process_sequencer.h"
bool process_sequencer(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
switch (keycode) {
case SQ_ON:
sequencer_on();
return false;
case SQ_OFF:
sequencer_off();
return false;
case SQ_TOG:
sequencer_toggle();
return false;
case SQ_TMPD:
sequencer_decrease_tempo();
return false;
case SQ_TMPU:
sequencer_increase_tempo();
return false;
case SEQUENCER_RESOLUTION_MIN ... SEQUENCER_RESOLUTION_MAX:
sequencer_set_resolution(keycode - SEQUENCER_RESOLUTION_MIN);
return false;
case SQ_RESD:
sequencer_decrease_resolution();
return false;
case SQ_RESU:
sequencer_increase_resolution();
return false;
case SQ_SALL:
sequencer_set_all_steps_on();
return false;
case SQ_SCLR:
sequencer_set_all_steps_off();
return false;
case SEQUENCER_STEP_MIN ... SEQUENCER_STEP_MAX:
sequencer_toggle_step(keycode - SEQUENCER_STEP_MIN);
return false;
case SEQUENCER_TRACK_MIN ... SEQUENCER_TRACK_MAX:
sequencer_toggle_single_active_track(keycode - SEQUENCER_TRACK_MIN);
return false;
}
}
return true;
}

View file

@ -0,0 +1,21 @@
/* Copyright 2020 Rodolphe Belouin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "quantum.h"
bool process_sequencer(uint16_t keycode, keyrecord_t *record);

View file

@ -14,10 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "process_space_cadet.h"
#ifndef TAPPING_TERM
# define TAPPING_TERM 200
#endif
#include "action_tapping.h"
// ********** OBSOLETE DEFINES, STOP USING! (pls?) **********
// Shift / paren setup
@ -85,7 +82,7 @@ static uint16_t sc_timer = 0;
static uint8_t sc_mods = 0;
#endif
void perform_space_cadet(keyrecord_t *record, uint8_t holdMod, uint8_t tapMod, uint8_t keycode) {
void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdMod, uint8_t tapMod, uint8_t keycode) {
if (record->event.pressed) {
sc_last = holdMod;
sc_timer = timer_read();
@ -96,7 +93,12 @@ void perform_space_cadet(keyrecord_t *record, uint8_t holdMod, uint8_t tapMod, u
register_mods(MOD_BIT(holdMod));
}
} else {
if (sc_last == holdMod && timer_elapsed(sc_timer) < TAPPING_TERM) {
#ifdef TAPPING_TERM_PER_KEY
if (sc_last == holdMod && timer_elapsed(sc_timer) < get_tapping_term(sc_keycode, record))
#else
if (sc_last == holdMod && timer_elapsed(sc_timer) < TAPPING_TERM)
#endif
{
if (holdMod != tapMod) {
if (IS_MOD(holdMod)) {
unregister_mods(MOD_BIT(holdMod));
@ -126,31 +128,31 @@ void perform_space_cadet(keyrecord_t *record, uint8_t holdMod, uint8_t tapMod, u
bool process_space_cadet(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_LSPO: {
perform_space_cadet(record, LSPO_KEYS);
perform_space_cadet(record, keycode, LSPO_KEYS);
return false;
}
case KC_RSPC: {
perform_space_cadet(record, RSPC_KEYS);
perform_space_cadet(record, keycode, RSPC_KEYS);
return false;
}
case KC_LCPO: {
perform_space_cadet(record, LCPO_KEYS);
perform_space_cadet(record, keycode, LCPO_KEYS);
return false;
}
case KC_RCPC: {
perform_space_cadet(record, RCPC_KEYS);
perform_space_cadet(record, keycode, RCPC_KEYS);
return false;
}
case KC_LAPO: {
perform_space_cadet(record, LAPO_KEYS);
perform_space_cadet(record, keycode, LAPO_KEYS);
return false;
}
case KC_RAPC: {
perform_space_cadet(record, RAPC_KEYS);
perform_space_cadet(record, keycode, RAPC_KEYS);
return false;
}
case KC_SFTENT: {
perform_space_cadet(record, SFTENT_KEYS);
perform_space_cadet(record, keycode, SFTENT_KEYS);
return false;
}
default: {

View file

@ -17,5 +17,5 @@
#include "quantum.h"
void perform_space_cadet(keyrecord_t *record, uint8_t holdMod, uint8_t tapMod, uint8_t keycode);
void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdMod, uint8_t tapMod, uint8_t keycode);
bool process_space_cadet(uint16_t keycode, keyrecord_t *record);

View file

@ -13,8 +13,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_STENO_H
#define PROCESS_STENO_H
#pragma once
#include "quantum.h"
@ -25,5 +25,3 @@ void steno_init(void);
void steno_set_mode(steno_mode_t mode);
uint8_t *steno_get_state(void);
uint8_t *steno_get_chord(void);
#endif

View file

@ -14,11 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "quantum.h"
#include "action_tapping.h"
#ifndef TAPPING_TERM
# define TAPPING_TERM 200
#endif
#ifndef NO_ACTION_ONESHOT
uint8_t get_oneshot_mods(void);
@ -171,7 +166,11 @@ void matrix_scan_tap_dance() {
if (action->custom_tapping_term > 0) {
tap_user_defined = action->custom_tapping_term;
} else {
#ifdef TAPPING_TERM_PER_KEY
tap_user_defined = get_tapping_term(action->state.keycode, NULL);
#else
tap_user_defined = TAPPING_TERM;
#endif
}
if (action->state.count && timer_elapsed(action->state.timer) > tap_user_defined) {
process_tap_dance_action_on_dance_finished(action);

View file

@ -13,8 +13,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_TAP_DANCE_H
#define PROCESS_TAP_DANCE_H
#pragma once
#ifdef TAP_DANCE_ENABLE
@ -101,5 +101,3 @@ void qk_tap_dance_dual_role_reset(qk_tap_dance_state_t *state, void *user_data);
# define TD(n) KC_NO
#endif
#endif

View file

@ -14,8 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_TERMINAL_H
#define PROCESS_TERMINAL_H
#pragma once
#include "quantum.h"
@ -23,5 +22,3 @@ extern const char keycode_to_ascii_lut[58];
extern const char shifted_keycode_to_ascii_lut[58];
extern const char terminal_prompt[8];
bool process_terminal(uint16_t keycode, keyrecord_t *record);
#endif

View file

@ -14,12 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROCESS_TERMINAL_H
#define PROCESS_TERMINAL_H
#pragma once
#include "quantum.h"
#define TERM_ON KC_NO
#define TERM_OFF KC_NO
#endif

View file

@ -27,7 +27,7 @@ void qk_ucis_start(void) {
__attribute__((weak)) void qk_ucis_start_user(void) {
unicode_input_start();
register_hex(0x2328);
register_hex(0x2328); // ⌨
unicode_input_finish();
}
@ -35,117 +35,95 @@ __attribute__((weak)) void qk_ucis_success(uint8_t symbol_index) {}
static bool is_uni_seq(char *seq) {
uint8_t i;
for (i = 0; seq[i]; i++) {
uint16_t code;
if (('1' <= seq[i]) && (seq[i] <= '0'))
code = seq[i] - '1' + KC_1;
else
code = seq[i] - 'a' + KC_A;
if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code) return false;
uint16_t keycode;
if ('1' <= seq[i] && seq[i] <= '0') {
keycode = seq[i] - '1' + KC_1;
} else {
keycode = seq[i] - 'a' + KC_A;
}
if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != keycode) {
return false;
}
}
return (qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC);
return qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC;
}
__attribute__((weak)) void qk_ucis_symbol_fallback(void) {
for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
uint8_t code = qk_ucis_state.codes[i];
register_code(code);
unregister_code(code);
uint8_t keycode = qk_ucis_state.codes[i];
register_code(keycode);
unregister_code(keycode);
wait_ms(UNICODE_TYPE_DELAY);
}
}
__attribute__((weak)) void qk_ucis_cancel(void) {}
void register_ucis(const char *hex) {
for (int i = 0; hex[i]; i++) {
uint8_t kc = 0;
char c = hex[i];
switch (c) {
case '0':
kc = KC_0;
break;
case '1' ... '9':
kc = c - '1' + KC_1;
break;
case 'a' ... 'f':
kc = c - 'a' + KC_A;
break;
case 'A' ... 'F':
kc = c - 'A' + KC_A;
break;
}
if (kc) {
register_code(kc);
unregister_code(kc);
wait_ms(UNICODE_TYPE_DELAY);
}
void register_ucis(const uint32_t *code_points) {
for (int i = 0; i < UCIS_MAX_CODE_POINTS && code_points[i]; i++) {
register_unicode(code_points[i]);
wait_ms(UNICODE_TYPE_DELAY);
}
}
bool process_ucis(uint16_t keycode, keyrecord_t *record) {
uint8_t i;
if (!qk_ucis_state.in_progress) return true;
if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
return false;
if (!qk_ucis_state.in_progress || !record->event.pressed) {
return true;
}
if (!record->event.pressed) return true;
bool special = keycode == KC_SPC || keycode == KC_ENT || keycode == KC_ESC || keycode == KC_BSPC;
if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !special) {
return false;
}
qk_ucis_state.codes[qk_ucis_state.count] = keycode;
qk_ucis_state.count++;
if (keycode == KC_BSPC) {
if (qk_ucis_state.count >= 2) {
qk_ucis_state.count -= 2;
return true;
} else {
qk_ucis_state.count--;
return false;
}
}
if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
bool symbol_found = false;
for (i = qk_ucis_state.count; i > 0; i--) {
register_code(KC_BSPC);
unregister_code(KC_BSPC);
wait_ms(UNICODE_TYPE_DELAY);
}
if (keycode == KC_ESC) {
qk_ucis_state.in_progress = false;
qk_ucis_cancel();
return false;
}
unicode_input_start();
for (i = 0; ucis_symbol_table[i].symbol; i++) {
if (is_uni_seq(ucis_symbol_table[i].symbol)) {
symbol_found = true;
register_ucis(ucis_symbol_table[i].code + 2);
break;
switch (keycode) {
case KC_BSPC:
if (qk_ucis_state.count >= 2) {
qk_ucis_state.count -= 2;
return true;
} else {
qk_ucis_state.count--;
return false;
}
}
if (!symbol_found) {
qk_ucis_symbol_fallback();
}
unicode_input_finish();
if (symbol_found) {
qk_ucis_success(i);
}
case KC_SPC:
case KC_ENT:
case KC_ESC:
for (uint8_t i = 0; i < qk_ucis_state.count; i++) {
register_code(KC_BSPC);
unregister_code(KC_BSPC);
wait_ms(UNICODE_TYPE_DELAY);
}
qk_ucis_state.in_progress = false;
return false;
if (keycode == KC_ESC) {
qk_ucis_state.in_progress = false;
qk_ucis_cancel();
return false;
}
uint8_t i;
bool symbol_found = false;
for (i = 0; ucis_symbol_table[i].symbol; i++) {
if (is_uni_seq(ucis_symbol_table[i].symbol)) {
symbol_found = true;
register_ucis(ucis_symbol_table[i].code_points);
break;
}
}
if (symbol_found) {
qk_ucis_success(i);
} else {
qk_ucis_symbol_fallback();
}
qk_ucis_state.in_progress = false;
return false;
default:
return true;
}
return true;
}

View file

@ -22,10 +22,13 @@
#ifndef UCIS_MAX_SYMBOL_LENGTH
# define UCIS_MAX_SYMBOL_LENGTH 32
#endif
#ifndef UCIS_MAX_CODE_POINTS
# define UCIS_MAX_CODE_POINTS 3
#endif
typedef struct {
char *symbol;
char *code;
char * symbol;
uint32_t code_points[UCIS_MAX_CODE_POINTS];
} qk_ucis_symbol_t;
typedef struct {
@ -36,12 +39,17 @@ typedef struct {
extern qk_ucis_state_t qk_ucis_state;
#define UCIS_TABLE(...) \
{ \
__VA_ARGS__, { NULL, NULL } \
// clang-format off
#define UCIS_TABLE(...) \
{ \
__VA_ARGS__, \
{ NULL, {} } \
}
#define UCIS_SYM(name, code) \
{ name, #code }
#define UCIS_SYM(name, ...) \
{ name, {__VA_ARGS__} }
// clang-format on
extern const qk_ucis_symbol_t ucis_symbol_table[];
@ -49,5 +57,7 @@ void qk_ucis_start(void);
void qk_ucis_start_user(void);
void qk_ucis_symbol_fallback(void);
void qk_ucis_success(uint8_t symbol_index);
void register_ucis(const char *hex);
void register_ucis(const uint32_t *code_points);
bool process_ucis(uint16_t keycode, keyrecord_t *record);

View file

@ -21,11 +21,12 @@
unicode_config_t unicode_config;
uint8_t unicode_saved_mods;
bool unicode_saved_caps_lock;
#if UNICODE_SELECTED_MODES != -1
static uint8_t selected[] = {UNICODE_SELECTED_MODES};
static uint8_t selected_count = sizeof selected / sizeof *selected;
static uint8_t selected_index;
static int8_t selected_count = sizeof selected / sizeof *selected;
static int8_t selected_index;
#endif
void unicode_input_mode_init(void) {
@ -33,7 +34,7 @@ void unicode_input_mode_init(void) {
#if UNICODE_SELECTED_MODES != -1
# if UNICODE_CYCLE_PERSIST
// Find input_mode in selected modes
uint8_t i;
int8_t i;
for (i = 0; i < selected_count; i++) {
if (selected[i] == unicode_config.input_mode) {
selected_index = i;
@ -60,9 +61,12 @@ void set_unicode_input_mode(uint8_t mode) {
dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode);
}
void cycle_unicode_input_mode(uint8_t offset) {
void cycle_unicode_input_mode(int8_t offset) {
#if UNICODE_SELECTED_MODES != -1
selected_index = (selected_index + offset) % selected_count;
selected_index = (selected_index + offset) % selected_count;
if (selected_index < 0) {
selected_index += selected_count;
}
unicode_config.input_mode = selected[selected_index];
# if UNICODE_CYCLE_PERSIST
persist_unicode_input_mode();
@ -74,6 +78,16 @@ void cycle_unicode_input_mode(uint8_t offset) {
void persist_unicode_input_mode(void) { eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode); }
__attribute__((weak)) void unicode_input_start(void) {
unicode_saved_caps_lock = host_keyboard_led_state().caps_lock;
// Note the order matters here!
// Need to do this before we mess around with the mods, or else
// UNICODE_KEY_LNX (which is usually Ctrl-Shift-U) might not work
// correctly in the shifted case.
if (unicode_config.input_mode == UC_LNX && unicode_saved_caps_lock) {
tap_code(KC_CAPS);
}
unicode_saved_mods = get_mods(); // Save current mods
clear_mods(); // Unregister mods to start from a clean state
@ -104,6 +118,9 @@ __attribute__((weak)) void unicode_input_finish(void) {
break;
case UC_LNX:
tap_code(KC_SPC);
if (unicode_saved_caps_lock) {
tap_code(KC_CAPS);
}
break;
case UC_WIN:
unregister_code(KC_LALT);
@ -122,6 +139,11 @@ __attribute__((weak)) void unicode_input_cancel(void) {
unregister_code(UNICODE_KEY_MAC);
break;
case UC_LNX:
tap_code(KC_ESC);
if (unicode_saved_caps_lock) {
tap_code(KC_CAPS);
}
break;
case UC_WINC:
tap_code(KC_ESC);
break;
@ -133,20 +155,10 @@ __attribute__((weak)) void unicode_input_cancel(void) {
set_mods(unicode_saved_mods); // Reregister previously set mods
}
__attribute__((weak)) uint16_t hex_to_keycode(uint8_t hex) {
if (hex == 0x0) {
return KC_0;
} else if (hex < 0xA) {
return KC_1 + (hex - 0x1);
} else {
return KC_A + (hex - 0xA);
}
}
void register_hex(uint16_t hex) {
for (int i = 3; i >= 0; i--) {
uint8_t digit = ((hex >> (i * 4)) & 0xF);
tap_code(hex_to_keycode(digit));
tap_code16(hex_to_keycode(digit));
}
}
@ -159,15 +171,36 @@ void register_hex32(uint32_t hex) {
uint8_t digit = ((hex >> (i * 4)) & 0xF);
if (digit == 0) {
if (!onzerostart) {
tap_code(hex_to_keycode(digit));
tap_code16(hex_to_keycode(digit));
}
} else {
tap_code(hex_to_keycode(digit));
tap_code16(hex_to_keycode(digit));
onzerostart = false;
}
}
}
void register_unicode(uint32_t code_point) {
if (code_point > 0x10FFFF || (code_point > 0xFFFF && unicode_config.input_mode == UC_WIN)) {
// Code point out of range, do nothing
return;
}
unicode_input_start();
if (code_point > 0xFFFF && unicode_config.input_mode == UC_MAC) {
// Convert code point to UTF-16 surrogate pair on macOS
code_point -= 0x10000;
uint32_t lo = code_point & 0x3FF, hi = (code_point & 0xFFC00) >> 10;
register_hex32(hi + 0xD800);
register_hex32(lo + 0xDC00);
} else {
register_hex32(code_point);
}
unicode_input_finish();
}
// clang-format off
void send_unicode_hex_string(const char *str) {
if (!str) {
return;
@ -175,12 +208,11 @@ void send_unicode_hex_string(const char *str) {
while (*str) {
// Find the next code point (token) in the string
for (; *str == ' '; str++)
;
for (; *str == ' '; str++); // Skip leading spaces
size_t n = strcspn(str, " "); // Length of the current token
char code_point[n + 1];
strncpy(code_point, str, n);
code_point[n] = '\0'; // Make sure it's null-terminated
char code_point[n+1];
strncpy(code_point, str, n); // Copy token into buffer
code_point[n] = '\0'; // Make sure it's null-terminated
// Normalize the code point: make all hex digits lowercase
for (char *p = code_point; *p; p++) {
@ -196,8 +228,10 @@ void send_unicode_hex_string(const char *str) {
}
}
// clang-format on
// Borrowed from https://nullprogram.com/blog/2017/10/06/
const char *decode_utf8(const char *str, int32_t *code_point) {
static const char *decode_utf8(const char *str, int32_t *code_point) {
const char *next;
if (str[0] < 0x80) { // U+0000-007F
@ -230,66 +264,80 @@ void send_unicode_string(const char *str) {
return;
}
int32_t code_point = 0;
while (*str) {
str = decode_utf8(str, &code_point);
int32_t code_point = 0;
str = decode_utf8(str, &code_point);
if (code_point >= 0) {
unicode_input_start();
register_hex32(code_point);
unicode_input_finish();
register_unicode(code_point);
}
}
}
// clang-format off
static void audio_helper(void) {
#ifdef AUDIO_ENABLE
switch (get_unicode_input_mode()) {
# ifdef UNICODE_SONG_MAC
static float song_mac[][2] = UNICODE_SONG_MAC;
case UC_MAC:
PLAY_SONG(song_mac);
break;
# endif
# ifdef UNICODE_SONG_LNX
static float song_lnx[][2] = UNICODE_SONG_LNX;
case UC_LNX:
PLAY_SONG(song_lnx);
break;
# endif
# ifdef UNICODE_SONG_WIN
static float song_win[][2] = UNICODE_SONG_WIN;
case UC_WIN:
PLAY_SONG(song_win);
break;
# endif
# ifdef UNICODE_SONG_BSD
static float song_bsd[][2] = UNICODE_SONG_BSD;
case UC_BSD:
PLAY_SONG(song_bsd);
break;
# endif
# ifdef UNICODE_SONG_WINC
static float song_winc[][2] = UNICODE_SONG_WINC;
case UC_WINC:
PLAY_SONG(song_winc);
break;
# endif
}
#endif
}
// clang-format on
bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) {
bool shifted = get_mods() & MOD_MASK_SHIFT;
switch (keycode) {
case UNICODE_MODE_FORWARD:
cycle_unicode_input_mode(+1);
cycle_unicode_input_mode(shifted ? -1 : +1);
audio_helper();
break;
case UNICODE_MODE_REVERSE:
cycle_unicode_input_mode(-1);
cycle_unicode_input_mode(shifted ? +1 : -1);
audio_helper();
break;
case UNICODE_MODE_MAC:
set_unicode_input_mode(UC_MAC);
#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_MAC)
static float song_mac[][2] = UNICODE_SONG_MAC;
PLAY_SONG(song_mac);
#endif
break;
case UNICODE_MODE_LNX:
set_unicode_input_mode(UC_LNX);
#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_LNX)
static float song_lnx[][2] = UNICODE_SONG_LNX;
PLAY_SONG(song_lnx);
#endif
break;
case UNICODE_MODE_WIN:
set_unicode_input_mode(UC_WIN);
#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WIN)
static float song_win[][2] = UNICODE_SONG_WIN;
PLAY_SONG(song_win);
#endif
break;
case UNICODE_MODE_BSD:
set_unicode_input_mode(UC_BSD);
#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_BSD)
static float song_bsd[][2] = UNICODE_SONG_BSD;
PLAY_SONG(song_bsd);
#endif
break;
case UNICODE_MODE_WINC:
set_unicode_input_mode(UC_WINC);
#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WINC)
static float song_winc[][2] = UNICODE_SONG_WINC;
PLAY_SONG(song_winc);
#endif
case UNICODE_MODE_MAC ... UNICODE_MODE_WINC: {
// Keycodes and input modes follow the same ordering
uint8_t delta = keycode - UNICODE_MODE_MAC;
set_unicode_input_mode(UC_MAC + delta);
audio_helper();
break;
}
}
}
#if defined(UNICODE_ENABLE)
return process_unicode(keycode, record);
#elif defined(UNICODEMAP_ENABLE)

View file

@ -75,12 +75,11 @@ typedef union {
} unicode_config_t;
extern unicode_config_t unicode_config;
extern uint8_t unicode_saved_mods;
void unicode_input_mode_init(void);
uint8_t get_unicode_input_mode(void);
void set_unicode_input_mode(uint8_t mode);
void cycle_unicode_input_mode(uint8_t offset);
void cycle_unicode_input_mode(int8_t offset);
void persist_unicode_input_mode(void);
void unicode_input_start(void);
@ -89,6 +88,8 @@ void unicode_input_cancel(void);
void register_hex(uint16_t hex);
void register_hex32(uint32_t hex);
void register_unicode(uint32_t code_point);
void send_unicode_hex_string(const char *str);
void send_unicode_string(const char *str);

View file

@ -21,7 +21,13 @@ __attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {
// Keycode is a pair: extract index based on Shift / Caps Lock state
uint16_t index = keycode - QK_UNICODEMAP_PAIR;
bool shift = unicode_saved_mods & MOD_MASK_SHIFT, caps = IS_HOST_LED_ON(USB_LED_CAPS_LOCK);
uint8_t mods = get_mods() | get_weak_mods();
#ifndef NO_ACTION_ONESHOT
mods |= get_oneshot_mods();
#endif
bool shift = mods & MOD_MASK_SHIFT;
bool caps = host_keyboard_led_state().caps_lock;
if (shift ^ caps) {
index >>= 7;
}
@ -35,25 +41,8 @@ __attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {
bool process_unicodemap(uint16_t keycode, keyrecord_t *record) {
if (keycode >= QK_UNICODEMAP && keycode <= QK_UNICODEMAP_PAIR_MAX && record->event.pressed) {
unicode_input_start();
uint32_t code = pgm_read_dword(unicode_map + unicodemap_index(keycode));
uint8_t input_mode = get_unicode_input_mode();
if (code > 0x10FFFF || (code > 0xFFFF && input_mode == UC_WIN)) {
// Character is out of range supported by the platform
unicode_input_cancel();
} else if (code > 0xFFFF && input_mode == UC_MAC) {
// Convert to UTF-16 surrogate pair on Mac
code -= 0x10000;
uint32_t lo = code & 0x3FF, hi = (code & 0xFFC00) >> 10;
register_hex32(hi + 0xD800);
register_hex32(lo + 0xDC00);
unicode_input_finish();
} else {
register_hex32(code);
unicode_input_finish();
}
uint32_t code_point = pgm_read_dword(unicode_map + unicodemap_index(keycode));
register_unicode(code_point);
}
return true;
}