First Release

Dependencies:   USBDevice

Revision:
0:e1265f6b3565
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_SSMulCon/Out_SSMulCon.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,577 @@
+#include "NiseKabuto.h"
+
+DigitalOut led1(LED1); 
+
+//
+// Constructor
+//
+Out_SSMulCon::Out_SSMulCon(
+    PinName pn_D0, PinName pn_D1, PinName pn_D2, PinName pn_D3, 
+    PinName pn_TL, PinName pn_TR, PinName pn_TH, 
+    InputStatus *inputStatus)
+    : _OUT_D0(pn_D0), _OUT_D1(pn_D1), _OUT_D2(pn_D2), _OUT_D3(pn_D3), 
+      _INTR_TL(pn_TL), _INTR_TR(pn_TR), _OUT_TH(pn_TH)
+{
+    _InputStatus = inputStatus;
+    Initialize();
+}
+
+//
+// Initialize
+//
+void Out_SSMulCon::Initialize()
+{
+    
+    // Pin Setting
+    _INTR_TL.mode(PullUp);
+    _INTR_TR.mode(PullUp);
+
+    // Class Variable Setting
+    RenewOutputMode();//_OutputMode = 0;
+    _PhaseCounter = 0;
+    _NowWriting = 0;
+    _RapidFireValue = 1;
+    
+    // Interrupt Setting
+    _INTR_TL.fall(this, &Out_SSMulCon::StrobeFallISR);
+    _INTR_TL.rise(this, &Out_SSMulCon::StrobeRiseISR);
+    _INTR_TR.fall(this, &Out_SSMulCon::ClockFallISR);
+    _INTR_TR.rise(this, &Out_SSMulCon::ClockRiseISR);
+    
+    // Initialize pin status
+    InitializePinStatus();
+
+}
+
+//
+// Initialize pin status
+//
+void Out_SSMulCon::InitializePinStatus()
+{
+    SetD3D2D1D0(0,0,0,1);
+
+    _OUT_TH = 1;
+    
+}
+
+//
+// ISR for S0/Strobe=L
+//
+void Out_SSMulCon::StrobeFallISR(void)
+{
+    if( _NowWriting != 1 )
+    {
+        /*
+        // デジタル出力・アナログ出力を_IN_CONFIGによって決める
+        _OutputMode = _IN_CONFIG;
+        led1 = _OutputMode;
+        */
+        
+        // データフェーズカウンタ初期化
+        _PhaseCounter = 0;
+
+        // ピン状態の設定(phase0向けデータ)
+        //SetPinStatus();
+        InitializePinStatus();
+        SetPinStatus();
+        
+        // データ出力中
+        _NowWriting = 1;
+        
+        DisableInput();
+    }
+
+    RenewOutputMode();
+}
+
+//
+// ISR for S0/Strobe=H
+//
+void Out_SSMulCon::StrobeRiseISR(void)
+{
+    led1 = 0;
+    
+    // データフェーズカウンタ初期化
+    _PhaseCounter = 0;
+    
+    // データ出力終了
+    _NowWriting = 0;
+    
+    // ピン状態戻す
+    InitializePinStatus();
+
+    EnableInput();
+
+    RenewOutputMode();
+    
+    _RapidFireValue=!_RapidFireValue;
+}
+
+//
+// ISR for S1/Clock=L
+//
+void Out_SSMulCon::ClockFallISR(void)
+{
+    // データ出力中の場合のみ処理する
+    if(_NowWriting==1)
+    {
+        // アナログ出力モード
+        if( _OutputMode==OUTPUTMODE_ANALOG )
+        {
+            switch(_PhaseCounter)
+            {
+                case 0:
+                case 2:
+                case 4:
+                case 6:
+                case 8:
+                case 10:
+                case 12:
+                case 14:
+                    _PhaseCounter++;
+                    break;
+            }
+        }
+        // デジタル出力モード
+        else
+        {
+            switch(_PhaseCounter)
+            {
+                case 0:
+                case 2:
+                case 4:
+                case 6:
+                    _PhaseCounter++;
+                    break;
+            }
+        }
+        SetPinStatus();
+        _OUT_TH = 0;
+    }
+}
+
+//
+// ISR for S1/Clock=H
+//
+void Out_SSMulCon::ClockRiseISR(void)
+{
+    // データ出力中の場合のみ処理する
+    if(_NowWriting==1)
+    {
+        // アナログ出力モード
+        if( _OutputMode==OUTPUTMODE_ANALOG )
+        {
+            switch(_PhaseCounter)
+            {
+                case 1:
+                case 3:
+                case 5:
+                case 7:
+                case 9:
+                case 11:
+                case 13:
+                    _PhaseCounter++;
+                    break;
+                case 15:
+                    _PhaseCounter=0;
+                    break;
+            }
+        }
+        // デジタル出力モード
+        else
+        {
+            switch(_PhaseCounter)
+            {
+                case 1:
+                case 3:
+                case 5:
+                    _PhaseCounter++;
+                    break;
+                case 7:
+                    _PhaseCounter=0;
+                    break;
+            }
+        }
+
+        SetPinStatus();
+        _OUT_TH = 1;
+    }
+}
+
+
+//
+// Set Pin D3,D2,D1,D0 Status
+//
+void Out_SSMulCon::SetD3D2D1D0(char d3, char d2, char d1, char d0)
+{
+    _OUT_D0  = d0;
+    _OUT_D1  = d1;
+    _OUT_D2  = d2;
+    _OUT_D3  = d3;
+}
+
+//
+// Set Pin D3,D2,D1,D0 Status (bus)
+//
+void Out_SSMulCon::SetBus(char data)
+{
+    _OUT_D0  = data      & 0x01;
+    _OUT_D1  = (data>>1) & 0x01;
+    _OUT_D2  = (data>>2) & 0x01;
+    _OUT_D3  = (data>>3) & 0x01;
+}
+
+
+
+//
+// Set Pin Status
+//
+void Out_SSMulCon::SetPinStatus(void)
+{
+    // データ出力中の場合のみ処理する
+    if(_NowWriting==1)
+    {
+        // Get InputStatus
+        InputStatus *inp = _InputStatus;
+        char chDat = 0;
+        
+        int buttons = _InputStatus->Buttons;
+        char ch0 = _InputStatus->Ch0;
+        char ch1 = _InputStatus->Ch1;
+        char ch2 = _InputStatus->Ch2;
+        char ch3 = _InputStatus->Ch3;
+        
+        char trigR;
+        char trigL;
+        
+        // サイバースティック アナログ出力モード
+        if( _OutputMode==OUTPUTMODE_ANALOG )
+        {
+            switch(_PhaseCounter)
+            {
+                case 0:
+                case 1:
+                    SetD3D2D1D0(0,0,0,1);
+                    break;
+
+                case 2:
+                    SetD3D2D1D0(0,1,1,0);
+                    break;
+
+                case 3:
+                    if(!(buttons & 0x01))   // G(SELECT)ボタンが押されてたら、アナログスティックで十字キー操作
+                    {
+                        SetD3D2D1D0
+                        (
+                            ch1>0xf0? 0:1,
+                            ch1<0x0f? 0:1,
+                            ch0>0xf0? 0:1,
+                            ch0<0x0f? 0:1
+                        );
+                    }
+                    else
+                    {
+                        SetD3D2D1D0(1,1,1,1);
+                    }
+                    break;
+
+                case 4:
+                    SetD3D2D1D0(
+                        ((inp->Buttons) & 0x0002)?1:0,  // Start
+                        ((inp->Buttons) & 0x0200)?1:0,  // A
+                        ((inp->Buttons) & 0x0020)?1:0,  // C
+                        ((inp->Buttons) & 0x0100)?1:0   // B
+                    );
+                    break;
+
+                case 5:
+                    trigR = 1;
+                    if(!(buttons & 0x01))   // G(SELECT)ボタンが押されてたら、スロットルでRキー操作
+                    {
+                        trigR = ch2<0x0f? 0:1;  //スロットル引く
+                    }
+
+                    SetD3D2D1D0(
+                        trigR,                          // R-Trigger
+                        ((inp->Buttons) & 0x0010)?1:0,  // D is X
+                        ((inp->Buttons) & 0x0008)?1:0,  // E1 is Y
+                        ((inp->Buttons) & 0x0004)?1:0   // E2 is Z
+                    );
+                    break;
+
+                case 6:
+                    trigL = 1;
+                    if(!(buttons & 0x01))   // G(SELECT)ボタンが押されてたら、スロットルでLキー操作
+                    {
+                        trigL = ch2>0xf0? 0:1;  //スロットル押す
+                    }
+
+                    SetD3D2D1D0(
+                        trigL,  // L-Trigger
+                        1,  // (H)
+                        1,  // (H)
+                        1   // (H)
+                    );
+                    break;
+
+                case 7:
+                    chDat = inp->Ch1;       // Upper4bits of axis-X
+                    SetBus(chDat>>4);
+                    break;
+
+                case 8:
+                    chDat = inp->Ch1;       // Lower4bits of axis-X
+                    SetBus(chDat);
+                    break;
+
+                case 9:
+                    chDat = inp->Ch0;       // Upper4bits of axis-Y
+                    SetBus(chDat>>4);
+                    break;
+
+                case 10:
+                    chDat = inp->Ch0;       // Lower4bits of axis-Y
+                    SetBus(chDat);
+                    break;
+
+                case 11:
+                    chDat = inp->Ch2;       // Upper4bits of throttle
+                    SetBus(chDat>>4);
+                    break;
+                                    
+                case 12:
+                    chDat = inp->Ch2;       // Lower4bits of throttle
+                    SetBus(chDat);
+                    break;
+
+                case 13:
+                    SetD3D2D1D0(0,0,0,0);   // L Trigger Upper 4bits
+                    break;
+
+                case 14:
+                    SetD3D2D1D0(0,0,0,0);   // L Trigger Lower 4bits
+                    break;
+
+                case 15:
+                    SetD3D2D1D0(0,0,0,0);   // final phase
+                    break;
+
+            }
+        }
+        // サイバースティック デジタル出力モード
+        else if( _OutputMode==OUTPUTMODE_DIGITAL )
+        {
+            switch(_PhaseCounter)
+            {
+                case 0:
+                    SetD3D2D1D0(0,0,0,1);
+                    break;
+                    
+                case 1:
+                    SetD3D2D1D0(0,0,0,0);
+                    break;
+
+                case 2:
+                    SetD3D2D1D0(0,0,1,0);
+                    break;
+
+                case 3:
+                    SetD3D2D1D0(
+                        ((inp->Buttons) & 0x0400)? 1 : 0,   // Right
+                        ((inp->Buttons) & 0x0800)? 1 : 0,   // Left
+                        ((inp->Buttons) & 0x1000)? 1 : 0,   // Down
+                        ((inp->Buttons) & 0x2000)? 1 : 0    // Up
+                    );
+
+                    break;
+
+                case 4:
+                    // サイバースティックはStartボタンが無い縺ョで、Dで代用
+                    SetD3D2D1D0(
+                        (((inp->Buttons) & 0x0002)?1:0) & (((inp->Buttons) & 0x0010)?1:0),  // Start & D
+                        ((inp->Buttons) & 0x0200)?1:0,  // A
+                        ((inp->Buttons) & 0x0020)?1:0,  // C
+                        ((inp->Buttons) & 0x0100)?1:0   // B
+                    );
+                    break;
+
+                case 5:
+                    SetD3D2D1D0(
+                        ((inp->Buttons) & 0x8000)?1:0,  // R-Trigger(=ThrotUp)
+                        ((inp->Buttons) & 0x0010)?1:0,  // X
+                        ((inp->Buttons) & 0x0008)?1:0,  // Y
+                        ((inp->Buttons) & 0x0004)?1:0   // Z
+                    );
+                    break;
+
+                case 6:
+                    SetD3D2D1D0(
+                        ((inp->Buttons) & 0x4000)?1:0,  // L-Trigger
+                        1,  // (H)
+                        1,  // (H)
+                        1   // (H)
+                    );
+                    break;
+
+                case 7:
+                    SetD3D2D1D0(0,0,0,0);
+                    break;
+            }
+        }
+        // 6B
+        else if( _OutputMode==OUTPUTMODE_6B )
+        {
+            switch(_PhaseCounter)
+            {
+                case 0:
+                    SetD3D2D1D0(0,0,0,1);
+                    break;
+                    
+                case 1:
+                    SetD3D2D1D0(0,0,0,0);
+                    break;
+
+                case 2:
+                    SetD3D2D1D0(0,0,1,0);
+                    break;
+
+                case 3:
+                    SetD3D2D1D0(
+                        ((inp->Buttons) & 0x0400)? 1 : 0,   // Right
+                        ((inp->Buttons) & 0x0800)? 1 : 0,   // Left
+                        ((inp->Buttons) & 0x1000)? 1 : 0,   // Down
+                        ((inp->Buttons) & 0x2000)? 1 : 0    // Up
+                    );
+
+                    break;
+
+                case 4:
+                    // modeキーが押されてたら、_RapidFireValue値を有効に
+                    if( !((inp->Buttons) & 0x0001) )
+                    {
+                        SetD3D2D1D0(
+                            ((inp->Buttons) & 0x0002)?1:0,  // Start
+                            ((inp->Buttons) & 0x0200)?1:_RapidFireValue,    // A
+                            ((inp->Buttons) & 0x0020)?1:_RapidFireValue,    // C
+                            ((inp->Buttons) & 0x0100)?1:_RapidFireValue     // B
+                        );
+                    }
+                    else
+                    {
+                        SetD3D2D1D0(
+                            ((inp->Buttons) & 0x0002)?1:0,  // Start
+                            ((inp->Buttons) & 0x0200)?1:0,  // A
+                            ((inp->Buttons) & 0x0020)?1:0,  // C
+                            ((inp->Buttons) & 0x0100)?1:0   // B
+                        );
+                    }
+                    break;
+
+                case 5:
+                    // modeキーが押されてたら、_RapidFireValue値を有効に
+                    if( !((inp->Buttons) & 0x0001) )
+                    {
+                        // Rトリガはmode+右
+                        SetD3D2D1D0(
+                            ((inp->Buttons) & 0x0401)?1:0,  // R-Trigger
+                            ((inp->Buttons) & 0x0010)?1:_RapidFireValue,    // X
+                            ((inp->Buttons) & 0x0008)?1:_RapidFireValue,    // Y
+                            ((inp->Buttons) & 0x0004)?1:_RapidFireValue // Z
+                        );
+                    }
+                    else
+                    {
+                        // Rトリガはmode+右  <-おかしい?
+                        SetD3D2D1D0(
+                            ((inp->Buttons) & 0x0401)?1:0,  // R-Trigger
+                            ((inp->Buttons) & 0x0010)?1:0,  // X
+                            ((inp->Buttons) & 0x0008)?1:0,  // Y
+                            ((inp->Buttons) & 0x0004)?1:0   // Z
+                        );
+                    }
+                    break;
+
+                case 6:
+                    // Lトリガはmode+左
+                    SetD3D2D1D0(
+                        ((inp->Buttons) & 0x0801)?1:0,  // L-Trigger
+                        1,  // (H)
+                        1,  // (H)
+                        1   // (H)
+                    );
+                    break;
+
+                case 7:
+                    SetD3D2D1D0(0,0,0,0);
+                    break;
+            }
+        }
+
+    }
+}
+
+
+//
+// Set output mode
+//
+void Out_SSMulCon::RenewOutputMode(void)
+{
+    switch(_InputStatus->InputDeviceType)
+    {
+        //
+        // Input: CyberStick ANALOG mode
+        //
+        case NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG:
+            _OutputMode = OUTPUTMODE_ANALOG;
+            break;
+            
+        //
+        // Input: CyberStick DIGITAL mode
+        //        6B
+        //
+        case NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL:
+            _OutputMode = OUTPUTMODE_DIGITAL;
+            break;
+            
+        case NiseKabuto::CONFIG_INMODE_MD6B:
+            _OutputMode = OUTPUTMODE_6B;
+            break;
+
+        default:
+            _OutputMode = OUTPUTMODE_ANALOG;
+            break;
+    }
+}
+
+
+void Out_SSMulCon::SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void))
+{
+    StartInputFunction = startInputFunction;
+    StopInputFunction  = stopInputFunction;
+}
+
+void Out_SSMulCon::EnableInput(void)
+{
+    if(_InputInstance && StartInputMethod)
+    {
+        (_InputInstance->*StartInputMethod)();
+    }
+    else if(StartInputFunction)
+    {
+        StartInputFunction();
+    }
+}
+
+void Out_SSMulCon::DisableInput(void)
+{
+    if(_InputInstance && StopInputMethod)
+    {
+        (_InputInstance->*StopInputMethod)();
+    }
+    else if(StopInputFunction)
+    {
+        StopInputFunction();
+    }
+}
+
+