qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

quantum.c (18232B)


      1 /* Copyright 2016-2017 Jack Humbert
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 
     17 #include "quantum.h"
     18 #include "process_quantum.h"
     19 
     20 #ifdef SLEEP_LED_ENABLE
     21 #    include "sleep_led.h"
     22 #endif
     23 
     24 #ifdef BACKLIGHT_ENABLE
     25 #    include "process_backlight.h"
     26 #endif
     27 
     28 #ifdef CONNECTION_ENABLE
     29 #    include "process_connection.h"
     30 #endif
     31 
     32 #ifdef GRAVE_ESC_ENABLE
     33 #    include "process_grave_esc.h"
     34 #endif
     35 
     36 #ifdef HAPTIC_ENABLE
     37 #    include "process_haptic.h"
     38 #endif
     39 
     40 #ifdef JOYSTICK_ENABLE
     41 #    include "process_joystick.h"
     42 #endif
     43 
     44 #ifdef LEADER_ENABLE
     45 #    include "process_leader.h"
     46 #endif
     47 
     48 #ifdef LED_MATRIX_ENABLE
     49 #    include "process_led_matrix.h"
     50 #endif
     51 
     52 #ifdef MAGIC_ENABLE
     53 #    include "process_magic.h"
     54 #endif
     55 
     56 #ifdef MIDI_ENABLE
     57 #    include "process_midi.h"
     58 #endif
     59 
     60 #if !defined(NO_ACTION_LAYER)
     61 #    include "process_default_layer.h"
     62 #endif
     63 
     64 #ifdef PROGRAMMABLE_BUTTON_ENABLE
     65 #    include "process_programmable_button.h"
     66 #endif
     67 
     68 #if defined(RGB_MATRIX_ENABLE)
     69 #    include "process_rgb_matrix.h"
     70 #endif
     71 
     72 #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
     73 #    include "process_underglow.h"
     74 #endif
     75 
     76 #ifdef SECURE_ENABLE
     77 #    include "process_secure.h"
     78 #endif
     79 
     80 #ifdef TRI_LAYER_ENABLE
     81 #    include "process_tri_layer.h"
     82 #endif
     83 
     84 #ifdef UNICODE_COMMON_ENABLE
     85 #    include "process_unicode_common.h"
     86 #endif
     87 
     88 #ifdef LAYER_LOCK_ENABLE
     89 #    include "process_layer_lock.h"
     90 #endif
     91 
     92 #ifndef NO_ACTION_ONESHOT
     93 #    include "process_oneshot.h"
     94 #endif
     95 
     96 #ifdef AUDIO_ENABLE
     97 #    ifndef GOODBYE_SONG
     98 #        define GOODBYE_SONG SONG(GOODBYE_SOUND)
     99 #    endif
    100 float goodbye_song[][2] = GOODBYE_SONG;
    101 #    ifdef DEFAULT_LAYER_SONGS
    102 float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS;
    103 #    endif
    104 #endif
    105 
    106 uint8_t extract_mod_bits(uint16_t code) {
    107     switch (code) {
    108         case QK_MODS ... QK_MODS_MAX:
    109             break;
    110         default:
    111             return 0;
    112     }
    113 
    114     uint8_t mods_to_send = 0;
    115 
    116     if (code & QK_RMODS_MIN) { // Right mod flag is set
    117         if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RIGHT_CTRL);
    118         if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RIGHT_SHIFT);
    119         if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RIGHT_ALT);
    120         if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RIGHT_GUI);
    121     } else {
    122         if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LEFT_CTRL);
    123         if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LEFT_SHIFT);
    124         if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LEFT_ALT);
    125         if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LEFT_GUI);
    126     }
    127 
    128     return mods_to_send;
    129 }
    130 
    131 void do_code16(uint16_t code, void (*f)(uint8_t)) {
    132     f(extract_mod_bits(code));
    133 }
    134 
    135 __attribute__((weak)) void register_code16(uint16_t code) {
    136     if (IS_MODIFIER_KEYCODE(code) || code == KC_NO) {
    137         do_code16(code, register_mods);
    138     } else {
    139         do_code16(code, register_weak_mods);
    140     }
    141     register_code(code);
    142 }
    143 
    144 __attribute__((weak)) void unregister_code16(uint16_t code) {
    145     unregister_code(code);
    146     if (IS_MODIFIER_KEYCODE(code) || code == KC_NO) {
    147         do_code16(code, unregister_mods);
    148     } else {
    149         do_code16(code, unregister_weak_mods);
    150     }
    151 }
    152 
    153 /** \brief Tap a keycode with a delay.
    154  *
    155  * \param code The modded keycode to tap.
    156  * \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it.
    157  */
    158 __attribute__((weak)) void tap_code16_delay(uint16_t code, uint16_t delay) {
    159     register_code16(code);
    160     wait_ms(delay);
    161     unregister_code16(code);
    162 }
    163 
    164 /** \brief Tap a keycode with the default delay.
    165  *
    166  * \param code The modded keycode to tap. If `code` is `KC_CAPS_LOCK`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
    167  */
    168 __attribute__((weak)) void tap_code16(uint16_t code) {
    169     tap_code16_delay(code, code == KC_CAPS_LOCK ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY);
    170 }
    171 
    172 __attribute__((weak)) bool pre_process_record_modules(uint16_t keycode, keyrecord_t *record) {
    173     return true;
    174 }
    175 
    176 __attribute__((weak)) bool pre_process_record_kb(uint16_t keycode, keyrecord_t *record) {
    177     return pre_process_record_user(keycode, record);
    178 }
    179 
    180 __attribute__((weak)) bool pre_process_record_user(uint16_t keycode, keyrecord_t *record) {
    181     return true;
    182 }
    183 
    184 __attribute__((weak)) bool process_record_modules(uint16_t keycode, keyrecord_t *record) {
    185     return true;
    186 }
    187 
    188 __attribute__((weak)) bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
    189     return process_record_user(keycode, record);
    190 }
    191 
    192 __attribute__((weak)) bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    193     return true;
    194 }
    195 
    196 __attribute__((weak)) void post_process_record_modules(uint16_t keycode, keyrecord_t *record) {}
    197 
    198 __attribute__((weak)) void post_process_record_kb(uint16_t keycode, keyrecord_t *record) {
    199     post_process_record_user(keycode, record);
    200 }
    201 
    202 __attribute__((weak)) void post_process_record_user(uint16_t keycode, keyrecord_t *record) {}
    203 
    204 __attribute__((weak)) bool shutdown_modules(bool jump_to_bootloader) {
    205     return true;
    206 }
    207 
    208 __attribute__((weak)) void suspend_power_down_modules(void) {}
    209 
    210 __attribute__((weak)) void suspend_wakeup_init_modules(void) {}
    211 
    212 void shutdown_quantum(bool jump_to_bootloader) {
    213     clear_keyboard();
    214 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
    215     process_midi_all_notes_off();
    216 #endif
    217 #ifdef AUDIO_ENABLE
    218 #    ifndef NO_MUSIC_MODE
    219     music_all_notes_off();
    220 #    endif
    221     uint16_t timer_start = timer_read();
    222     PLAY_SONG(goodbye_song);
    223     shutdown_modules(jump_to_bootloader);
    224     shutdown_kb(jump_to_bootloader);
    225     while (timer_elapsed(timer_start) < 250)
    226         wait_ms(1);
    227     stop_all_notes();
    228 #else
    229     shutdown_modules(jump_to_bootloader);
    230     shutdown_kb(jump_to_bootloader);
    231     wait_ms(250);
    232 #endif
    233 #ifdef HAPTIC_ENABLE
    234     haptic_shutdown();
    235 #endif
    236 }
    237 
    238 void reset_keyboard(void) {
    239     shutdown_quantum(true);
    240     bootloader_jump();
    241 }
    242 
    243 void soft_reset_keyboard(void) {
    244     shutdown_quantum(false);
    245     mcu_reset();
    246 }
    247 
    248 /* Convert record into usable keycode via the contained event. */
    249 uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) {
    250 #if defined(COMBO_ENABLE) || defined(REPEAT_KEY_ENABLE)
    251     if (record->keycode) {
    252         return record->keycode;
    253     }
    254 #endif
    255     return get_event_keycode(record->event, update_layer_cache);
    256 }
    257 
    258 /* Convert event into usable keycode. Checks the layer cache to ensure that it
    259  * retains the correct keycode after a layer change, if the key is still pressed.
    260  * "update_layer_cache" is to ensure that it only updates the layer cache when
    261  * appropriate, otherwise, it will update it and cause layer tap (and other keys)
    262  * from triggering properly.
    263  */
    264 uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) {
    265 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
    266     /* TODO: Use store_or_get_action() or a similar function. */
    267     if (!disable_action_cache) {
    268         uint8_t layer;
    269 
    270         if (event.pressed && update_layer_cache) {
    271             layer = layer_switch_get_layer(event.key);
    272             update_source_layers_cache(event.key, layer);
    273         } else {
    274             layer = read_source_layers_cache(event.key);
    275         }
    276         return keymap_key_to_keycode(layer, event.key);
    277     } else
    278 #endif
    279         return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key);
    280 }
    281 
    282 /* Get keycode, and then process pre tapping functionality */
    283 bool pre_process_record_quantum(keyrecord_t *record) {
    284     return pre_process_record_modules(get_record_keycode(record, true), record) && pre_process_record_kb(get_record_keycode(record, true), record) &&
    285 #ifdef COMBO_ENABLE
    286            process_combo(get_record_keycode(record, true), record) &&
    287 #endif
    288            true;
    289 }
    290 
    291 /* Get keycode, and then call keyboard function */
    292 void post_process_record_quantum(keyrecord_t *record) {
    293     uint16_t keycode = get_record_keycode(record, false);
    294     post_process_record_modules(keycode, record);
    295     post_process_record_kb(keycode, record);
    296 }
    297 
    298 /** \brief Core keycode function
    299  *
    300  * Hands off handling to other quantum/process_keycode/ functions
    301  */
    302 bool process_record_quantum(keyrecord_t *record) {
    303     uint16_t keycode = get_record_keycode(record, true);
    304 
    305     // This is how you use actions here
    306     // if (keycode == QK_LEADER) {
    307     //   action_t action;
    308     //   action.code = ACTION_DEFAULT_LAYER_SET(0);
    309     //   process_action(record, action);
    310     //   return false;
    311     // }
    312 
    313 #if defined(SECURE_ENABLE)
    314     if (!preprocess_secure(keycode, record)) {
    315         return false;
    316     }
    317 #endif
    318 
    319 #ifdef TAP_DANCE_ENABLE
    320     if (preprocess_tap_dance(keycode, record)) {
    321         // The tap dance might have updated the layer state, therefore the
    322         // result of the keycode lookup might change.
    323         keycode = get_record_keycode(record, true);
    324     }
    325 #endif
    326 
    327 #ifdef RGBLIGHT_ENABLE
    328     if (record->event.pressed) {
    329         preprocess_rgblight();
    330     }
    331 #endif
    332 
    333 #ifdef WPM_ENABLE
    334     if (record->event.pressed) {
    335         update_wpm(keycode);
    336     }
    337 #endif
    338 
    339     if (!(
    340 #if defined(KEY_LOCK_ENABLE)
    341             // Must run first to be able to mask key_up events.
    342             process_key_lock(&keycode, record) &&
    343 #endif
    344 #if defined(DYNAMIC_MACRO_ENABLE) && !defined(DYNAMIC_MACRO_USER_CALL)
    345             // Must run asap to ensure all keypresses are recorded.
    346             process_dynamic_macro(keycode, record) &&
    347 #endif
    348 #ifdef REPEAT_KEY_ENABLE
    349             process_last_key(keycode, record) && process_repeat_key(keycode, record) &&
    350 #endif
    351 #if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY)
    352             process_clicky(keycode, record) &&
    353 #endif
    354 #ifdef HAPTIC_ENABLE
    355             process_haptic(keycode, record) &&
    356 #endif
    357 #if defined(POINTING_DEVICE_ENABLE) && defined(POINTING_DEVICE_AUTO_MOUSE_ENABLE)
    358             process_auto_mouse(keycode, record) &&
    359 #endif
    360             process_record_modules(keycode, record) && // modules must run before kb
    361             process_record_kb(keycode, record) &&
    362 #if defined(VIA_ENABLE)
    363             process_record_via(keycode, record) &&
    364 #endif
    365 #if defined(SECURE_ENABLE)
    366             process_secure(keycode, record) &&
    367 #endif
    368 #if defined(SEQUENCER_ENABLE)
    369             process_sequencer(keycode, record) &&
    370 #endif
    371 #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)
    372             process_midi(keycode, record) &&
    373 #endif
    374 #ifdef AUDIO_ENABLE
    375             process_audio(keycode, record) &&
    376 #endif
    377 #if defined(BACKLIGHT_ENABLE)
    378             process_backlight(keycode, record) &&
    379 #endif
    380 #if defined(LED_MATRIX_ENABLE)
    381             process_led_matrix(keycode, record) &&
    382 #endif
    383 #ifdef STENO_ENABLE
    384             process_steno(keycode, record) &&
    385 #endif
    386 #if (defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE)
    387             process_music(keycode, record) &&
    388 #endif
    389 #ifdef CAPS_WORD_ENABLE
    390             process_caps_word(keycode, record) &&
    391 #endif
    392 #ifdef KEY_OVERRIDE_ENABLE
    393             process_key_override(keycode, record) &&
    394 #endif
    395 #ifdef TAP_DANCE_ENABLE
    396             process_tap_dance(keycode, record) &&
    397 #endif
    398 #if defined(UNICODE_COMMON_ENABLE)
    399             process_unicode_common(keycode, record) &&
    400 #endif
    401 #ifdef LEADER_ENABLE
    402             process_leader(keycode, record) &&
    403 #endif
    404 #ifdef AUTO_SHIFT_ENABLE
    405             process_auto_shift(keycode, record) &&
    406 #endif
    407 #ifdef DYNAMIC_TAPPING_TERM_ENABLE
    408             process_dynamic_tapping_term(keycode, record) &&
    409 #endif
    410 #ifdef SPACE_CADET_ENABLE
    411             process_space_cadet(keycode, record) &&
    412 #endif
    413 #ifdef MAGIC_ENABLE
    414             process_magic(keycode, record) &&
    415 #endif
    416 #ifdef GRAVE_ESC_ENABLE
    417             process_grave_esc(keycode, record) &&
    418 #endif
    419 #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
    420             process_underglow(keycode, record) &&
    421 #endif
    422 #if defined(RGB_MATRIX_ENABLE)
    423             process_rgb_matrix(keycode, record) &&
    424 #endif
    425 #ifdef JOYSTICK_ENABLE
    426             process_joystick(keycode, record) &&
    427 #endif
    428 #ifdef PROGRAMMABLE_BUTTON_ENABLE
    429             process_programmable_button(keycode, record) &&
    430 #endif
    431 #ifdef AUTOCORRECT_ENABLE
    432             process_autocorrect(keycode, record) &&
    433 #endif
    434 #ifdef TRI_LAYER_ENABLE
    435             process_tri_layer(keycode, record) &&
    436 #endif
    437 #if !defined(NO_ACTION_LAYER)
    438             process_default_layer(keycode, record) &&
    439 #endif
    440 #ifdef LAYER_LOCK_ENABLE
    441             process_layer_lock(keycode, record) &&
    442 #endif
    443 #ifdef CONNECTION_ENABLE
    444             process_connection(keycode, record) &&
    445 #endif
    446 #ifndef NO_ACTION_ONESHOT
    447             process_oneshot(keycode, record) &&
    448 #endif
    449             process_quantum(keycode, record))) {
    450         return false;
    451     }
    452 
    453     return true;
    454 }
    455 
    456 void set_single_default_layer(uint8_t default_layer) {
    457 #if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS)
    458     PLAY_SONG(default_layer_songs[default_layer]);
    459 #endif
    460     default_layer_set((layer_state_t)1 << default_layer);
    461 }
    462 
    463 void set_single_persistent_default_layer(uint8_t default_layer) {
    464     eeconfig_update_default_layer((layer_state_t)1 << default_layer);
    465     set_single_default_layer(default_layer);
    466 }
    467 
    468 //------------------------------------------------------------------------------
    469 // Override these functions in your keymap file to play different tunes on
    470 // different events such as startup and bootloader jump
    471 
    472 __attribute__((weak)) bool shutdown_user(bool jump_to_bootloader) {
    473     return true;
    474 }
    475 
    476 __attribute__((weak)) bool shutdown_kb(bool jump_to_bootloader) {
    477     if (!shutdown_user(jump_to_bootloader)) {
    478         return false;
    479     }
    480     return true;
    481 }
    482 
    483 void suspend_power_down_quantum(void) {
    484     suspend_power_down_modules();
    485     suspend_power_down_kb();
    486 #ifndef NO_SUSPEND_POWER_DOWN
    487 // Turn off backlight
    488 #    ifdef BACKLIGHT_ENABLE
    489     backlight_level_noeeprom(0);
    490 #    endif
    491 
    492 #    ifdef SLEEP_LED_ENABLE
    493     sleep_led_enable();
    494 #    endif
    495 
    496 #    ifdef LED_MATRIX_ENABLE
    497     led_matrix_task();
    498 #    endif
    499 #    ifdef RGB_MATRIX_ENABLE
    500     rgb_matrix_task();
    501 #    endif
    502 
    503     // Turn off LED indicators
    504     led_suspend();
    505 
    506 // Turn off audio
    507 #    ifdef AUDIO_ENABLE
    508     stop_all_notes();
    509 #    endif
    510 
    511 // Turn off underglow
    512 #    if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
    513     rgblight_suspend();
    514 #    endif
    515 
    516 #    if defined(LED_MATRIX_ENABLE)
    517     led_matrix_set_suspend_state(true);
    518 #    endif
    519 #    if defined(RGB_MATRIX_ENABLE)
    520     rgb_matrix_set_suspend_state(true);
    521 #    endif
    522 
    523 #    ifdef OLED_ENABLE
    524     oled_off();
    525 #    endif
    526 #    ifdef ST7565_ENABLE
    527     st7565_off();
    528 #    endif
    529 #    if defined(POINTING_DEVICE_ENABLE)
    530     // run to ensure scanning occurs while suspended
    531     pointing_device_task();
    532 #    endif
    533 #endif
    534 }
    535 
    536 __attribute__((weak)) void suspend_wakeup_init_quantum(void) {
    537 // Turn on backlight
    538 #ifdef BACKLIGHT_ENABLE
    539     backlight_init();
    540 #endif
    541 
    542 #ifdef SLEEP_LED_ENABLE
    543     sleep_led_disable();
    544 #endif
    545 
    546     // Restore LED indicators
    547     led_wakeup();
    548 
    549 // Wake up underglow
    550 #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
    551     rgblight_wakeup();
    552 #endif
    553 
    554 #if defined(LED_MATRIX_ENABLE)
    555     led_matrix_set_suspend_state(false);
    556 #endif
    557 #if defined(RGB_MATRIX_ENABLE)
    558     rgb_matrix_set_suspend_state(false);
    559 #endif
    560     suspend_wakeup_init_modules();
    561     suspend_wakeup_init_kb();
    562 }
    563 
    564 /** \brief converts unsigned integers into char arrays
    565  *
    566  * Takes an unsigned integer and converts that value into an equivalent char array
    567  * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
    568  */
    569 
    570 const char *get_numeric_str(char *buf, size_t buf_len, uint32_t curr_num, char curr_pad) {
    571     buf[buf_len - 1] = '\0';
    572     for (size_t i = 0; i < buf_len - 1; ++i) {
    573         char c               = '0' + curr_num % 10;
    574         buf[buf_len - 2 - i] = (c == '0' && i == 0) ? '0' : (curr_num > 0 ? c : curr_pad);
    575         curr_num /= 10;
    576     }
    577     return buf;
    578 }
    579 
    580 /** \brief converts uint8_t into char array
    581  *
    582  * Takes an uint8_t, and uses an internal static buffer to render that value into a char array
    583  * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
    584  *
    585  * NOTE: Subsequent invocations will reuse the same static buffer and overwrite the previous
    586  *       contents. Use the result immediately, instead of caching it.
    587  */
    588 const char *get_u8_str(uint8_t curr_num, char curr_pad) {
    589     static char    buf[4]   = {0};
    590     static uint8_t last_num = 0xFF;
    591     static char    last_pad = '\0';
    592     if (last_num == curr_num && last_pad == curr_pad) {
    593         return buf;
    594     }
    595     last_num = curr_num;
    596     last_pad = curr_pad;
    597     return get_numeric_str(buf, sizeof(buf), curr_num, curr_pad);
    598 }
    599 
    600 /** \brief converts uint16_t into char array
    601  *
    602  * Takes an uint16_t, and uses an internal static buffer to render that value into a char array
    603  * A padding character may be specified, ' ' for leading spaces, '0' for leading zeros.
    604  *
    605  * NOTE: Subsequent invocations will reuse the same static buffer and overwrite the previous
    606  *       contents. Use the result immediately, instead of caching it.
    607  */
    608 const char *get_u16_str(uint16_t curr_num, char curr_pad) {
    609     static char     buf[6]   = {0};
    610     static uint16_t last_num = 0xFF;
    611     static char     last_pad = '\0';
    612     if (last_num == curr_num && last_pad == curr_pad) {
    613         return buf;
    614     }
    615     last_num = curr_num;
    616     last_pad = curr_pad;
    617     return get_numeric_str(buf, sizeof(buf), curr_num, curr_pad);
    618 }
    619 
    620 #if defined(SECURE_ENABLE)
    621 void secure_hook_quantum(secure_status_t secure_status) {
    622     // If keys are being held when this is triggered, they may not be released properly
    623     // this can result in stuck keys, mods and layers.  To prevent that, manually
    624     // clear these, when it is triggered.
    625 
    626     if (secure_status == SECURE_PENDING) {
    627         clear_keyboard();
    628         layer_clear();
    629     }
    630 }
    631 #endif