メモ帳DPA

ぐぐってあまり引っかからないような何かがあったら書いたりする

IIDX ULTIMATE MOBILE用PS2専コン変換器(PHOENIXWAN対応)の作り方

PHOENIXWANを買った。

アルティメットモバイルは、以前メルカリで買った変換基板+初代純正専コンでそれまでプレイしていた。PHOENIXWANも同様に使えるだろうと予想していたら、実際には入力を受け付けてくれなかった。困った。

理屈上は認識できるはずに思えるんだけど、変換器のソースが公開されてない以上動かないまま対処のしようがない。
どういう仕組みでアプリに認識させているのか不明ではあったものの、純正コンではちゃんと認識する現物があるので、これをヒントに自分で作り直してみることにした。

結果

できた。

作り方

全体的にかなり素直な方法で作ることができた。特殊な要素はデバイス情報指定くらいしかなかった。

流れ
  1. PS2コントローラの端子とPro Microをはんだ付けする
  2. バイス情報を書き換える
  3. スケッチを書き込む
  4. 適当に外装を整える
作成のポイント
  • プロダクト名、ベンダ名、ベンダIDを揃えればUltimate Mobile側で認識される
  • PHOENIXWANは、PSXNewLibを使えば認識できる

以下に詳細を書きます。

材料

  • Pro Micro または何かしらのArduino
  • PS2コントローラのメス端子(を部品取りするためのUSB変換器)
  • リード線
  • はんだ
  • 保護ケースなど(任意)

今回5V版のPro Microを使って作ってしまったんだけどこれは選択ミスだった。
一応動いてはいるけど、PS2コントローラの電圧仕様的には本当は3.3V版の方を使ったほうがよさそう。作り終わってから気づいた。

なお、PS2端子の代わりに皿とスイッチ7個を直接繋ぎ、ソースを多少調整すれば専コン自体が作れる。(と思う)

PS2コントローラの端子とPro Microをはんだ付けする

PS2の変換器を分解してコネクタ部分だけ入手し、コネクタのピンとArduinoのピンを接続する。

PS2のピン配置については以下のページが分かりやすい。基板側はGNDとVCCの位置だけ気をつければ残りの繋ぎ先はどこでも可。
darekasan.net
f:id:de0:20200903222456j:plain

バイス情報を書き換える

boards.txtを編集して、エントリーモデル相当のハードウェア扱いとして書き込むように各パラメータを書き換える。

Pro Microの場合はboards.txtは以下にある。

C:\Users\username\AppData\Local\Arduino15\packages\SparkFun\hardware\avr\1.1.13\

以下の値を指定したらUltimate Mobile側でUSBコントローラとして認識された。

promicro.build.usb_product="beatmania IIDX controller Entry Model"
promicro.build.usb_manufacturer="Konami Amusement"
promicro.build.vid=0x1ccf

スケッチを書き込む

以下のスケッチをPro Microに書き込む。

皿の挙動が独特(回すたびX軸を移動し端でループする)なのでそこだけは追加が必要だったが、それ以外はライブラリ2つのサンプルスケッチのパッチワークでほぼ済んでしまった。

PHOENIXWANのPS2が何か特殊なのか、PSXLibraryでは入力を拾えなかったので、代わりにPSXNewLibを使ったらうまくいった。

//https://github.com/NicoHood/HID
#include <HID-Project.h>

//https://github.com/SukkoPera/PsxNewLib
#include <DigitalIO.h>
#include <PsxControllerBitBang.h>

//皿の移動幅(値は適当)
const int scr_sensitivity = 1000;

//ピン配線に合わせる
const byte PIN_PS2_ATT = 20;
const byte PIN_PS2_CMD = 5;
const byte PIN_PS2_DAT = 3;
const byte PIN_PS2_CLK = 18;

PsxControllerBitBang<PIN_PS2_ATT, PIN_PS2_CMD, PIN_PS2_DAT, PIN_PS2_CLK> psx;

int scr_pos = 0;                //皿位置
unsigned int data;              //入力情報

void setup() {
  Gamepad.begin();
//  Serial.begin(9600);
}

void loop(){
  psx.begin (); //たまに認識が外れてるっぽいので毎回beginさせとく
  psx.read ();

  data = psx.getButtonWord();
//  Serial.println (data);

  //皿
  if(data&PSB_PAD_DOWN){
    scr_pos -= scr_sensitivity;
    if(scr_pos < -32768) scr_pos = 32768;
    Gamepad.xAxis(scr_pos);
  }
  if(data&PSB_PAD_UP){
    scr_pos += scr_sensitivity;
    if(scr_pos > 32768) scr_pos = -32768;
    Gamepad.xAxis(scr_pos);
  }

  //七健
  if(data&PSB_SQUARE)   Gamepad.press(1); else Gamepad.release(1);
  if(data&PSB_L1)       Gamepad.press(2); else Gamepad.release(2);
  if(data&PSB_CROSS)    Gamepad.press(3); else Gamepad.release(3);
  if(data&PSB_R1)       Gamepad.press(4); else Gamepad.release(4);
  if(data&PSB_CIRCLE)   Gamepad.press(5); else Gamepad.release(5);
  if(data&PSB_L2)       Gamepad.press(6); else Gamepad.release(6);
  if(data&PSB_PAD_LEFT) Gamepad.press(7); else Gamepad.release(7);

  //E1-E4(アプリでは使えない)
  if(data&PSB_START)    Gamepad.press(9); else Gamepad.release(9);
  if(data&PSB_SELECT)   Gamepad.press(10);else Gamepad.release(10);
  if(data&PSB_TRIANGLE) Gamepad.press(11);else Gamepad.release(11);
  if(data&PSB_PAD_RIGHT)Gamepad.press(12);else Gamepad.release(12);

  Gamepad.write();
  
  //認識頻度の調整
  delay (1);
}

認識周りとdelayやscr_sensitivityの値は調整の余地がありそう。ノーツ多めの譜面だと若干ラグってるようなそうでもないような気がする。

純正初代専コンも含め、PHOENIXWAN以外のPS2コントローラももちろん使えるし、PCに繋いでUSBコントローラとしても使える。(使うことはないけど)

適当に外装を整える

基板も配線も剥き出しなので、適当にホットボンドで固めたりケースに入れたりしたら完成。
f:id:de0:20200904100506j:plain

おわり

アプリ側がUSBデバイスの制限をかけずかつキーコンフィグ可能になればわざわざこんな回りくどくて面倒くさいことしなくて済むので、もうちょっとどうにかしてほしい感じはある。
そもそもINFINITASが同じくらい選曲できればパーフェクトなんだけど、そんな日はたぶん来ないし、Ultimate MobileがDPに対応することもキー音出すことも多分無いので、それぞれ抱えている重大な欠点はこれからもずっと改善が見込めなそうなままのが困ったところだなあと思う。

PHOENIXWANがUltimate Mobileモードを追加してくれると助かるんだけども、他社のベンダIDを勝手に振った機器を量産して売る形になってしまうのであまり期待できないかもしれない...と書いている途中でPHOENIXWANのVIDが気になり調べてみたら普通に1ccfだった。その辺あまり気にしてないっぽい。いいのか?