First Release

Dependencies:   USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers C_Out_FC.cpp Source File

C_Out_FC.cpp

00001 #include "mbed.h"
00002 #include "NiseKabuto.h" // InputDeviceType
00003 #include "C_Out_FC.h"
00004 
00005 // mbed pins
00006 DigitalOut  led2_FC(LED2); 
00007 DigitalOut  led3_FC(LED3); 
00008 InterruptIn *_INTR_LATCH;
00009 DigitalOut  *_OUT_DATA;
00010 InterruptIn *_INTR_CLOCK;
00011 InterruptIn *_INTR_POWDETECT;
00012 
00013 // File local variables
00014 static volatile int     *_pButtons; //PhaseData[12]
00015 static volatile char    *_pCh0;
00016 static volatile char    *_pCh1;
00017 static volatile char    *_pCh2;
00018 static volatile char    *_pInputDeviceType;
00019 static volatile char    _Flag_NowOutput;
00020 static volatile char    _PhaseCounter;
00021 static volatile char    _SpeedType;
00022 static FunctionPointer  *_fp_EnableInput;
00023 static FunctionPointer  *_fp_DisableInput;
00024 static volatile char    _RapidFireValue;
00025 static Ticker           _RapidStateTicker;
00026 
00027 // Const variables
00028 static const int    DIGITALPAD_SPEED_STARFORCE = 120;
00029 static const int    DIGITALPAD_SPEED_RECCA     = 75;
00030 static const int    RAPIDFIRE_PER_SEC = 15;     // 高橋名人連射速度-1
00031 
00032 // File local functions
00033 static void ISR_Rise_LATCH_STARFORCE(void); // 遅い読み取りルーチン for スターフォース
00034 static void ISR_Rise_LATCH(void);           // フツー
00035 static void ISR_Rise_LATCH_RECCA(void);     // 速い読み取りルーチン for サマーカーニバル'92 烈火
00036 //static void ISR_Rise_POWERDETECT(void);
00037 static void RenewData(void);
00038 static char CheckSpeedType(void);
00039 static int  CheckOneReadTime(void);
00040 static void ConfigureSpeed(void);
00041 static void RapidStateTickerMethod(void);
00042 
00043 void C_Out_FC_Initialize(
00044     InterruptIn *intr_LATCH,
00045     DigitalOut  *out_DATA,
00046     InterruptIn *intr_CLOCK,
00047     InterruptIn *intr_POWDETECT,
00048     volatile int *pButtons,
00049     volatile char *pCh0,
00050     volatile char *pCh1,
00051     volatile char *pCh2,
00052     volatile char *pInputDeviceType,
00053     FunctionPointer *pFunc_InputEnable,
00054     FunctionPointer *pFunc_InputDisable
00055 )
00056 {
00057     // 入出力pin
00058     _INTR_LATCH     = intr_LATCH;
00059     _OUT_DATA       = out_DATA;
00060     _INTR_CLOCK     = intr_CLOCK;
00061     _INTR_POWDETECT = intr_POWDETECT;
00062 
00063     // 割り込み設定
00064     //_INTR_POWDETECT->rise(&ISR_Rise_POWERDETECT); // 電源ON/OFFでスピード切り替え判定を行う場合
00065 
00066     led2_FC.write(0);                               // 初期:フツー
00067     led3_FC.write(1);                               //
00068     _INTR_LATCH->rise(&ISR_Rise_LATCH);             //
00069     
00070     // 出力速度設定
00071     ConfigureSpeed();
00072 
00073     // ポインタ
00074     _pButtons         = pButtons;
00075     _pCh0             = pCh0;
00076     _pCh1             = pCh1;
00077     _pCh2             = pCh2;
00078     _pInputDeviceType = pInputDeviceType;
00079     _fp_EnableInput   = pFunc_InputEnable;
00080     _fp_DisableInput  = pFunc_InputDisable;
00081     
00082     _Flag_NowOutput = 0;
00083     _RapidFireValue = 1;
00084     
00085     //_pTemp = pTemp;
00086     
00087     // 連射ステータス変更設定
00088     _RapidStateTicker.attach_us(&RapidStateTickerMethod, (int)(1000000/(RAPIDFIRE_PER_SEC*2)));
00089     
00090     // Initialize pin status
00091     _PhaseCounter = 0;
00092     RenewData();
00093 }
00094 
00095 void ISR_Rise_LATCH(void)
00096 {
00097     int loopCounter;
00098 
00099     // 止める
00100     if(
00101         (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG ||
00102         (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL
00103     )
00104     {
00105         (*_fp_DisableInput).call();
00106     }
00107 
00108     // この関数開始時点で、phase0読み取り(DATAの立下り1回分)は
00109     // 終了しているものと仮定する
00110     // (mbedのピン割り込み時の反応速度は7usくらい)
00111     //
00112     // ただしMetalMaxでは。Latch立ち上がりから初回DATA立下りの間が
00113     // 6.5-7.0usくらいで微妙なので、
00114     // 絶対にphase0から開始することを保証するため、ちょっと待つ
00115     wait_us(1);
00116     
00117     
00118     // Phase1に移行
00119     _PhaseCounter=1;
00120     RenewData();
00121 
00122     // Lの間待つ
00123     while( !(_INTR_CLOCK->read()) )
00124     {
00125         loopCounter = 400;
00126 
00127         loopCounter--;
00128         if( !loopCounter )
00129         {
00130             break;
00131         }
00132     }
00133     
00134     // 開始
00135     for(int i=1; i<8; i++ )
00136     {
00137         
00138         // Hの間待つ
00139         loopCounter = 5000;     
00140         while( _INTR_CLOCK->read() )
00141         {
00142             loopCounter--;
00143             if( !loopCounter )
00144             {
00145                 break;
00146             }
00147         }
00148 
00149         // Set data for current phase
00150         _PhaseCounter++;
00151         RenewData();
00152         
00153         // Lの間待つ
00154         loopCounter = 200;
00155         while( !(_INTR_CLOCK->read()) )
00156         {
00157             loopCounter--;
00158             if( !loopCounter )
00159             {
00160                 break;
00161             }
00162         }
00163     }
00164 
00165     _PhaseCounter = 0;
00166     RenewData();
00167 
00168     // 再開
00169     if(
00170         (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG ||
00171         (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL
00172     )
00173     {
00174         (*_fp_EnableInput).call();
00175     }
00176 
00177 }
00178 
00179 void ISR_Rise_LATCH_RECCA(void)
00180 {
00181     // おまじない(Phase0を長引かせる)
00182     wait_us(2);
00183     
00184     // Phase1に移行
00185     _PhaseCounter=1;
00186     RenewData();
00187     
00188     // 開始
00189     for(int i=1; i<8; i++ )
00190     {
00191         wait_us(6); 
00192 
00193         // Set data for current phase
00194         _PhaseCounter++;
00195         RenewData();
00196     }
00197 
00198     _PhaseCounter = 0;
00199     RenewData();
00200 
00201 }
00202 
00203 // 遅い読み取りルーチン
00204 void ISR_Rise_LATCH_STARFORCE(void)
00205 {
00206     int loopCounter;
00207 
00208     // 止める
00209     if(
00210         (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG ||
00211         (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL
00212     )
00213     {
00214         (*_fp_DisableInput).call();
00215     }
00216 
00217     // Hの間待つ
00218     loopCounter = 5000;     
00219     while( _INTR_CLOCK->read() )
00220     {
00221         loopCounter--;
00222         if( !loopCounter )
00223         {
00224             break;
00225         }
00226     }
00227 
00228     
00229     // Phase1に移行
00230     _PhaseCounter=1;
00231     RenewData();
00232 
00233     // Lの間待つ
00234     while( !(_INTR_CLOCK->read()) )
00235     {
00236         loopCounter = 400;
00237 
00238         loopCounter--;
00239         if( !loopCounter )
00240         {
00241             break;
00242         }
00243     }
00244     
00245     // 開始
00246     for(int i=1; i<8; i++ )
00247     {
00248         
00249         // Hの間待つ
00250         loopCounter = 5000;     
00251         while( _INTR_CLOCK->read() )
00252         {
00253             loopCounter--;
00254             if( !loopCounter )
00255             {
00256                 break;
00257             }
00258         }
00259 
00260         // Set data for current phase
00261         _PhaseCounter++;
00262         RenewData();
00263         
00264         // Lの間待つ
00265         loopCounter = 200;
00266         while( !(_INTR_CLOCK->read()) )
00267         {
00268             loopCounter--;
00269             if( !loopCounter )
00270             {
00271                 break;
00272             }
00273         }
00274     }
00275 
00276     _PhaseCounter = 0;
00277     RenewData();
00278 
00279     // 再開
00280     if(
00281         (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG ||
00282         (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL
00283     )
00284     {
00285         (*_fp_EnableInput).call();
00286     }
00287 
00288 }
00289 
00290 
00291 
00292 
00293 void RenewData(void)
00294 {
00295     switch(_PhaseCounter)
00296     {
00297         case 0:
00298             //
00299             // A
00300             //
00301             if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
00302             {
00303                 _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0);  // Digital B
00304             }
00305             else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B
00306             {
00307                 // Zが押されてたら連射、押されてなかったらCの結果
00308                 if( ((*_pButtons) & 0x010000) ) // Z
00309                 {
00310                     // 真:押されてない
00311                     _OUT_DATA->write(((*_pButtons) & 0x0020) ? 1 : 0);  // Digital C
00312                 }
00313                 else
00314                 {
00315                     // 偽:押されてる
00316                     _OUT_DATA->write(_RapidFireValue&1);
00317                 }
00318             }
00319             else
00320             {
00321                 _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0);  // Digital B
00322             }
00323             break;
00324 
00325         case 1:
00326             //
00327             // B
00328             //
00329             if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
00330             {
00331                 _OUT_DATA->write(((*_pButtons) & 0x0200) ? 1 : 0);  // Digital A
00332             }
00333             else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B
00334             {
00335                 // Yが押されてたら連射、押されてなかったらBの結果
00336                 if( ((*_pButtons) & 0x020000) ) // Y
00337                 {
00338                     // 真:押されてない
00339                     _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0);  // Digital B
00340                 }
00341                 else
00342                 {
00343                     // 偽:押されてる
00344                     _OUT_DATA->write(_RapidFireValue&1);
00345                 }
00346             }
00347             else
00348             {
00349                 _OUT_DATA->write(((*_pButtons) & 0x0200) ? 1 : 0);  // Digital A
00350             }
00351             break;
00352 
00353         case 2: 
00354             //
00355             // Select
00356             //
00357             if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
00358             {
00359                 _OUT_DATA->write(((*_pButtons) & 0x0001) ? 1 : 0);  // G(Sel,Mode)
00360             }
00361             else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B
00362             {
00363                 _OUT_DATA->write(((*_pButtons) & 0x0001) ? 1 : 0);  // G(Sel,Mode)
00364             }
00365             else
00366             {
00367                 _OUT_DATA->write(((*_pButtons) & 0x0020) ? 1 : 0);  // Digital C
00368             }
00369             break;
00370 
00371         case 3:
00372             //
00373             // Start
00374             //
00375             if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
00376             {
00377                 _OUT_DATA->write(
00378                     ( ((*_pButtons) & 0x0002) ? 1 : 0) &    // F(Start)
00379                     ( (*_pCh2)>0xf0? 0:1 )                  // スロットル引く
00380                 
00381                 );
00382                 //_OUT_DATA->write( ((*_pButtons) & 0x0002) ? 1 : 0) );
00383                 
00384             }
00385             else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B
00386             {
00387                 _OUT_DATA->write(((*_pButtons) & 0x0002) ? 1 : 0);  // F(Start)
00388             }
00389             else
00390             {
00391                 _OUT_DATA->write(((*_pButtons) & 0x0010) ? 1 : 0);  // Digital C
00392             }
00393             break;
00394 
00395         case 4:
00396             //
00397             // Up
00398             //
00399             //  ch1>0xf0? 0:1,  //  右
00400             //  ch1<0x0f? 0:1,  //  左
00401             //  ch0>0xf0? 0:1,  //  下
00402             //  ch0<0x0f? 0:1   //  上
00403             //  ch2>0xf0? 0:1,  //  スロットル引く
00404 
00405             if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
00406             {
00407                 _OUT_DATA->write((*_pCh0)<0x40? 0:1);
00408             }
00409             else
00410             {
00411                 _OUT_DATA->write(((*_pButtons) & 0x2000) ? 1 : 0);
00412             }
00413             break;
00414 
00415         case 5:
00416             //
00417             // Down
00418             //
00419             if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
00420             {
00421                 _OUT_DATA->write((*_pCh0)>0xb0? 0:1);
00422             }
00423             else
00424             {
00425                 _OUT_DATA->write(((*_pButtons) & 0x1000) ? 1 : 0);
00426             }
00427             break;
00428 
00429         case 6:
00430             //
00431             // Left
00432             //
00433             if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
00434             {
00435                 _OUT_DATA->write((*_pCh1)<0x40? 0:1);
00436             }
00437             else
00438             {
00439                 _OUT_DATA->write(((*_pButtons) & 0x0800) ? 1 : 0);
00440             }
00441             break;
00442 
00443         case 7:     
00444             //
00445             // Right
00446             //
00447             if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
00448             {
00449                 _OUT_DATA->write((*_pCh1)>0xb0? 0:1);
00450             }
00451             else
00452             {
00453                 _OUT_DATA->write(((*_pButtons) & 0x0400) ? 1 : 0);
00454             }
00455             break;
00456         
00457         default:
00458             _OUT_DATA->write(1);    // H
00459     }
00460 }
00461 
00462 // 
00463 // ファミコンからの読み取り処理の長さを得る(1回分)
00464 // 
00465 // return:
00466 //      0     = 読み取りが行えない(烈火の可能性がある)
00467 //      0以外 = 読み取り処理長さ[us]
00468 int CheckOneReadTime(void)
00469 {
00470     int   retVal = 0;
00471     char  stat = 1;
00472     int   intLoopCounter;   // ZanacはGunnac&MMに比べて2倍
00473     Timer t;
00474     
00475     // Latch = Hまで待つ
00476     intLoopCounter = 500000;
00477     while( !(_INTR_LATCH->read()) )
00478     {
00479         intLoopCounter--;
00480         if( !intLoopCounter )
00481         {
00482             stat = 0;
00483             break;
00484         }
00485     }
00486     
00487     if(stat)
00488     {
00489         // 時刻計測開始
00490         t.start();
00491         
00492         // Clockが8回Lになることを確認
00493         for(int i=0; i<8; i++ )
00494         {
00495             intLoopCounter = 1000;
00496             while( _INTR_CLOCK->read() )
00497             {
00498                 intLoopCounter--;
00499                 if( !intLoopCounter )
00500                 {
00501                     stat = 0;
00502                     break;
00503                 }
00504             }
00505             
00506             intLoopCounter = 100;
00507             while( !(_INTR_CLOCK->read()) )
00508             {
00509                 intLoopCounter--;
00510                 if( !intLoopCounter )
00511                 {
00512                     break;
00513                 }
00514             }           
00515         }
00516     }
00517     
00518     if(stat)
00519     {
00520         t.stop();
00521         retVal =  t.read_us();
00522     }
00523     
00524     return retVal;
00525 }
00526 
00527 
00528 
00529 // 
00530 // SpeedTypeを判定する
00531 // 
00532 // return:
00533 //      0 = 普通モード(普通のゲーム)
00534 //      1 = 高速モード(烈火)
00535 //      2 = 低速モード(スターフォース)
00536 //      よくわからないときは0を返す
00537 char CheckSpeedType(void)
00538 {
00539     char retVal = 0;
00540     int readTime[8];
00541     char counter_recca     = 0;
00542     char counter_starforce = 0;
00543     
00544     // Dataは常にH
00545     _OUT_DATA->write(1);
00546     
00547     // 8回くらいチェックする
00548     for(int i=0; i<8; i++ )
00549     {
00550         readTime[i] = CheckOneReadTime();
00551         printf("readTime[%d]: %d\r\n",i,readTime[i]);
00552     }
00553     
00554     // 個別の結果判定
00555     for(int i=0; i<8; i++ )
00556     {
00557         if( readTime[i]>DIGITALPAD_SPEED_STARFORCE )
00558         {
00559             counter_starforce++;
00560         }
00561         else if( readTime[i]<DIGITALPAD_SPEED_RECCA )
00562         {
00563             counter_recca++;
00564         }
00565         else
00566         {
00567         }
00568     }
00569     
00570     // 判定
00571     if(counter_starforce >= 4)
00572     {
00573         retVal = 2;
00574     }
00575     else if(counter_recca >= 4)
00576     {
00577         retVal = 1;
00578     }
00579     
00580     return retVal;
00581 }
00582 
00583 //
00584 // Configure speed setting
00585 //
00586 void ConfigureSpeed(void)
00587 {
00588     char speed;
00589     
00590     // ISR登録解除
00591     _INTR_LATCH->rise(0);
00592     
00593     // ちょっと待つ
00594     wait_ms(500);
00595     
00596     speed = CheckSpeedType();
00597     
00598     // Interrupt Setting
00599     if( speed==1 )
00600     {
00601         led2_FC.write(1);
00602         led3_FC.write(1);
00603         _INTR_LATCH->rise(&ISR_Rise_LATCH_RECCA);
00604     }
00605     else if( speed==2 )
00606     {
00607         led2_FC.write(0);
00608         led3_FC.write(0);
00609         _INTR_LATCH->rise(&ISR_Rise_LATCH_STARFORCE);
00610     }
00611     else
00612     {
00613         led2_FC.write(0);
00614         led3_FC.write(1);
00615         _INTR_LATCH->rise(&ISR_Rise_LATCH);
00616     }
00617 
00618 }
00619 
00620 //
00621 // ISR for POWERDETECT L->H
00622 //
00623 void ISR_Rise_POWERDETECT(void)
00624 {
00625     ConfigureSpeed();
00626 }
00627 
00628 void RapidStateTickerMethod(void)
00629 {
00630     _RapidFireValue = !_RapidFireValue;
00631 }
00632