custom_quantum_functions.md 15 KB

ζ̵Ĺ

ںܶ˵ƻ̿ɲֻĵԷ㰴Ǹô򵥡϶ʵֱȼ򵥰ͺӵĹܡQMKעĹ, ǹ, ⣬ԶڲͬµΪ

ҳٶκQMK֪ʶĶQMKڸIJⷢʲô

A Word on Core vs vs

ǰqmk֯һνṹ

  • Core (_quantum)
    • Keyboard/Revision (_kb)
    • Keymap (_user)

ÿһڶϼһ_kb() _user() ׺ ڼ/޶ʹ_kb()׺ڲֲʹ_user()׺

ڼ/޶㶨庯ʱ_kb()ִκδǰȵ_user()DZҪģȻֲ㺯ͲҪá

Զ

ĿǰΪֹǸмΪ򴴽µļ롣ӴǶЩơ

һ¼

һöٳȫҲǸֲΨһֵQMKûֱֵСṩһSAFE_RANGEꡣöʱSAFE_RANGE֤ȡΨһļֵ

öӡӵkeymap.cĻڲFOOBARˡ

enum my_keycodes {
  FOO = SAFE_RANGE,
  BAR
};

ΪΪ

㸲һѴڰΪʱΪ¼ʱҪprocess_record_kb()process_record_user()ڼʵ¼ǰQMKátrueQMKķʽ롣ԺܷչĹܶ滻false QMKȻͼ̧ǰ¼ˡ

ij»ͷʱᱻá

process_record_user()`ʾʵ

¡ԶһFOOļΪڰ»سʱ

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  switch (keycode) {
    case FOO:
      if (record->event.pressed) {
        // ʱЩʲô
      } else {
        // ͷʱЩʲô
      }
      return false; // ˼нһ
    case KC_ENTER:
      // »سʱ
      if (record->event.pressed) {
        PLAY_NOTE_ARRAY(tone_qwerty);
      }
      return true; // QMKس/ͷ¼
    default:
      return true; // 
  }
}

process_record_* ĵ

  • /޶: bool process_record_kb(uint16_t keycode, keyrecord_t *record)
  • : bool process_record_user(uint16_t keycode, keyrecord_t *record)

keycode()ڲ϶ģMO(1), KC_L, ȵȡ Ҫ switch...case Щ¼

recordʵʰϢ

keyrecord_t record {
  keyevent_t event {
    keypos_t key {
      uint8_t col
      uint8_t row
    }
    bool     pressed
    uint16_t time
  }
}

LED

qmkṩ˶ȡHID淶5LEDķ:

  • USB_LED_NUM_LOCK
  • USB_LED_CAPS_LOCK
  • USB_LED_SCROLL_LOCK
  • USB_LED_COMPOSE
  • USB_LED_KANA

ӦLED״̬λλ ַԻLED״̬

  • ִͨ led_set_user()
  • ͨ host_keyboard_leds()

led_set_user()

5LEDκһ״̬Ҫıʱ˺á˺ͨLED ʹIS_LED_ON(usb_led, led_name)IS_LED_OFF(usb_led, led_name)LED״̬

!> host_keyboard_leds()ܻled_set_user()ǰֵ

led_set_user()ʾʵ

void led_set_user(uint8_t usb_led) {
    if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) {
        writePinLow(B0);
    } else {
        writePinHigh(B0);
    }
    if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
        writePinLow(B1);
    } else {
        writePinHigh(B1);
    }
    if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) {
        writePinLow(B2);
    } else {
        writePinHigh(B2);
    }
    if (IS_LED_ON(usb_led, USB_LED_COMPOSE)) {
        writePinLow(B3);
    } else {
        writePinHigh(B3);
    }
    if (IS_LED_ON(usb_led, USB_LED_KANA)) {
        writePinLow(B4);
    } else {
        writePinHigh(B4);
    }
}

led_set_*ĵ

  • /޶: void led_set_kb(uint8_t usb_led)
  • : void led_set_user(uint8_t usb_led)

host_keyboard_leds()

᷵յLED״̬led_set_*֮ȡLED״̬ʱãmatrix_scan_user(). Ϊ˱ݣIS_HOST_LED_ON(led_name)IS_HOST_LED_OFF(led_name) ֱ꣬ӵúͼhost_keyboard_leds()

LED״̬

һЩʵΪLED״̬ṩ˷ķ

Ergodox Boards

Ergodoxʵṩergodox_right_led_1/2/3_on/off()ÿLED, Ҳ ergodox_right_led_on/off(uint8_t led) 򿪻رǡ

⣬ʹergodox_led_all_set(uint8_t n)ָLEDȼÿLEDergodox_right_led_1/2/3_set(uint8_t n)ʹĻergodox_right_led_set(uint8_t led, uint8_t n)

Ergodox boards ͬʱȼLED_BRIGHTNESS_LOȼLED_BRIGHTNESS_HI(Ĭ).

̳ʼ

̳ʼм衣ǸȡҪʲô

Ҫʼ˳г

  • keyboard_pre_init_* - ڴǰСЩҪǰеӲʼ
  • matrix_init_* - ڹ̼м䱻áʱӲѳʼδʼ
  • keyboard_post_init_* - ڹ̼󱻵á£ġƻ붼Է

!> ڴ˵keyboard_post_init_userҪõĺ, ʱRGBƷ⡣

Ԥʼ

뼫УUSBʼǰС

֮󲻾þͱʼˡ

ڴû˵,òΪҪӲijʼ

ӲʼĻٺò(ʼLEDһ).

keyboard_pre_init_user()ʾʵ

ڼ̼趨 B0, B1, B2, B3, B4 LEDš

void keyboard_pre_init_user(void) {
  // üԤʼ

  // LEDΪģʽ
  setPinOutput(B0);
  setPinOutput(B1);
  setPinOutput(B2);
  setPinOutput(B3);
  setPinOutput(B4);
}

keyboard_pre_init_* ĵ

  • /޶: void keyboard_pre_init_kb(void)
  • : void keyboard_pre_init_user(void)

ʼ

⽫ھʼʱãijЩӲúú󣬵һЩܱʼǰ

طõĶʱãӲ޹أҲλá

matrix_init_*ĵ

  • /޶: void matrix_init_kb(void)
  • : void matrix_init_user(void)

̺ʼ

Ǽ̳ʼеһijЩԣãΪʱӦöǽгʼ

keyboard_post_init_user()ʾʵ

ʾгʼɺУRGBơ

void keyboard_post_init_user(void) {
  // úʼ
  rgblight_enable_noeeprom(); // ʹRgb
  rgblight_sethsv_noeeprom(180, 255, 255); // ɫõɫ(ɫ)
  rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3); // ÿٺģʽ
}

keyboard_post_init_* ĵ

  • /޶: void keyboard_post_init_kb(void)
  • : void keyboard_post_init_user(void)

ɨ

ܵĻҪprocess_record_*()Զַ̣ʽӵ¼Уȷ벻Լ̲Ӱ졣Ȼڼ£бҪоɨ衣ЩҪرעܣΪÿٱ10Ρ

matrix_scan_*ʾʵ

ӱʡˡhookһܼе֮ǰӦ㹻˽qmkڲṹԱûʾ±дҪһissueDiscordǽ.

matrix_scan_* ĵ

  • /޶: void matrix_scan_kb(void)
  • : void matrix_scan_user(void)

úÿξɨʱãMCUͬдҪΪкܶΡ

ԶɨʱõҲԶ״̬(LEDƻĻ)ûҲ붨еĹܡ

/

֧־ͿֹͨͣһƱﵽ""RGBƺͱǺܺõӡԽԼܺģҲ̷ζѡ

: suspend_power_down_*suspend_wakeup_init_*, ֱϵͳкͻʱá

suspend_power_down_user()suspend_wakeup_init_user()ʾʵ

void suspend_power_down_user(void) {
    rgb_matrix_set_suspend_state(true);
}

void suspend_wakeup_init_user(void) {
    rgb_matrix_set_suspend_state(false);
}

/ ĵ

  • /޶: void suspend_power_down_kb(void) void suspend_wakeup_init_user(void)
  • : void suspend_power_down_kb(void) void suspend_wakeup_init_user(void)

ı

ÿıд롣ڲָʾԶ㴦á

layer_state_set_* ʾʵ

ʹPlanckʾ RGBʹ֮Ӧ

uint32_t layer_state_set_user(uint32_t state) {
    switch (biton32(state)) {
    case _RAISE:
        rgblight_setrgb (0x00,  0x00, 0xFF);
        break;
    case _LOWER:
        rgblight_setrgb (0xFF,  0x00, 0x00);
        break;
    case _PLOVER:
        rgblight_setrgb (0x00,  0xFF, 0x00);
        break;
    case _ADJUST:
        rgblight_setrgb (0x7A,  0x00, 0xFF);
        break;
    default: //  for any other layers, or the default layer
        rgblight_setrgb (0x00,  0xFF, 0xFF);
        break;
    }
  return state;
}

layer_state_set_* ĵ

  • /޶: uint32_t layer_state_set_kb(uint32_t state)
  • : uint32_t layer_state_set_user(uint32_t state)

״̬ǻbitmask, ָ

籣 (EEPROM)

óڵıڼСЩñصEEPROM粻ʧ ÿeeconfig_read_kbeeconfig_read_userȡeeconfig_update_kbeeconfig_update_userд롣ϣܹлĹܺ(лRGBָʾ⣬eeconfig_init_kbeeconfig_init_userEEPROMĬֵ

ӵIJֿǣкܶ෽ͨEEPROM洢ͷݣҲûַǡȷġÿֻһ˫(ֽ)ռ䡣

סEEPROMдġдܸߣDzֻдEEPROMСдƵMCU̡

  • ӣôϣʹԣΪ൱ӡ

ʾʵ

ãҶдʹû֡һӵĺкܶҪʵϣʹ˺ܶ

keymap.cļУ´:

typedef union {
  uint32_t raw;
  struct {
    bool     rgb_layer_change :1;
  };
} user_config_t;

user_config_t user_config;

ϴ뽨һṹ壬ýṹԴ洢òдEEPROM㽫趨ΪڽṹȻ塣Ҫסbool ()ֵʹ1λ, uint8_tʹ8λ, uint16_tʹ16λԻϴʹã˳Ǵܻ鷳Ϊǻıддֵ

layer_state_set_*ʹrgb_layer_changeʹkeyboard_post_init_userprocess_record_userһС

Ҫʹkeyboard_post_init_userҪeeconfig_read_user()`ոմĽṹ塣ȻʹṹIJеĹܡ

void keyboard_post_init_user(void) {
  // òּľʼ

  // EEPROMû
  user_config.raw = eeconfig_read_user();

  // ʹܣĬϲ
  if (user_config.rgb_layer_change) {
    rgblight_enable_noeeprom();
    rgblight_sethsv_noeeprom_cyan(); 
    rgblight_mode_noeeprom(1);
  }
}

ϺڶEEPROMúʹøĬϲRGBɫ"raw"ֵǴ"union"Ľṹתġ

uint32_t layer_state_set_user(uint32_t state) {
    switch (biton32(state)) {
    case _RAISE:
        if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_magenta(); rgblight_mode_noeeprom(1); }
        break;
    case _LOWER:
        if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_red(); rgblight_mode_noeeprom(1); }
        break;
    case _PLOVER:
        if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_green(); rgblight_mode_noeeprom(1); }
        break;
    case _ADJUST:
        if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_white(); rgblight_mode_noeeprom(1); }
        break;
    default: //  Ĭϲ
        if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_cyan(); rgblight_mode_noeeprom(1); }
        break;
    }
  return state;
}

ֵʹʱıRGBơֵ, Ϊprocess_record_userһ¼RGB_LYRҪȷʹRGB룬ʹʾرգ뽫Ϊ


bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  switch (keycode) {
    case FOO:
      if (record->event.pressed) {
        // ʱʲô
      } else {
        // ͷʱʲô
      }
      return false; // ˼Ľһ
    case KC_ENTER:
        // ڰ»سʱ
        if (record->event.pressed) {
            PLAY_NOTE_ARRAY(tone_qwerty);
        }
        return true; // QMKس/ͷ¼
    case RGB_LYR:  // underglowΪָʾʹá
        if (record->event.pressed) { 
            user_config.rgb_layer_change ^= 1; // л״̬
            eeconfig_update_user(user_config.raw); // EEPROMд״̬
            if (user_config.rgb_layer_change) { // ״̬ʹ
                layer_state_set(layer_state);   // ô̸²ɫ
            }
        }
        return false; break;
    case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // еRGB (see quantum_keycodes.h, L400 Բο)
        if (record->event.pressed) { //ʧָܲʾıҪ
            if (user_config.rgb_layer_change) {        // ʹʱ
                user_config.rgb_layer_change = false;  // ʧܣȻ 
                eeconfig_update_user(user_config.raw); // EEPROMд
            }
        }
        return true; break;
    default:
      return true; // 
  }
}

Ҫeeconfig_init_userԵEEPROMʱָĬֵ, ԶǿEEPROMEEP_RSTBootmagic磬ҪĬRGBָʾĬֵ

void eeconfig_init_user(void) {  // EEPROM
  user_config.raw = 0;
  user_config.rgb_layer_change = true; // ҪĬʹ
  eeconfig_update_user(user_config.raw); // EEPROMдĬֵ

  // use the non noeeprom versions, ҪEEPROMдЩֵ
  rgblight_enable(); // ĬʹRGB
  rgblight_sethsv_cyan();  // Ĭɫ
  rgblight_mode(1); // Ĭó
}

ȻˡRGBָʾʱûһֱ棬¼̡ʹRGB룬ָʾʧܣˡ

'EECONFIG' ĵ

  • /޶: void eeconfig_init_kb(void), uint32_t eeconfig_read_kb(void)void eeconfig_update_kb(uint32_t val)
  • : void eeconfig_init_user(void), uint32_t eeconfig_read_user(void)void eeconfig_update_user(uint32_t val)

val дEEPROMֵeeconfig_read_*EEPROMһ32λ(˫)ֵ

Զ-ٽֵ(TAPPING_TERM)

Ĭ,-ٽֵȫͳһģҲͨáڴû˵ܺáЩ£LT˵ʱ˫ܼ󣬿ΪЩļװסΪ˲ÿԶ룬ܿΪÿTAPPING_TERM

ʹܵĻ, Ҫconfig.h#define TAPPING_TERM_PER_KEY

get_tapping_termʾʵ

Ҫ޸ĻڼTAPPING TERMkeymap.cļ´:

uint16_t get_tapping_term(uint16_t keycode) {
  switch (keycode) {
    case SFT_T(KC_SPC):
      return TAPPING_TERM + 1250;
    case LT(1, KC_GRV):
      return 130;
    default:
      return TAPPING_TERM;
  }
}

get_tapping_term ĵ

ƪ,Ҫquantum߼̼ĺֻҪûɡ