マイコン用DUALSHOCK 2制御ライブラリ

神原です.

PlayStation 2用のコントローラであるDUALSHOCK 2をマイコンで使用するためのライブラリを作成しました.
以前投稿したLCDライブラリと同様,PICだけでなく他のマイコンにも簡単に移植できるようになっています.

DUALSHOCK 2とマイコンの接続

以下の回路図のように接続します.DAT,CMD,SEL,CLKは”HardwareProfile_PSpad.h”内で設定したピンに接続してください.
プルアップ抵抗は420Ω程度がいいようですが,今回は手元にあった470Ωを選択しました.

DUALSHOCK 2 との接続

ライブラリを構成するファイル

  • PSpad_lib.h                            ライブラリ本体
  • HardwareProfile_PSpad.h    各種マイコンに対応させるためのユーザー設定項目が書かかれたファイル

ユーザーは”HardwareProfile_PSpad.h”のみを書き換える必要があります.

“HardwareProfile_PSpad.h”内の設定項目

  • ピン設定
  • delay設定

ユーザーが使用する関数

void PSpad_init(void);			// PSpad初期化
void PSpad_getdata(void);		// PSpadからデータを受け取る

DUALSHOCK 2から受け取るデータ

受け取ったデータはPSpad_lib.h内でグローバル変数として宣言した変数に格納されます.
ジョイスティックのデータは0~255までの変数として受け取ります.

PSpad_ANALOG_LEFT_X		左ジョイスティックX軸(0~255)
PSpad_ANALOG_LEFT_Y		左ジョイスティックY軸(0~255)
PSpad_ANALOG_RIGHT_X		右ジョイスティックX軸(0~255)
PSpad_ANALOG_RIGHT_Y		右ジョイスティックY軸(0~255)

ボタンのデータは以下のマクロを使います.ちなみに,押したときに1,押されていないときに0となります.

PSpad_SELECT		セレクトボタン
PSpad_L3		L3ボタン
PSpad_R3		R3ボタン
PSpad_START		スタートボタン
PSpad_UP		十字キー:↑ボタン
PSpad_RIGHT		十字キー:→ボタン
PSpad_DOWN		十字キー:↓ボタン
PSpad_LEFT		十字キー:←ボタン
PSpad_L2		L2ボタン
PSpad_R2		R2ボタン
PSpad_L1		L1ボタン
PSpad_R1		R1ボタン
PSpad_SANKAKU		△ボタン
PSpad_MARU		○ボタン
PSpad_BATSU		×ボタン
PSpad_SHIKAKU		□ボタン

ダウンロード

ライブラリはここからダウンロードできます.dsPIC33FJ128MC302を用いた場合のサンプルコードも置いておきました.多分動きます.

ソースコード

  • HardwareProfile_PSpad.h

/******************************************************************************
 *
 *                 Hardware Profile for PSpad(Dualshock2) library
 *
 *                        動作確認した型番はSCPH-10010
 *        ライブラリに必要なファイル: "PSpad_lib.h", "HardwareProfile_PSpad.h"
 *
 *     ユーザーは"HardwareProfile_PSpad.h"の設定を変えることでライブラリを使用可能
 *                        "PSpad_lib.h"は変えなくてよい
 *
 *              mainプログラムでは"PSpad_lib.h"のみをインクルードする
 *
 *        ※このライブラリの全てのファイルはmainファイルと同じディレクトリに配置する
 *
 ******************************************************************************/

#ifndef _HARDWAREPROFILE_PSPAD_H_		//重複回避
#define _HARDWAREPROFILE_PSPAD_H_

#ifndef PSPAD_LIB_H
	#error PrivateError : please define only "PSpad_lib.h" when you use PSpad library.
#endif

/* ユーザー設定項目 ----------------------------------------------------------*/
/* ピン設定 --------------------------------------------------------*/
#define PSPAD_PIN_STATE_SETTING_ON	// 各I/Oピンの入出力設定ON (使わないならばこの行をコメントアウト)

#define PSpad_DAT			PORTBbits.RB0		// DualShock2からのデータ(pin1), 0Vなら0, 3.3Vなら1の値が返るようにする
#define PSpad_CMD_HIGH		LATBbits.LATB1=1	// DualShock2へのコマンド(pin2)ピンをHIGH
#define PSpad_CMD_LOW		LATBbits.LATB1=0	//                                   LOW
#define PSpad_SEL_HIGH		LATBbits.LATB2=1	// DualShock2へのセレクト(pin6)
#define PSpad_SEL_LOW		LATBbits.LATB2=0
#define PSpad_CLK_HIGH		LATBbits.LATB3=1	// DualShock2へのクロック(pin7)
#define PSpad_CLK_LOW		LATBbits.LATB3=0

#ifdef PSPAD_PIN_STATE_SETTING_ON
#define PSpad_DAT_Input		TRISBbits.TRISB0=1	// データピンをInputに設定
#define PSpad_CMD_Output	TRISBbits.TRISB1=0	// コマンドピンをOutputに設定
#define PSpad_SEL_Output	TRISBbits.TRISB2=0	// セレクトピンをOutputに設定
#define PSpad_CLK_Output	TRISBbits.TRISB3=0	// クロックピンをOutputに設定
#endif // PSPAD_PIN_STATE_SETTING_ON
/*-------------------------------------------------------- ピン設定 */

/* delayの定義 -----------------------------------------------------*/
#include 	// dsPICでdelay関数を使用 (FCYを定義しておくことが必要)

#define PSpad_DELAY_5us		__delay_us(5)
#define PSpad_DELAY_15us	__delay_us(15)
#define PSpad_DELAY_30us	__delay_us(30)
#define PSpad_DELAY_500us	__delay_us(500)
#define PSpad_DELAY_700us	__delay_us(700)
#define PSpad_DELAY_1ms		__delay_ms(1)
#define PSpad_DELAY_10ms	__delay_ms(10)
/*----------------------------------------------------- delayの定義 */
/*---------------------------------------------------------- ユーザー設定項目 */

#endif	// _HARDWAREPROFILE_PSPAD_H_

  • PSpad_lib.h

/******************************************************************************
 *
 *                  Header File for PSpad(Dualshock2) library
 *
 *                        動作確認した型番はSCPH-10010
 *        ライブラリに必要なファイル: "PSpad_lib.h", "HardwareProfile_PSpad.h"
 *
 *     ユーザーは"HardwareProfile_PSpad.h"の設定を変えることでライブラリを使用可能
 *                        "PSpad_lib.h"は変えなくてよい
 *
 *              mainプログラムでは"PSpad_lib.h"のみをインクルードする
 *
 *        ※このライブラリの全てのファイルはmainファイルと同じディレクトリに配置する
 *
 * //参考にしたサイト
 * //http://applause.elfmimi.jp/dualshock.txt
 * //http://applause.elfmimi.jp/dualshock/millar/NT/dualshock_2.txt
 ******************************************************************************/

/**********************************************
* ユーザーが使用する関数:
* void PSpad_init(void);				// PSpad初期化
* void PSpad_getdata(void);				// PSpadからデータを受け取る
************************************************/

#ifndef PSPAD_LIB_H		//重複回避
#define PSPAD_LIB_H

#include "HardwareProfile_PSpad.h"		// 各種マイコンへの移植用設定(ピンなど)を格納

//ボタン設定(押されたら1)
#define PSpad_SELECT	((PSpad_BUTTON1>>0)&0x01)	// セレクトボタン
#define PSpad_L3		((PSpad_BUTTON1>>1)&0x01)	// L3ボタン
#define PSpad_R3		((PSpad_BUTTON1>>2)&0x01)	// R3ボタン
#define PSpad_START		((PSpad_BUTTON1>>3)&0x01)	// スタートボタン
#define PSpad_UP		((PSpad_BUTTON1>>4)&0x01)	// 十字キー:↑ボタン
#define PSpad_RIGHT		((PSpad_BUTTON1>>5)&0x01)	// 十字キー:→ボタン
#define PSpad_DOWN		((PSpad_BUTTON1>>6)&0x01)	// 十字キー:↓ボタン
#define PSpad_LEFT		((PSpad_BUTTON1>>7)&0x01)	// 十字キー:←ボタン
#define PSpad_L2		((PSpad_BUTTON2>>0)&0x01)	// L2ボタン
#define PSpad_R2		((PSpad_BUTTON2>>1)&0x01)	// R2ボタン
#define PSpad_L1		((PSpad_BUTTON2>>2)&0x01)	// L1ボタン
#define PSpad_R1		((PSpad_BUTTON2>>3)&0x01)	// R1ボタン
#define PSpad_SANKAKU	((PSpad_BUTTON2>>4)&0x01)	// △ボタン
#define PSpad_MARU		((PSpad_BUTTON2>>5)&0x01)	// ○ボタン
#define PSpad_BATSU		((PSpad_BUTTON2>>6)&0x01)	// ×ボタン
#define PSpad_SHIKAKU	((PSpad_BUTTON2>>7)&0x01)	// □ボタン

// グローバル変数
// PSpadから受け取るデータを格納する変数
unsigned char PSpad_BUTTON1 = 0,		PSpad_BUTTON2 = 0;
unsigned char PSpad_ANALOG_LEFT_X=0,	PSpad_ANALOG_LEFT_Y=0;
unsigned char PSpad_ANALOG_RIGHT_X=0,	PSpad_ANALOG_RIGHT_Y=0;

/***** 通信データ1バイト分送受信 *****/
unsigned char PsComm(unsigned char dat)
{
	unsigned char i=0;
	PSpad_DELAY_5us;
	for(i=0;i<8;i++) 	{ 		PSpad_CLK_LOW; 		if(dat & 0x01){		//datの1bit目が1だったら 			PSpad_CMD_HIGH; 		} else {			//0だったら 			PSpad_CMD_LOW; 		} 		 		PSpad_DELAY_5us; 		dat >>= 1;			//datを右に1bitシフトして
		PSpad_CLK_HIGH;		//CLKを立ち上げ、CMDをセット
		PSpad_DELAY_5us;

		if(PSpad_DAT) {		//もしDATが1なら
		dat |=  (1<<7);		//datの8bit目を1に
		} else {			//もし0なら
		dat &= ~(1<<7);		//datの8bit目を0に
		}

		PSpad_DELAY_5us;
	}
	PSpad_CMD_HIGH;
	PSpad_DELAY_5us;
	PSpad_CLK_HIGH;
	PSpad_DELAY_15us;
	return dat;
}

//最終ビットを受信できるようにした関数
unsigned char PsComm_LastByte(unsigned char dat)
{
	unsigned char i;
	PSpad_DELAY_5us;
	for(i=0;i<8;i++) 	{ 		PSpad_CLK_LOW; 		if(dat & 0x01){		//datの1bit目が1だったら 			PSpad_CMD_HIGH; 		} else {			//0だったら 			PSpad_CMD_LOW; 		} 		 		dat >>= 1;			//datを右に1bitシフトして

		if(i < 7)
		{
			PSpad_CLK_HIGH;
			PSpad_DELAY_5us;
		} else {
			PSpad_CLK_HIGH;
		}

		if(PSpad_DAT){		//もしDATが1なら
			dat |= 0x80;	//datの8bit目を1に
		} else {			//もし0なら
			dat &= 0x7F;	//datの8bit目を0に
		}

		PSpad_DELAY_5us;
	}
	PSpad_CMD_HIGH;
	PSpad_DELAY_5us;
	PSpad_CLK_HIGH;
	PSpad_DELAY_30us;
	return dat;
}

/***** 通信データ1セット分を送受信 *****/
void PsCtrl(const unsigned char *cmd, unsigned char size)
{
	unsigned char i;
	PSpad_SEL_LOW;
	__delay_ms(1);

	for(i=0; i<size; i++){
		PsComm( *(cmd + i) );
	}

	PSpad_DELAY_1ms;
	PSpad_SEL_HIGH;
	PSpad_DELAY_10ms;
}

/***** PSpad初期化 *****/
void PSpad_init(void)
{
	// PSpadの初期設定に必要なCMDの配列
	const unsigned char CMD_CONFIG_MODE_ENTER[]			= {0x01, 0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
	const unsigned char CMD_CONFIG_MODE_EXIT[]			= {0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A};
	const unsigned char CMD_SET_ANALOG_MODE_AND_LOCK[]	= {0x01, 0x44, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
	const unsigned char CMD_QUERY_MODEL_AND_MODE[]		= {0x01, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
	const unsigned char CMD_VIBRATION_DISABLE[]			= {0x01, 0x4D, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

#ifdef PSPAD_PIN_STATE_SETTING_ON
	PSpad_DAT_Input;
	PSpad_CMD_Output;
	PSpad_SEL_Output;
	PSpad_CLK_Output;
#endif // PSPAD_PIN_STATE_SETTING_ON

	PSpad_CMD_HIGH;
	PSpad_CLK_HIGH;
	PSpad_SEL_HIGH;

	// PSpadの設定(PsCtrlにCMD配列と配列の要素数を渡す)
	PsCtrl(&CMD_CONFIG_MODE_ENTER[0],		sizeof(CMD_CONFIG_MODE_ENTER));
	PsCtrl(&CMD_QUERY_MODEL_AND_MODE[0],	sizeof(CMD_QUERY_MODEL_AND_MODE));
	PsCtrl(&CMD_SET_ANALOG_MODE_AND_LOCK[0],sizeof(CMD_SET_ANALOG_MODE_AND_LOCK));
	PsCtrl(&CMD_VIBRATION_DISABLE[0],		sizeof(CMD_VIBRATION_DISABLE));
	PsCtrl(&CMD_CONFIG_MODE_EXIT[0],		sizeof(CMD_CONFIG_MODE_EXIT));
}

/***** PSpadからデータを受け取る *****/
void PSpad_getdata(void)
{
	unsigned char i;
	unsigned char id_dat[3], PSpad_data[6];

	PSpad_SEL_LOW;
	PSpad_DELAY_700us;
	// SELを出してから,CLKを出すまでは数クロック分のwaitを挟まないとキーの読み取りが上手くいかない

	i = PsComm(0x01);						// 1byte目 不定
	id_dat[0] = PsComm(0x42);				// 上位4bit:コントローラータイプ、下位4bit*2:のこりの通信バイト数(0x5a除く)
	id_dat[1] = (id_dat[0] & 0x07) << 1;	// 通信データ量をマスク処理で取り出す
	id_dat[2] = PsComm(0x00);				// 0x5A固定

	for(i=0; i<id_dat[1]; i++)	//残り通信バイト数を数えるまで通信
	{
		if(i != id_dat[1]-1){
			PSpad_data[i] = PsComm(0x00);	//Receive PadData
		} else {
			PSpad_data[i] = PsComm_LastByte(0x00);
		}
	}

	//押されると'1'となるように変更
	PSpad_BUTTON1 = ~PSpad_data[0];
	PSpad_BUTTON2 = ~PSpad_data[1];
	PSpad_ANALOG_LEFT_X  = PSpad_data[4];
	PSpad_ANALOG_LEFT_Y  = 0xFF - PSpad_data[5];
	PSpad_ANALOG_RIGHT_X = PSpad_data[2];
	PSpad_ANALOG_RIGHT_Y = 0xFF - PSpad_data[3];

	PSpad_DELAY_500us;
	// PSpadとの通信は10ms以上空けないといけない
	// PSpad_DELAY_10ms;
	PSpad_SEL_HIGH;
}

#endif //PSPAD_LIB_H

広告

マイコン用DUALSHOCK 2制御ライブラリ」への3件のフィードバック

  1. ピンバック: DualShock2(PS2コントローラ)の信号解析と電子工作 | Scratchpad

  2. 河合章宏

    大阪工業大学 ロボットプロジェクトの河合と申します。
    mbed Nucleoでdualshock2を使おうとしているのですが、なかなかうまくいかず調べているうちにこのサイトを見つけたので、試してみようと思ったのですがライブラリをダウンロードすることができません。
    お手数ですが、メールで送っていただけないでしょうか。

    返信
    1. kambara0x59 投稿作成者

      ダウンロードリンクが期限切れになっており申し訳ございません。
      プログラムはホームページ上のソースコード欄にある”HardwareProfile_PSpad.h”および”PSpad_lib.h”の2つのみを使用すればPSpadから情報を読み取ることができるはずです。

      使用方法については各ファイル上部のコメント欄に記載しております。
      具体的には、ユーザーが使用する際は、
      ①”HardwareProfile_PSpad.h”および”PSpad_lib.h”をmain.c等からインクルードできるようなディレクトリに配置
      ②”HardwareProfile_PSpad.h”の”ユーザー設定項目”の欄を書き換える
      ③main.c等から”PSpad_lib.h”のみをインクルードする
      ④最初に”void PSpad_init(void);”で初期化する
      ⑤PSpadからデータを読み取る時に”void PSpad_getdata(void);”でデータ読み取り
      ⑥”PSpad_lib.h”内で定義された”PSpad_SANKAKU”等で各ボタンの状態を確認
      という流れになっております。

      返信

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中