2020/08/09

Zaunkoenig M1Kのカスタムファームウェアの書き込み方法

はじめに

クラウドファンディングで開発されたZaunkoenig M1Kが手元に届きました。

「マウスは軽量であればあるほどよい」というのは、物理的な法則として自明ですが、ここ数年でユーザ全体に定着しつつあります。そうした時流の中で「最低限のモノ以外を全て削ぎ落とし、極限まで軽量化したマウスはどうなるか?」という疑問に対して、明確に解答する素晴らしいマウスだと思います。

使い手は選びますが、競技AIM界隈の方などは検討されてはいかがでしょうか?
細かいレビュー等はデバイス界隈の方が積極的に発信されているので割愛します。


分解画像

とりあえず分解画像を置いておきます。


ファームウェアのカスタマイズについて

一般的なゲーミングマウスでは、ファームウェアはバイナリファイルという形で配布されており、ソースコードは公開されません。そのため内部のアルゴリズムなどを変更するためには、多大な手間と技術が要求されるリバースエンジニアリングが必要であり、非常に難しいものでした。M1Kの良いところは軽量である以上に、ファームウェアがオープンソースとして公開しており、ユーザが自由にカスタマイズできることです。

ファームウェアをカスタマイズできるということは、少し考えるだけでも以下のようなことが出来ます。

  • センサの出力に対して、独自に考案した補正アルゴリズムで適用することで、最強のトラッキング特性を持つマウスを作る
  • ハードウェアベースでのマウス加速を追加する
    • こうすることでソフトウェアベースのマウス加速ツールと違い、アンチチートソフトに誤認される*ようなことがなくなります
  • センサの設定をレジスタベルでチューニングする
  • マウスのCPI設定やポーリングレートについて独自の値をプリセットする
  • ボタンを追加してマウスホイールなどの機能を追加する
    • M1Kの基板には機能追加を前提として予備端子をはんだ付けすることができる場所が用意されています
  • クリックの応答速度を最適化する
    • (M1Kのファームウェアはoverclock.netで活躍されているqsxcvも関わっているので、かなり最適化されていると思いますが…)
などなど。夢が広がりますね。

*巷の噂によると、Valorantではマウス加速ツールの「InterAccel」が一時期ブロックされていたようです。



環境構築について

カスタムファームウェアを作るために、まずは環境構築をしてみましょう。

本ブログの大半の方はWindowsを利用されていると思いますので、Windows向けの手順について、マニュアルを翻訳して以下にアップロードしました。この手順通りにやれば問題なく環境構築できると思います。

日本語マニュアル: https://github.com/systema-tic/m1k-firmware/blob/master/README_JA.md

ファームウェアのビルド環境について

公開されている状態だとソースコードのビルド環境としてはLinuxを前提としているため、コンパイラをWindowsで動かすのはかなり面倒なようです。
WindowsにおけるAVR用コンパイラとしてはWin-AVRが有名ですが、古すぎて動作しないようです。最新のAVR Studioなどをインストールしてビルドする環境を整えることは一応できましたが、公開されている状態のソースコードをAVR Studioに適用するには、AVRでの開発経験とIDEへの理解の理解が必要なので、上級者向けだと思います。
今回の手順では、Windows上でLinux環境を簡単に動かすための仕組みであるWSLを導入することで解決しています。


ファームウェアの書き込み環境

こちらはコマンド操作が必要ですが、Windowsで動くツールがありますので、難しい手順はありません。


その他

とりあえず、ソースコードのビルド→マウスへの書き込みまで実施できました。
まだソースコードのカスタマイズ自体には手を出していないので、なにか成果があれば適宜GitHubに上げていこうと思います。

2019/09/08

Zaunkoenig M1KのAMAに参加しました

デバイス沼Discordさんが主催した、現在開発中の重量23gという超軽量マウスZaunkoenig M1Kの開発者の方のAMAに参加しました。配信のアーカイブはここから見れます。

私からのいくつか質問させていただきましたが、解説のリクエストをいただきましたので、簡単にまとめられておきます。

Q. 3360センサーはPixartから直接買っているのですか?それともTindieのようなサービスを利用して間接的に購入していますか?
A. CODICOという会社から直接買っている。その会社がPixartから買っている。
  • 質問の意図:
    DigiKeyなどの電子部品をバラ売りしてくれるサイトを探してもハイエンドセンサは売っていないという現状がありました。今だと、センサを小ロットで入手する方法がTindieくらいしかないため、いい感じの流通経路があれば良いなぁと思ったため。
  • 分かったこと:
    ディストリビュータを利用されているようです。他の部品を合わせて買っているのだと思います。これは普通のメーカさんのやり方なので、私の趣味レベルだとちょっと規模的に足りないです。本格的にやるにはやはりディストリビュータを介した方が安全安心、手間もかからないですね。


Q. USB HIDに対応したマイクロコントローラは様々なメーカが出荷していますが、ATmega(AVR)を採用した理由があれば教えて下さい。
A. オープンソースで自分のファームウェアをインストールするときにも楽だから。
  • 質問の意図:
    私は数年前まではCypressのPSoC、今は気分でTeensyを使っていますが、他にもPIC、mbed、STMなど色々な選択肢がある中で、メインで使うMCUの選定は迷っているので、意見を聞いてみたかったです。
  • 分かったこと:
    下の質問に繋がりますが、専用ライタが不要でUSB経由でファームウェアの書き換えができるという点が決め手になったのだと思います。
    回答には出なかったですが、この選定については、ファームを書く人が常用しているかどうかもポイントになってきます。マイクロコントローラなどの組み込み系の部品はメーカを切り替えると、開発環境やプログラムの書き方のお作法が大きく変わる場合が多く、ソースコードの移植性も高くないので、学習コストやコードの書き換えが大変です。

Q. ファームウェアをオープンソースにすることで、コミュニティがファームウェアを改良していくようなムーブメントを意識されていますか?
A. はい。それによってインプットラグの軽減、マウスのプログラミング、ゴールドピンを自分ではんだ付けしたり、ホイールを自分で追加したければ出来るようになる。また、そのホイールを使うためにプログラミング出来る。
  • 質問の意図:
    新しくマウスを買ってきて試験すると「形は最高なんだけど、ファームウェアの実装が良くなくてトラッキング性能が低い/クリックレイテンシが高いから使えない」みたいな事がよくあります。そうしたときに「ファームウェアのソースコードがあれば自前で書き換えて、自分向けにカスタマイズできるのになぁ」と思うことが多いので、パトリックさんも同じことを考えていたのかなぁと確認したかったです。
  • 分かったこと:
    恐らく上記の経験をされていたか、経験をした人の意見を聞かれていたのではないかと思います。ゲーミングデバイスのファームウェアのオープンソース化が進むのは、デバイス勢にとってはとても良い事で、「フレームの形や搭載センサなどのハードウェアにだけ注目して購入※して、メーカが準備したファームウェアに不満があれば、自分で改良できる」みたいな感じになっていけば良いなぁと思いました。
    ※ハードウェアにセンサ付け替え機構などのカスタマイズ機構を入れるのは、私としては重量増の原因になるため支持していません。従って、ある程度メーカが最良だと思うハードウェア要件で、重量を切り詰めたものをメーカが製造・販売するほうが良いと考えています。
デバイス開発者の方とやり取りできる機会は少ないので、とても貴重な機会になりました。とりまとめ、翻訳などをしていただいて、ありがとうございました。

2019/08/15

Logicoolゲーミングマウスのスクロールホイールの解析と実装

はじめに

Logicool(Logitech)のゲーミングマウスは大抵の場合光学式のスクロールホイールを有しています。一般的な物理ホイールや光学式は2本の信号線を使ってホイールの回転数や回転方向を読み取りますが、Logicoolのホイールエンコーダーは1本の信号線でマイコンとやりとりします。それについての解析や実装をした文献があまり無いので記事にしました。

この記事の対象者

本記事は詳細かつ汎用性の薄い内容です。以下のような人を対象としています。
・Logicoolのマウス筐体に自作の制御基板(マイコン)を組み込もうとしている人
本記事では、Logicoolのマウスが持つ光学式スクロールホイールをスポイルせずに活用するための、マイコンの自作ファームウェアへの実装の支援を目的としています。

なお、Logicoolのマウスに別のメーカの制御基板(MCU)を組み込もうとしている場合は、信号線の本数や制御方法が根本的に違うため、間に互いの信号をエミュレートして仲介する機能が追加で必要になると思われます。

特許について

Logitech(Logicool)は、光学式エンコーダーの特許を取得しています。

Transmission of differential optical detector signal over a single line
https://patents.google.com/patent/US6552716

1本の線だけでホイールがどちらに回ったかを読み取れるという特殊なホイールエンコーダーです。通常の方法では、2つの信号線を2つのフォトインタラプタなどに接続し、フォトインタラプタの出力タイミングの違いから回転したタイミングと回転方向を取得するのですが、Logicoolのものはエンコーダー内に回路があり、そちらで信号処理した上で1つの信号線で回転したタイミングと回転方向ををやりとりします。

1. 各部品の結線

G300rの例をとって解説します。Logicoolのホイールエンコーダーは赤外線LED(IRLED)とエンコーダー本体の2つの電子部品から構成されています。
G300rの基板上部

1.1 IR LED

左側の透明な部品は赤外線LEDです。光る側にドーム状のレンズがついています。
以下に各ピンの結線先を示します。

アノード

基板に+Aと書いてあります。
USBのVcc(5V)に直結されています。

カソード

マイコンと実測148Ωの抵抗を介して接続されています。ピン番号は割愛(目が限界感)
論理的な動作は後述します。



1.2 エンコーダー

右側の黒い部品はエンコーダーです。メジャーな部品に例えると、トランジスタに見た目は似ています。型番やデータシートは数時間探したのですが見つかりませんでした。多分Logicoolにしか卸していないと思います。C国の通販サイトでは少し探すとバラ売りされていますが、流通経路は不明です。
以下に各ピンの結線先を示します。

電源

USBのVcc(5V)に直結されています。

信号線

MCUに直結されています。MCUのピンは内蔵プルアップかもしれません。

GND

USBのGND(0V)に直結されています。


2. 各信号線の動作

2.1 IR LEDのPWM動作

IR LEDのカソード側はPWM動作しています。普段は電圧はVcc(=電位差がないのでLEDは光らない状態)で、約11.5%の間だけ、電圧が約1.25V下がり、LEDを光らせる動作を一秒間に5000回しています。つまり5KHz デューティー比88.5%のPWMです(5VとMCUのピン電圧の差を利用してLEDを駆動していうため、通常のLEDの制御とはデューティー比が逆転することに注意してください)。


2.2 エンコーダーの信号線の動作

エンコーダーの信号線も5KHzで1連の動作をしています。

何もないとき

何も無いときはマイコン側からの信号のみが発出されています。
下の図でいうと右側の部分です。
マイコン側から2usのパルスが発出され、8usほど待って再度2usのパルスが発出されます。
右側に注目(青が信号線、黄色がLED)

ホイールが下に動いた時

ホイールが下に動いた時は、1回目のマイコン側のパルスの直後に、エンコーダー側から出力があります。下図の左右で見比べればわかりますが、左の方はエンコーダー側がホイールが下に動いたことを検知したため、1回目のパルスの直後にエンコーダーからの出力があります。結果として、マイコンの2回目のパルスが長くなっているように見えます。
左側に注目(青が信号線、黄色がLED)


ホイールが上に動いた時

ホイールが下に動いた時は、2回目のマイコンのパルスの直後にエンコーダー側から出力があります。下図の中央がその状態を示しており、2回目のパルス後に一瞬出力が下がりますが、その後約188usに渡ってエンコーダーの信号の出力があることが分かります。
中央に注目(青が信号線、黄色がLED)


つまり、、、どういうことだってばよ?

MCU向けのプログラム的に書き下すとこのようになります。
①ピンを出力ピンにし、2usのパルスを出力
②ピンを入力ピンにし、8usの間にエンコーダからの出力を読んで、出力があればホイールは下に動いている
③ピンを出力ピンにし、2usのパルスを出力
④ピンを入力ピンにし、188usの間にエンコーダからの出力を読んで、出力があればホイールは上に動いてる

※ただし、④の間にピンを読み続けていたら、それ以外のこと(例えば、USBでの通信やマウスセンサからの信号の受信)が全くできないので、数us後の値を読めば良いと思います。

ホイールの1ノッチ分での信号の出力回数

ホイールの1ノッチ、つまり1回だけホイールが動いた場合に上の信号は6回~9回程度出力されます。この回数はある程度ばらつきがあるため、ソフトウェアで補正する必要があります。



3. 実装

実装例としてTeensy LC+ Arduino Studioでのコードの一部を載せます。

3.1 LEDのPWM制御

LEDが5KHz周期で点滅している部分は、PWM制御で行います。大抵の場合セットアップシーケンスでPWM出力を設定します。
analogWriteFrequency(17, 5000); //17ピンに5kHz周期でPWM出力する
analogWrite(17, 228); //17ピンに228のデューティー比でPWM出力する
90%のデューティー比としたいので、228÷255=0.89となる228を指定しています。

3.2 ホイールの読み出し

5KHzで一連の処理を読み出す必要があります。
TeensyのIntervalTimerを使用するよう、グローバルで宣言します。
IntervalTimer WheelTimer; //WheelTimerをIntervalTimerとして利用する

セットアップシーケンスでタイマーをスタートさせます。
WheelTimer.begin(readWheel, 200); //200us毎にreadWheel関数を呼び出す
毎200usで呼び出す関数は下記のような感じです。
void readWheel() {
  int scroll_val = 0;
  int a, b;
  pinMode (WHL, OUTPUT); //出力ピンにする
  digitalWrite(WHL, HIGH); //ピンをHIGHへ
  delayMicroseconds(1); //本当は2us
  digitalWrite(WHL, LOW); //ピンをLOWへ
  pinMode (WHL, INPUT); //入力ピンにする
  delayMicroseconds(2); //エンコーダーの出力の立ち上がりを待つ
  a = digitalRead(WHL); //エンコーダーの値を読む(HIGHならホイールダウン)
  delayMicroseconds(2); //ちょっと待つ
  pinMode (WHL, OUTPUT); //出力ピンにする
  digitalWrite(WHL, HIGH); //ピンをHIGHへ
  delayMicroseconds(1); //本当は2us
  digitalWrite(WHL, LOW); //ピンをLOWへ
  pinMode (WHL, INPUT); //入力ピンにする
  delayMicroseconds(2); //エンコーダーの出力の立ち上がりを待つ
  b = digitalRead(WHL);; //エンコーダーの値を読む(HIGHならホイールアップ)
  wheel_ticks += b - a; 
}
基本的には、ピンのI/Oを切り替えながら、適宜ディレイを入れてあるべき姿にします。
前半がホイールダウンを読む部分、後半がホイールアップを読む部分です。

随所のdelayMicroseconds()がオシロスコープの測定値より短いのは、マイコン側のオーバーヘッドも考慮して、実測値と一番近い長さになるように測定しながら調整したためです。これはマイコンによって調整の必要があるでしょう。

wheel_ticksはグローバル変数で、これをホイールの回転数として出力します。ただし、ホイールの1ノッチあたり6~9程度は変化するので、USBに出力する際は後処理が必要です。


謝辞

本記事の情報、実装についてはqsxcv氏の投稿及びソースコードを参考にさせていただきました。

2019/01/26

マウス用センサーのレジスタを直接触れるようにする


はじめに

年末年始にかけてPMW3360センサーをG300rに移植しました。G300rは形状は素晴らしいのですが、センサは貧弱なので、近代化改修すれば最強なのでは?というモチベーションです。現状ではFPSをプレイする時間と気力がないんですけどね。
ファームウェアは有名どころだとqsxcvさんなどが公開されていますが、使っているボードの種類がちょっと違うという点もあって自前で書き始めています。とりあえずマウスとしては動きますが、データパスの16bit化や、ホイール周りが完了しておらず、まだまだ未完成です。
せっかく自前で書くのならもう少し面白い機能を付けてみようってことで、レジスタの値をUART経由で読み書きできる機能を付けました。


これができると何が嬉しいか?

ファームウェアにレジスタの値を固定値として入れ込んでしまうと、レジスタの値を変更したい場合、ファームウェアを焼き直さない限り変更ができません。
普通のゲーミングマウスの場合、PCに専用のソフトウェア(Logicool ゲームソフトウェアなど)をインストールすれば、GUI経由で一部のパラメータ(DPIやポーリングレート、LED色など)が変更できます。しかし、専用のソフトウェアの実装自体が(私の能力がないのもあって)大変ですし、様々なパラメータの変更を全てGUI経由で変更できるようにするのはとてもめんどくさいです。
そこで、原始的な実装として、UART経由でレジスタの値を直接読み書きできるようにしました。レジスタを直接編集できるようになるため、レジスタの値を変更したい時にMCUへファームウェアの焼き直しが不要になり、色々な設定をすぐに適用し、試すことができます。また、任意のレジスタの情報を好きなタイミングで読み取ることができるのでデバッグが捗るかもしれません。

デモ

下記の動画がデモです。DPIを設定できるレジスタに色々な値を書き込んで、DPIが変更されていることを確認しています。


所感

組み込み用のファームウェアの開発というより、シェルや、ターミナルエミュレータの開発に近いです。そもそもエコーバックすらないので、キーボードで入力した文字列を画面上に描画したり、バックスペースが入力されたらカーソル位置の文字を削除するみたいな動作も書く必要があります。おかげで、ちょっとだけASCIIコードに詳しくなりました。
色々なコマンドと複数なパラメータをいい感じにハンドリングする方法も考えないといけないですね。
とりあえずFrameCaptureくらいはできるようにしたいです。

2017/06/24

#LogicalGaming

最終回!というわけでもないのですが・・・
予告していた4月がとっくに過ぎているので一区切りということで.

現状としては,たまたま空いた土日にちょろっとプレイする程度のカジュアルゲーマーになりました.
金銭的な余裕はあるので,Steamで面白そうなゲームを買っていますがそのまま積むという流れ.
プレイヤーとしては昨年度HOT Gamingで半年程プレイして,自分の中で区切りがついてしまったのかなと.(チームメンバーの皆様,本当にありがとうございました.足引っ張ってごめんなさい.)
身体的な理由もあって,今後競技的にゲームをプレイする予定はありません.
2億円くらい降ってくれば復帰できるのですが・・・理系として「期待値」という概念を学んでしまったために宝くじの購入に中々踏み切れません.

今後このブログをどうするかはノープランということで.
ポロッと理論系の記事を書くかもしれませんし,何か作ったりするかもしれません.
何にせよ更新頻度は大きく落ちると思うのでご了承ください.
「上げる」と言って放置してる記事が沢山ありますね.申し訳有りません・・・・


ゲーマーが何かを区切る時はやはりゲーミングポエムだと思っているので,慣例にならってカマしたいと思います.

ゲームって思っていた以上に奥が深いし,難しい

元々私はコンピューターグラフィックス(の製作ではなく技術動向の把握)を趣味としていた人間で,#LogicalGamingは数ヶ月程度で終わらせる予定でした.
しかし,始めたての頃にrafa様に言及していただいたり,デバイス勢の方々と関わっていくにつれて,楽しくなってここまで続いたのだと思います.RT/Fav,コメントなどなどありがとうございました.書いた記事のRTの通知がピコピコ鳴っている時の快楽性はかなりのものです.


「#LogicalGaming」ってなんだ?

せっかくなので名前の由来の話でも.
#を付けた理由は簡単で,弊ブログをタイトル付きでツイートした時にTwitterでタグ化されるためです.タグ化されると検索しやすいですし,弊ブログがTwitterをもう一つのチャンネルとして使っていることを示せると思って付けました.

LogicalGamingは簡単で「ゲーミングを論理的に」というだけです.ID野球じゃないですけど,ゲームシーンの色々な事象がもっとデータ化して最適化できると思うんですよね.
例えば「解像度をいくつにするか?」という議論においても「プロが使ってるから」っていうのはあまり理由にならないと思っています.そもそもプロもなんとなくとかジンクスで決めてることが多いんじゃないでしょうか.
本当は,「理論的にはこうで,統計的にはこうで,こういうメリットとデメリットがある」みたいな話が数字に基づいて議論されないと決まらないはずなんです.もちろん,理論を考えて,データを集めて,最適な値を決めるというのはとても難しいはずです.しかし,私は「PCゲームが誕生してから随分立つのに,もうちょっとそういう観点で考えようという風潮があっても良いんじゃないの?」と思っていた訳です.

結果的にデバイス方面に偏った内容ではありましたけど,論理的であることや定性・定量的であることを意識した内容だったと思います(その到達度に関しては議論の余地がありそうでしたが).


systemaというHNはsystematic(組織的・体系的)から取っています.これは「ゲーミングってもっと体系化できないのかな?」という過去の経験から生まれたものです.10年ほど前,サドンアタックというゲームをはじめた頃の私のKDは38%でした.KDRで言うと0.61くらいで,平均レベルまでスキルをつけるのに非常に苦労したことを覚えています.

例えば,プレイヤースキルをとっても「AIM」と「立ち回り」という用語で語られることが多いですが,初心者が「AIM」と「立ち回り」を鍛えようとしても用語の指す内容が高度かる抽象的すぎてなにをしていいか分からないですよね.
例えば「立ち回り」でしたら,「ポジショニング」や「シフト判断」,「エリア理論」などの色々な要素があります.しかし,それぞれの要素も粒度が色々あって,「ポジショニング」という粒度の低い要素の中には,「マップ知識」や「右壁左壁の概念」などの要素もはいっていますし,それぞれの要素が複雑に絡み合って「立ち回り」ひいてはプレイヤースキルを形作っているわけです.

そうしたプレイヤースキルに含まれる様々な粒度の要素のそれぞれを定義付けて,関係性を明らかにし,鍛え方(考え方)をまとめられたら,自分に足りないスキルとかを効率よく習得できるんじゃないかな?と考えていた訳です.

ゲーミングデバイスの選び方やデバイスとPCの設定なんかも体系化されていなくて,なんとなくやっている場合が多いと思いますので,同じ事ですね.

つまり,LogicalGaming, systemaというのは「ゲーミングの各要素を論理的に定式・定量化して,それらを体系化しよう」という目標があったプロジェクトでした.

まあ,進捗的に言うとLogicalGaming, systemaくらいなので,ゲーミングってとても奥が深いし,私が
「数ヶ月で終わる」と思っていたのは凄まじい勘違いだったわけです.


途中からちょくちょく「優秀なゲーミングデバイス若人」という単語を使いはじめたのは,この大目標を自分でやることを諦めたからです.私はrafaさんのブログからゲーミングデバイスを工学的に見るということを学んで,こうしたことを始めて終わりそうになっているわけですが,「今後出てきた人のちょっとした参考になれば良いな」と思っています.

2017/01/12

ゲーミングデバイスが1680万色に光る理由

ゲーミングデバイスって1680(書き方によっては1677万色)に光りますが,なぜ1680万色なのでしょうか?
これはゲーミングデバイス内のMCU(マイコン)の都合だったりします.

ゲーミングデバイスのLED制御

一般的に,ゲーミングデバイスではLEDの明るさをパルス幅変調(PWM)を用いて変えています.
PWMは,ONとOFFを切り替えることで時間あたりの平均的な電力を変える方法です.

つまり,フィラメント電球を使った理科の実験のように電圧を上下させてLEDの明るさを変えるのではなく,人間の目では知覚できない速さでON/OFFを切り替えることで明るさを変えるわけですね.人間の目では明るかったり暗かったり色々な色に見えているわけですが,マイコン的にはとても素早くLEDを点滅させているだけなのです.ここで,明るさの度合いは,ONとOFFの比率(デューティー比)を変えることで調整しています.


G302のLEDの点滅の様子をハイスピード撮影で見てみましょう.動画の撮影は1200fpsで行い,30fpsで再生しています.
まずは暗いときの場合です.


次に明るい時の場合です.

このように,LEDは目に見えない速度で点滅しています.また,点灯する時間を変えることで,見かけ上の明るさを調整していることがわかります.

PWMと色の関係

さて,PWMで明るさを変えるにはデューティー比を変えれば良いことが分かりましたが,デューティー比はマイコンでどのように設定しているのでしょうか.

よくあるのは8bitの変数を使ってデューティー比を表現する場合です.16bitやそれ以上のbit数もマイコンによっては可能だったりしますが,bit数を増やすとマイコンのリソースを使います.所詮は装飾ですし,人の目はそんなに細かく色を見分けられないので,デューティー比は8bitが多いでしょう.
8bitの変数は,(正負の区別をしない場合)0から255の値をとることができます.つまり,0から255のデューティー比で明るさを表現できます※1

そしてRGBな製品の場合,光の三原色である赤(Red,R),緑(Green,G),青(Blue,B)の3色のLEDを搭載しています.そこで,LED1色ごとに256パターンで明るさを表現して,3色合わせると256の3乗になります.つまり,256の3乗で16777216パターン,約1680万色ということになります.


※1
「1色あたり0~100とかのほうが分かりやすいのでは?」と思う方も多いと思いますが,マイコンは基本的に2進数で物を考えており,特に8bit単位(例: 8,16,32bit)でマイコン内部の機能を制御したがります.無理やり0~100などの10進法的にキリの良い数字で制御することもできますが,内部の機能は8bit単位の値しか受け付けないので,それに直すために余計な計算が必要になりますし,プログラマ的には特に意味がないので,8bitで制御することが多いようです.

2017/01/04

2017年

あけましておめでとうございます.今年も#LogicalGaming#LogicalGamingGlobal@systema_ をよろしくお願いします.

ブログを立ち上げてから3年が経ちましたが,徐々にページビューやTwitterのフォロワーが増えてきて,望外の喜びです.いつもRT/Favなどなどありがとうございます.


2016年のまとめ

毎年恒例ですが,昨年1年間を簡単に振り返ります.

マウスのスクロールホイールを3Dプリントする

http://logical-gaming.blogspot.jp/2016/02/3d.html
マウスの部品を3Dプリントして使ってみたという記事です.やってることはモデルデータを作って外注しているだけなので技術的にはまったく難しくありませんが,「可能であるということを実証した」ということに意義を見出しています.言うだけなら簡単ですが,実際に可能かどうかというのは別問題なので.
この記事では単一の部品を出力したわけですが,マウス全体の出力に適用するには,課題が存在しているかもしれません.


マウスパッド表面評価のためのセンサー可視化デバイス

http://logical-gaming.blogspot.jp/2016/04/adns-3090adns-9800framecapture.html
このブログを立ち上げた直後から取り組んでいる「ゲーミングマウス向けセンサの制御」の集大成的な記事です.ADNS-3090とADNS-9800というゲーミンググレードのセンサを制御できるようになりました.
また,ゲーミンググレードのセンサの視界を見える化することができたのは大きな進捗でしょう.これを使えばマウスパッドの良し悪しや,色々なことが分かるようになります.


DPIと振り向きとセンシティビティ

http://logical-gaming.blogspot.jp/2016/05/dpi.html
一般のゲーマー向けに書いた記事です.400DPI+センシティビティ2.0より,800DPI+センシティビティ1.0の方が理論上は優れているという話です.この記事には続きがあるので,いつか続きを上げたいですね.


描画遅延とデバイスの出力周期の関係に関する一考察

http://logical-gaming.blogspot.jp/2016/12/blog-post.html
ポーリングレートやフレームレートが変わると遅延の期待値が変化する,というのを理論的?に説明した記事です.この記事では,ポーリングレートなりフレームレートは高ければ高いほど良いということを示しました.
よく「モニタのリフレッシュレート以上にフレームレートが出てれば十分」,「マウスのポーリングレートは何でも良い」などと言いますが,実際には高ければ高いほど有利になるということが分かりました.皆さんもGTX1080で最低設定+640x480でプレイしましょう().


ゲーミングマウス向けのUSB HIDディスクリプタ

http://logical-gaming.blogspot.jp/2016/12/usb-hid.html
ゲーミングマウスのHIDディスクリプタのテンプレートとして作成しました.マイコンにHIDマウスの機能を持たせる記事は多いですが,マウスホイールと16bitのデータパスを持つ日本語の記事は無かったので,少しは貢献できたと考えています.


ゲーミングマウスのセンサとして電磁誘導方式を考える

http://logical-gaming.blogspot.jp/2016/12/blog-post_99.html
小ネタ記事です.今のゲーミングマウスは光学式一択の現状ですが,別な方式も考えてみませんか?という提案をしました.
光学式マウスの暗黙のメリットとして「マウスパッド無しでどこでも使える」というのがありますが,「ゲーミングマウスはマウスパッドの上だけでしか使われない」という点に着目しました.「滑走面が限定されても良い」という条件なら光学式にこだわる必要はなく,絶対値で座標が取得できる方式の方が正確にトラッキングできるのでは?という提案です.


遅延測定用のファームウェア公開

日本語の記事にはしていませんが,描画遅延ネタで使っているマイコンのファームウェアを公開しました.(英語記事)
ソースコード : https://github.com/systema-tic/input-lag-test-firmware
1500円で売ってるマイコンボードとハイスピード撮影ができるカメラがあれば,簡単に描画遅延を測定できます.詳しくはreadmeに書いてあります.


近況

デバイス

今はLogicool G300r + Razer Goliathus Control Editionです.Goliathus Controlはいいマウスパッドだと思います.G300はセンサー的に厳しいですが,乗り換え先が見つからないです.

2016年も色々見ましたが,ベストなマウスパッドはCOUGAR Control(2じゃなくて無印の方)だと考えています.マウスに関しては個人の手の大きさや持ち方に大きく依存するのでなんとも言えません.個人的にはG300系でセンサー改良版が出て欲しいです.


ゲーム

5月から秋まで,PC版OverwatchのチームであるHOT-Gamingのメインタンクとしてプレイしました.本当に楽しかったです.一緒にプレイしてくれたチームメイトに感謝したいです.
Overwatchは,どこかマンネリ化していたFPSのゲーム性に一石を投じましたが,これからどのような影響を及ぼすか要注目でしょう.

最近はMirror's Edge CatalystをOriginで買いました.セールで約1500円だったのでとても安かったです.シナリオと戦闘は評価が低いようですが,逆に言えばそれ以外は素晴らしいです.既に30時間ほどプレイしましたが,シングルプレイヤーのFPSを30時間プレイするのは最初で最後かもしれません.前作が好きな方におすすめです.


今年の抱負

そろそろこのブログもまとめの時期に入る必要がありますが,現状では「俺たちの戦いはこれからだ!」的な感じなので,どうオチをつけるかまだ決まっていません.ボチボチ頑張りたいと思います.

ソースコードが欲しいなどの要望や,ゲーミングデバイスに関する疑問点などがあればAboutに書いてある連絡先に連絡お願いします.

2016/12/30

ゲーミングマウスのセンサとして電磁誘導方式を考える

光学式マウスのセンサ

光学式(LED式,レーザー式)マウスのセンサの原理を大まかに説明すると,内部のカメラで高速撮影した画像の変化を見て,センサがの移動量を相対的に推測するものです.
移動量の推定 (画像はADNS-3090のFrame Capture)
しかし,この方式の精度はセンサが取得した画像の品質に大きく依存します.そのため,平滑面などのトラッキングに向かない面で動作させた場合,精度が大きく低下しトラッキングエラーが発生します.
また,マウスが高速に動いていたり加速度の変化が伴う場合にトラッキングエラーが発生することが知られています.
Logitech G300(125Hz,750DPI)のトラッキングデータとエラー箇所
トラッキングエラーについてはrafa様の記事が非常に参考になります.
rafalog: ゲーミングマウスのトラッキング特性簡易検証 Tracking characteristic test of gaming mice

光学式センサの性能は向上していますが,上で挙げた通り理想的な精度を出すのはまだ難しいという問題点があります.


電磁誘導方式

電磁誘導方式はペンタブレットなどに採用されているもので,アンテナコイル群と座標支持器を用いて座標支持器の位置を絶対値で検出するものです.
Wacom Bamboo Pen CTL-460/K0のトラッキングデータ
移動量を絶対値から検出できるため,上図のように理想的トラッキングが行われていることが分かります.そこで,ゲーミングマウス用のセンサとして電磁誘導方式を採用した場合のメリットとデメリットを考えます.

メリット

  • 高精度

デメリット

  • トラッキング面の広さは,アンテナコイル群のサイズに依存
  • 現行機種ではリフトオフディスタンス(LoD)が大きい
  • 高価(特にトラッキング面が大きいもの)
  • ポーリングレートが低い

課題

先程挙げたデメリットは電磁誘導方式のゲーミングマウスを実現するための課題になります.
そこで,いくつかの課題について議論します.

トラッキング面の制限

トラッキング面の制限ですが,現状のゲーミングマウスの使い方においては問題になりません.光学式マウスの暗黙的なメリットとして「どこでも使用できる」という特徴がありますが,ゲーミングマウスはゲーミングマウスパッドと一緒に使用されることが多く,センサが読み取る面はマウスパッドのみにほぼ限定されています.

LoDが大きい

現行機種ではLoDが数cmあります(ペンタブレットとしてはメリットです).マウス用途として考えるのなら,測距センサなどの非接触で接地検出できるセンサを用いることで,リフトオフを検出することができます.また,マウスソールの裏に圧力センサなどを取り付けることで,のリフトオフ検出も可能だと考えられます.


まとめ

本記事では,光学式センサの問題点と,新しいゲーミングマウスのセンサとしての電磁誘導方式について考えました.

現在,WacomはKC-100などのペンタブレット上で使用可能なマウスをリリースしていますが,ゲーミングを意識した製品ではないため,実際にゲーミングマウスとして運用するのは難しいと思います.また,ポーリングレートの低さや,価格などの問題も存在しているのも事実で,製品化するには様々な課題を解決する必要があるでしょう.

しかし,電磁誘導方式の精度の高さは素晴らしく,電磁誘導方式を採用したゲーミングマウスが出ると,ゲーミングマウスもさらに面白くなるのではないでしょうか.

ゲーミングマウス向けのUSB HIDディスクリプタ

前に3ボタンマウスのデータパスを16Bit化したHIDディスクリプタを紹介しました.
この時のディスクリプタは,3ボタンでX,Y変位がそれぞれ16bitなディスクリプタですが,スクロールホイールの情報は転送できません.

本記事では,そこにスクロールホイールを加えたディスクリプタを紹介します.
USB HID Descriptor (3 button, 16bit data-path, wheel)
これによって,3ボタン(左・中・右クリック),16bitのXY変位,スクロールホイールの変位を転送できることになり,ゲーミングマウスとして最低限必要な情報を転送できます.

送られる情報は8bit×6の配列で,各バイトの情報は以下のようになります.
  • 1バイト目 : ボタンのON/OFF情報
  • 2,3バイト目 : X変位
  • 4,5バイト目 : Y変位
  • 6バイト目 : スクロールホイールの変位

実はこのディスクリプタを使ってポインティングデバイスを開発しました.

この記事もそのデバイス(と市販のキーボード)を使いながら書いています.自前でファームウェアを開発することで,機能の追加や微妙なチューニングができ,とても便利です.入力機器は様々な種類を経て拘りはじめると,「結局自分で作るしか無いじゃん」という展開になりがちですね.
この話を始めるととても長くなるので,またいずれ(書けるといいですが・・・).

2016/12/03

描画遅延とデバイスの出力周期の関係に関する一考察

はじめに

描画遅延(入力遅延とも言います)は,競技ゲームにおけるプレイヤーのパフォーマンスに大きく影響します.本記事は,ゲーミングシステムを構成するゲーミングデバイスやプログラムの出力周期に着目して,描画遅延の定式化を行い,描画遅延を減らすために要求されるシステム要件について議論します.

記事が長いので,「理屈はどうでも良い」という方は最後のまとめの項だけ参照してください.

出力周期

ゲーミングシステムは,ヒューマンインタフェースからの入力を,ゲームエンジンが受け取り,その情報に基いてディスプレイに描画します.これらのデバイスやプログラムはそれぞれ出力周期を持っています.

以下にそれぞれのデバイス,プログラムの一般的な出力周期とその名称を示します.

  • マウス,キーボード,コントローラ
    • レポートレート : 125Hz~1000Hz
  • ゲームエンジン(ゲームプログラム)
    • フレームレート : 30fps~500fps
  • ディスプレイ
    • リフレッシュレート : 60Hz~240Hz

遅延時間の見積もり

単純化した例

遅延時間も見積もるために,単純化した例で議論します.まず,マウスからの入力がリフレッシュレートが1Hzのディスプレイに出力された例を考えます.この時,入力された情報はデバイスやプログラムには即時反映されるものとします.

図1 リフレッシュレート1Hzの場合の遅延時間

図1に,リフレッシュレートが1Hzの場合の遅延時間について,最良・最悪・平均(期待値)の3パターンの入力と描画のタイミングを示します.

図1のように,入力の直後にディスプレイがリフレッシュされる場合,入力結果がディスプレイに即反映されるため,遅延時間は0sとなります.一方,リフレッシュ直後に入力がされる場合,入力結果は1s後にディスプレイに反映されるため,遅延時間は1sとなります.

プレイヤーによる入力のタイミングはランダムであるため,入力のタイミングは一様に分布することになります.したがって,遅延時間の期待値は,0s~1sの中間の0.5sとなります.

このように,遅延時間の期待値はディスプレイの出力周期に依存します.例えば,リフレッシュレートが100Hzの場合,最短の遅延時間は0sであり,最長の遅延時間は0.01sとなります.つまり,遅延時間の期待値は0s~0.01sの中間である0.005sとなります.

以上を踏まえると,1つの出力周期をもつシステムの場合,遅延時間の期待値t[s]は出力周期r[Hz]を用いて以下の式で表すことができます.
t = 1/2r


複数の出力周期が存在する場合

次に,複数のシステムが連なった時の例を考えます.レポートレートが1Hzのマウスとリフレッシュレートが1Hzのディスプレイで構成されている場合を考えます.
レポートレート1Hz,リフレッシュレート1Hzの場合の遅延時間


図2に,リフレッシュレートが1Hzのディスプレイとレポートレートが1Hzのマウスから成るシステムの場合の遅延時間について,最良・最悪の2パターンの入力と描画のタイミングを示します.
それぞれのデバイスは同期をしていないため,それぞれの出力(描画)タイミングはランダムになります.

図2のように,最良のケースでは入力の直後にマウスがレポート,その直後にディスプレイが描画することになり,遅延時間は0sとなります.一方最悪のケースでは,マウスのレポートの直後に入力が起き,1s後に入力された情報をレポートし,さらに1s後にディスプレイが描画するため,遅延時間は2sとなります.
したがって,それぞれのデバイスの同期タイミングと物理的な入力のタイミングを加味すると,遅延時間の期待値は1sとなります.

ゲームエンジンについて考えると,図2のマウスとディスプレイの間にゲームエンジンのタイミングが追加されます.この場合は,ゲームエンジンの出力周期に応じて描画遅延の期待値は増加します.つまり,ゲームエンジンの出力周期(フレームレート)を上げれば,描画遅延の期待値は減少し,フレームレートが下がれば期待値は増加することになります.

以上ように,複数のデバイス/プログラムが出力周期をもつ場合,全体の遅延時間はそれぞれのデバイス/プログラムの遅延時間の期待値の合計になります.


遅延時間の定式化

以上を踏まえると,出力周期に基づいた遅延時間の期待値は以下のように見積もることができます.全体の遅延時間をT[s]とし,それぞれの出力周期をr[Hz]とすると,Tはシステムを構成するデバイスとプログラムの遅延時間tの合計値となるため,以下のようになります.
T = Σ(1/2r)


実際のシステム構成の場合

マウスのレポートレートが1000Hz,ゲームエンジンのフレームレートが200fps,ディスプレイのリフレッシュレートが120Hzである場合は,以下のように遅延時間を見積もることができます.
T = (1/(2*1000))+(1/(2*200))+(1/(2*120)) = 0.00716[s] = 7.2[ms]


出力周期以外の遅延時間(オーバヘッド)

今までの例は,入力された情報をそれぞれのデバイス/プログラムがすぐに次のデバイス/プログラムに渡せる場合を考えてきました.しかし,実際のシステムにおいては,出力周期以外の遅延時間(本記事ではオーバヘッドと呼びます)が存在しています.
今回は以前行った測定データ(図3)から,それらのオーバヘッドを見積もることにします.

図3 ゲームタイトルごとの描画遅延
※測定方法/環境については当該記事参照

まずは,Baselineのプログラムについて考えます.このBaselineのプログラムは4300fps程度で動作します.したがって,出力周期から見積もれる遅延時間は,
T = (1/(2*1000))+(1/(2*4300))+(1/(2*120)) = 0.00478[s] = 4.8[ms]
となります.しかし,実際に測定された描画遅延の時間は8.4msです.したがって,残りの3.6msはUSBホストコントローラ,OS,OpenGLのAPI,グラフィックカード,ディスプレイなどがもつオーバヘッドであるといえます.

次に,CS:GOのSource Engine自体がもつオーバヘッドについて考えます.CS:GOのde_dust2は私の環境ではおよそ200fps程度で動作していたと思うので(うろ覚えですいません),出力周期から見積もれる遅延時間は,
T = (1/(2*1000))+(1/(2*200))+(1/(2*120)) = 0.00716[s] = 7.2[ms]
となります.ここに測定環境のオーバヘッド3.6msを足した10.8msが出力周期とシステムのオーバヘッドから予想できる描画遅延ですが,実際は15.7msとなっています.この差のゲームエンジン自体のオーバヘッドである4.9msは,OSから受け取ったマウスの変位からカメラの姿勢計算などを行い,グラフィックカードへのデータ転送,グラフィックカードが描画処理(ラスタライズ,シェーディング,ポストプロセスなど)を行うための時間だと考えられます.

CS1.6はフレームレートの制限があり,全体の描画遅延はCS:GOと大きく変わりませんが,フレームレート制限の分を加味すると,ゲームエンジン自体のオーバヘッドはCS:GOと比較して小さいと言えます.この差は,CS1.6からCS:GOでグラフィックがリッチになった影響で,グラフィックパイプラインがより深くなり,ゲーム内の内部処理もより複雑になったためだと考えられます.

ゲームエンジンの高度化,グラフィックのリッチ化は多くの一般的なプレイヤーにとって利益になります.しかし,コンペティティブなタイトルでは描画遅延の増加というトレードオフも存在しており,競技性を意識したタイトルでは慎重に調整するべきだと思います.


遅延を減らすためにプレイヤーができること

遅延時間を少なくするためには,それぞれの出力周期を上げる必要があります.
つまり,マウスに関して言えば,レポートレートをできるだけ高くすることです.デバイスの設定によって1000Hzや,設定できるのならそれ以上の値に設定します.
また,プロセッサとメモリを高速なものに移行することと,ゲーム内設定をできるだけ低負荷なものにすることでフレームレートを上げるのも有効です.
そして,リフレッシュレートの高いディスプレイに置き換えることも有効でしょう.
デバイスやディスプレイを買い換える場合は,余計な遅延が発生するようなものは避けることが必要です.

特に,フレームレートはゲームの設定を調整するだけで容易に改善できます.フレームレートを上げるには,レンダリング解像度やテクスチャ解像度,シェーディングなどの設定を下げるとよいでしょう.グラフィック設定は基本全部低設定にして,視認性に影響を与えない範囲でレンダリング解像度を下げるというのがよいでしょう.


まとめ

まとめます.

  • 出力周期に基づく描画遅延時間の期待値はΣ(1/2*出力周期)で表すことができる
    • 遅延時間はそれに加えて,プログラムの計算時間やデータ転送時間などの要素で増加する
  • 出力周期を小さくすることで描画遅延時間を小さくできる
    • デバイス
      • デバイスのレポートレートを上げる
      • レポートレートの高いデバイスを買う
    • ゲーム(エンジン)のフレームレートを上げる
      • CPU・メモリ・GPUを高速なものに買い換える
      • グラフィックの設定(解像度,その他)をできる限り下げる
    • ディスプレイのリフレッシュレートを上げる
    • リフレッシュレートの高いディスプレイに買い換える
  • 描画遅延の中でオーバヘッドが占める割合は大きく,プレイヤーが出力周期を上げることで対応できる範囲は小さい
    • 描画遅延を極限まで小さくするには,より小さいオーバヘッドのシステムを考える必要がある
      • 今までのソフトウェア資産を失うことになるため,システムのアーキテクチャ自体を大きく変える事はとても難しい
      • オーバヘッドの小さいゲームエンジンを高く評価するような雰囲気づくりが必要