diff --git a/.gitignore b/.gitignore
index 3fec32c84..eca1c9fab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
tmp/
+.idea
\ No newline at end of file
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keyball39.c b/qmk_firmware/keyboards/keyball/keyball39/keyball39.c
index 5472a0d48..a92c9153f 100644
--- a/qmk_firmware/keyboards/keyball/keyball39/keyball39.c
+++ b/qmk_firmware/keyboards/keyball/keyball39/keyball39.c
@@ -14,6 +14,28 @@ 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 .
+-------------------------------------------------------------------
+参考文献:
+- リポジトリ:
+ https://github.com/kamiichi99/keyball/tree/main/qmk_firmware/keyboards/keyball/keyball39/keymaps/kamidai
+- keyballの販売ページ
+ https://shirogane-lab.com/collections/all
+コード表:
+- 公式ファームウェアのキーコード:
+ KBC_RST(0x5DA5): Keyball 設定のリセット
+ KBC_SAVE(0x5DA6): 現在の Keyball 設定を EEPROM に保存します
+ CPI_I100(0x5DA7): CPI を 100 増加させます(最大:12000)
+ CPI_D100(0x5DA8): CPI を 100 減少させます(最小:100)
+ CPI_I1K(0x5DA9): CPI を 1000 増加させます(最大:12000)
+ CPI_D1K(0x5DAA): CPI を 1000 減少させます(最小:100)
+ SCRL_TO(0x5DAB): タップごとにスクロールモードの ON/OFF を切り替えます
+ SCRL_MO(0x5DAC): キーを押している間、スクロールモードになります
+ SCRL_DVI(0x5DAD): スクロール除数を1つ上げます(max D7 = 1/128)← 最もスクロール遅い
+ SCRL_DVD(0x5DAE): スクロール除数を1つ下げます(min D0 = 1/1)← 最もスクロール速い
+- オリジナルのキーコード:
+ KC_BACK_TO_LAYER0_BTN1(0x5DAF): レイヤー0に遷移できるBTN1
+ KC_DOUBLE_CLICK_BTN1(0x5DB0): 1タップでダブルクリックできるBTN1
+ KC_TRIPLE_CLICK_BTN1(0x5DB1): 1タップでトリプルクリックできるBTN1
*/
#include QMK_KEYBOARD_H
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/config.h b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/config.h
new file mode 100644
index 000000000..d9ff8668e
--- /dev/null
+++ b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/config.h
@@ -0,0 +1,47 @@
+/*
+This is the c configuration file for the keymap
+
+Copyright 2022 @Yowkees
+Copyright 2022 MURAOKA Taro (aka KoRoN, @kaoriya)
+
+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 .
+*/
+
+#pragma once
+
+//#ifdef RGBLIGHT_ENABLE
+//# define RGBLIGHT_EFFECT_BREATHING
+//# define RGBLIGHT_EFFECT_RAINBOW_MOOD
+//# define RGBLIGHT_EFFECT_RAINBOW_SWIRL
+//# define RGBLIGHT_EFFECT_SNAKE
+//# define RGBLIGHT_EFFECT_KNIGHT
+//# define RGBLIGHT_EFFECT_CHRISTMAS
+//# define RGBLIGHT_EFFECT_STATIC_GRADIENT
+//# define RGBLIGHT_EFFECT_RGB_TEST
+//# define RGBLIGHT_EFFECT_ALTERNATING
+//# define RGBLIGHT_EFFECT_TWINKLE
+//#endif
+
+//#define COMBO_COUNT 9
+
+//#define KEYBALL_SCROLLSNAP_ENABLE 0 // scrollsnapをオフにする
+
+#define TAP_CODE_DELAY 5
+#define DYNAMIC_KEYMAP_LAYER_COUNT 7
+
+#define KEYBALL_CPI_DEFAULT 700 // 光学センサーPMW3360DM の解像度 (CPI) の規定値
+#define KEYBALL_SCROLL_DIV_DEFAULT 4 // スクロール速度の規定値
+
+//#define POINTING_DEVICE_AUTO_MOUSE_ENABLE
+//#define AUTO_MOUSE_DEFAULT_LAYER 1
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/auto_click_layer.h b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/auto_click_layer.h
new file mode 100644
index 000000000..e1bd93b2e
--- /dev/null
+++ b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/auto_click_layer.h
@@ -0,0 +1,152 @@
+/* Copyright 2023 kamidai (@d_kamiichi)
+ *
+ * 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 .
+ */
+
+////////////////////////////////////
+///
+/// 自動マウスレイヤーの実装 ここから
+/// 参考にさせていただいたページ
+/// https://zenn.dev/takashicompany/articles/69b87160cda4b9
+///
+////////////////////////////////////
+
+enum ball_state {
+ NONE = 0,
+ WAITING, // マウスレイヤーが有効になるのを待つ。 Wait for mouse layer to activate.
+ CLICKABLE, // マウスレイヤー有効になりクリック入力が取れる。 Mouse layer is enabled to take click input.
+ CLICKING, // クリック中。 Clicking.
+ CLICKED, // クリック直後。 Clicked.
+ SWIPE, // スワイプモードが有効になりスワイプ入力が取れる。 Swipe mode is enabled to take swipe input.
+ SWIPING // スワイプ中。 swiping.
+};
+
+enum ball_state state; // 現在のクリック入力受付の状態 Current click input reception status
+uint16_t click_timer; // タイマー。状態に応じて時間で判定する。 Timer. Time to determine the state of the system.
+
+uint16_t clicked_stay_time = 200; // CLICKEDの滞在時間(千分の一秒)。その後、クリックレイヤーが無効になる。 For this number of seconds (milliseconds), the click layer is disabled if in CLICKED state.
+uint16_t clickable_stay_time = 1600; // CLICKABLEの滞在時間(千分の一秒)。その後、クリックレイヤーが無効になる。 For this number of seconds (milliseconds), the click layer is disabled if in CLICKABLE state.
+
+const int16_t to_clickable_movement = 0; // クリックレイヤーが有効になるしきい値
+const uint16_t click_layer = 6; // マウス入力が可能になった際に有効になるレイヤー。Layers enabled when mouse input is enabled
+
+int16_t mouse_record_threshold = 30; // ポインターの動きを一時的に記録するフレーム数。 Number of frames in which the pointer movement is temporarily recorded.
+int16_t mouse_move_count_ratio = 5; // ポインターの動きを再生する際の移動フレームの係数。 The coefficient of the moving frame when replaying the pointer movement.
+
+// Modifierが絡むときの挙動が理想とは違ったので、一旦コメントアウト
+// const uint16_t ignore_disable_mouse_layer_keys[] = {KC_LANG1, KC_LANG2}; // この配列で指定されたキーはマウスレイヤー中に押下してもマウスレイヤーを解除しない
+
+int16_t mouse_movement;
+
+// クリック用のレイヤーを有効にする。 Enable layers for clicks
+void enable_click_layer(void) {
+ layer_on(click_layer);
+ click_timer = timer_read();
+ state = CLICKABLE;
+}
+
+// クリック用のレイヤーを無効にする。 Disable layers for clicks.
+void disable_click_layer(void) {
+ state = NONE;
+ layer_off(click_layer);
+}
+
+//
+report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
+ int16_t current_x = mouse_report.x;
+ int16_t current_y = mouse_report.y;
+
+ if (current_x != 0 || current_y != 0) {
+ switch (state) {
+ case CLICKABLE:
+ click_timer = timer_read();
+ break;
+
+ case CLICKING:
+ break;
+
+ case WAITING:
+ mouse_movement += my_abs(current_x) + my_abs(current_y);
+
+ if (mouse_movement >= to_clickable_movement) {
+ mouse_movement = 0;
+ enable_click_layer();
+ }
+ break;
+
+ case SWIPE:
+ click_timer = timer_read();
+
+ if (my_abs(current_x) >= SWIPE_THRESHOLD || my_abs(current_y) >= SWIPE_THRESHOLD) {
+// rgblight_sethsv(HSV_PINK);
+ process_swipe_gesture(current_x, current_y);
+ is_swiped = true;
+
+ if (is_repeat == false) {
+ state = SWIPING;
+ }
+ }
+ break;
+
+ case SWIPING:
+ break;
+
+ default:
+ click_timer = timer_read();
+ state = WAITING;
+ mouse_movement = 0;
+ }
+ } else {
+ switch (state) {
+ case CLICKING:
+ break;
+
+ case CLICKED:
+ if (timer_elapsed(click_timer) > clicked_stay_time) {
+ disable_click_layer();
+ }
+ break;
+ case CLICKABLE:
+ if (timer_elapsed(click_timer) > clickable_stay_time) {
+ disable_click_layer();
+ }
+ break;
+
+ case WAITING:
+ if (timer_elapsed(click_timer) > 50) {
+ mouse_movement = 0;
+ state = NONE;
+ }
+ break;
+
+ case SWIPE:
+// rgblight_sethsv(HSV_SPRINGGREEN);
+ break;
+
+ case SWIPING:
+ if (timer_elapsed(click_timer) > 300) {
+ state = SWIPE;
+ }
+ break;
+
+ default:
+ mouse_movement = 0;
+ state = NONE;
+ }
+ }
+ mouse_report.x = current_x;
+ mouse_report.y = current_y;
+
+ return mouse_report;
+}
\ No newline at end of file
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/combo.h b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/combo.h
new file mode 100644
index 000000000..85140830f
--- /dev/null
+++ b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/combo.h
@@ -0,0 +1,58 @@
+/* Copyright 2023 kamidai (@d_kamiichi)
+ *
+ * 参考ページ
+ * 公式:https://docs.qmk.fm/#/ja/feature_combo?id=%e3%82%b3%e3%83%b3%e3%83%9c
+ *
+ * 注意: 以下の設定が必要です
+ * rules.mk: COMBO_ENABLE = yes
+ * config.h: #define COMBO_COUNT 2(=実際に設定するコンボ数)
+ */
+
+enum combos {
+ COMBO_F14,
+ COMBO_F15
+};
+
+// const uint16_t PROGMEM f14_combo[] = {KC_DOWN, KC_I, COMBO_END};
+// const uint16_t PROGMEM f15_combo[] = {G(KC_C), KC_UP, COMBO_END};
+// const uint16_t PROGMEM combo_layer_1[] = {KC_F, KC_D, COMBO_END};
+// const uint16_t PROGMEM combo_layer_2[] = {KC_J, KC_K, COMBO_END};
+// const uint16_t PROGMEM combo_layer_3[] = {KC_D, KC_S, COMBO_END};
+// const uint16_t PROGMEM combo_layer_3[] = {KC_S, KC_A, COMBO_END};
+
+const uint16_t PROGMEM combo_BRC[] = {KC_LBRC, KC_RBRC, COMBO_END};
+const uint16_t PROGMEM combo_select_BRC[] = {KC_LBRC, S(KC_EQUAL), COMBO_END};
+
+const uint16_t PROGMEM combo_S9_S0[] = {S(KC_9), S(KC_0), COMBO_END};
+const uint16_t PROGMEM combo_select_S9_S0[] = {S(KC_9), KC_MINUS, COMBO_END};
+
+const uint16_t PROGMEM combo_S_BRC[] = {S(KC_LBRC), S(KC_RBRC), COMBO_END};
+const uint16_t PROGMEM combo_select_S_BRC[] = {S(KC_LBRC), KC_RBRC, COMBO_END};
+
+const uint16_t PROGMEM combo_sumitsuki_BRC[] = {SFT_T(KC_GRAVE), KC_LBRC, COMBO_END};
+const uint16_t PROGMEM combo_select_sumitsuki_BRC[] = {SFT_T(KC_GRAVE), S(KC_0), COMBO_END};
+
+const uint16_t PROGMEM combo_MINUS_SPACE[] = {KC_RBRC, S(KC_EQUAL), COMBO_END};
+
+combo_t key_combos[] = {
+ // [COMBO_F14] = COMBO(f14_combo, KC_F14),
+ // [COMBO_F15] = COMBO(f15_combo, KC_F15)
+ // COMBO(combo_layer_1, MO(3)),
+ // COMBO(combo_layer_2, MO(3)),
+ // COMBO(combo_layer_3, MO(2)),
+
+ COMBO(combo_BRC, COMBO_BRC),
+ COMBO(combo_select_BRC, COMBO_select_BRC),
+
+ COMBO(combo_S9_S0, COMBO_S9_S0),
+ COMBO(combo_select_S9_S0, COMBO_select_S9_S0),
+
+ COMBO(combo_S_BRC, COMBO_S_BRC),
+ COMBO(combo_select_S_BRC, COMBO_select_S_BRC),
+
+ COMBO(combo_sumitsuki_BRC, COMBO_sumitsuki_BRC),
+ COMBO(combo_select_sumitsuki_BRC, COMBO_select_sumitsuki_BRC),
+
+ COMBO(combo_MINUS_SPACE, COMBO_MINUS_SPACE),
+
+};
\ No newline at end of file
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/functions.h b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/functions.h
new file mode 100644
index 000000000..bb30523c6
--- /dev/null
+++ b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/functions.h
@@ -0,0 +1,15 @@
+// 自前の絶対数を返す関数。 Functions that return absolute numbers.
+int16_t my_abs(int16_t num) {
+ if (num < 0) {
+ num = -num;
+ }
+ return num;
+}
+
+// 自前の符号を返す関数。 Function to return the sign.
+int16_t mmouse_move_y_sign(int16_t num) {
+ if (num < 0) {
+ return -1;
+ }
+ return 1;
+}
\ No newline at end of file
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/macro_keys.h b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/macro_keys.h
new file mode 100644
index 000000000..46dae9a9e
--- /dev/null
+++ b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/macro_keys.h
@@ -0,0 +1,147 @@
+/* Copyright 2023 kamidai (@d_kamiichi)
+ *
+ * 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 .
+ */
+
+// マクロキーを設定
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ current_keycode = keycode;
+
+ switch (keycode) {
+ case KC_MY_BTN0:
+ case KC_MY_BTN1:
+ case KC_MY_BTN2:
+ case KC_MY_BTN3: {
+ report_mouse_t currentReport = pointing_device_get_report();
+
+ // どこのビットを対象にするか。 Which bits are to be targeted?
+ uint8_t btn = 1 << (keycode - KC_MY_BTN1);
+
+ if (record->event.pressed) {
+ // キーダウン時
+ // ビットORは演算子の左辺と右辺の同じ位置にあるビットを比較して、両方のビットのどちらかが「1」の場合に「1」にします。
+ // Bit OR compares bits in the same position on the left and right sides of the operator and sets them to "1" if either of both bits is "1".
+ currentReport.buttons |= btn;
+ state = CLICKING;
+ } else {
+ // キーアップ時
+ // ビットANDは演算子の左辺と右辺の同じ位置にあるビットを比較して、両方のビットが共に「1」の場合だけ「1」にします。
+ // Bit AND compares the bits in the same position on the left and right sides of the operator and sets them to "1" only if both bits are "1" together.
+ currentReport.buttons &= ~btn;
+ enable_click_layer();
+ state = CLICKED;
+
+ if (keycode == KC_MY_BTN0) {
+ disable_click_layer();
+ }
+ }
+
+ pointing_device_set_report(currentReport);
+ pointing_device_send();
+ return false;
+ }
+
+ // 以下スワイプジェスチャー
+ // クリックすると state が SWIPE になり、離したら NONE になる
+ // モッドタップ系
+ case KC_GESTURE1:
+ case KC_GESTURE2:
+ case KC_GESTURE3: {
+ if (record->event.pressed) {
+ // キーダウン時
+ state = SWIPE;
+ } else {
+ // キーアップ時
+ clear_mods();
+ disable_click_layer();
+ }
+
+ if (is_swiped == true) {
+ is_swiped = false;
+ return false;
+ }
+ if (is_swiped == false) {
+ return true;
+ }
+ }
+
+ // MOD系
+ // case KC_LCMD:
+ // case KC_LALT:
+ // if (record->event.pressed)
+ // {
+ // // キーダウン時
+ // state = SWIPE;
+ // register_code(keycode);
+ // }
+ // else
+ // {
+ // // キーアップ時
+ // clear_mods();
+ // disable_click_layer();
+ // is_repeat = false;
+ // }
+ // return false;
+
+ // TAP系
+ // case KC_F:
+ // case KC_D:
+ // case KC_S:
+ // uint16_t alt_tab_timer = 0;
+
+ // TAP系(キーリピートあり)
+ // case LT(2, KC_ESC):
+ // if (record->event.pressed)
+ // {
+ // // キーダウン時
+ // state = SWIPE;
+ // tap_code(keycode);
+ // }
+ // else
+ // {
+ // // キーアップ時
+ // if (is_swiped == true)
+ // {
+ // tap_code(KC_BSPC);
+ // }
+ // disable_click_layer();
+ // is_repeat = false;
+ // is_swiped = false;
+ // }
+ // return false;
+
+ // TAP系(フリック風)
+ // case KC_S:
+ // if (record->event.pressed)
+ // {
+ // // キーダウン時
+ // state = SWIPE;
+ // tap_code(keycode);
+ // }
+ // else
+ // {
+ // // キーアップ時
+ // disable_click_layer();
+ // }
+ // return false;
+
+ default:
+ if (record->event.pressed) {
+ // キーダウン時
+ disable_click_layer();
+ }
+ }
+
+ return true;
+}
\ No newline at end of file
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/swipe_gesture.h b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/swipe_gesture.h
new file mode 100644
index 000000000..457818323
--- /dev/null
+++ b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/features/swipe_gesture.h
@@ -0,0 +1,82 @@
+/* Copyright 2023 kamidai (@d_kamiichi)
+ *
+ * 参考にさせていただいたページ
+ * https://www.reddit.com/r/ploopy/comments/pbmrh3/qmk_options_on_ploopy_mouse_gestures/
+ * https://github.com/RobertCurry0216/qmk_firmware/blob/59f83aac8fa06010c3a1a0a53fcd453d96ce2f80/keyboards/ploopyco/trackball/keymaps/robertcurry0216/keymap.c
+ *
+ */
+
+int16_t current_keycode;
+const int16_t SWIPE_THRESHOLD = 10;
+bool is_swiped = false;
+bool is_repeat = false;
+
+// スワイプジェスチャーで何が起こるかを実際に処理する関数
+// 上、下、左、右、スワイプなしの5つのオプションがあります
+void process_swipe_gesture(int16_t x, int16_t y) {
+ // KC_GESTURE1
+ if (current_keycode == KC_GESTURE1) {
+ if (my_abs(x) < my_abs(y)) {
+ if (y < 0) {
+ // swipe up
+ tap_code(KC_F13);
+ } else {
+ // swipe down
+ tap_code(KC_F14);
+ }
+ }
+ if (my_abs(x) > my_abs(y)) {
+ if (x < 0) {
+ // swipe left
+ tap_code(KC_F15);
+ } else {
+ // swipe right
+ tap_code(KC_F16);
+ }
+ }
+ }
+
+ // KC_GESTURE2
+ if (current_keycode == KC_GESTURE2) {
+ if (my_abs(x) < my_abs(y)) {
+ if (y < 0) {
+ // swipe up
+ tap_code(KC_F17);
+ } else {
+ // swipe down
+ tap_code(KC_F18);
+ }
+ }
+ if (my_abs(x) > my_abs(y)) {
+ if (x < 0) {
+ // swipe left
+ tap_code(KC_F19);
+ } else {
+ // swipe right
+ tap_code(KC_F20);
+ }
+ }
+ }
+
+ // KC_GESTURE3
+ if (current_keycode == KC_GESTURE3) {
+ if (my_abs(x) < my_abs(y)) {
+ if (y < 0) {
+ // swipe up
+ tap_code(KC_F21);
+ } else {
+ // swipe down
+ tap_code(KC_F22);
+ }
+ }
+ if (my_abs(x) > my_abs(y)) {
+ if (x < 0) {
+ // swipe left
+ tap_code(KC_F23);
+ } else {
+ // swipe right
+ tap_code(KC_F24);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/keymap.c b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/keymap.c
new file mode 100644
index 000000000..4770dc061
--- /dev/null
+++ b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/keymap.c
@@ -0,0 +1,108 @@
+/*
+Copyright 2022 @Yowkees
+Copyright 2022 MURAOKA Taro (aka KoRoN, @kaoriya)
+
+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 .
+*/
+
+#include QMK_KEYBOARD_H
+
+#include "quantum.h"
+
+enum custom_keycodes {
+ KC_MY_BTN0 = KEYBALL_SAFE_RANGE, // Remap上では 0x5DAF(レイヤー0に遷移できるBTN1)
+ KC_MY_BTN1, // Remap上では 0x5DB0
+ KC_MY_BTN2, // Remap上では 0x5DB1
+ KC_MY_BTN3, // Remap上では 0x5DB2
+ KC_GESTURE1, // Remap上では 0x5DB3(ジェスチャーボタン1)
+ KC_GESTURE2, // Remap上では 0x5DB4(ジェスチャーボタン2)
+ KC_GESTURE3, // Remap上では 0x5DB5(ジェスチャーボタン3)
+};
+
+#include "features/functions.h"
+#include "features/swipe_gesture.h"
+#include "features/auto_click_layer.h"
+#include "features/macro_keys.h"
+
+// clang-format off
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ // keymap for default (VIA)
+ [0] = LAYOUT_universal(
+ KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P ,
+ KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_MINS ,
+ KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM , KC_DOT , KC_SLSH ,
+ KC_LCTL , KC_LGUI , KC_LALT ,LSFT_T(KC_LNG2),LT(1,KC_SPC),LT(3,KC_LNG1),KC_BSPC,LT(2,KC_ENT),LSFT_T(KC_LNG2),KC_RALT,KC_RGUI, KC_RSFT
+ ),
+
+ [1] = LAYOUT_universal(
+ KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_RBRC , KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 ,
+ KC_F5 , KC_EXLM , S(KC_6) ,S(KC_INT3), S(KC_8) , S(KC_INT1), KC_BTN1 , KC_PGUP , KC_BTN2 , KC_SCLN ,
+ S(KC_EQL),S(KC_LBRC),S(KC_7) , S(KC_2) ,S(KC_RBRC), KC_LBRC , KC_DLR , KC_PGDN , KC_BTN3 , KC_F11 ,
+ KC_INT1 , KC_EQL , S(KC_3) , _______ , _______ , _______ , TO(2) , TO(0) , _______ , KC_RALT , KC_RGUI , KC_F12
+ ),
+
+ [2] = LAYOUT_universal(
+ KC_TAB , KC_7 , KC_8 , KC_9 , KC_MINS , KC_NUHS , _______ , KC_BTN3 , _______ , KC_BSPC ,
+ S(KC_QUOT), KC_4 , KC_5 , KC_6 ,S(KC_SCLN), S(KC_9) , KC_BTN1 , KC_UP , KC_BTN2 , KC_QUOT ,
+ KC_SLSH , KC_1 , KC_2 , KC_3 ,S(KC_MINS), S(KC_NUHS), KC_LEFT , KC_DOWN , KC_RGHT , _______ ,
+ KC_ESC , KC_0 , KC_DOT , KC_DEL , KC_ENT , KC_BSPC , _______ , _______ , _______ , _______ , _______ , _______
+ ),
+
+ [3] = LAYOUT_universal(
+ RGB_TOG , AML_TO , AML_I50 , AML_D50 , _______ , _______ , _______ , SSNP_HOR , SSNP_VRT , SSNP_FRE ,
+ RGB_MOD , RGB_HUI , RGB_SAI , RGB_VAI , SCRL_DVI , _______ , _______ , _______ , _______ , _______ ,
+ RGB_RMOD , RGB_HUD , RGB_SAD , RGB_VAD , SCRL_DVD , CPI_D1K , CPI_D100 , CPI_I100 , CPI_I1K , KBC_SAVE ,
+ QK_BOOT , KBC_RST , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , KBC_RST , QK_BOOT
+ ),
+
+ [4] = LAYOUT_universal(
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ,
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ,
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ,
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______
+ ),
+
+ [5] = LAYOUT_universal(
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ,
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ,
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ ,
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______
+ ),
+
+ [6] = LAYOUT_universal(
+ _______ ,KC_GESTURE1,KC_GESTURE2,KC_GESTURE3,_______, _______ , _______ , _______ , _______ , _______ ,
+ _______ , _______ , _______ , _______ , _______ , _______ ,KC_MY_BTN1,KC_MY_BTN3,KC_MY_BTN2, _______ ,
+ _______ , _______ , _______ ,KC_MY_BTN0,KC_MY_BTN0, _______ , _______ , _______ , _______ , _______ ,
+ _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______ , _______
+ )
+};
+// clang-format on
+
+layer_state_t layer_state_set_user(layer_state_t state) {
+ // Auto enable scroll mode when the highest layer is 3
+ // keyball_set_scroll_mode(get_highest_layer(state) == 3);
+ keyball_set_scroll_mode(get_highest_layer(state) == 1 || get_highest_layer(state) == 3);
+ return state;
+}
+
+#ifdef OLED_ENABLE
+
+#include "lib/oledkit/oledkit.h"
+
+void oledkit_render_info_user(void) {
+ keyball_oled_render_keyinfo();
+ keyball_oled_render_ballinfo();
+ keyball_oled_render_layerinfo();
+}
+#endif
diff --git a/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/rules.mk b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/rules.mk
new file mode 100644
index 000000000..7ca4f9c37
--- /dev/null
+++ b/qmk_firmware/keyboards/keyball/keyball39/keymaps/viamy/rules.mk
@@ -0,0 +1,5 @@
+RGBLIGHT_ENABLE = no
+
+OLED_ENABLE = yes
+
+VIA_ENABLE = yes