KQB keymap.c QMK薙刀式

2022.04.26 限定公開の解除理由
この手順でKeyboard Quantizer Bで
QMK薙刀式が使用できた実例が確認できたので
限定公開を解除して全体公開に変更します。

QMK薙刀式をRemap対応する方法
https://qiita.com/deepprog/items/7e20a4623224800dbf57
上記の記事を先に読んでから、この記事をお読み下さい。
Keyboard Quantizer Bに適用するための
変更する箇所を説明した記事になります。

2022.03.16 限定公開時の記事内容
パソコンが使えない状況のために
スマホから修正しただけのプログラムです
コンパイルや動作確認は未確認です。

KQBのデフォルトのkeymap.cに修正しました
keymap.cは、これに変更します。

他のファイルは
https://github.com/deepprog/qmk_firmware/tree/rp2040/keyboards/keyboard_quantizer/rp/keymaps/naginata

config.h
nagina.h
naginata_v14.c
rules.mk
の4つをファイルコピーします。

コピー先はビルドガイドでクローンしたフォルダの
qmk_firmware_bmp/keyboards/keyboard_quantizer/kqb/keymaps/naginata

コンパイルはdefault　を　naginataに変更した
make keyboard_quantizer/kqb:naginata:uf2

追加した箇所は
//s1 で始まり
//e1 で終わり
の間が追加したプログラムです。
s1-e1からs4-e4までの
4箇所の追加をしています。

```c:keymap.c
/* Copyright 2020 sekigon-gonnoc
 *
 * 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 <http://www.gnu.org/licenses/>.
 */
#include "keycode.h"
#include QMK_KEYBOARD_H
#include "bmp.h"
#include "bmp_custom_keycode.h"
#include "keycode_str_converter.h"

#include "pointing_device.h"
#include "report_parser.h"

//s1
// 薙刀式
#include "naginata.h"
NGKEYS naginata_keys;
// 薙刀式

enum keymap_layers {
  _QWERTY = 0,
// 薙刀式
  _NAGINATA = 1, // 薙刀式入力レイヤー
// 薙刀式
  _LOWER = 2,
  _RAISE = 3,
};
//e1

// Defines the keycodes used by our macros in process_record_user
enum custom_keycodes {
    CUSTOM_KEYCODE_START = BMP_SAFE_RANGE,
//s2
    E ISU = NG_SAFE_RANGE,
	KANA2,
	
	SPD_1,
    SPD_2,
    SPD_3,
//e2
};

//s3
#define KC_L_SPC LT(_LOWER, KC_SPC)  // lower
#define KC_R_ENT LT(_RAISE, KC_ENT)  // raise
#define KC_G_JA LGUI_T(KC_LANG1)     // cmd or win
#define KC_G_EN LGUI_T(KC_LANG2)     // cmd or win
#define KC_C_BS LCTL_T(KC_BSPC)      // ctrl
#define KC_A_DEL ALT_T(KC_DEL)       // alt

void matrix_init_user(void) {
  // 薙刀式
  uint16_t ngonkeys[] = {KC_H, KC_J};
  uint16_t ngoffkeys[] = {KC_F, KC_G};
  set_naginata(_NAGINATA, ngonkeys, ngoffkeys);
  // 薙刀式
}
//e3

const key_string_map_t custom_keys_user = {.start_kc    = CUSTOM_KEYCODE_START,
                                           .end_kc      = CUSTOM_KEYCODE_START,
                                           .key_strings = "\0"};

const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {{{KC_NO}}};

uint32_t keymaps_len() { return 70; }

typedef enum {
    GESTURE_NONE = 0,
    GESTURE_DOWN_RIGHT,
    GESTURE_DOWN_LEFT,
    GESTURE_UP_LEFT,
    GESTURE_UP_RIGHT,
} gesture_id_t;

extern bool          matrix_has_changed;
extern matrix_row_t* matrix_mouse_dest;
extern bool          mouse_send_flag;

static uint8_t spd_rate_num       = 1;
static uint8_t spd_rate_den       = 1;
static int16_t gesture_move_x     = 0;
static int16_t gesture_move_y     = 0;
static bool    gesture_wait       = false;
static uint8_t kc_no_to_kc_offset = 0;
static uint8_t btn_release_flag   = 0;
static int16_t wheel_move_v       = 0;
static int16_t wheel_move_h       = 0;

static uint8_t get_gesture_threshold() {
    return BMPAPI->app.get_config()->reserved[5];
}

bool process_record_user(uint16_t keycode, keyrecord_t* record) {
    bool continue_process = process_record_user_bmp(keycode, record);
    if (continue_process == false) {
        return false;
    }
//s4
	switch (keycode) {
		case EISU:
			if (record->event.pressed) {
				// 薙刀式
				naginata_off();
				// 薙刀式
			}
		return false;
		break;
		
		case KANA2:
		if (record->event.pressed) {
			// 薙刀式
			naginata_on();
			// 薙刀式
		}
		return false;
		break;
	}

	// 薙刀式
		if (!process_naginata(keycode, record))
			return false;
	// 薙刀式
//e4
    switch (keycode) {
        case KC_BTN1 ... KC_BTN5:
            mouse_send_flag = true;
            return true;
            break;

        case KC_MS_WH_UP ... KC_MS_WH_DOWN: {
            if (wheel_move_v != 0) {
                report_mouse_t report = pointing_device_get_report();
                report.v = keycode == KC_MS_WH_UP ? abs(wheel_move_v)
                                                  : -abs(wheel_move_v);
                pointing_device_set_report(report);
                mouse_send_flag = true;
                return false;
            } else {
                return true;
            }
        } break;

        case KC_MS_WH_LEFT ... KC_MS_WH_RIGHT: {
            if (wheel_move_h != 0) {
                report_mouse_t report = pointing_device_get_report();
                report.h = keycode == KC_MS_WH_LEFT ? abs(wheel_move_h)
                                                    : -abs(wheel_move_h);
                pointing_device_set_report(report);
                mouse_send_flag = true;
                return false;
            } else {
                return true;
            }
        } break;

        default:
            break;
    }

    // Enable layer tap with KC_BTNx
    if (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) {
        uint8_t kc = keycode & 0xFF;
        if (kc == KC_NO) {
            kc = kc_no_to_kc_offset;
            dprintf("KC:%d, tap:%d\n", kc, record->tap.count);
            if (record->tap.count > 0 && !record->tap.interrupted) {
                // set mouse button bit
                report_mouse_t mouse = pointing_device_get_report();
                mouse.buttons |= (1 << (kc - KC_BTN1));
                pointing_device_set_report(mouse);
                mouse_send_flag = true;
                btn_release_flag |= (1 << (kc - KC_BTN1));
            }
        }
    }

    return true;
}

gesture_id_t recognize_gesture(int16_t x, int16_t y) {
    gesture_id_t gesture_id = 0;

    if (abs(x) + abs(y) < get_gesture_threshold()) {
        gesture_id = GESTURE_NONE;
    } else if (x >= 0 && y >= 0) {
        gesture_id = GESTURE_DOWN_RIGHT;
    } else if (x < 0 && y >= 0) {
        gesture_id = GESTURE_DOWN_LEFT;
    } else if (x < 0 && y < 0) {
        gesture_id = GESTURE_UP_LEFT;
    } else if (x >= 0 && y < 0) {
        gesture_id = GESTURE_UP_RIGHT;
    }

    return gesture_id;
}

void process_gesture(uint8_t layer, gesture_id_t gesture_id) {
    switch (gesture_id) {
        case GESTURE_DOWN_RIGHT ... GESTURE_UP_RIGHT: {
            keypos_t keypos  = {.row = MATRIX_MSGES_ROW, .col = gesture_id - 1};
            uint16_t keycode = keymap_key_to_keycode(layer, keypos);
            tap_code16(keycode);
        } break;
        default:
            break;
    }
}

// Start gesture recognition
static void gesture_start(void) {
    dprint("Gesture start\n");
    gesture_wait   = true;
    gesture_move_x = 0;
    gesture_move_y = 0;
}

uint16_t keymap_key_to_keycode_bmp(uint8_t layer, keypos_t key) {
    uint16_t keycode =
        BMPAPI->app.keymap_key_to_keycode(layer, (bmp_api_keypos_t*)&key);

    // To use LT with mouse button, replace keycode and save offset
    if (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) {
        uint8_t kc = keycode & 0xFF;
        if (kc >= KC_BTN1 && kc <= KC_BTN5) {
            kc_no_to_kc_offset = kc;

            // Gesture recognition trick
            // Start gesture when LT key is pressed
            if (matrix_is_on(key.row, key.col) && gesture_wait == false) {
                gesture_start();
            }

            return keycode & 0xFF00;
        } else {
            kc_no_to_kc_offset = 0;
        }
    }

    return keycode;
}

void matrix_scan_user(void) {
    if (btn_release_flag) {
        report_mouse_t mouse = pointing_device_get_report();
        mouse.buttons &= ~btn_release_flag;
        btn_release_flag = 0;
        pointing_device_set_report(mouse);
        mouse_send_flag = true;
    }
}

void post_process_record_user(uint16_t keycode, keyrecord_t* record) {
    if (keycode >= QK_MOMENTARY && keycode <= QK_MOMENTARY_MAX) {
        if (record->event.pressed && gesture_wait == false) {
            gesture_start();
        }
    }

    if ((keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) ||
        (keycode >= QK_MOMENTARY && keycode <= QK_MOMENTARY_MAX)) {
        if (gesture_wait == true && (!record->event.pressed)) {
            gesture_wait = false;
            gesture_id_t gesture_id =
                recognize_gesture(gesture_move_x, gesture_move_y);

            uint8_t layer = 0;
            if ((keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
                layer = (keycode >> 8) & 0x0F;
            } else {
                layer = keycode & 0xFF;
            }

            process_gesture(layer, gesture_id);
            dprintf("id:%d x:%d,y:%d\n", gesture_id, gesture_move_x,
                    gesture_move_y);
        }
    }
}

void mouse_report_hook(mouse_parse_result_t const* report) {
    if (debug_enable) {
        xprintf("Mouse report\n");
        xprintf("b:%d ", report->button);
        xprintf("x:%d ", report->x);
        xprintf("y:%d ", report->y);
        xprintf("v:%d ", report->v);
        xprintf("h:%d ", report->h);
        xprintf("undef:%u\n", report->undefined);
    }

    //
    // Assign buttons to matrix
    // 8 button mouse is assumed
    //
    uint8_t button_prev    = matrix_mouse_dest[0];
    uint8_t button_current = report->button;

    if (button_current != button_prev) {
        matrix_has_changed = true;
    }
    matrix_mouse_dest[0] = button_current;

    //
    // Assign wheel to key action
    //
    if (report->v != 0) {
        keypos_t key;
        wheel_move_v = report->v;
        key.row      = MATRIX_MSWHEEL_ROW;
        key.col = report->v > 0 ? MATRIX_MSWHEEL_COL : MATRIX_MSWHEEL_COL + 1;
        action_exec((keyevent_t){
            .key = key, .pressed = true, .time = (timer_read() | 1)});
        action_exec((keyevent_t){
            .key = key, .pressed = false, .time = (timer_read() | 1)});
    }

    if (report->h != 0) {
        keypos_t key;
        wheel_move_h = report->h;
        key.row      = MATRIX_MSWHEEL_ROW;
        key.col =
            report->h > 0 ? MATRIX_MSWHEEL_COL + 2 : MATRIX_MSWHEEL_COL + 3;
        action_exec((keyevent_t){
            .key = key, .pressed = true, .time = (timer_read() | 1)});
        action_exec((keyevent_t){
            .key = key, .pressed = false, .time = (timer_read() | 1)});
    }

    //
    // Assign mouse movement
    //
    mouse_send_flag      = true;
    report_mouse_t mouse = pointing_device_get_report();

    static int16_t x_rem;
    static int16_t y_rem;

    int16_t x = (x_rem + report->x) * spd_rate_num / spd_rate_den;
    int16_t y = (y_rem + report->y) * spd_rate_num / spd_rate_den;

    if (spd_rate_den - spd_rate_num > 0) {
        x_rem = (x_rem + report->x) - (x * spd_rate_den);
        y_rem = (y_rem + report->y) - (y * spd_rate_den);
    } else {
        x_rem = 0;
        y_rem = 0;
    }

    mouse.x += x;
    mouse.y += y;

    pointing_device_set_report(mouse);

    //
    // Save movement to recognize gesture
    //
    if (gesture_wait) {
        gesture_move_x += report->x;
        gesture_move_y += report->y;
    }
}
```