Keyboard Quantizer Mini のファームウェアのビルド環境作成 (obsolete)

:::note warn
Keyboard Quantizer Mini のファームウェアが新しくなっています。最新のRemapに対応しています。
この記事はすでに古いので参考にしないでください。
:::

新しい Keyboard Quantizer Mini のファームウェアのビルド方法は下記のページにあります。

https://github.com/sekigon-gonnoc/keyboard-quantizer-doc/blob/master/mini/vial.md--

この記事は、私のメモ用に残しています。以下は古い記事です。
---

# 参考にしたサイト

https://github.com/sekigon-gonnoc/keyboard-quantizer-doc/tree/master

https://github.com/sekigon-gonnoc/keyboard-quantizer-doc/blob/master/mini/remap.md

http://www.neko.ne.jp/~freewing/hardware/qmk_via_rp2040_keyboard_quantizer/

# きっかけ

キーボードで操作するより、ロータリーエンコーダによるボリューム操作は便利だった。QMK USB-USB converter も便利だったので、これが一つにならないかな。[Adafruit Feather RP2040 with USB Type A Host](https://learn.adafruit.com/adafruit-feather-rp2040-with-usb-type-a-host) でも [Keyboard Quantizer Mini](https://nogikes.booth.pm/items/4823647) のファームウェアが動きそうなのと、ロータリーエンコーダとかも追加できそうだったので、まずは Keyboard Quantizer Mini のファームウェアのビルド環境を作るところから始めました。

# ビルド環境

私のビルド環境がどうも古いのかも。素直にあげれば良かった

WSL 上の Ubuntu。[python3 とか開発環境](https://github.com/qmk/qmk_firmware/blob/master/docs/newbs_getting_started.md)が必要です。

私の環境では、`qmk` でエラーがでたので、`hid` のバージョンをダウングレードしています。
`qmk --help` で以下のようなエラーがでた場合は、`hid` を `1.0.4` にしてみてください。

```
$ qmk --help
Traceback (most recent call last):
  File "/home/sugyo/qmk/venv/bin/qmk", line 8, in <module>
    sys.exit(main())
  File "/home/sugyo/qmk/venv/lib/python3.8/site-packages/qmk_cli/script_qmk.py", line 76, in main
    import qmk.cli  # noqa
  File "/home/sugyo/qmk/mini/qmk_firmware/lib/python/qmk/cli/__init__.py", line 223, in <module>
    __import__(subcommand)
  File "/home/sugyo/qmk/mini/qmk_firmware/lib/python/qmk/cli/console.py", line 9, in <module>
    import hid
  File "/home/sugyo/qmk/venv/lib/python3.8/site-packages/hid/__init__.py", line 83, in <module>
    hidapi.hid_get_input_report.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t]
  File "/usr/lib/python3.8/ctypes/__init__.py", line 382, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python3.8/ctypes/__init__.py", line 387, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /usr/lib/x86_64-linux-gnu/libhidapi-hidraw.so.0: undefined symbol: hid_get_input_report
$
```

## hid を 1.0.4 にする

```
python3 -m pip uninstall hid
python3 -m pip install --user hid==1.0.4
```

# ソースコードの取得

git をつかって取得します

```
$ git clone https://github.com/sekigon-gonnoc/qmk_firmware.git
...
```

## quantizer_miniブランチに切り替え

```
$ cd qmk_firmware
$ git branch -r | grep quantizer_mini
  origin/quantizer_mini
$ git checkout quantizer_mini
...
```

## git submodule updateの事前作業とgit submodule update

この後 `submodule` をアップデートするのですが、urlがhttpsでなくgitになっていたのでので`submodule update`する前にその部分を修正してから`submodule update`をします。`submodule update`は`make git-submodule`とします。

```:make git-submoduleによるsubmoduleの取得
$ sed -i 's/git@\([^:]*\):/https:\/\/\1\//' .gitmodules
$ make git-submodule
...
```

# ビルド

私の環境だと `__always_inline` が以下のようなエラーがでるので、`{__always_inline,static __force_inline,static inline __force_inline}` は、`static __force_inline` に統一しました。

```
error: always_inline function might not be inlinable [-Werror=attributes]
```

## `__always_inline` 修正

{__always_inline,static __force_inline,static inline __force_inline} は、static __force_inline をに修正

```
grep -lr '^static __always_inline' lib/Pico-PIO-USB | xargs -r sed -i 's/^static __always_inline/static __force_inline/'
grep -lr '^static inline __force_inline' lib/Pico-PIO-USB | xargs -r sed -i 's/^static inline __force_inline/static __force_inline/'
```

## ビルドします。

```
$ make keyboard_quantizer/mini:default:uf2
...
$ ls keyboard_quantizer_mini_default.uf2
keyboard_quantizer_mini_default.uf2
$
```

これで、`keyboard_quantizer_mini_default.uf2` が出来上がりました。

# Keyboard Quantizer Mini の情報

Keyboard Quantizer Mini は、USB HOSTの配線が `D+ = 4` で、LEDが `7`でした。

```c:keyboards/keyboard_quantizer/mini/mini.c
    pio_cfg.pin_dp = 4;
```

```c:keyboards/keyboard_quantizer/mini/mini.h
#define KQ_PIN_LED 7
```

# Adafruit Feather RP2040 with USB Type A Host の情報

[Adafruit Feather RP2040 with USB Type A Host](https://learn.adafruit.com/adafruit-feather-rp2040-with-usb-type-a-host) だと、USB HOSTは `D+ = 16`、LEDが `13`で、USB HOSTの5v も有効にしないといけない。なるべく早くUSB HOSTの5v を有効にするため、mini.cに`keyboard_pre_init_kb()`を追加して以下のように入れるのがよさそうに今は思っています。

```c:keyboards/keyboard_quantizer/mini/mini.c
#define PIN_5V_EN 18  // Adafruit Feather RP2040 with USB Type A Host
#ifdef PIN_5V_EN
void keyboard_pre_init_kb(void) {
    setPinOutput(PIN_5V_EN);
    writePinHigh(PIN_5V_EN);
}
#endif
```

eepromも違うようなのでそこも見ないといけないような気がしています。→大丈夫なような気がしてきた

# スイッチサイエンス Picossci USBホスト の情報

[スイッチサイエンス Picossci USBホスト](https://www.switch-science.com/products/9158) だと、USB HOSTは `D+ = 0`、LEDが `25`です。PIN_5V_ENとかはないので2か所の修正でいけそう

# ソースコードの差分

試した時のソースコードの差分です

```diff_c:git diff --submodule=diff
diff --git a/.gitmodules b/.gitmodules
index 1a36514bd5..2f4e86428b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -28,4 +28,4 @@
        branch = for-keyboard-quantizer
 [submodule "lib/Pico-PIO-USB"]
        path = lib/Pico-PIO-USB
-       url = git@github.com:sekigon-gonnoc/Pico-PIO-USB.git
+       url = https://github.com/sekigon-gonnoc/Pico-PIO-USB.git
diff --git a/keyboards/keyboard_quantizer/mini/mini.c b/keyboards/keyboard_quantizer/mini/mini.c
index 2cf2d2b9d7..b842192a36 100644
--- a/keyboards/keyboard_quantizer/mini/mini.c
+++ b/keyboards/keyboard_quantizer/mini/mini.c
@@ -55,13 +55,20 @@ static volatile bool core1_active;
 static volatile bool core1_stop_trigger;
 static volatile bool core1_start_trigger;

+#ifdef PIN_5V_EN
+void keyboard_pre_init_kb(void) {
+    setPinOutput(PIN_5V_EN);
+    writePinHigh(PIN_5V_EN);
+}
+#endif
+
 void __not_in_flash_func(core1_main)(void) {
     core1_active = true;

     // Use tuh_configure() to pass pio configuration to the host stack
     // Note: tuh_configure() must be called before
     pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
-    pio_cfg.pin_dp = 4;
+    pio_cfg.pin_dp = PIN_PIO_USB_DP;
     pio_cfg.extra_error_retry_count = 10;
     tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg);

diff --git a/keyboards/keyboard_quantizer/mini/mini.h b/keyboards/keyboard_quantizer/mini/mini.h
index 197ef25450..4b491d6855 100644
--- a/keyboards/keyboard_quantizer/mini/mini.h
+++ b/keyboards/keyboard_quantizer/mini/mini.h
@@ -19,7 +19,19 @@
 #include <stdint.h>
 #include "keycode.h"

+// Keyboard Quantizer Mini
 #define KQ_PIN_LED 7
+#define PIN_PIO_USB_DP 4
+
+// Adafruit Feather RP2040 with USB Type A Host
+//#define KQ_PIN_LED 13
+//#define PIN_PIO_USB_DP 16
+//#define PIN_5V_EN 18
+
+// Switch Science Picossci USB Host
+//#define KQ_PIN_LED 25
+//#define PIN_PIO_USB_DP 0
+

 void uart_recv_callback(uint8_t dat);
 void uart_buf_init(void);
Submodule lib/Pico-PIO-USB contains modified content
diff --git a/lib/Pico-PIO-USB/src/pio_usb.c b/lib/Pico-PIO-USB/src/pio_usb.c
index 66f7ffe..a459c25 100644
--- a/lib/Pico-PIO-USB/src/pio_usb.c
+++ b/lib/Pico-PIO-USB/src/pio_usb.c
@@ -207,7 +207,7 @@ int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
   return -1;
 }

-static __always_inline void add_pio_host_rx_program(PIO pio,
+static __force_inline void add_pio_host_rx_program(PIO pio,
                                              const pio_program_t *program,
                                              const pio_program_t *debug_program,
                                              uint *offset, int debug_pin) {
@@ -363,7 +363,7 @@ void __no_inline_not_in_flash_func(pio_usb_ll_configure_endpoint)(
   ep->data_id = 0;
 }

-static inline __force_inline void prepare_tx_data(endpoint_t *ep) {
+static __force_inline void prepare_tx_data(endpoint_t *ep) {
   uint16_t const xact_len = pio_usb_ll_get_transaction_len(ep);
   ep->buffer[0] = USB_SYNC;
   ep->buffer[1] = (ep->data_id == 1)
diff --git a/lib/Pico-PIO-USB/src/pio_usb_device.c b/lib/Pico-PIO-USB/src/pio_usb_device.c
index 119f473..f3872d3 100644
--- a/lib/Pico-PIO-USB/src/pio_usb_device.c
+++ b/lib/Pico-PIO-USB/src/pio_usb_device.c
@@ -36,14 +36,14 @@ static void __no_inline_not_in_flash_func(update_ep0_crc5_lut)(uint8_t addr) {
   }
 }

-static __always_inline void restart_usb_reveiver(pio_port_t *pp) {
+static __force_inline void restart_usb_reveiver(pio_port_t *pp) {
   pio_sm_exec(pp->pio_usb_rx, pp->sm_rx, pp->rx_reset_instr);
   pio_sm_exec(pp->pio_usb_rx, pp->sm_rx, pp->rx_reset_instr2);
   pio_sm_restart(pp->pio_usb_rx, pp->sm_rx);
   pp->pio_usb_rx->irq = IRQ_RX_ALL_MASK;
 }

-static __always_inline int8_t device_receive_token(uint8_t *buffer,
+static __force_inline int8_t device_receive_token(uint8_t *buffer,
                                                    uint8_t dev_addr) {
   pio_port_t *pp = PIO_USB_PIO_PORT(0);
   uint8_t idx = 0;
diff --git a/lib/Pico-PIO-USB/src/pio_usb_host.c b/lib/Pico-PIO-USB/src/pio_usb_host.c
index 227ea6a..ff318fa 100644
--- a/lib/Pico-PIO-USB/src/pio_usb_host.c
+++ b/lib/Pico-PIO-USB/src/pio_usb_host.c
@@ -113,7 +113,7 @@ static void __no_inline_not_in_flash_func(override_pio_program)(PIO pio, const p
     }
 }

-static __always_inline void override_pio_rx_program(PIO pio,
+static __force_inline void override_pio_rx_program(PIO pio,
                                              const pio_program_t *program,
                                              const pio_program_t *debug_program,
                                              uint offset, int debug_pin) {
@@ -384,7 +384,7 @@ void pio_usb_host_close_device(uint8_t root_idx, uint8_t device_address) {
   }
 }

-static inline __force_inline endpoint_t * _find_ep(uint8_t root_idx,
+static __force_inline endpoint_t * _find_ep(uint8_t root_idx,
                                                    uint8_t device_address, uint8_t ep_address) {
   for (int ep_pool_idx = 0; ep_pool_idx < PIO_USB_EP_POOL_CNT; ep_pool_idx++) {
     endpoint_t *ep = PIO_USB_ENDPOINT(ep_pool_idx);
diff --git a/lib/Pico-PIO-USB/src/pio_usb_ll.h b/lib/Pico-PIO-USB/src/pio_usb_ll.h
index 3329ebc..82cf6dd 100644
--- a/lib/Pico-PIO-USB/src/pio_usb_ll.h
+++ b/lib/Pico-PIO-USB/src/pio_usb_ll.h
@@ -131,7 +131,7 @@ void pio_usb_bus_send_handshake(const pio_port_t *pp, uint8_t pid);
 void pio_usb_bus_send_token(const pio_port_t *pp, uint8_t token, uint8_t addr,
                             uint8_t ep_num);

-static __always_inline port_pin_status_t
+static __force_inline port_pin_status_t
 pio_usb_bus_get_line_state(root_port_t *root) {
   uint8_t dp = gpio_get(root->pin_dp) ? 0 : 1;
   uint8_t dm = gpio_get(root->pin_dm) ? 0 : 1;
@@ -150,7 +150,7 @@ bool pio_usb_ll_transfer_start(endpoint_t *ep, uint8_t *buffer,
 bool pio_usb_ll_transfer_continue(endpoint_t *ep, uint16_t xferred_bytes);
 void pio_usb_ll_transfer_complete(endpoint_t *ep, uint32_t flag);

-static inline __force_inline uint16_t
+static __force_inline uint16_t
 pio_usb_ll_get_transaction_len(endpoint_t *ep) {
   uint16_t remaining = ep->total_len - ep->actual_len;
   return (remaining < ep->size) ? remaining : ep->size;
@@ -188,7 +188,7 @@ bool pio_usb_device_endpoint_open(uint8_t const *desc_endpoint);
 bool pio_usb_device_transfer(uint8_t ep_address, uint8_t *buffer,
                              uint16_t buflen);

-static inline __force_inline endpoint_t *
+static __force_inline endpoint_t *
 pio_usb_device_get_endpoint_by_address(uint8_t ep_address) {
   // index = 2*num + dir e.g out1, in1, out2, in2
   uint8_t const ep_idx = ((ep_address & 0x7f) << 1) | (ep_address >> 7);
diff --git a/lib/Pico-PIO-USB/src/usb_rx.pio b/lib/Pico-PIO-USB/src/usb_rx.pio
index bcd9d5e..97aacc5 100644
--- a/lib/Pico-PIO-USB/src/usb_rx.pio
+++ b/lib/Pico-PIO-USB/src/usb_rx.pio
@@ -165,7 +165,7 @@ flip:
 % c-sdk {
 #include "hardware/clocks.h"

-static __always_inline void pio_sm_set_jmp_pin(PIO pio, uint sm, uint jmp_pin) {
+static __force_inline void pio_sm_set_jmp_pin(PIO pio, uint sm, uint jmp_pin) {
   pio->sm[sm].execctrl =
       (pio->sm[sm].execctrl & ~PIO_SM0_EXECCTRL_JMP_PIN_BITS) |
       (jmp_pin << PIO_SM0_EXECCTRL_JMP_PIN_LSB);
diff --git a/lib/Pico-PIO-USB/src/usb_rx.pio.h b/lib/Pico-PIO-USB/src/usb_rx.pio.h
index b581797..69980b0 100644
--- a/lib/Pico-PIO-USB/src/usb_rx.pio.h
+++ b/lib/Pico-PIO-USB/src/usb_rx.pio.h
@@ -183,7 +183,7 @@ static inline pio_sm_config usb_nrzi_decoder_debug_program_get_default_config(ui
 }

 #include "hardware/clocks.h"
-static __always_inline void pio_sm_set_jmp_pin(PIO pio, uint sm, uint jmp_pin) {
+static __force_inline void pio_sm_set_jmp_pin(PIO pio, uint sm, uint jmp_pin) {
   pio->sm[sm].execctrl =
       (pio->sm[sm].execctrl & ~PIO_SM0_EXECCTRL_JMP_PIN_BITS) |
       (jmp_pin << PIO_SM0_EXECCTRL_JMP_PIN_LSB);
Submodule lib/ugfx contains modified content
diff --git a/lib/ugfx/tools/mcufontencoder/binaries/windows/mcufont.exe b/lib/ugfx/tools/mcufontencoder/binaries/windows/mcufont.exe
deleted file mode 100644
index f12c9c47..00000000
Binary files a/lib/ugfx/tools/mcufontencoder/binaries/windows/mcufont.exe and /dev/null differ
```

元にしたソースコードのコミットのID

```:git show --no-patch
commit a984225f6ad58e457cba3e1889c49841a7b5b55c (HEAD, origin/quantizer_mini)
Author: sekigon-gonnoc <43873124+sekigon-gonnoc@users.noreply.github.com>
Date:   Sat Jul 8 20:50:09 2023 +0900

    Increase CFG_TUH_HID to 8
```

# REMAP

Remapがアップデートされて、Keyboard Quantizer Miniのベースのqmkが少し古いので、Remapで変更できなくなりました。[旧バージョンのRemap](https://qmk018.remap-keys.app/)を利用すればできます。

https://shop.yushakobo.jp/blogs/news/remap

# さいごに

[せきごん](https://nogikes.booth.pm/items/4823647)さん、ありがとうございます