First Release

Dependencies:   USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Out_PCE.cpp Source File

Out_PCE.cpp

00001 #include "NiseKabuto.h"
00002 #include "Cfunc_PCEDigital.h"
00003 
00004 volatile char test = 0;
00005 
00006 //extern "C" void mbed_reset();
00007 
00008 //
00009 // Constructor
00010 //
00011 Out_PCE::Out_PCE(
00012     PinName pn_1Y, PinName pn_2Y, PinName pn_3Y, PinName pn_4Y, 
00013     PinName pn_DSEL, PinName pn_ST, PinName pn_POWDETECT,
00014     InputStatus *inputStatus)
00015     : _OUT_1Y(pn_1Y), _OUT_2Y(pn_2Y), _OUT_3Y(pn_3Y), _OUT_4Y(pn_4Y), 
00016       _INTR_DSEL(pn_DSEL), _INTR_ST(pn_ST), _INTR_POWDETECT(pn_POWDETECT)
00017 {
00018     _InputStatus = inputStatus;
00019     
00020     // OutputMode Initialize
00021     _OutputMode = _InputStatus->InputDeviceType;
00022 
00023     //printf("_OutputMode: %d(constructor)\r\n",_OutputMode);
00024 
00025 //    InitInterruptPriority();
00026     Initialize();
00027 
00028 }
00029 
00030 //
00031 // Initialize
00032 //
00033 void Out_PCE::Initialize()
00034 {
00035     
00036     // Pin Setting
00037     _INTR_ST.mode(PullUp);
00038     _INTR_DSEL.mode(PullUp);
00039     _INTR_POWDETECT.mode(PullUp);
00040 
00041     // Class Variable Setting
00042     _PhaseCounter = 0;
00043     _NowWriting = 0;
00044     _DataSelectStatus = 1;
00045     _TransferSpeed = TRANSFERSPEED_MAX__MICROSEC;
00046     _RapidFireValue = 1;
00047     
00048     // Reset Interrupt Settings
00049     _INTR_ST.fall(NULL);
00050     _INTR_ST.rise(NULL);
00051     _INTR_DSEL.fall(NULL);
00052     _INTR_DSEL.rise(NULL);
00053     _PhaseChangeTicker.detach();
00054     _DigitalPadPhase0SetTicker.detach();
00055     _ModeCheckTicker.detach();
00056 
00057     // 入力デバイスにより場合わけ
00058     _OutputMode = _InputStatus->InputDeviceType;
00059     //printf("_OutputMode: %d(init)\r\n",_OutputMode);
00060 
00061     // ModeCheckTicker Setting
00062     _ModeCheckTicker.attach_us(this, &Out_PCE::ModeChecker, MODECHECKPERIOD__MICROSEC);
00063 
00064     switch(_OutputMode)
00065     {
00066         //
00067         // Input: CyberStick DIGITAL mode
00068         // Input: FightingPad 6B
00069         //
00070         case NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL:
00071         case NiseKabuto::CONFIG_INMODE_MD6B:
00072             Cfunc_PCEDigital_Initialize(
00073                 &_OUT_1Y, 
00074                 &_OUT_2Y, 
00075                 &_OUT_3Y, 
00076                 &_OUT_4Y, 
00077                 &_INTR_DSEL, 
00078                 &_INTR_ST, 
00079                 _PhaseData, 
00080                 &_RapidFireValue,
00081                 &(_InputStatus->Temp[4])
00082             );
00083             
00084             
00085             // Ticker Setting
00086             _DigitalPadPhase0SetTicker.attach_us(
00087                 this, 
00088                 &Out_PCE::Digital_TickerMethod, 
00089                 DIGITALPAD_STATERENEWINTERVAL__MICROSEC
00090             );
00091             
00092             EnableInput();
00093             
00094             SetOutputPinsValue(0x00);
00095             wait_us(5000);  // PCエンジンに気づかせる
00096             break;
00097 
00098         //
00099         // Input: CyberStick ANALOG mode
00100         //
00101         default:
00102         case NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG:
00103 
00104             // Interrupt Setting
00105             _INTR_ST.fall(this, &Out_PCE::StrobeFallISR);
00106 
00107             // Initialize pin status
00108             //SetOutputPinsValue(0x0f); // AfterBurner Boot時にRUN押されちゃう
00109             SetOutputPinsValue(0x02);   // 
00110             break;
00111         
00112     }
00113 }
00114 
00115 
00116 //
00117 // Set Pins
00118 //
00119 void Out_PCE::SetOutputPinsValue(char dat)
00120 {
00121     _OUT_1Y = dat & 1;
00122     _OUT_2Y = (dat & 2) >> 1;
00123     _OUT_3Y = (dat & 4) >> 2;
00124     _OUT_4Y = (dat & 8) >> 3;
00125 }
00126 
00127 //
00128 // Set Pins2
00129 //
00130 void Out_PCE::SetOutputPinsValue2(char dat)
00131 {
00132     // D0
00133     _OUT_1Y = dat & 1;          // D0
00134     // D1
00135     _OUT_2Y = (dat & 8) >> 3;   // D3
00136     // D2
00137     _OUT_3Y = (dat & 2) >> 1;   // D1
00138     // D3
00139     _OUT_4Y = (dat & 4) >> 2;   // D2
00140 }
00141 
00142 //
00143 // ISR for Strobe=L
00144 //
00145 void Out_PCE::StrobeFallISR(void)
00146 {
00147     //_PCEActiveCounter++;
00148     
00149     if( _NowWriting == 0)
00150     {
00151         _INTR_ST.fall(NULL);
00152         
00153         
00154         
00155         // Disableしないと、入力にまれにノイズがのる
00156         // Disable/Enable有る場合も無い場合も、しばらくすると入力が受け付けられなくなる
00157         // EnableInput()時にInitialize()を実行させるように修正
00158         
00159         //wait_us(_TransferSpeed>>1);   //AfterBurnerはこれで良かった.OutRun動かないかも?
00160                                     //wait_us(10);  //Outrun対策
00161 
00162         _NowWriting = 1;
00163 
00164         // データフェーズごとのデータ用意
00165         int buttons = _InputStatus->Buttons;
00166         char ch0    = _InputStatus->Ch0;
00167         char ch1    = _InputStatus->Ch1;
00168         char ch2    = _InputStatus->Ch2;
00169         char ch3    = _InputStatus->Ch3;
00170 
00171         // DisableInput();
00172 
00173         // |A|B|C|D
00174         _PhaseData[0] =
00175             (
00176                 (((buttons) & 0x0200)?1:0)<<3 | // A
00177                 (((buttons) & 0x0100)?1:0)<<2 | // B
00178                 (((buttons) & 0x0020)?1:0)<<1 | // C
00179                 (((buttons) & 0x0010)?1:0)      // D
00180             );
00181             
00182         // |E1|E2|F|G
00183         _PhaseData[1] =
00184             (
00185                 (((buttons) & 0x0008)?1:0)<<3 | // E1
00186                 (((buttons) & 0x0004)?1:0)<<2 | // E2
00187                 (((buttons) & 0x0002)?1:0)<<1 | // F
00188                 (((buttons) & 0x0001)?1:0)      // G
00189             );
00190             
00191         // 1H
00192         _PhaseData[2] = 
00193             ( ((ch0)>>4) & 0x0f );
00194             
00195         // 2H
00196         _PhaseData[3] = 
00197             ( ((ch1)>>4) & 0x0f );
00198             
00199         // 3H
00200         _PhaseData[4] = 
00201             ( ((ch2)>>4) & 0x0f );
00202             
00203         // 4H
00204         _PhaseData[5] = 
00205             ( 0x010 );
00206             
00207         // 1L
00208         _PhaseData[6] = 
00209             ( ch0 );
00210             
00211         // 2L
00212         _PhaseData[7] = 
00213             ( ch1 );
00214             
00215         // 3L
00216         _PhaseData[8] = 
00217             ( ch2 );
00218             
00219         // 4L
00220         _PhaseData[9] = 
00221             ( 0 );
00222             
00223         _PhaseData[10] = 
00224             // |A|B|A'|B'|
00225             (
00226                 (((buttons) & 0x0200)?1:0)<<3 | // A
00227                 (((buttons) & 0x0100)?1:0)<<2 | // B
00228                 (((buttons) & 0x0080)?1:0)<<1 | // A'
00229                 (((buttons) & 0x0040)?1:0)      // B'
00230             );
00231             
00232         _PhaseData[11] = (0x0f);
00233 
00234 //      DisableInput();
00235         _PhaseChangeTicker.attach_us(this, &Out_PCE::ChangePhase, _TransferSpeed>>1);
00236     }
00237 }
00238 
00239 
00240 //
00241 // Tickerにより呼ばれる処理
00242 // PhaseCounterを変化
00243 //
00244 void Out_PCE::ChangePhase(void)
00245 {
00246     int loopCounter=0;
00247     char state=1;
00248     
00249     // 一瞬だけ2Yを下げて
00250     SetOutputPinsValue( _PhaseCounter&1 );
00251     wait_us(2); //PCEがアナログモードになるwait_us値:10, 5, 3, 2
00252 
00253     // すぐデータ変更
00254     SetOutputPinsValue2( _PhaseData[_PhaseCounter] );
00255 
00256     // DSELがHになるまで待つ
00257     loopCounter=100;
00258     while(!(_INTR_DSEL))
00259     {
00260         loopCounter--;
00261         if(loopCounter<0)
00262         {
00263             state=0;
00264             break;
00265         }
00266     }
00267     
00268     if(state)
00269     {
00270         // DSELがLになるまで待つ
00271         loopCounter=100;
00272         while(_INTR_DSEL)
00273         {
00274             loopCounter--;
00275             if(loopCounter<0)
00276             {
00277                 state=0;
00278                 break;
00279             }
00280         }
00281     }
00282 
00283     if(state)
00284     {
00285         
00286         // その後、Ack出力に戻す
00287         SetOutputPinsValue( _PhaseCounter&1 | 0x02);
00288 
00289         _PhaseCounter++;
00290         
00291         //if(_PhaseCounter==12)
00292         if(_PhaseCounter>=11)
00293         {
00294             _PhaseCounter = 0;
00295             _PhaseChangeTicker.detach();
00296             SetOutputPinsValue(0x02);
00297             _NowWriting = 0;
00298 //          EnableInput();
00299             _INTR_ST.fall(this, &Out_PCE::StrobeFallISR);
00300         }
00301     }
00302     else
00303     {
00304         _PhaseCounter = 0;
00305         _PhaseChangeTicker.detach();
00306         SetOutputPinsValue(0x02);
00307         _NowWriting = 0;
00308 //      EnableInput();
00309         _INTR_ST.fall(this, &Out_PCE::StrobeFallISR);
00310     }
00311 
00312 }
00313 
00314 
00315 
00316 //
00317 // Ticker method for digital pad output
00318 //
00319 // 1. 全phase用のデータを集め、クラス変数に保存
00320 // 2. Phase0データを出力する
00321 void Out_PCE::Digital_TickerMethod(void)
00322 {
00323     // デバッグ用:この関数が呼ばれるたび+1される
00324     (_InputStatus->Temp[2])++;
00325     
00326     //printf("I\r\n");  // これがあるとhungup起きない?(1)
00327 //  _InputStatus->Temp[0] = 1;
00328 //  wait_us(14000);
00329     
00330     volatile int idx;
00331 
00332     // データフェーズごとのデータ用意
00333     __disable_irq();
00334     volatile int buttons = _InputStatus->Buttons;
00335     volatile char type = _InputStatus->InputDeviceType;
00336     __enable_irq();
00337 
00338     volatile int val_1a=0x0f;
00339     volatile int val_1b=0x0f;
00340     volatile int trgState_I  = 1;
00341     volatile int trgState_II = 1;
00342 
00343     if( type == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL)
00344     {
00345         // 入力デバイス=サイバースティック/カブトガニ デジタルモード
00346 
00347         //  4Y  3Y  2Y 1Y
00348         //  L   D   R  U
00349         val_1a =
00350             (
00351                 ((buttons & 0x0800) ? 0x08 : 0) |   // L
00352                 ((buttons & 0x1000) ? 0x04 : 0) |   // D
00353                 ((buttons & 0x0400) ? 0x02 : 0) |   // R
00354                 ((buttons & 0x2000) ? 0x01 : 0)     // U
00355             );
00356 
00357         //  4Y  3Y  2Y 1Y
00358         // |Run|Sel|II|I
00359         val_1b =
00360             (
00361                 ((buttons & 0x0002) ? 0x08 : 0)&((buttons & 0x0010) ? 0x08 : 0) |   // F(Start) & D
00362                 ((buttons & 0x0001) ? 0x04 : 0)&((buttons & 0x0020) ? 0x04 : 0) |   // G(Sel,Mode) & C
00363                 ((buttons & 0x0100) ? 0x02 : 0) |   // B
00364                 ((buttons & 0x0200) ? 0x01 : 0)     // A
00365             );
00366 
00367     }
00368     else if (type == NiseKabuto::CONFIG_INMODE_MD6B)
00369     {
00370         // 入力デバイス=6B
00371 
00372         if( !(buttons & 0x020000) ) //Y
00373         {
00374             trgState_II = ((_RapidFireValue) ? 0x02 : 0);
00375         }
00376         else
00377         {
00378             trgState_II = ((buttons & 0x0100) ? 0x02 : 0); // B
00379         }
00380         if( !(buttons & 0x010000) ) //Z
00381         {
00382             trgState_I  = ((_RapidFireValue) ? 0x01 : 0);
00383         }
00384         else
00385         {
00386             trgState_I  = ((buttons & 0x0020) ? 0x01 : 0); // C
00387         }
00388             
00389         //  4Y  3Y  2Y 1Y
00390         //  L   D   R  U
00391         val_1a =
00392             (
00393                 ((buttons & 0x0800) ? 0x08 : 0) |   // L
00394                 ((buttons & 0x1000) ? 0x04 : 0) |   // D
00395                 ((buttons & 0x0400) ? 0x02 : 0) |   // R
00396                 ((buttons & 0x2000) ? 0x01 : 0)     // U
00397             );
00398 
00399         //  4Y  3Y  2Y 1Y
00400         // |Run|Sel|II|I
00401         val_1b =
00402             (
00403                 ((buttons & 0x0002) ? 0x08 : 0) |   // F(Start)
00404                 ((buttons & 0x0001) ? 0x04 : 0) |   // G(Sel,Mode)
00405                 trgState_II |
00406                 trgState_I
00407             );
00408         
00409         
00410     }
00411     
00412     __disable_irq();
00413     for(idx=0; idx<12; idx+=2)
00414     {
00415         //printf("idx:%d\r\n",idx);
00416         _PhaseData[idx  ] = val_1a;
00417         _PhaseData[idx+1] = val_1b;
00418     }
00419     __enable_irq();
00420     
00421     
00422 //    //phase0データをset
00423 //    Digital_SetDataOfPhase(0);
00424     
00425 
00426     //printf("O\r\n");  // これがあるとhungup起きない?(2)
00427 //  _InputStatus->Temp[0] = 0;
00428 //  wait_us(14000);
00429 
00430 }
00431 
00432 
00433 void Out_PCE::Digital_SetDataOfPhase(char phaseCounter)
00434 {
00435     if( phaseCounter < 10 )
00436     {
00437         SetOutputPinsValue(_PhaseData[phaseCounter]);
00438     }
00439     else
00440     {
00441         SetOutputPinsValue(0x0f);
00442     }
00443     
00444 }
00445 
00446 void Out_PCE::ModeChecker(void)
00447 {
00448     // デバッグ用:この関数が呼ばれるたび+1される
00449     (_InputStatus->Temp[5])++;
00450 
00451     __disable_irq();
00452     char curOutMode = _InputStatus->InputDeviceType;
00453     __enable_irq();
00454     
00455     // Analog/Digital切り替え判定
00456     if(_OutputMode != curOutMode)
00457     {
00458         _OutputMode = curOutMode;
00459     //  printf("InputDeviceType changed. Calling Initialize().\r\n");
00460         Initialize();
00461     }
00462 }
00463 
00464 
00465 
00466 void Out_PCE::SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void))
00467 {
00468     StartInputFunction = startInputFunction;
00469     StopInputFunction  = stopInputFunction;
00470 }
00471 
00472 void Out_PCE::EnableInput(void)
00473 {
00474     //printf("Out_PCE::EnableInput() called!!");
00475     if(_InputInstance && StartInputMethod)
00476     {
00477         (_InputInstance->*StartInputMethod)();
00478     }
00479     else if(StartInputFunction)
00480     {
00481         StartInputFunction();
00482     }
00483 }
00484 
00485 void Out_PCE::DisableInput(void)
00486 {
00487     //printf("Out_PCE::DisableInput() called!!");
00488     
00489     if(_InputInstance && StopInputMethod)
00490     {
00491         (_InputInstance->*StopInputMethod)();
00492     }
00493     else if(StopInputFunction)
00494     {
00495         StopInputFunction();
00496     }
00497 }
00498 
00499 
00500