■
PSパッドのコンフィギュレーションモードを試す。
これまでは、Analogボタンでデジタルモード⇔アナログモードの切り替えをおこなっていたが、Analogボタンを無効にしてアナログ固定にできた。
アセンブラで作業していたときと比較して、ちょっと何か試すのにCは便利。
現状のソースは次のとおり。
なんじゃこれは!と思われる方はぜひコメント願います。
#include <pic.h> #include <conio.h> #include "delay.h" #define DEBUG 1 //RCB-3への接続時:0 RA0をRCB-3の低速シリアル端子の信号線として使用 //動作確認時 :1 RA0をMAX232Cドライバなどを経由しPCのCOMポートへ接続 // パッド情報およびRCB-3への送信データをシリアル出力する __CONFIG( HS & WDTDIS & PWRTEN & UNPROTECT); //発振モード :RC HS XT LP //watchdogの有無 :WDTEN=O WDTDIS=OFF //power up timerの有無 :PWRTEN=ON PWRTDIS=OFF //コードプロテクトの有無:PROTECT=プロテクトあり UNPROTECT=プロテクトなし #define CDAT RA4 #define CCMD RA3 #define CSEL RA2 #define CCLK RA1 /* PLAYSTATION PAD 9PIN ASIGN 1: DAT (PIC <- PAD) 2: CMD (PIC -> PAD) 3: 7.6V 4: GND 5: 3.6V 6: SEL (PIC -> PAD) 7: CLK (PIC -> PAD) 8: NC 9: ACK (PIC <- PAD) *接続せず PIC <---> PS PAD VCC------5:Vcc 3.6V 3:Vcc 7.6V RB.0*<---1:DAT *PULL UP必要 RB.1---->2:CMD RB.2---->6:SEL RB.3---->7:CLK 9:ACK GND------4:GND */ persistent unsigned char pad_buf[10]; persistent unsigned char pad_byte; /** * 1バイト送受信 */ unsigned char pad_comm(unsigned char tx_chr) { unsigned char rx_chr, bitno; rx_chr = 0; bitno = 8; do { //CCLKの立ち下がりで送信 if(tx_chr & 1) CCMD = 1; if(!(tx_chr & 1)) CCMD = 0; tx_chr = (tx_chr >> 1) | 0x80; CCLK = 0; DelayUs(12); //CCLKの立ち上がりで受信 rx_chr = (rx_chr >> 1) | (CDAT << 7); CCLK = 1; DelayUs(12); } while(--bitno); //各BYTEの間隔を40us以上あける DelayUs(40); pad_buf[pad_byte] = rx_chr; pad_byte++; return rx_chr; } /* * パッド情報取得 */ void pad_get(void) { unsigned char lastbyte; //残りバイト数 unsigned char rx_chr; //受信データ pad_byte = 0; //SEL下げて、初めのCLK下げるまで2us待つ CSEL = 0; DelayUs(2); //1バイト送受信(送信[+0]=01h, 受信[+0]→不定(無視)) rx_chr = pad_comm(0x01); //1バイト送受信(送信[+1]=42h, 受信[+1]→応答ID) rx_chr = pad_comm(0x42); if (rx_chr!=0 && rx_chr!=0xff) { //応答ID(下位4bit*2+1)→受信残りバイト数 lastbyte = (rx_chr & 0x0f) << 1; //1バイト送受信(送信[+2]=00h), 受信データ[+2]→Z pad_comm(0x00); do { //1バイト送受信(送信[+3〜]=00h), 受信データ1バイトを格納 pad_comm(0x00); } while(--lastbyte); } CSEL = 1; } #if DEBUG //動作確認用 10進数で1バイトを表示 void put1byte(unsigned char c) { putch(((c /100)%10)+0x30); //100の位を計算してアスキーコード0x30を足す putch(((c / 10)%10)+0x30); // 10の位を計算してアスキーコード0x30を足す putch(((c )%10)+0x30); // 1の位を計算してアスキーコード0x30を足す return; } //動作確認用 16進数で1バイトを表示 void put1hex(unsigned char c) { unsigned char c0; unsigned char c1; c0 = c & 0b00001111; c1 = c & 0b11110000; c1 = c1 >> 4; if (c1 < 10) { putch(c1 + 0x30); } else { putch(c1 + 0x37); } if (c0 < 10) { putch(c0 + 0x30); } else { putch(c0 + 0x37); } return; } #endif /** * ハンドル値0-0xffを0-0x7fに変換する * ハンドル値中心0x80付近に不感帯(0x68-0x97)を設ける */ unsigned char marume(unsigned char c) { if (c >= 0x68 && c <= 0x97) { c = 0x80; } return (c >> 1) & 0x7f; } /** * パッドをアナログモードに固定化する */ void set_analog() { unsigned char rx_chr; //受信データ //コンフィギュレーションモードエンター pad_byte = 0; CSEL = 0; DelayUs(2); pad_comm(0x01); rx_chr = pad_comm(0x43); pad_comm(0x00); pad_comm(0x01); pad_comm(0x00); if (rx_chr == 0x73) { pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); } CSEL = 1; DelayMs(16); //セットモード&ロック pad_byte = 0; CSEL = 0; DelayUs(2); pad_comm(0x01); pad_comm(0x44); pad_comm(0x00); pad_comm(0x01); // アナログモード pad_comm(0x03); // モード固定/ボタンにより切り替え不能 pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); CSEL = 1; DelayMs(16); //コンフィギュレーションモードイクジット pad_byte = 0; CSEL = 0; DelayUs(2); pad_comm(0x01); pad_comm(0x43); pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); pad_comm(0x00); CSEL = 1; DelayMs(16); } /* * メイン */ void main(void){ unsigned char i; //ループ用 unsigned char j = 0; //活性監視LED点滅用 unsigned char pad_mode; //コントローラのタイプ unsigned char rcb_buf[8]; //RCB-3への送信データ //ポート初期化 TRISA = 0b00010000; //(in)RA4:CDAT TRISB = 0b00000000; //処理開始 DelayMs(16); CSEL = 1; CCLK = 1; while(1){ #if DEBUG //DEBUG情報 putch(0x0d); //改行 putch(0x0a); //改行 put1byte(j); putch(0x20); //空白 putch(0x20); //空白 #endif //パッド情報の取得 DelayMs(16); pad_get(); pad_mode = (pad_buf[1] & 0xf0) >> 4; //デジタルモードなら強制的にアナログモードへ if (pad_mode == 4) { DelayMs(16); set_analog(); pad_get(); } //アナログモードなら処理続行 if (pad_mode == 7) { #if DEBUG //パッド情報の表示 for(i=0; i<pad_byte; i++) { put1hex(pad_buf[i]); putch(0x20); //空白 } putch(0x20); //空白 putch(0x20); //空白 #endif rcb_buf[0] = 0x80; //固定 rcb_buf[1] = 0; if ((pad_buf[3] & 0x01) == 0) rcb_buf[1] += 0x40; //PS:SL if ((pad_buf[3] & 0x08) == 0) rcb_buf[1] += 0x20; //PS:ST if ((pad_buf[4] & 0x02) == 0) rcb_buf[1] += 0x10; //PS:R2 if ((pad_buf[4] & 0x08) == 0) rcb_buf[1] += 0x08; //PS:R1 if ((pad_buf[4] & 0x01) == 0) rcb_buf[1] += 0x04; //PS:L2 if ((pad_buf[4] & 0x04) == 0) rcb_buf[1] += 0x02; //PS:L1 if ((pad_buf[4] & 0x80) == 0) rcb_buf[1] += 0x01; //PS:□ rcb_buf[2] = 0; if ((pad_buf[4] & 0x20) == 0) rcb_buf[2] += 0x40; //PS:○ if ((pad_buf[4] & 0x40) == 0) rcb_buf[2] += 0x20; //PS:× if ((pad_buf[4] & 0x10) == 0) rcb_buf[2] += 0x10; //PS:△ if ((pad_buf[3] & 0x80) == 0) rcb_buf[2] += 0x08; //PS:左 if ((pad_buf[3] & 0x20) == 0) rcb_buf[2] += 0x04; //PS:右 if ((pad_buf[3] & 0x40) == 0) rcb_buf[2] += 0x02; //PS:下 if ((pad_buf[3] & 0x10) == 0) rcb_buf[2] += 0x01; //PS:上 rcb_buf[3] = marume(pad_buf[7]); //左ハンドル左右 rcb_buf[4] = marume(pad_buf[8]); //左ハンドル上下 rcb_buf[5] = marume(pad_buf[5]); //右ハンドル左右 rcb_buf[6] = marume(pad_buf[6]); //右ハンドル上下 rcb_buf[7] = (rcb_buf[1] + rcb_buf[2] + rcb_buf[3] + rcb_buf[4] + rcb_buf[5] + rcb_buf[6]) & 0x7f; for(i=0; i<8; i++) { #if DEBUG put1hex(rcb_buf[i]); putch(0x20); //空白 #else putch(rcb_buf[i]); #endif } //活性監視LED点滅 j++; if ((j & 0x04)!=0) RB0=1; if ((j & 0x04)==0) RB0=0; } } }