// Copyright 2021 Nicolas Druoton (druotoni) // SPDX-License-Identifier: GPL-2.0-or-later #include QMK_KEYBOARD_H #include "transactions.h" // global #include "boot.h" #include "gui_state.h" #include "navi_logo.h" #include "draw_helper.h" #include "fast_random.h" // left side #include "burst.h" #include "layer_frame.h" // right side #include "ring.h" // clang-format off const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {[0] = LAYOUT(KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_QUOT, KC_LSFT, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT, KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC, KC_RBRC, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_BSLS, KC_LGUI, KC_LAPO, MO(1), KC_SPC, KC_SPC, MO(2), KC_RAPC, KC_RCTL), [1] = LAYOUT(KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_GRV, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_BRID, KC_BRIU, KC_MPRV, KC_MNXT, KC_NO, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_NO, KC_NO, KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_MSTP, KC_LPRN, KC_NO, KC_NO, KC_RPRN, KC_EQL, KC_MINS, KC_NO, KC_DEL, KC_BSLS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, KC_TRNS), [2] = LAYOUT(KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_F11, KC_F12, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_NO, KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)}; // clang-format on // sync transport typedef struct _sync_keycode_t { uint16_t keycode; } sync_keycode_t; // force rigth side to update bool b_sync_need_send = false; // last keycode typed sync_keycode_t last_keycode; oled_rotation_t oled_init_user(oled_rotation_t rotation) { // vertical orientation return OLED_ROTATION_270; } void render(gui_state_t t) { // logo render_logo(t); #if IS_LEFT // left side render_layer_frame(t); render_gears(); decay_scope(); render_scope(t); #endif #if IS_RIGHT // right side render_circle(t); #endif } void update(uint16_t keycode) { #if IS_LEFT update_scope(); #endif #if IS_RIGHT update_circle(keycode); #endif } void reset(void) { #if IS_LEFT reset_scope(); #endif #if IS_RIGHT reset_ring(); #endif } void set_wackingup_mode_clean(void) { oled_clear(); reset(); } bool oled_task_user(void) { gui_state_t t = get_gui_state(); // in sleep mode => turn display off if (t == _SLEEP) { oled_off(); return false; } // not in sleep mode => screen is on oled_on(); #ifdef WITH_BOOT // in booting mode => display booting animation if (t == _BOOTING) { bool boot_finished = render_boot(); if (boot_finished) { // end of the boot : wacking up set_wackingup_mode_clean(); update_gui_state(); } return false; } #endif // in halting mode => display booting animation if (t == _HALTING) { render_halt(); return false; } render(t); return false; } void process_key(uint16_t keycode) { // update screen with the new key update(keycode); gui_state_t t = get_gui_state(); if (t == _IDLE) { // wake up animation reset(); } if (t == _BOOTING || t == _HALTING) { // cancel booting or halting : waking_up set_wackingup_mode_clean(); } if (t == _SLEEP) { // boot sequence set_wackingup_mode_clean(); reset_boot(); } update_gui_state(); } void user_sync_a_slave_handler(uint8_t in_buflen, const void *in_data, uint8_t out_buflen, void *out_data) { const sync_keycode_t *m2s = (const sync_keycode_t *)in_data; // get the last char typed on left side and update the right side process_key(m2s->keycode); } void keyboard_post_init_user(void) { // callback for tranport sync data transaction_register_rpc(USER_SYNC_A, user_sync_a_slave_handler); } void housekeeping_task_user(void) { // only for master side if (!is_keyboard_master()) return; // only if a new char was typed if (!b_sync_need_send) return; // send the char to the slave side : sync is done if (transaction_rpc_send(USER_SYNC_A, sizeof(last_keycode), &last_keycode)) { b_sync_need_send = false; } } bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { // master : store keycode to sent to the other side to be process_key last_keycode.keycode = keycode; b_sync_need_send = true; // gui process the input process_key(keycode); } return true; } #if IS_LEFT layer_state_t layer_state_set_user(layer_state_t state) { // update the frame with the layer name update_layer_frame(state); return state; } #endif