如何用QMK实现键盘旋钮切换八度/移调?代码调试求助
QMK键盘旋钮实现MIDI八度切换/移调功能的修复方案
我希望通过转动键盘旋钮实现MIDI八度切换或移调功能,但现有代码无法正常触发对应功能,代码如下:
typedef enum { ENCODER_MODE_OCTAVE, ENCODER_MODE_TRANSPOSE, } encoder_mode_t; encoder_mode_t encoder_mode = ENCODER_MODE_OCTAVE; bool encoder_update_user(uint8_t index, bool clockwise) { if (layer_state_is(MIDI_BASE)) { if (clockwise) { if (encoder_mode == ENCODER_MODE_OCTAVE) { tap_code16(MI_OCTU); } else { tap_code16(MI_TRSU); } } else { if (encoder_mode == ENCODER_MODE_OCTAVE) { tap_code16(MI_OCTD); } else { tap_code16(MI_TRSD); } } } return false; }
当前问题:
- 转动旋钮时有反应,但未触发
MI_OCTx或MI_TRSx对应的MIDI功能 - 文档说明
tap_code16(<kc>)仅支持KC_x类普通键码,对此存疑 - 在keymap中直接使用
MI_OCTx或MI_TRSx是有效的 - 可通过
process_record_user修改MIDI音符值实现,但希望有更简便的方案
修复方案
tap_code16确实仅适用于普通键盘键码,MI_OCTx、MI_TRSx属于QMK MIDI模块的专用键码,这类键码的处理逻辑由MIDI模块在process_record_user中实现,直接调用tap_code16无法触发对应的MIDI操作。最简便的方式是直接调用QMK MIDI模块提供的API函数:
#include "midi.h" // 必须包含MIDI头文件 typedef enum { ENCODER_MODE_OCTAVE, ENCODER_MODE_TRANSPOSE, } encoder_mode_t; encoder_mode_t encoder_mode = ENCODER_MODE_OCTAVE; bool encoder_update_user(uint8_t index, bool clockwise) { if (layer_state_is(MIDI_BASE)) { if (clockwise) { if (encoder_mode == ENCODER_MODE_OCTAVE) { midi_increase_octave(); // 直接调用八度提升API } else { midi_increase_transpose(); // 直接调用移调提升API } } else { if (encoder_mode == ENCODER_MODE_OCTAVE) { midi_decrease_octave(); // 直接调用八度降低API } else { midi_decrease_transpose(); // 直接调用移调降低API } } } return false; }
替代方案(模拟键码触发)
如果坚持要通过键码模拟的方式实现,可以手动调用process_record_user来模拟按键按下/释放的过程,效果和keymap中使用键码一致:
typedef enum { ENCODER_MODE_OCTAVE, ENCODER_MODE_TRANSPOSE, } encoder_mode_t; encoder_mode_t encoder_mode = ENCODER_MODE_OCTAVE; bool encoder_update_user(uint8_t index, bool clockwise) { if (layer_state_is(MIDI_BASE)) { keyrecord_t record = { .event = { .key = (keypos_t){.row = 0, .col = 0}, // 位置参数不影响,可随意填写 .pressed = true } }; uint16_t target_code = 0; // 确定要触发的键码 if (clockwise) { target_code = (encoder_mode == ENCODER_MODE_OCTAVE) ? MI_OCTU : MI_TRSU; } else { target_code = (encoder_mode == ENCODER_MODE_OCTAVE) ? MI_OCTD : MI_TRSD; } // 模拟按键按下和释放 process_record_user(target_code, &record); record.event.pressed = false; process_record_user(target_code, &record); } return false; }
内容的提问来源于stack exchange,提问作者Max May
相关产品推荐
相关产品推荐

