First Release
Diff: Out_PCE/Out_PCE.cpp
- Revision:
- 0:e1265f6b3565
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Out_PCE/Out_PCE.cpp Sat Jul 27 14:05:47 2013 +0000 @@ -0,0 +1,500 @@ +#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(); + } +} + + +