First Release

Dependencies:   USBDevice

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();
+    }
+}
+
+
+