First Release
Out_PCE/Out_PCE.cpp
- Committer:
- sankichi
- Date:
- 2013-07-27
- Revision:
- 1:6c392ebcd4d4
- Parent:
- 0:e1265f6b3565
File content as of revision 1:6c392ebcd4d4:
#include "NiseKabuto.h" #include "Cfunc_PCEDigital.h" volatile char test = 0; //extern "C" void mbed_reset(); // // Constructor // Out_PCE::Out_PCE( PinName pn_1Y, PinName pn_2Y, PinName pn_3Y, PinName pn_4Y, PinName pn_DSEL, PinName pn_ST, PinName pn_POWDETECT, InputStatus *inputStatus) : _OUT_1Y(pn_1Y), _OUT_2Y(pn_2Y), _OUT_3Y(pn_3Y), _OUT_4Y(pn_4Y), _INTR_DSEL(pn_DSEL), _INTR_ST(pn_ST), _INTR_POWDETECT(pn_POWDETECT) { _InputStatus = inputStatus; // OutputMode Initialize _OutputMode = _InputStatus->InputDeviceType; //printf("_OutputMode: %d(constructor)\r\n",_OutputMode); // InitInterruptPriority(); Initialize(); } // // Initialize // void Out_PCE::Initialize() { // Pin Setting _INTR_ST.mode(PullUp); _INTR_DSEL.mode(PullUp); _INTR_POWDETECT.mode(PullUp); // Class Variable Setting _PhaseCounter = 0; _NowWriting = 0; _DataSelectStatus = 1; _TransferSpeed = TRANSFERSPEED_MAX__MICROSEC; _RapidFireValue = 1; // Reset Interrupt Settings _INTR_ST.fall(NULL); _INTR_ST.rise(NULL); _INTR_DSEL.fall(NULL); _INTR_DSEL.rise(NULL); _PhaseChangeTicker.detach(); _DigitalPadPhase0SetTicker.detach(); _ModeCheckTicker.detach(); // 入力デバイスにより場合わけ _OutputMode = _InputStatus->InputDeviceType; //printf("_OutputMode: %d(init)\r\n",_OutputMode); // ModeCheckTicker Setting _ModeCheckTicker.attach_us(this, &Out_PCE::ModeChecker, MODECHECKPERIOD__MICROSEC); switch(_OutputMode) { // // Input: CyberStick DIGITAL mode // Input: FightingPad 6B // case NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL: case NiseKabuto::CONFIG_INMODE_MD6B: Cfunc_PCEDigital_Initialize( &_OUT_1Y, &_OUT_2Y, &_OUT_3Y, &_OUT_4Y, &_INTR_DSEL, &_INTR_ST, _PhaseData, &_RapidFireValue, &(_InputStatus->Temp[4]) ); // Ticker Setting _DigitalPadPhase0SetTicker.attach_us( this, &Out_PCE::Digital_TickerMethod, DIGITALPAD_STATERENEWINTERVAL__MICROSEC ); EnableInput(); SetOutputPinsValue(0x00); wait_us(5000); // PCエンジンに気づかせる break; // // Input: CyberStick ANALOG mode // default: case NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG: // Interrupt Setting _INTR_ST.fall(this, &Out_PCE::StrobeFallISR); // Initialize pin status //SetOutputPinsValue(0x0f); // AfterBurner Boot時にRUN押されちゃう SetOutputPinsValue(0x02); // break; } } // // Set Pins // void Out_PCE::SetOutputPinsValue(char dat) { _OUT_1Y = dat & 1; _OUT_2Y = (dat & 2) >> 1; _OUT_3Y = (dat & 4) >> 2; _OUT_4Y = (dat & 8) >> 3; } // // Set Pins2 // void Out_PCE::SetOutputPinsValue2(char dat) { // D0 _OUT_1Y = dat & 1; // D0 // D1 _OUT_2Y = (dat & 8) >> 3; // D3 // D2 _OUT_3Y = (dat & 2) >> 1; // D1 // D3 _OUT_4Y = (dat & 4) >> 2; // D2 } // // ISR for Strobe=L // void Out_PCE::StrobeFallISR(void) { //_PCEActiveCounter++; if( _NowWriting == 0) { _INTR_ST.fall(NULL); // Disableしないと、入力にまれにノイズがのる // Disable/Enable有る場合も無い場合も、しばらくすると入力が受け付けられなくなる // EnableInput()時にInitialize()を実行させるように修正 //wait_us(_TransferSpeed>>1); //AfterBurnerはこれで良かった.OutRun動かないかも? //wait_us(10); //Outrun対策 _NowWriting = 1; // データフェーズごとのデータ用意 int buttons = _InputStatus->Buttons; char ch0 = _InputStatus->Ch0; char ch1 = _InputStatus->Ch1; char ch2 = _InputStatus->Ch2; char ch3 = _InputStatus->Ch3; // DisableInput(); // |A|B|C|D _PhaseData[0] = ( (((buttons) & 0x0200)?1:0)<<3 | // A (((buttons) & 0x0100)?1:0)<<2 | // B (((buttons) & 0x0020)?1:0)<<1 | // C (((buttons) & 0x0010)?1:0) // D ); // |E1|E2|F|G _PhaseData[1] = ( (((buttons) & 0x0008)?1:0)<<3 | // E1 (((buttons) & 0x0004)?1:0)<<2 | // E2 (((buttons) & 0x0002)?1:0)<<1 | // F (((buttons) & 0x0001)?1:0) // G ); // 1H _PhaseData[2] = ( ((ch0)>>4) & 0x0f ); // 2H _PhaseData[3] = ( ((ch1)>>4) & 0x0f ); // 3H _PhaseData[4] = ( ((ch2)>>4) & 0x0f ); // 4H _PhaseData[5] = ( 0x010 ); // 1L _PhaseData[6] = ( ch0 ); // 2L _PhaseData[7] = ( ch1 ); // 3L _PhaseData[8] = ( ch2 ); // 4L _PhaseData[9] = ( 0 ); _PhaseData[10] = // |A|B|A'|B'| ( (((buttons) & 0x0200)?1:0)<<3 | // A (((buttons) & 0x0100)?1:0)<<2 | // B (((buttons) & 0x0080)?1:0)<<1 | // A' (((buttons) & 0x0040)?1:0) // B' ); _PhaseData[11] = (0x0f); // DisableInput(); _PhaseChangeTicker.attach_us(this, &Out_PCE::ChangePhase, _TransferSpeed>>1); } } // // Tickerにより呼ばれる処理 // PhaseCounterを変化 // void Out_PCE::ChangePhase(void) { int loopCounter=0; char state=1; // 一瞬だけ2Yを下げて SetOutputPinsValue( _PhaseCounter&1 ); wait_us(2); //PCEがアナログモードになるwait_us値:10, 5, 3, 2 // すぐデータ変更 SetOutputPinsValue2( _PhaseData[_PhaseCounter] ); // DSELがHになるまで待つ loopCounter=100; while(!(_INTR_DSEL)) { loopCounter--; if(loopCounter<0) { state=0; break; } } if(state) { // DSELがLになるまで待つ loopCounter=100; while(_INTR_DSEL) { loopCounter--; if(loopCounter<0) { state=0; break; } } } if(state) { // その後、Ack出力に戻す SetOutputPinsValue( _PhaseCounter&1 | 0x02); _PhaseCounter++; //if(_PhaseCounter==12) if(_PhaseCounter>=11) { _PhaseCounter = 0; _PhaseChangeTicker.detach(); SetOutputPinsValue(0x02); _NowWriting = 0; // EnableInput(); _INTR_ST.fall(this, &Out_PCE::StrobeFallISR); } } else { _PhaseCounter = 0; _PhaseChangeTicker.detach(); SetOutputPinsValue(0x02); _NowWriting = 0; // EnableInput(); _INTR_ST.fall(this, &Out_PCE::StrobeFallISR); } } // // Ticker method for digital pad output // // 1. 全phase用のデータを集め、クラス変数に保存 // 2. Phase0データを出力する void Out_PCE::Digital_TickerMethod(void) { // デバッグ用:この関数が呼ばれるたび+1される (_InputStatus->Temp[2])++; //printf("I\r\n"); // これがあるとhungup起きない?(1) // _InputStatus->Temp[0] = 1; // wait_us(14000); volatile int idx; // データフェーズごとのデータ用意 __disable_irq(); volatile int buttons = _InputStatus->Buttons; volatile char type = _InputStatus->InputDeviceType; __enable_irq(); volatile int val_1a=0x0f; volatile int val_1b=0x0f; volatile int trgState_I = 1; volatile int trgState_II = 1; if( type == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL) { // 入力デバイス=サイバースティック/カブトガニ デジタルモード // 4Y 3Y 2Y 1Y // L D R U val_1a = ( ((buttons & 0x0800) ? 0x08 : 0) | // L ((buttons & 0x1000) ? 0x04 : 0) | // D ((buttons & 0x0400) ? 0x02 : 0) | // R ((buttons & 0x2000) ? 0x01 : 0) // U ); // 4Y 3Y 2Y 1Y // |Run|Sel|II|I val_1b = ( ((buttons & 0x0002) ? 0x08 : 0)&((buttons & 0x0010) ? 0x08 : 0) | // F(Start) & D ((buttons & 0x0001) ? 0x04 : 0)&((buttons & 0x0020) ? 0x04 : 0) | // G(Sel,Mode) & C ((buttons & 0x0100) ? 0x02 : 0) | // B ((buttons & 0x0200) ? 0x01 : 0) // A ); } else if (type == NiseKabuto::CONFIG_INMODE_MD6B) { // 入力デバイス=6B if( !(buttons & 0x020000) ) //Y { trgState_II = ((_RapidFireValue) ? 0x02 : 0); } else { trgState_II = ((buttons & 0x0100) ? 0x02 : 0); // B } if( !(buttons & 0x010000) ) //Z { trgState_I = ((_RapidFireValue) ? 0x01 : 0); } else { trgState_I = ((buttons & 0x0020) ? 0x01 : 0); // C } // 4Y 3Y 2Y 1Y // L D R U val_1a = ( ((buttons & 0x0800) ? 0x08 : 0) | // L ((buttons & 0x1000) ? 0x04 : 0) | // D ((buttons & 0x0400) ? 0x02 : 0) | // R ((buttons & 0x2000) ? 0x01 : 0) // U ); // 4Y 3Y 2Y 1Y // |Run|Sel|II|I val_1b = ( ((buttons & 0x0002) ? 0x08 : 0) | // F(Start) ((buttons & 0x0001) ? 0x04 : 0) | // G(Sel,Mode) trgState_II | trgState_I ); } __disable_irq(); for(idx=0; idx<12; idx+=2) { //printf("idx:%d\r\n",idx); _PhaseData[idx ] = val_1a; _PhaseData[idx+1] = val_1b; } __enable_irq(); // //phase0データをset // Digital_SetDataOfPhase(0); //printf("O\r\n"); // これがあるとhungup起きない?(2) // _InputStatus->Temp[0] = 0; // wait_us(14000); } void Out_PCE::Digital_SetDataOfPhase(char phaseCounter) { if( phaseCounter < 10 ) { SetOutputPinsValue(_PhaseData[phaseCounter]); } else { SetOutputPinsValue(0x0f); } } void Out_PCE::ModeChecker(void) { // デバッグ用:この関数が呼ばれるたび+1される (_InputStatus->Temp[5])++; __disable_irq(); char curOutMode = _InputStatus->InputDeviceType; __enable_irq(); // Analog/Digital切り替え判定 if(_OutputMode != curOutMode) { _OutputMode = curOutMode; // printf("InputDeviceType changed. Calling Initialize().\r\n"); Initialize(); } } void Out_PCE::SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void)) { StartInputFunction = startInputFunction; StopInputFunction = stopInputFunction; } void Out_PCE::EnableInput(void) { //printf("Out_PCE::EnableInput() called!!"); if(_InputInstance && StartInputMethod) { (_InputInstance->*StartInputMethod)(); } else if(StartInputFunction) { StartInputFunction(); } } void Out_PCE::DisableInput(void) { //printf("Out_PCE::DisableInput() called!!"); if(_InputInstance && StopInputMethod) { (_InputInstance->*StopInputMethod)(); } else if(StopInputFunction) { StopInputFunction(); } }