First Release

Dependencies:   USBDevice

Files at this revision

API Documentation at this revision

Comitter:
sankichi
Date:
Sat Jul 27 14:05:47 2013 +0000
Child:
1:6c392ebcd4d4
Commit message:
First Release

Changed in this revision

In_CyberStick/In_CyberStick.cpp Show annotated file Show diff for this revision Revisions of this file
In_CyberStick/In_CyberStick.h Show annotated file Show diff for this revision Revisions of this file
In_MD6B/In_MD6B.cpp Show annotated file Show diff for this revision Revisions of this file
In_MD6B/In_MD6B.h Show annotated file Show diff for this revision Revisions of this file
InputDeviceDetector.h Show annotated file Show diff for this revision Revisions of this file
InputStatus.h Show annotated file Show diff for this revision Revisions of this file
NiseKabuto.cpp Show annotated file Show diff for this revision Revisions of this file
NiseKabuto.h Show annotated file Show diff for this revision Revisions of this file
Out_FC/C_Out_FC.cpp Show annotated file Show diff for this revision Revisions of this file
Out_FC/C_Out_FC.h Show annotated file Show diff for this revision Revisions of this file
Out_FC/Out_FC.cpp Show annotated file Show diff for this revision Revisions of this file
Out_FC/Out_FC.h Show annotated file Show diff for this revision Revisions of this file
Out_MD/CFunc_Out_MD.cpp Show annotated file Show diff for this revision Revisions of this file
Out_MD/CFunc_Out_MD.h Show annotated file Show diff for this revision Revisions of this file
Out_MD/Out_MD.cpp Show annotated file Show diff for this revision Revisions of this file
Out_MD/Out_MD.h Show annotated file Show diff for this revision Revisions of this file
Out_PCE/Cfunc_PCEDigital.cpp Show annotated file Show diff for this revision Revisions of this file
Out_PCE/Cfunc_PCEDigital.h Show annotated file Show diff for this revision Revisions of this file
Out_PCE/Out_PCE.cpp Show annotated file Show diff for this revision Revisions of this file
Out_PCE/Out_PCE.h Show annotated file Show diff for this revision Revisions of this file
Out_PS3USB/Out_PS3USB.cpp Show annotated file Show diff for this revision Revisions of this file
Out_PS3USB/Out_PS3USB.h Show annotated file Show diff for this revision Revisions of this file
Out_PS3USB/USBHID/USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
Out_PS3USB/USBHID/USBJoystick.cpp Show annotated file Show diff for this revision Revisions of this file
Out_PS3USB/USBHID/USBJoystick.h Show annotated file Show diff for this revision Revisions of this file
Out_SSMulCon/Out_SSMulCon.cpp Show annotated file Show diff for this revision Revisions of this file
Out_SSMulCon/Out_SSMulCon.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/In_CyberStick/In_CyberStick.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,422 @@
+#include "In_CyberStick.h"
+#include "NiseKabuto.h"
+
+DigitalOut led11(LED1); 
+DigitalOut led22(LED2); 
+DigitalOut dbgPin(p8); 
+
+//
+// Constructor
+//
+In_CyberStick::In_CyberStick(
+    PinName pn_D0, PinName pn_D1, PinName pn_D2, PinName pn_D3, 
+    PinName pn_LH, PinName pn_ACK, PinName pn_REQ,
+    InputStatus *inputStatus
+)  : _IN_D0(pn_D0), _IN_D1(pn_D1), _IN_D2(pn_D2), _IN_D3(pn_D3), _IN_LH(pn_LH), _IN_ACK(pn_ACK), _OUT_REQ(pn_REQ)
+{
+    _InputStatus = inputStatus;
+    _InputStatus->Reset();  // ボタンなどリセット
+    _InputStatus->InputDeviceType = NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG;    //とりあえずアナログにしておく
+
+    _AnalogReadFailCounter = 0;
+
+    Initialize();
+}
+
+
+void In_CyberStick::StartReading(void)
+{
+    //printf("In_CyberStick::StartReading()\r\n");
+    if(!_ReadEnable)
+    {
+        _ReadEnable = 1;
+        Initialize();
+    }
+}
+void In_CyberStick::StopReading(void)
+{
+    //printf("In_CyberStick::StopReading()\r\n");
+    if(_ReadEnable)
+    {
+        _ReadEnable = 0;
+        DisablePolling();
+    }
+}
+
+
+
+//
+// Initialize
+//
+void In_CyberStick::Initialize()
+{
+    // Pin Setting
+    _IN_D0.mode(PullUp);
+    _IN_D1.mode(PullUp);
+    _IN_D2.mode(PullUp);
+    _IN_D3.mode(PullUp);
+    _IN_LH.mode(PullUp);
+    _IN_ACK.mode(PullUp);
+
+    // Class Variable Setting
+    _ReadEnable = 1;
+
+    // Interrupt Setting
+    // Initialize pin status
+    _OUT_REQ = 1;   // output REQ = H
+
+    // Ticker Setting
+    EnablePolling();
+}
+
+
+
+//
+// Enable polling
+//
+void In_CyberStick::EnablePolling(void)
+{
+    _PollingTicker.attach_us(this, &In_CyberStick::PollingMethod, REQUESTINTERVAL__MICROSEC);
+
+    // FCAB 入力乱れ対策
+    _ReadEnable = 1;
+    _OUT_REQ = 1;  
+}
+
+
+//
+// Polling method
+//
+void In_CyberStick::PollingMethod()
+{
+    // デバッグ用:この関数が呼ばれるたび+1される
+    (_InputStatus->Temp[0])++;
+
+    if(_ReadEnable)
+    {
+
+        // 割り込み停止しない
+        //__disable_irq();  
+        
+        int waitLoop = 8000; //8000;//11300;//22600;
+        char state = 1;
+        char phase = 0;
+        char cycle = 0;
+        
+        // Req下げ
+        _OUT_REQ = 0;
+        //wait_us(2);
+        //_OUT_REQ = 1;
+
+        cycle = 0;
+        while( cycle<6 )
+        {
+            // LH=1の間待つ
+            if(state)
+            {
+                while( _IN_LH )
+                {
+                    waitLoop--;
+                    if(!waitLoop)
+                    {
+                        // TimeOut !
+                        state = 0;
+                        break;
+                    }
+                }
+            }
+            
+            // ACK=1の間待つ
+            if(state)
+            {
+                while( _IN_ACK )
+                {
+                    waitLoop--;
+                    if(!waitLoop)
+                    {
+                        // TimeOut !
+                        state = 0;
+                        break;
+                    }
+                }
+                
+            }
+            
+            if(state)
+            {
+                // データ読み出し
+                ReadPhase(phase++);
+            }
+            
+            // LH=0の間待つ
+            if(state)
+            {
+                while( !(_IN_LH) )
+                {
+                    waitLoop--;
+                    if(!waitLoop)
+                    {
+                        // TimeOut !
+                        state = 0;
+                        break;
+                    }
+                }
+            }
+            
+            // ACK=1の間待つ
+            if(state)
+            {
+                // REQ立ち上げ
+                // (最速モードのため、2回目のAck立下りまでに行う。このあたり?)
+                _OUT_REQ = 1;
+
+                while( _IN_ACK )
+                {
+                    waitLoop--;
+                    if(!waitLoop)
+                    {
+                        // TimeOut !
+                        state = 0;
+                        break;
+                    }
+                }
+            }
+
+            if(state)
+            {
+                // データ読み出し
+                ReadPhase(phase++);
+            }
+        
+            if(!state)
+            {
+                break;
+            }
+            cycle++;
+        }
+
+        // 割り込み禁止しない
+        //__enable_irq();
+        
+        if(state)
+        {
+            // ここまでstate==1のままで終わったら、完全にアナログスティックといえる
+            _InputStatus->InputDeviceType = NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG;
+            led11 = 1;
+
+            // Analog読み失敗カウンタリセット
+            _AnalogReadFailCounter = 0;
+
+            //データ確定
+            CommitAnalogData();
+        }
+        else
+        {
+        //  printf("_AnalogReadFailCounter: %d\r\n",_AnalogReadFailCounter);
+            // 数回のAnalog読み失敗を許容
+            //
+            // 出力処理側のISRなどに割り込まれ、失敗するケースもある
+            //
+            //
+            _AnalogReadFailCounter++;
+            
+            // この値を大きくすると、一時的なデジタルスティック化は避けられるが
+            // DIGITAL/ANALOG切り替えスイッチへの追従が遅れる
+            if(_AnalogReadFailCounter > 10)
+            {
+                // この時点でstate==0なら、未接続/デジタルモード
+                _InputStatus->InputDeviceType = NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL;
+                led11 = 0;
+                DigitalModeReader();
+                
+                if(_AnalogReadFailCounter>1000)
+                {
+                    _AnalogReadFailCounter = 10;
+                }
+            }
+        }
+    }
+}
+
+
+//
+// Disable polling
+//
+void In_CyberStick::DisablePolling(void)
+{
+    _PollingTicker.detach();
+    
+    //Enable/DisableInput()を頻繁に呼ぶと、デジアナモード判定が乱れる問題対策
+    if( _ReadEnable )
+    {
+    }
+}
+
+
+
+//
+// デジタルモードでの読み取り処理
+//
+void In_CyberStick::DigitalModeReader(void)
+{
+    int btnData = _InputStatus->Buttons;
+    
+    // PC4=“0”
+    _OUT_REQ = 0;
+    wait_us(1);
+
+    btnData = 
+        (_IN_D0?   0x02000 : 0) |   // Up
+        (_IN_D1?   0x01000 : 0) |   // Down
+        (_IN_D2?   0x00800 : 0) |   // Left
+        (_IN_D3?   0x00400 : 0) |   // Right
+        (_IN_LH?   0x00200 : 0) |   // A
+        (_IN_ACK?  0x00100 : 0) |   // B
+        ((_IN_D2==0 && _IN_D3==0)? 0 : 0x02) |  // F(Start)
+        ((_IN_D0==0 && _IN_D1==0)? 0 : 0x01) ;  // G(Select)
+
+    /*
+    // デジタルモードのとき、サイバースティックは
+    // Start,Selectの情報は得られない。
+    // カブトガニのF(Start),G(Select)については、
+    // F=LR同時押し、G=UD同時押しとして認識される。
+    */
+    
+    // PC4=“1”
+    _OUT_REQ = 1;
+    wait_us(1);
+
+    btnData = btnData           |
+        (_IN_D0?   0x08000 : 0) |   // Throt Up
+        (_IN_D1?   0x04000 : 0) |   // Throt Down
+        (_IN_D2?   0x00020 : 0) |   // C
+        (_IN_D3?   0x00010 : 0) |   // D
+        (_IN_LH?   0x00008 : 0) |   // E1
+        (_IN_ACK?  0x00004 : 0) |   // E2
+        0xc0;                       //A'B'は常にOFF
+
+    _InputStatus->Buttons = btnData;
+}
+
+//
+//ReadPinValue (Pin status -> Class value)
+//
+int In_CyberStick::ReadPinValue()
+{
+    return ( _IN_D0 | (_IN_D1<<1) | (_IN_D2<<2) | (_IN_D3<<3) );
+}
+
+
+
+
+
+
+
+//
+// あるデータフェーズのデータを読み取り、格納
+//
+void In_CyberStick::ReadPhase(char phase)
+{
+    int readVal = ReadPinValue();
+    
+    switch(phase)
+    {
+        case 0:
+            // Ack No.1
+            _Buttons = 
+                (_Buttons & 0xfffffccf) |       // mask bit9,8,5,4
+                ((readVal & 0x0c)<<6) |         // AB(bit3 & 2)
+                ((readVal & 0x03)<<4) ;         // CD(bit1 & 0)
+            break;
+
+        case 1:
+            // Ack No.2
+            _Buttons = 
+                (_Buttons & 0xfffffff0) |       // mask bit3,2,1,0
+                (readVal & 0x0f)      ;         // E1E2FG(bit3 & 2 & 1 & 0)
+            break;
+
+        case 2:
+            // Ack No.3
+            _Ch0 = 
+                (_Ch0 & 0x0f) |                 // mask upper 4 bits
+                (readVal & 0x0f)<<4   ;         // 1H(bit3 & 2 & 1 & 0)
+            break;
+
+        case 3:
+            // Ack No.4
+            _Ch1 = 
+                (_Ch1 & 0x0f) |                 // mask upper 4 bits
+                (readVal & 0x0f)<<4   ;         // 2H(bit3 & 2 & 1 & 0)
+            break;
+
+        case 4:
+            // Ack No.5
+            _Ch2 = 
+                (_Ch2 & 0x0f) |                 // mask upper 4 bits
+                (readVal & 0x0f)<<4   ;         // 3H(bit3 & 2 & 1 & 0)
+            break;
+
+        case 5:
+            // Ack No.6
+            _Ch3 = 
+                (_Ch3 & 0x0f) |                 // mask upper 4 bits
+                (readVal & 0x0f)<<4   ;         // 4H(bit3 & 2 & 1 & 0)
+            break;
+
+        case 6:
+            // Ack No.7
+            _Ch0 = 
+                (_Ch0 & 0xf0) |                 // mask lower 4 bits
+                (readVal & 0x0f)      ;         // 1L(bit3 & 2 & 1 & 0)
+            break;
+
+        case 7:
+            // Ack No.8
+            _Ch1 = 
+                (_Ch1 & 0xf0) |                 // mask lower 4 bits
+                (readVal & 0x0f)      ;         // 2L(bit3 & 2 & 1 & 0)
+            break;
+
+        case 8:
+            // Ack No.9
+            _Ch2 = 
+                (_Ch2 & 0xf0) |                 // mask lower 4 bits
+                (readVal & 0x0f)      ;         // 3L(bit3 & 2 & 1 & 0)
+            break;
+
+        case 9:
+            // Ack No.10
+            _Ch3 = 
+                (_Ch3 & 0xf0) |                 // mask lower 4 bits
+                (readVal & 0x0f)      ;         // 4L(bit3 & 2 & 1 & 0)
+            break;
+
+        case 10:
+            // Ack No.11
+            _Buttons = 
+                (_Buttons & 0xffffff3f) |       // mask bit7,6
+                ((readVal & 0x03)<<6) ;         // A+A', B+B'(bit1 & 0)
+            break;
+
+        default:
+            break;
+    }
+}
+
+
+//
+// Analogスティック情報を確定
+//
+void In_CyberStick::CommitAnalogData(void)
+{
+    //サイバースティックアナログモードで使わないボタンをビット強制ON
+    // ThrotUp |ThrotDw |   Up   |   Dw   ||   Lf   |   Rg
+    _Buttons = (_Buttons) | 0x0000fc00;
+
+    _InputStatus->Buttons = _Buttons;
+    _InputStatus->Ch0 = _Ch0;
+    _InputStatus->Ch1 = _Ch1;
+    _InputStatus->Ch2 = _Ch2;
+    _InputStatus->Ch3 = _Ch3;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/In_CyberStick/In_CyberStick.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,84 @@
+#pragma once
+
+/** Class: In_CyberStick
+ *
+ * Used for reading from CyberStick(CZ-8NJ2)
+ *
+ * Example:
+ *
+ * > #include "mbed.h"
+ *
+ * > In_CyberStick myCS(p20, p19,... inputStates);
+ */
+
+#include "mbed.h"
+#include "InputStatus.h"
+
+class In_CyberStick
+{
+public:
+    /** Constructor: In_CyberStick
+     *
+     * Parameters:
+     * pn_D0  - DigitalIn for CyberStick's D0 (D-Sub 9pin connector's pin1)
+     * pn_D1  - DigitalIn for D1 (D-Sub9 pin2)
+     * pn_D2  - DigitalIn for D2 (D-Sub9 pin3)
+     * pn_D3  - DigitalIn for D3 (D-Sub9 pin4)
+     * pn_LH  - DigitalIn for L/H (D-Sub9 pin6)
+     * pn_ACK - DigitalIn for Ack (D-Sub9 pin7)
+     * pn_REQ - DigitalOut for Req (D-Sub9 pin8)
+     * inputStatus - The variable to store input status
+     */
+    In_CyberStick(
+        PinName pn_D0, PinName pn_D1, PinName pn_D2, PinName pn_D3, 
+        PinName pn_LH, PinName pn_ACK, PinName pn_REQ,
+        InputStatus *inputStatus
+    );
+
+    void TestShow(void);
+    
+    void StartReading(void);
+    void StopReading(void);
+        
+private:
+    // Private constants
+    static const int REQUESTINTERVAL__MICROSEC      = 2500; // reading period microsec
+    static const int TRANSFERSPEED_MAX__MICROSEC    = 50;    // from AJOY_SUB.DOC
+    static const int TRANSFERSPEED_1_2__MICROSEC    = 96;
+    static const int TRANSFERSPEED_1_3__MICROSEC    = 144;
+    static const int TRANSFERSPEED_1_4__MICROSEC    = 192;
+
+    // mbed pins
+    DigitalIn   _IN_D0;
+    DigitalIn   _IN_D1;
+    DigitalIn   _IN_D2;
+    DigitalIn   _IN_D3;
+    DigitalIn   _IN_LH;
+    DigitalIn   _IN_ACK;
+    DigitalOut  _OUT_REQ;
+
+    // Variables
+    InputStatus     *_InputStatus;
+    volatile char   _ReadEnable;
+    Ticker          _PollingTicker;
+    Timer           _AckTimer;
+    volatile int    _Buttons;
+    volatile char   _Ch0;
+    volatile char   _Ch1;
+    volatile char   _Ch2;
+    volatile char   _Ch3;
+    volatile int    _AnalogReadFailCounter;
+
+    // Private Method
+    void Initialize(void);
+    void EnablePolling(void);
+    void DisablePolling(void);
+    void PollingMethod(void);
+    void ReadPhase(char phase);
+
+    void DigitalModeReader(void);
+
+    int  ReadPinValue(void);
+    void CommitAnalogData(void);
+
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/In_MD6B/In_MD6B.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,265 @@
+#include "In_MD6B.h"
+#include "NiseKabuto.h"
+
+//
+// Constructor
+//
+In_MD6B::In_MD6B(
+    PinName pn_D0, PinName pn_D1, PinName pn_D2, PinName pn_D3, 
+    PinName pn_D4, PinName pn_D5, PinName pn_SEL,
+    InputStatus *inputStatus
+)  : _IN_D0(pn_D0), _IN_D1(pn_D1), _IN_D2(pn_D2), _IN_D3(pn_D3), 
+     _IN_D4(pn_D4), _IN_D5(pn_D5), _OUT_SEL(pn_SEL)
+{
+    _InputStatus = inputStatus;
+    _InputStatus->Reset();  // ボタンなどリセット
+    _InputStatus->InputDeviceType = NiseKabuto::CONFIG_INMODE_MD6B;
+    
+    Initialize();
+}
+
+
+void In_MD6B::StartReading(void)
+{
+    //printf("In_MD6B::StartReading()!!!\r\n");
+    if(!_ReadEnable)
+    {
+        _ReadEnable = 1;
+        Initialize();
+    }
+}
+void In_MD6B::StopReading(void)
+{
+    //printf("In_MD6B::StopReading()!!!\r\n");
+    if(_ReadEnable)
+    {
+        _ReadEnable = 0;
+        DisablePolling();
+    }
+}
+
+
+
+//
+// Initialize
+//
+void In_MD6B::Initialize()
+{
+    // Pin Setting
+    _IN_D0.mode(PullUp);
+    _IN_D1.mode(PullUp);
+    _IN_D2.mode(PullUp);
+    _IN_D3.mode(PullUp);
+    _IN_D4.mode(PullUp);
+    _IN_D5.mode(PullUp);
+    
+    // Class Variable Setting
+    _ReadEnable = 1;
+    
+    // Interrupt Setting
+    /*
+    _INTR_LH.rise(this, &In_MD6B::LHCounter);
+    _INTR_ACK.fall(this, &In_MD6B::AckFallISR);
+    */
+    
+    // Initialize pin status
+    _OUT_SEL = 1;   // output SEL = H
+
+    // Ticker Setting
+    EnablePolling();
+}
+
+
+//
+// Enable polling
+//
+void In_MD6B::EnablePolling(void)
+{
+    _PollingTicker.attach_us(this, &In_MD6B::PollingMethod, READINGINTERVAL__MICROSEC);
+}
+
+//
+// Disable polling
+//
+void In_MD6B::DisablePolling(void)
+{
+//  printf("In_MD6B::DisablePolling() called!!\r\n");
+    _PollingTicker.detach();
+}
+
+
+//
+// Polling method
+//
+void In_MD6B::PollingMethod()
+{
+    // デバッグ用:この関数が呼ばれるたび+1される
+    (_InputStatus->Temp[0])++;
+    
+    if( _ReadEnable )
+    {
+        char flag6B = 0;
+        int idxPhaseStart = 0;
+        int idx = 0;
+
+        // Selを立ち下げ、データ読みを8回
+        idx = 0;
+        for(int i=0; i<4; i++)
+        {
+            _OUT_SEL = 0;
+            wait_us(SELSTATETIME__MICROSEC);
+            
+            _PhaseData[idx++] = ReadPinValue();
+            
+            _OUT_SEL = 1;
+            wait_us(SELSTATETIME__MICROSEC);
+
+            _PhaseData[idx++] = ReadPinValue();
+        }
+        
+        idx = 0;
+        while(1)
+        {
+            (_InputStatus->Temp[1])++;
+            
+            // D0-D3がLなものを探す
+            if( (_PhaseData[idx]&0x0f)==0 )
+            {
+                // idx+2をチェック
+                // ただし6を超えた場合はidx-6の位置をチェック
+                if(idx < 6)
+                {
+                    if( (_PhaseData[idx+2]&0x0f)==0x0f )
+                    {
+                        flag6B = 1;
+                        idxPhaseStart = idx; // 仮の値
+                        break;
+                    }
+                }
+                else
+                {
+                    if( (_PhaseData[idx-6]&0x0f)==0x0f )
+                    {
+                        flag6B = 1;
+                        idxPhaseStart = idx; // 仮の値
+                        break;
+                    }
+                }
+            }
+            
+            // このidxではなかった
+            idx++;
+            
+            // 全部チェックしてしまった
+            if( idx >= 8 )  // 2013/05/02
+            {
+                break;
+            }
+            
+        }
+        
+        // この時点でflag6B==0の場合、6Bではない
+        if( flag6B )
+        {
+            // ボタン情報が入る予定のビットをoff
+            __disable_irq();
+            int buttons = (_InputStatus->Buttons) & 0x0f8c0dc;
+            //                                             f    8    c    0    d    c
+            //                                          1111 1XYZ 11UD LRAB 11C1 11SM
+            __enable_irq();
+
+            // idxPhaseStart補正
+            if(idx >= 4)
+            {
+                idxPhaseStart = idxPhaseStart-4;
+            }
+            else
+            {
+                idxPhaseStart = idxPhaseStart+4;
+            }
+            
+            // InputStatus
+            char data;
+            
+            //      Phase 0
+            data = _PhaseData[idxPhaseStart++];
+            if( idxPhaseStart == 8)
+            {
+                idxPhaseStart = 0;
+            }
+            buttons = buttons |
+                ((data & 0x20) ? 0x000002 : 0) |    // ST
+                ((data & 0x10) ? 0x000200 : 0) |    // A
+                ((data & 0x02) ? 0x001000 : 0) |    // Dw
+                ((data & 0x01) ? 0x002000 : 0) ;    // Up
+            
+            
+            //      Phase 1
+            data = _PhaseData[idxPhaseStart++];
+            if( idxPhaseStart == 8)
+            {
+                idxPhaseStart = 0;
+            }
+            buttons = buttons |
+                ((data & 0x20) ? 0x000020 : 0) |    // C
+                ((data & 0x10) ? 0x000100 : 0) |    // B
+                ((data & 0x08) ? 0x000400 : 0) |    // Rg
+                ((data & 0x04) ? 0x000800 : 0) ;    // Lf
+            
+
+            //      Phase 2
+            //          無視
+            data = _PhaseData[idxPhaseStart++];
+            if( idxPhaseStart == 8)
+            {
+                idxPhaseStart = 0;
+            }
+            //      Phase 3
+            //          無視
+            data = _PhaseData[idxPhaseStart++];
+            if( idxPhaseStart == 8)
+            {
+                idxPhaseStart = 0;
+            }
+            //      Phase 4
+            //          無視
+            data = _PhaseData[idxPhaseStart++];
+            if( idxPhaseStart == 8)
+            {
+                idxPhaseStart = 0;
+            }
+
+            //      Phase 5
+            data = _PhaseData[idxPhaseStart++];
+            if( idxPhaseStart == 8)
+            {
+                idxPhaseStart = 0;
+            }
+            buttons = buttons |
+                ((data & 0x08) ? 0x000001 : 0) |    // Mode
+                ((data & 0x04) ? 0x040000 : 0) |    // X
+                ((data & 0x02) ? 0x020000 : 0) |    // Y
+                ((data & 0x01) ? 0x010000 : 0) ;    // Z
+            
+            __disable_irq();
+            _InputStatus->Buttons = buttons;
+            __enable_irq();
+        }
+
+    }
+//  printf("E\r\n");
+}
+
+
+//
+//ReadPinValue (Pin status -> Class value)
+//
+int In_MD6B::ReadPinValue()
+{
+    return ( 
+        (_IN_D5<<5) | (_IN_D4<<4) |
+        (_IN_D3<<3) | (_IN_D2<<2) | (_IN_D1<<1) |  _IN_D0
+    );
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/In_MD6B/In_MD6B.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,70 @@
+#pragma once
+
+/** Class: In_MD6B
+ *
+ * For reading input from Sega Fighting pad 6B
+ *
+ * Example:
+ *
+ * > #include "mbed.h"
+ *
+ * > In_MD6B myFightingPad6B(p20, p19,... inputStates);
+ */
+
+#include "mbed.h"
+#include "InputStatus.h"
+
+class In_MD6B
+{
+public:
+    /** Constructor: In_MD6B
+     *
+     * Parameters:
+     * pn_D0  - DigitalIn for 6B's D0 (D-Sub9 connector's pin1)
+     * pn_D1  - DigitalIn for D1 (D-Sub9 pin2)
+     * pn_D2  - DigitalIn for D2 (D-Sub9 pin3)
+     * pn_D3  - DigitalIn for D3 (D-Sub9 pin4)
+     * pn_D4  - DigitalIn for D4 (D-Sub9 pin6)
+     * pn_D5  - DigitalIn for D5 (D-Sub9 pin9)
+     * pn_SEL - DigitalOut for Select (D-Sub9 pin7)
+     * inputStatus - The variable to store input status
+     */
+    In_MD6B(
+        PinName pn_D0, PinName pn_D1, PinName pn_D2, PinName pn_D3, 
+        PinName pn_D4, PinName pn_D5, PinName pn_SEL,
+        InputStatus *inputStatus
+    );
+
+    void StartReading(void);
+    void StopReading(void);
+        
+private:
+    // Private constants
+    static const int READINGINTERVAL__MICROSEC = 5000;  // reading period microsec
+    static const int SELSTATETIME__MICROSEC    = 2;     // Select信号の立ち上げ_立ち下げを行う長さ
+                                                        // 短すぎると6Bが反応しない?
+
+    // mbed pins
+    DigitalIn   _IN_D0;
+    DigitalIn   _IN_D1;
+    DigitalIn   _IN_D2;
+    DigitalIn   _IN_D3;
+    DigitalIn   _IN_D4;
+    DigitalIn   _IN_D5;
+    DigitalOut  _OUT_SEL;
+
+    // Variables
+    InputStatus     *_InputStatus;
+    volatile char   _ReadEnable;
+    Ticker          _PollingTicker;
+    volatile char   _PhaseData[8];
+    
+    
+    // Private Method
+    void Initialize(void);
+    void EnablePolling(void);
+    void DisablePolling(void);
+    void PollingMethod(void);
+
+    int  ReadPinValue(void);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InputDeviceDetector.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,146 @@
+/** Class: InputDeviceDetector
+ *
+ * Detect input device
+ *
+ */
+
+#include "mbed.h"
+#include "NiseKabuto.h"
+
+class InputDeviceDetector
+{
+    private:
+        // constant
+        static const int SELSTATETIME__MICROSEC    = 2;     // Select信号の立ち上げ_立ち下げを行う長さ
+                                                            // 短すぎると6Bが反応しない?
+
+        // mbed pins
+        DigitalIn   _IN_D0;
+        DigitalIn   _IN_D1;
+        DigitalIn   _IN_D2;
+        DigitalIn   _IN_D3;
+        DigitalIn   _IN_D4;
+        DigitalIn   _IN_D5;
+        DigitalOut  _OUT_SEL;
+    
+        char        _InputType;
+        
+    public:
+        // Constructor
+        InputDeviceDetector(PinName inputPins[])
+            :_IN_D0(inputPins[0]), _IN_D1(inputPins[1]), 
+             _IN_D2(inputPins[2]), _IN_D3(inputPins[3]), 
+             _IN_D4(inputPins[4]), _IN_D5(inputPins[5]), 
+             _OUT_SEL(inputPins[6])
+        {
+            // Pin Setting
+            _IN_D0.mode(PullUp);
+            _IN_D1.mode(PullUp);
+            _IN_D2.mode(PullUp);
+            _IN_D3.mode(PullUp);
+            _IN_D4.mode(PullUp);
+            _IN_D5.mode(PullUp);
+            
+            // Initialize pin status
+            _OUT_SEL = 1;   // output SEL = H
+        }
+
+        // public: Return input device type
+        char GetInputType()
+        {
+            char retVal = NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG;
+            
+            if( Check_MD6B() )
+            {
+                retVal = NiseKabuto::CONFIG_INMODE_MD6B;
+            }
+            
+            return retVal;
+        }
+
+        // Check if MD6B is connected ?
+        //  return:
+        //      non-0: Connected
+        //          0: Not connected
+        char Check_MD6B()
+        {
+            char retVal = 0;
+            
+            char flag6B = 0;
+            int idx = 0;
+            char _PhaseData[8];
+
+            // Selを立ち下げ、データ読みを8回
+            idx = 0;
+            for(int i=0; i<4; i++)
+            {
+                _OUT_SEL = 0;
+                wait_us(SELSTATETIME__MICROSEC);
+                
+                _PhaseData[idx++] = ReadPinValue();
+                
+                _OUT_SEL = 1;
+                wait_us(SELSTATETIME__MICROSEC);
+
+                _PhaseData[idx++] = ReadPinValue();
+            }
+            
+            idx = 0;
+            while(1)
+            {
+                // D0-D3がLなものを探す
+                if( (_PhaseData[idx]&0x0f)==0 )
+                {
+                    // idx+2をチェック
+                    // ただし6を超えた場合はidx-6の位置をチェック
+                    if(idx < 6)
+                    {
+                        if( (_PhaseData[idx+2]&0x0f)==0x0f )
+                        {
+                            flag6B = 1;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        if( (_PhaseData[idx-6]&0x0f)==0x0f )
+                        {
+                            flag6B = 1;
+                            break;
+                        }
+                    }
+                }
+                
+                // このidxではなかった
+                idx++;
+                // 全部チェックしてしまった
+                if( idx == 8 )
+                {
+                    break;
+                }
+            }
+            
+            // この時点でflag6B==0の場合、6Bではない
+            if( flag6B != 1 )
+            {
+                retVal = 0;
+            }
+            else
+            {
+                retVal = 1;
+            }
+            
+            return retVal;
+        }
+        
+        // ReadPinValue
+        char ReadPinValue()
+        {
+            return ( 
+                (_IN_D5<<5) | (_IN_D4<<4) |
+                (_IN_D3<<3) | (_IN_D2<<2) | (_IN_D1<<1) |  _IN_D0
+            );
+        }
+
+        
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InputStatus.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,44 @@
+#pragma once
+/** Class: InputStatus
+ *
+ * Used for store input status from Joypad/Joystick
+ *
+ */
+class InputStatus
+{
+    public:
+        volatile char   Ch0;    // axis_y
+        volatile char   Ch1;    // axis_x
+        volatile char   Ch2;    // throttle
+        volatile char   Ch3;    // option
+
+        volatile int    Buttons;
+        // 32 bits
+        // *MSB*
+        //                                               |   X    |   Y    |   Z    |
+        //  ------------------------------------------------------------------------
+        //  ThrotUp |ThrotDw |   Up   |   Dw   ||   Lf   |   Rg   |   A    |   B    |
+        //  ------------------------------------------------------------------------
+        //    A+A'  |  B+B'  |   C    |   D    ||   E1   |   E2   |START(F)|SELECT(G)
+        //          |        |        |        ||        |        |        |Mode
+        //                                                                     *LSB*
+        //
+
+        volatile char   InputDeviceType;// 0:CS-Analog mode
+                                        // 1:CS-Digital mode
+                                        // 2:MD6B
+
+        volatile char   Temp[8];
+       
+    public:
+        void Reset(void)
+        {
+            Ch0 = 0x7f;
+            Ch1 = 0x7f;
+            Ch2 = 0x7f;
+            Ch3 = 0x7f;
+            Buttons = 0x7fffffff;
+            InputDeviceType = 1;
+        }
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NiseKabuto.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,481 @@
+#include "NiseKabuto.h"
+#include "InputDeviceDetector.h"
+
+// _InputTypeとInputStatus.InputDeviceTypeの違いは????
+
+/**
+--------------------------------------------------
+
+ Constructor
+
+--------------------------------------------------
+**/
+NiseKabuto::NiseKabuto(PinName inputPins[], PinName outputPins[], PinName configurePins[])
+ : 
+    _ConfigSwitch(
+        configurePins[0],configurePins[1],configurePins[2],configurePins[3],
+        configurePins[4],configurePins[5],configurePins[6],configurePins[7]
+    )
+{
+    InitInterruptPriority();
+//  InitTimer0();
+    
+    // Pin Setting
+    _ConfigSwitch.mode(PullUp);
+    
+    // Detect Input device
+    InputDeviceDetector myDetector = InputDeviceDetector(inputPins);
+    _InputType = myDetector.GetInputType();
+    //printf("_InputType: %d\n",_InputType & 0xff);
+    
+
+    // Initialize  input instance
+    switch(_InputType)
+    {
+        case CONFIG_INMODE_CYBERSTICK_ANALOG:
+        case CONFIG_INMODE_CYBERSTICK_DIGITAL:
+            // Initialize Input: CyberStick
+            InitInput_CyberStick(inputPins);
+            break;
+            
+        case CONFIG_INMODE_MD6B:
+            // Initialize Input: MD6B
+            InitInput_MD6B(inputPins);
+            break;
+
+        default:
+            InitInput_MD6B(inputPins);
+            break;
+    }
+
+    /*
+    wait_ms(5000);
+    printf("_ConfigSwitch: %d\n",_ConfigSwitch & 0xff);
+    */
+    
+    // Save output mode
+    //printf("CS:%02x\n\r",~_ConfigSwitch);
+    _OutputType = (~_ConfigSwitch) & 0x0ff;
+
+    // Initialize output instance
+    switch(_OutputType)
+    {
+        case CONFIGPIN_OUTMODE_SSMULCON:
+            // Initialize Output: SS Multi Controller
+            InitOutput_SSMulCon(outputPins);
+            break;
+            
+        case CONFIGPIN_OUTMODE_PCE:
+            // Initialize Output: PCE Analog/Digital Controller
+            InitOutput_PCE(outputPins);
+            break;
+
+        case CONFIGPIN_OUTMODE_FC:
+            // Initialize Output: Famicom Controller
+            InitOutput_FC(outputPins);
+            break;
+        case CONFIGPIN_OUTMODE_MD:
+            // Initialize Output: Megadrive analog joystick
+            InitOutput_MD(outputPins);
+            break;
+        default:
+            // Initialize Output: PlayStation3 USB Joystick
+            InitOutput_PS3USB();
+            break;
+    }
+}
+
+
+/**
+--------------------------------------------------
+
+ Initialize Input Device: CyberStick
+
+--------------------------------------------------
+**/
+void NiseKabuto::InitInput_CyberStick(PinName inputPins[])
+{
+    // Create In_CyberStick instance
+    _In_CyberStick = new In_CyberStick(
+                    inputPins[0],inputPins[1],inputPins[2],inputPins[3],
+                    inputPins[4],inputPins[5],inputPins[6],&_InputStatus);
+}
+
+
+
+/**
+--------------------------------------------------
+
+ Initialize Input Device: Fighting Pad 6B
+
+--------------------------------------------------
+**/
+void NiseKabuto::InitInput_MD6B(PinName inputPins[])
+{
+    // Create In_CyberStick instance
+    _In_MD6B= new In_MD6B(
+                    inputPins[0],inputPins[1],inputPins[2],inputPins[3],
+                    inputPins[4],inputPins[5],inputPins[6],&_InputStatus);
+}
+
+
+
+/**
+--------------------------------------------------
+
+ Initialize Output Device: Megadrive analog/digital joystick
+
+--------------------------------------------------
+**/
+void NiseKabuto::InitOutput_MD(PinName outputPins[])
+{
+    // Create Out_MD instance
+    _Out_MD = new Out_MD(
+                    outputPins[0],outputPins[1],outputPins[2],outputPins[3],
+                    outputPins[4],outputPins[5],outputPins[6],
+                    &_InputStatus
+                );
+    
+    if( _InputType == CONFIG_INMODE_CYBERSTICK_ANALOG || _InputType == CONFIG_INMODE_CYBERSTICK_DIGITAL) 
+    {
+        _Out_MD->SetupInputControll(_In_CyberStick, &In_CyberStick::StartReading, &In_CyberStick::StopReading);
+    }
+    else if( _InputType == CONFIG_INMODE_MD6B )
+    {
+        _Out_MD->SetupInputControll(_In_MD6B, &In_MD6B::StartReading, &In_MD6B::StopReading);
+    }
+}
+
+/**
+--------------------------------------------------
+
+ Initialize Output Device: SS Multi Controller
+
+--------------------------------------------------
+**/
+void NiseKabuto::InitOutput_SSMulCon(PinName outputPins[])
+{
+    // Create Out_SSMulCon instance
+    _Out_SSMulCon = new Out_SSMulCon(
+                    outputPins[0],outputPins[1],outputPins[2],outputPins[3],
+                    outputPins[4],outputPins[5],outputPins[6],
+                    &_InputStatus
+                );
+
+    if( _InputType == CONFIG_INMODE_CYBERSTICK_ANALOG || _InputType == CONFIG_INMODE_CYBERSTICK_DIGITAL) 
+    {
+        _Out_SSMulCon->SetupInputControll(_In_CyberStick, &In_CyberStick::StartReading, &In_CyberStick::StopReading);
+    }
+    else if( _InputType == CONFIG_INMODE_MD6B )
+    {
+        _Out_SSMulCon->SetupInputControll(_In_MD6B, &In_MD6B::StartReading, &In_MD6B::StopReading);
+    }
+}
+
+/**
+--------------------------------------------------
+
+ Initialize Output Device: PCE Analog/Digital Controller
+
+--------------------------------------------------
+**/
+void NiseKabuto::InitOutput_PCE(PinName outputPins[])
+{
+    // Create Out_PCEAnalog instance
+    _Out_PCE = new Out_PCE(
+                    outputPins[0],outputPins[1],outputPins[2],outputPins[3],
+                    outputPins[4],outputPins[5],outputPins[6],
+                    &_InputStatus
+                );
+
+    if( _InputType == CONFIG_INMODE_CYBERSTICK_ANALOG || _InputType == CONFIG_INMODE_CYBERSTICK_DIGITAL) 
+    {
+        _Out_PCE->SetupInputControll(_In_CyberStick, &In_CyberStick::StartReading, &In_CyberStick::StopReading);
+    }
+    else if( _InputType == CONFIG_INMODE_MD6B )
+    {
+        _Out_PCE->SetupInputControll(_In_MD6B, &In_MD6B::StartReading, &In_MD6B::StopReading);
+    }
+}
+
+
+/**
+--------------------------------------------------
+
+ Initialize Output Device: Famicom Controller
+
+--------------------------------------------------
+**/
+void NiseKabuto::InitOutput_FC(PinName outputPins[])
+{
+    // Create Out_FC instance
+    _Out_FC = new Out_FC(
+                    outputPins[0],outputPins[1],outputPins[2],outputPins[3],
+                    &_InputStatus
+                );
+
+    if( _InputType == CONFIG_INMODE_CYBERSTICK_ANALOG || _InputType == CONFIG_INMODE_CYBERSTICK_DIGITAL) 
+    {
+        _Out_FC->SetupInputControll(_In_CyberStick, &In_CyberStick::StartReading, &In_CyberStick::StopReading);
+    }
+    else if( _InputType == CONFIG_INMODE_MD6B )
+    {
+        _Out_FC->SetupInputControll(_In_MD6B, &In_MD6B::StartReading, &In_MD6B::StopReading);
+    }
+}
+
+/**
+--------------------------------------------------
+
+ Initialize Output Device: PlayStation3 USB Joystick
+
+--------------------------------------------------
+**/
+void NiseKabuto::InitOutput_PS3USB(void)
+{
+    // Create Out_PS3USB instance
+    _Out_PS3USB = new Out_PS3USB(
+                    &_InputStatus
+                );
+
+    if( _InputType == CONFIG_INMODE_CYBERSTICK_ANALOG || _InputType == CONFIG_INMODE_CYBERSTICK_DIGITAL) 
+    {
+        _Out_PS3USB->SetupInputControll(_In_CyberStick, &In_CyberStick::StartReading, &In_CyberStick::StopReading);
+    }
+    else if( _InputType == CONFIG_INMODE_MD6B )
+    {
+        _Out_PS3USB->SetupInputControll(_In_MD6B, &In_MD6B::StartReading, &In_MD6B::StopReading);
+    }
+}
+
+
+/**
+--------------------------------------------------
+
+ Show (for test)
+
+--------------------------------------------------
+**/
+
+void NiseKabuto::Show()
+{
+    char    strBuf[100];
+
+    __disable_irq();
+    int val = _InputStatus.Buttons;
+    int ch0 = _InputStatus.Ch0;
+    int ch1 = _InputStatus.Ch1;
+    int ch2 = _InputStatus.Ch2;
+    int ch3 = _InputStatus.Ch3;
+    char mode = _InputStatus.InputDeviceType;
+    char temp0 = _InputStatus.Temp[0];
+    char temp1 = _InputStatus.Temp[1];
+    char temp2 = _InputStatus.Temp[2];
+    char temp3 = _InputStatus.Temp[3];
+    char temp4 = _InputStatus.Temp[4];
+    char temp5 = _InputStatus.Temp[5];
+    __enable_irq();
+    
+    strBuf[0]=0;
+
+    switch(mode)
+    {
+        case CONFIG_INMODE_CYBERSTICK_ANALOG:
+        case CONFIG_INMODE_CYBERSTICK_DIGITAL:
+            strcat(strBuf, "CS");
+            if( mode==CONFIG_INMODE_CYBERSTICK_ANALOG )
+            {
+                strcat(strBuf, "AN");
+            }
+            else
+            {
+                strcat(strBuf, "DG");
+            }
+            break;
+            
+        case CONFIG_INMODE_MD6B:
+            strcat(strBuf, "6B");
+            break;
+    }
+
+    switch(_OutputType)
+    {
+        case CONFIGPIN_OUTMODE_SSMULCON:
+            strcat(strBuf, "->SSMC ");
+            break;
+            
+        case CONFIGPIN_OUTMODE_PCE:
+            strcat(strBuf, "->PCE ");
+            break;
+
+        case CONFIGPIN_OUTMODE_FC:
+            strcat(strBuf, "->Famicom ");
+            break;
+
+        case CONFIGPIN_OUTMODE_MD:
+            strcat(strBuf, "->MD ");
+            break;      
+
+        default:
+            strcat(strBuf, "->PS3USB ");
+            break;      
+    }
+    
+    switch(mode)
+    {
+        case CONFIG_INMODE_CYBERSTICK_ANALOG:
+        case CONFIG_INMODE_CYBERSTICK_DIGITAL:
+            strcat(strBuf, val & 0x8000? "---" : "Tup");
+            strcat(strBuf, val & 0x4000? "---" : "Tdw");
+            strcat(strBuf, val & 0x2000? "-" : "U");
+            strcat(strBuf, val & 0x1000? "-" : "D");
+            strcat(strBuf, val & 0x0800? "-" : "L");
+            strcat(strBuf, val & 0x0400? "-" : "R");
+            strcat(strBuf, val & 0x0200? "-" : "A");
+            strcat(strBuf, val & 0x0100? "-" : "B");
+            strcat(strBuf, val & 0x0020? "-" : "C");
+            strcat(strBuf, val & 0x0010? "-" : "D");
+            strcat(strBuf, val & 0x0008? "--" : "E1");
+            strcat(strBuf, val & 0x0004? "--" : "E2");
+            strcat(strBuf, val & 0x0002? "---" : "Fst");
+            strcat(strBuf, val & 0x0001? "---" : "Gsl");
+            strcat(strBuf, val & 0x0080? "--" : "A'");
+            strcat(strBuf, val & 0x0040? "--" : "B'");
+            printf("%s ",strBuf);
+
+            printf("CH0:%02X ",   ch0);
+            printf("CH1:%02X ",   ch1);
+            printf("CH2:%02X ",   ch2);
+            printf("CH3:%02X ",   ch3);
+            /*
+            printf("\r\ni:%02x o:%02x %02x %02x ", temp0, temp2, temp5, temp4); // debug(in, out functions)
+            printf("tc(%u) mr0(%u) ", LPC_TIM3->TC, LPC_TIM3->MR0);             // debug(TIMER3)
+            */
+            printf("\r\n");
+
+            break;
+
+        case CONFIG_INMODE_MD6B:
+            strcat(strBuf, val & 0x002000? "-" : "U");
+            strcat(strBuf, val & 0x001000? "-" : "D");
+            strcat(strBuf, val & 0x000800? "-" : "L");
+            strcat(strBuf, val & 0x000400? "-" : "R");
+            strcat(strBuf, val & 0x000200? "-" : "A");
+            strcat(strBuf, val & 0x000100? "-" : "B");
+            strcat(strBuf, val & 0x000020? "-" : "C");
+            strcat(strBuf, val & 0x040000? "-" : "X");
+            strcat(strBuf, val & 0x020000? "-" : "Y");
+            strcat(strBuf, val & 0x010000? "-" : "Z");
+            strcat(strBuf, val & 0x000002? "-" : "S");
+            strcat(strBuf, val & 0x000001? "-" : "M");
+            printf("%s ",strBuf);
+            //printf("%02x %02x %02x %02x %02x %02x", temp0, temp1, temp2, temp3, temp4, temp5);
+            /*
+            printf("i:%02x o:%02x %02x %02x ", temp0, temp2, temp5, temp4);
+            printf("TIM3 tc(%u) mr0(%u) diff(%d)", 
+                LPC_TIM3->TC, 
+                LPC_TIM3->MR0, 
+                int(LPC_TIM3->MR0) - int(LPC_TIM3->TC) );
+            */
+            printf("\r\n");
+            /*
+            printf("\r\nIR:%08x,TCR:%08x,PR:%08x,PC:%08x,MCR:%08x,EMR:%08x,CTCR:%08x tc(%u) mr0(%u) diff(%d) pending:%u ", 
+            //  NVIC_GetActive(TIMER3_IRQn),
+                LPC_TIM3->IR, 
+                LPC_TIM3->TCR, 
+                LPC_TIM3->PR, 
+                LPC_TIM3->PC, 
+                LPC_TIM3->MCR, 
+                LPC_TIM3->EMR, 
+                LPC_TIM3->CTCR, 
+                LPC_TIM3->TC, 
+                LPC_TIM3->MR0, 
+                int(LPC_TIM3->MR0) - int(LPC_TIM3->TC), 
+                ( NVIC->ISPR[0] & ( 1<<4 ) ) );
+            printf("\r\n");
+            */
+            break;
+    }
+
+    //
+    // ここで実行させるのはおかしいが、暫定的に
+    //
+    if( (int(LPC_TIM3->MR0) - int(LPC_TIM3->TC)) <0 )
+    {
+        printf("=================================================\r\n");
+        printf("                   Resetting MR0 !!!!            \r\n");
+        printf("=================================================\r\n");
+        LPC_TIM3->MR0 = LPC_TIM3->TC + 1000;
+    }
+
+}
+
+void NiseKabuto::InitInterruptPriority(void)
+{
+    // http://mbed.org/users/earlz/code/MbedConsole/file/370b9e559f92/main.cpp
+    
+    NVIC_SetPriority(NonMaskableInt_IRQn, 100 ); 
+    NVIC_SetPriority(MemoryManagement_IRQn, 100);
+    
+    NVIC_SetPriority(BusFault_IRQn, 100);
+    NVIC_SetPriority(UsageFault_IRQn, 100);
+    NVIC_SetPriority(SVCall_IRQn, 100);
+    NVIC_SetPriority(DebugMonitor_IRQn, 100);
+    NVIC_SetPriority(PendSV_IRQn, 100);
+    NVIC_SetPriority(SysTick_IRQn, 50);
+    NVIC_SetPriority(WDT_IRQn, 100);
+    NVIC_SetPriority(TIMER0_IRQn, 85);
+    NVIC_SetPriority(TIMER1_IRQn, 85);
+    NVIC_SetPriority(TIMER2_IRQn, 85);
+    NVIC_SetPriority(TIMER3_IRQn, 85);
+    NVIC_SetPriority(UART0_IRQn, 75);
+    NVIC_SetPriority(UART1_IRQn, 100);
+    NVIC_SetPriority(UART2_IRQn, 100);
+    NVIC_SetPriority(UART3_IRQn, 100);
+    
+    NVIC_SetPriority(PWM1_IRQn, 100);
+    NVIC_SetPriority(I2C0_IRQn, 100);
+    NVIC_SetPriority(I2C1_IRQn, 100);
+    NVIC_SetPriority(I2C2_IRQn, 100);
+    NVIC_SetPriority(SPI_IRQn, 100);
+    NVIC_SetPriority(SSP0_IRQn, 100);
+    NVIC_SetPriority(SSP1_IRQn, 100);
+    NVIC_SetPriority(PLL0_IRQn, 100);
+    NVIC_SetPriority(RTC_IRQn, 100);
+    NVIC_SetPriority(EINT0_IRQn, 100);
+    NVIC_SetPriority(EINT1_IRQn, 100);
+    
+    NVIC_SetPriority(EINT2_IRQn, 100);
+    NVIC_SetPriority(EINT3_IRQn, 20);    // 最高
+    NVIC_SetPriority(ADC_IRQn, 100);
+    NVIC_SetPriority(BOD_IRQn, 100);
+    NVIC_SetPriority(USB_IRQn, 100);
+    NVIC_SetPriority(CAN_IRQn, 100);
+    NVIC_SetPriority(DMA_IRQn, 100);
+    
+    NVIC_SetPriority(I2S_IRQn, 100);
+    NVIC_SetPriority(ENET_IRQn, 100);
+    NVIC_SetPriority(RIT_IRQn, 100);
+    NVIC_SetPriority(MCPWM_IRQn, 100);
+    NVIC_SetPriority(QEI_IRQn, 100);
+    NVIC_SetPriority(PLL1_IRQn, 100);
+    
+}
+
+
+void NiseKabuto::WaitUs(uint32_t nus)
+{
+    uint32_t countNop, countNopMAX;
+    countNopMAX = 24;   // 96MHz動作のmbedで、1usになるような値にする
+    
+    for(uint32_t i=0; i<nus; i++)
+    {
+        countNop = countNopMAX;
+        while(countNop--)
+        {
+            __nop();
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NiseKabuto.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,70 @@
+#pragma once
+/** Class: In_CyberStick
+ *
+ * Use CyberStick(CZ-8NJ2) as fake XE-1AP(Kabutogani) MD mode
+ * Use CyberStick(CZ-8NJ2) as SS Multi Controller
+ * Use CyberStick(CZ-8NJ2) as PC-Engine Analog Controller
+ * Use CyberStick(CZ-8NJ2) Digital mode as Famicom controller
+ * Use CyberStick(CZ-8NJ2) as PlayStation3 USB Joystick
+ *
+ * Example:
+ *
+ */
+#include "In_CyberStick.h"
+#include "In_MD6B.h"
+#include "Out_MD.h"
+#include "Out_SSMulCon.h"
+#include "Out_PCE.h"
+#include "Out_FC.h"
+#include "Out_PS3USB.h"
+#include "InputStatus.h"
+
+static volatile int _Timer0Counter;
+
+class NiseKabuto
+{
+public:
+    // Public constants
+    static const char CONFIG_INMODE_CYBERSTICK_ANALOG  = 0;
+    static const char CONFIG_INMODE_CYBERSTICK_DIGITAL = 1;
+    static const char CONFIG_INMODE_MD6B               = 2;
+
+    static const char CONFIGPIN_OUTMODE_PS3USB    = 0;
+    static const char CONFIGPIN_OUTMODE_SSMULCON  = 1;
+    static const char CONFIGPIN_OUTMODE_PCE       = 2;
+    static const char CONFIGPIN_OUTMODE_MD        = 3;  // changed!!
+    static const char CONFIGPIN_OUTMODE_FC        = 4;
+    
+    // Public Method/Constructor
+    NiseKabuto(PinName inputPins[], PinName outputPins[], PinName configurePins[]);
+    void Show(void);
+
+private:
+    // Variables
+    char                _InputType;
+    char                _OutputType;
+    In_CyberStick       *_In_CyberStick;
+    In_MD6B             *_In_MD6B;
+    Out_MD              *_Out_MD;
+    Out_SSMulCon        *_Out_SSMulCon;
+    Out_PCE             *_Out_PCE;
+    Out_FC              *_Out_FC;
+    Out_PS3USB          *_Out_PS3USB;
+    InputStatus         _InputStatus;
+    BusInOut            _ConfigSwitch;
+
+    // Private Method
+    void InitInterruptPriority(void);
+
+    void InitInput_CyberStick (PinName inputPins[]);
+    void InitInput_MD6B       (PinName inputPins[]);
+    void InitOutput_MD        (PinName outputPins[]);
+    void InitOutput_SSMulCon  (PinName outputPins[]);
+    void InitOutput_PCE       (PinName outputPins[]);
+    void InitOutput_FC        (PinName outputPins[]);
+    void InitOutput_PS3USB    (void);
+
+public:
+    static void WaitUs(uint32_t us);
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_FC/C_Out_FC.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,632 @@
+#include "mbed.h"
+#include "NiseKabuto.h" // InputDeviceType
+#include "C_Out_FC.h"
+
+// mbed pins
+DigitalOut  led2_FC(LED2); 
+DigitalOut  led3_FC(LED3); 
+InterruptIn *_INTR_LATCH;
+DigitalOut  *_OUT_DATA;
+InterruptIn *_INTR_CLOCK;
+InterruptIn *_INTR_POWDETECT;
+
+// File local variables
+static volatile int     *_pButtons; //PhaseData[12]
+static volatile char    *_pCh0;
+static volatile char    *_pCh1;
+static volatile char    *_pCh2;
+static volatile char    *_pInputDeviceType;
+static volatile char    _Flag_NowOutput;
+static volatile char    _PhaseCounter;
+static volatile char    _SpeedType;
+static FunctionPointer  *_fp_EnableInput;
+static FunctionPointer  *_fp_DisableInput;
+static volatile char    _RapidFireValue;
+static Ticker           _RapidStateTicker;
+
+// Const variables
+static const int    DIGITALPAD_SPEED_STARFORCE = 120;
+static const int    DIGITALPAD_SPEED_RECCA     = 75;
+static const int    RAPIDFIRE_PER_SEC = 15;     // 高橋名人連射速度-1
+
+// File local functions
+static void ISR_Rise_LATCH_STARFORCE(void); // 遅い読み取りルーチン for スターフォース
+static void ISR_Rise_LATCH(void);           // フツー
+static void ISR_Rise_LATCH_RECCA(void);     // 速い読み取りルーチン for サマーカーニバル'92 烈火
+//static void ISR_Rise_POWERDETECT(void);
+static void RenewData(void);
+static char CheckSpeedType(void);
+static int  CheckOneReadTime(void);
+static void ConfigureSpeed(void);
+static void RapidStateTickerMethod(void);
+
+void C_Out_FC_Initialize(
+    InterruptIn *intr_LATCH,
+    DigitalOut  *out_DATA,
+    InterruptIn *intr_CLOCK,
+    InterruptIn *intr_POWDETECT,
+    volatile int *pButtons,
+    volatile char *pCh0,
+    volatile char *pCh1,
+    volatile char *pCh2,
+    volatile char *pInputDeviceType,
+    FunctionPointer *pFunc_InputEnable,
+    FunctionPointer *pFunc_InputDisable
+)
+{
+    // 入出力pin
+    _INTR_LATCH     = intr_LATCH;
+    _OUT_DATA       = out_DATA;
+    _INTR_CLOCK     = intr_CLOCK;
+    _INTR_POWDETECT = intr_POWDETECT;
+
+    // 割り込み設定
+    //_INTR_POWDETECT->rise(&ISR_Rise_POWERDETECT); // 電源ON/OFFでスピード切り替え判定を行う場合
+
+    led2_FC.write(0);                               // 初期:フツー
+    led3_FC.write(1);                               //
+    _INTR_LATCH->rise(&ISR_Rise_LATCH);             //
+    
+    // 出力速度設定
+    ConfigureSpeed();
+
+    // ポインタ
+    _pButtons         = pButtons;
+    _pCh0             = pCh0;
+    _pCh1             = pCh1;
+    _pCh2             = pCh2;
+    _pInputDeviceType = pInputDeviceType;
+    _fp_EnableInput   = pFunc_InputEnable;
+    _fp_DisableInput  = pFunc_InputDisable;
+    
+    _Flag_NowOutput = 0;
+    _RapidFireValue = 1;
+    
+    //_pTemp = pTemp;
+    
+    // 連射ステータス変更設定
+    _RapidStateTicker.attach_us(&RapidStateTickerMethod, (int)(1000000/(RAPIDFIRE_PER_SEC*2)));
+    
+    // Initialize pin status
+    _PhaseCounter = 0;
+    RenewData();
+}
+
+void ISR_Rise_LATCH(void)
+{
+    int loopCounter;
+
+    // 止める
+    if(
+        (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG ||
+        (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL
+    )
+    {
+        (*_fp_DisableInput).call();
+    }
+
+    // この関数開始時点で、phase0読み取り(DATAの立下り1回分)は
+    // 終了しているものと仮定する
+    // (mbedのピン割り込み時の反応速度は7usくらい)
+    //
+    // ただしMetalMaxでは。Latch立ち上がりから初回DATA立下りの間が
+    // 6.5-7.0usくらいで微妙なので、
+    // 絶対にphase0から開始することを保証するため、ちょっと待つ
+    wait_us(1);
+    
+    
+    // Phase1に移行
+    _PhaseCounter=1;
+    RenewData();
+
+    // Lの間待つ
+    while( !(_INTR_CLOCK->read()) )
+    {
+        loopCounter = 400;
+
+        loopCounter--;
+        if( !loopCounter )
+        {
+            break;
+        }
+    }
+    
+    // 開始
+    for(int i=1; i<8; i++ )
+    {
+        
+        // Hの間待つ
+        loopCounter = 5000;     
+        while( _INTR_CLOCK->read() )
+        {
+            loopCounter--;
+            if( !loopCounter )
+            {
+                break;
+            }
+        }
+
+        // Set data for current phase
+        _PhaseCounter++;
+        RenewData();
+        
+        // Lの間待つ
+        loopCounter = 200;
+        while( !(_INTR_CLOCK->read()) )
+        {
+            loopCounter--;
+            if( !loopCounter )
+            {
+                break;
+            }
+        }
+    }
+
+    _PhaseCounter = 0;
+    RenewData();
+
+    // 再開
+    if(
+        (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG ||
+        (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL
+    )
+    {
+        (*_fp_EnableInput).call();
+    }
+
+}
+
+void ISR_Rise_LATCH_RECCA(void)
+{
+    // おまじない(Phase0を長引かせる)
+    wait_us(2);
+    
+    // Phase1に移行
+    _PhaseCounter=1;
+    RenewData();
+    
+    // 開始
+    for(int i=1; i<8; i++ )
+    {
+        wait_us(6); 
+
+        // Set data for current phase
+        _PhaseCounter++;
+        RenewData();
+    }
+
+    _PhaseCounter = 0;
+    RenewData();
+
+}
+
+// 遅い読み取りルーチン
+void ISR_Rise_LATCH_STARFORCE(void)
+{
+    int loopCounter;
+
+    // 止める
+    if(
+        (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG ||
+        (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL
+    )
+    {
+        (*_fp_DisableInput).call();
+    }
+
+    // Hの間待つ
+    loopCounter = 5000;     
+    while( _INTR_CLOCK->read() )
+    {
+        loopCounter--;
+        if( !loopCounter )
+        {
+            break;
+        }
+    }
+
+    
+    // Phase1に移行
+    _PhaseCounter=1;
+    RenewData();
+
+    // Lの間待つ
+    while( !(_INTR_CLOCK->read()) )
+    {
+        loopCounter = 400;
+
+        loopCounter--;
+        if( !loopCounter )
+        {
+            break;
+        }
+    }
+    
+    // 開始
+    for(int i=1; i<8; i++ )
+    {
+        
+        // Hの間待つ
+        loopCounter = 5000;     
+        while( _INTR_CLOCK->read() )
+        {
+            loopCounter--;
+            if( !loopCounter )
+            {
+                break;
+            }
+        }
+
+        // Set data for current phase
+        _PhaseCounter++;
+        RenewData();
+        
+        // Lの間待つ
+        loopCounter = 200;
+        while( !(_INTR_CLOCK->read()) )
+        {
+            loopCounter--;
+            if( !loopCounter )
+            {
+                break;
+            }
+        }
+    }
+
+    _PhaseCounter = 0;
+    RenewData();
+
+    // 再開
+    if(
+        (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG ||
+        (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL
+    )
+    {
+        (*_fp_EnableInput).call();
+    }
+
+}
+
+
+
+
+void RenewData(void)
+{
+    switch(_PhaseCounter)
+    {
+        case 0:
+            //
+            // A
+            //
+            if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0);  // Digital B
+            }
+            else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B
+            {
+                // Zが押されてたら連射、押されてなかったらCの結果
+                if( ((*_pButtons) & 0x010000) ) // Z
+                {
+                    // 真:押されてない
+                    _OUT_DATA->write(((*_pButtons) & 0x0020) ? 1 : 0);  // Digital C
+                }
+                else
+                {
+                    // 偽:押されてる
+                    _OUT_DATA->write(_RapidFireValue&1);
+                }
+            }
+            else
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0);  // Digital B
+            }
+            break;
+
+        case 1:
+            //
+            // B
+            //
+            if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0200) ? 1 : 0);  // Digital A
+            }
+            else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B
+            {
+                // Yが押されてたら連射、押されてなかったらBの結果
+                if( ((*_pButtons) & 0x020000) ) // Y
+                {
+                    // 真:押されてない
+                    _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0);  // Digital B
+                }
+                else
+                {
+                    // 偽:押されてる
+                    _OUT_DATA->write(_RapidFireValue&1);
+                }
+            }
+            else
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0200) ? 1 : 0);  // Digital A
+            }
+            break;
+
+        case 2: 
+            //
+            // Select
+            //
+            if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0001) ? 1 : 0);  // G(Sel,Mode)
+            }
+            else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0001) ? 1 : 0);  // G(Sel,Mode)
+            }
+            else
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0020) ? 1 : 0);  // Digital C
+            }
+            break;
+
+        case 3:
+            //
+            // Start
+            //
+            if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
+            {
+                _OUT_DATA->write(
+                    ( ((*_pButtons) & 0x0002) ? 1 : 0) &    // F(Start)
+                    ( (*_pCh2)>0xf0? 0:1 )                  // スロットル引く
+                
+                );
+                //_OUT_DATA->write( ((*_pButtons) & 0x0002) ? 1 : 0) );
+                
+            }
+            else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0002) ? 1 : 0);  // F(Start)
+            }
+            else
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0010) ? 1 : 0);  // Digital C
+            }
+            break;
+
+        case 4:
+            //
+            // Up
+            //
+            //  ch1>0xf0? 0:1,  //  右
+            //  ch1<0x0f? 0:1,  //  左
+            //  ch0>0xf0? 0:1,  //  下
+            //  ch0<0x0f? 0:1   //  上
+            //  ch2>0xf0? 0:1,  //  スロットル引く
+
+            if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
+            {
+                _OUT_DATA->write((*_pCh0)<0x40? 0:1);
+            }
+            else
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x2000) ? 1 : 0);
+            }
+            break;
+
+        case 5:
+            //
+            // Down
+            //
+            if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
+            {
+                _OUT_DATA->write((*_pCh0)>0xb0? 0:1);
+            }
+            else
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x1000) ? 1 : 0);
+            }
+            break;
+
+        case 6:
+            //
+            // Left
+            //
+            if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
+            {
+                _OUT_DATA->write((*_pCh1)<0x40? 0:1);
+            }
+            else
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0800) ? 1 : 0);
+            }
+            break;
+
+        case 7:     
+            //
+            // Right
+            //
+            if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ)
+            {
+                _OUT_DATA->write((*_pCh1)>0xb0? 0:1);
+            }
+            else
+            {
+                _OUT_DATA->write(((*_pButtons) & 0x0400) ? 1 : 0);
+            }
+            break;
+        
+        default:
+            _OUT_DATA->write(1);    // H
+    }
+}
+
+// 
+// ファミコンからの読み取り処理の長さを得る(1回分)
+// 
+// return:
+//      0     = 読み取りが行えない(烈火の可能性がある)
+//      0以外 = 読み取り処理長さ[us]
+int CheckOneReadTime(void)
+{
+    int   retVal = 0;
+    char  stat = 1;
+    int   intLoopCounter;   // ZanacはGunnac&MMに比べて2倍
+    Timer t;
+    
+    // Latch = Hまで待つ
+    intLoopCounter = 500000;
+    while( !(_INTR_LATCH->read()) )
+    {
+        intLoopCounter--;
+        if( !intLoopCounter )
+        {
+            stat = 0;
+            break;
+        }
+    }
+    
+    if(stat)
+    {
+        // 時刻計測開始
+        t.start();
+        
+        // Clockが8回Lになることを確認
+        for(int i=0; i<8; i++ )
+        {
+            intLoopCounter = 1000;
+            while( _INTR_CLOCK->read() )
+            {
+                intLoopCounter--;
+                if( !intLoopCounter )
+                {
+                    stat = 0;
+                    break;
+                }
+            }
+            
+            intLoopCounter = 100;
+            while( !(_INTR_CLOCK->read()) )
+            {
+                intLoopCounter--;
+                if( !intLoopCounter )
+                {
+                    break;
+                }
+            }           
+        }
+    }
+    
+    if(stat)
+    {
+        t.stop();
+        retVal =  t.read_us();
+    }
+    
+    return retVal;
+}
+
+
+
+// 
+// SpeedTypeを判定する
+// 
+// return:
+//      0 = 普通モード(普通のゲーム)
+//      1 = 高速モード(烈火)
+//      2 = 低速モード(スターフォース)
+//      よくわからないときは0を返す
+char CheckSpeedType(void)
+{
+    char retVal = 0;
+    int readTime[8];
+    char counter_recca     = 0;
+    char counter_starforce = 0;
+    
+    // Dataは常にH
+    _OUT_DATA->write(1);
+    
+    // 8回くらいチェックする
+    for(int i=0; i<8; i++ )
+    {
+        readTime[i] = CheckOneReadTime();
+        printf("readTime[%d]: %d\r\n",i,readTime[i]);
+    }
+    
+    // 個別の結果判定
+    for(int i=0; i<8; i++ )
+    {
+        if( readTime[i]>DIGITALPAD_SPEED_STARFORCE )
+        {
+            counter_starforce++;
+        }
+        else if( readTime[i]<DIGITALPAD_SPEED_RECCA )
+        {
+            counter_recca++;
+        }
+        else
+        {
+        }
+    }
+    
+    // 判定
+    if(counter_starforce >= 4)
+    {
+        retVal = 2;
+    }
+    else if(counter_recca >= 4)
+    {
+        retVal = 1;
+    }
+    
+    return retVal;
+}
+
+//
+// Configure speed setting
+//
+void ConfigureSpeed(void)
+{
+    char speed;
+    
+    // ISR登録解除
+    _INTR_LATCH->rise(0);
+    
+    // ちょっと待つ
+    wait_ms(500);
+    
+    speed = CheckSpeedType();
+    
+    // Interrupt Setting
+    if( speed==1 )
+    {
+        led2_FC.write(1);
+        led3_FC.write(1);
+        _INTR_LATCH->rise(&ISR_Rise_LATCH_RECCA);
+    }
+    else if( speed==2 )
+    {
+        led2_FC.write(0);
+        led3_FC.write(0);
+        _INTR_LATCH->rise(&ISR_Rise_LATCH_STARFORCE);
+    }
+    else
+    {
+        led2_FC.write(0);
+        led3_FC.write(1);
+        _INTR_LATCH->rise(&ISR_Rise_LATCH);
+    }
+
+}
+
+//
+// ISR for POWERDETECT L->H
+//
+void ISR_Rise_POWERDETECT(void)
+{
+    ConfigureSpeed();
+}
+
+void RapidStateTickerMethod(void)
+{
+    _RapidFireValue = !_RapidFireValue;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_FC/C_Out_FC.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,17 @@
+#include "mbed.h"
+
+void C_Out_FC_Initialize(
+/*  char        *pTemp,         // テスト用     */
+    InterruptIn *intr_LATCH,
+    DigitalOut  *out_DATA,
+    InterruptIn *intr_CLOCK,
+    InterruptIn *intr_POWDETECT,
+    volatile int *pFCInputData,
+    volatile char *pCh0,
+    volatile char *pCh1,
+    volatile char *pCh2,
+//  volatile char *pRapidFireValue,
+    volatile char *pInputDeviceType,
+    FunctionPointer *pFunc_InputEnable,
+    FunctionPointer *pFunc_InputDisable
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_FC/Out_FC.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,112 @@
+#include "Out_FC.h"
+#include "C_Out_FC.h"
+
+//
+// Constructor
+//
+Out_FC::Out_FC(
+    PinName pn_LATCH, PinName pn_DATA, PinName pn_CLOCK, PinName pn_POWDETECT,
+    InputStatus *inputStatus)
+    : _INTR_LATCH(pn_LATCH), _OUT_DATA(pn_DATA), _INTR_CLOCK(pn_CLOCK), _INTR_POWDETECT(pn_POWDETECT)
+{
+    
+    _InputStatus = inputStatus;
+    
+    Initialize();
+
+    // C function Initializer
+    
+    _pEnableInput.attach(this, &Out_FC::EnableInput);
+    _pDisableInput.attach(this, &Out_FC::DisableInput);
+    
+    C_Out_FC_Initialize(
+        &_INTR_LATCH,
+        &_OUT_DATA,
+        &_INTR_CLOCK,
+        &_INTR_POWDETECT,
+        &_Buttons,
+        &_Ch0,
+        &_Ch1,
+        &_Ch2,
+    //  &_RapidFireValue,
+        &_InputDeviceType,
+        &_pEnableInput,
+        &_pDisableInput
+    );
+}
+
+//
+// Initialize
+//
+void Out_FC::Initialize()
+{
+//  InitInterruptPriority();
+    
+    // Pin Setting
+    _INTR_LATCH.mode(PullUp);
+    _INTR_CLOCK.mode(PullUp);
+
+    // Ticker Setting
+    _RenewFCInputTicker.attach_us(
+        this, 
+        &Out_FC::RenewFCInputDataPeriodically, 
+        FC_INPUTSTATE_RENEWINTERVAL__MICROSEC
+    );
+    
+}
+
+
+//
+// 入力データ更新Ticker処理
+//
+void Out_FC::RenewFCInputDataPeriodically(void)
+{
+    _Buttons         = _InputStatus->Buttons;
+    _Ch0             = _InputStatus->Ch0;
+    _Ch1             = _InputStatus->Ch1;
+    _Ch2             = _InputStatus->Ch2;
+    _InputDeviceType = _InputStatus->InputDeviceType;
+}
+
+
+
+void Out_FC::SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void))
+{
+    StartInputFunction = startInputFunction;
+    StopInputFunction  = stopInputFunction;
+}
+
+void Out_FC::EnableInput(void)
+{
+    // Ticker Setting
+    _RenewFCInputTicker.attach_us(
+        this, 
+        &Out_FC::RenewFCInputDataPeriodically, 
+        FC_INPUTSTATE_RENEWINTERVAL__MICROSEC
+    );
+
+    if(_InputInstance && StartInputMethod)
+    {
+        (_InputInstance->*StartInputMethod)();
+    }
+    else if(StartInputFunction)
+    {
+        StartInputFunction();
+    }
+}
+
+void Out_FC::DisableInput(void)
+{
+    _RenewFCInputTicker.detach();
+    
+    if(_InputInstance && StopInputMethod)
+    {
+        (_InputInstance->*StopInputMethod)();
+    }
+    else if(StopInputFunction)
+    {
+        StopInputFunction();
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_FC/Out_FC.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,82 @@
+/** Class: Out_FC
+ *
+ * Output class for Famicom
+ *
+ */
+#include "mbed.h"
+#include "InputStatus.h"
+
+class Out_FC
+{
+public:
+    /** Constructor: Out_FC
+     *
+     * Parameters:
+     * pn_LATCH     - InterruptIn for LATCH       (pin12)
+     * pn_DATA      - DigitalOut for DATA         (pin13)
+     * pn_CLOCK     - InterruptIn for LATCH       (pin14)
+     * pn_POWDETECT - InterruptIn for PowerDetect (pin15)
+     * inputStatus  - Input status
+     */
+
+    Out_FC(
+        PinName pn_LATCH, PinName pn_DATA, PinName pn_CLOCK, PinName pn_POWDETECT,
+        InputStatus *inputStatus
+    );
+     
+private:
+    // Private constants
+    static const int FC_INPUTSTATE_RENEWINTERVAL__MICROSEC = 2000;
+    
+    // mbed pins
+    InterruptIn  _INTR_LATCH;
+    DigitalOut   _OUT_DATA;
+    InterruptIn  _INTR_CLOCK;
+    InterruptIn  _INTR_POWDETECT;
+
+    // Variable
+    volatile int    _Buttons;
+    volatile char   _Ch0;
+    volatile char   _Ch1;
+    volatile char   _Ch2;
+    volatile char   _InputDeviceType;
+    InputStatus     *_InputStatus;
+    Ticker          _RenewFCInputTicker;
+//  volatile char   _RapidFireValue;
+    FunctionPointer _pEnableInput;
+    FunctionPointer _pDisableInput;
+
+    // Private Method
+    void Initialize(void);
+    void RenewFCInputDataPeriodically(void);
+//  void InitInterruptPriority(void);
+
+
+
+
+
+
+// for InputControll
+public:
+    void SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void));
+    class CDummy;
+    template<class T>
+    void SetupInputControll(T* inputInstance, void (T::*startInputMethod)(void), void (T::*stopInputMethod)(void))
+    {
+        _InputInstance    = (CDummy*) inputInstance;
+        StartInputMethod = (void (CDummy::*)(void)) startInputMethod;
+        StopInputMethod  = (void (CDummy::*)(void)) stopInputMethod;
+    }
+
+private:
+    CDummy*         _InputInstance;
+    void (CDummy::*StartInputMethod)(void);
+    void (CDummy::*StopInputMethod)(void);
+    void (*StartInputFunction)(void);
+    void (*StopInputFunction)(void);
+    void EnableInput(void);
+    void DisableInput(void);
+
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_MD/CFunc_Out_MD.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,143 @@
+#include "mbed.h"
+#include "CFunc_Out_MD.h"
+#include "Out_MD.h"
+
+// mbed pins
+DigitalOut   *_OUT_D0;
+DigitalOut   *_OUT_D1;
+DigitalOut   *_OUT_D2;
+DigitalOut   *_OUT_D3;
+DigitalOut   *_OUT_LH;
+InterruptIn  *_INTR_REQ;
+DigitalOut   *_OUT_ACK;
+
+// File local variables
+static volatile int *_Buttons;
+static volatile char _flagSwapAC;
+// Static variables
+
+// File local functions
+
+
+void Cfunc_Out_MD_Initialize(
+    DigitalOut  *out_D0,
+    DigitalOut  *out_D1,
+    DigitalOut  *out_D2,
+    DigitalOut  *out_D3,
+    DigitalOut  *out_LH,
+    InterruptIn *intr_REQ,
+    DigitalOut  *out_ACK,
+    volatile int *pButtons,
+    char        flagSwapAC
+)
+{
+    // 入出力pin
+    _OUT_D0   = out_D0;
+    _OUT_D1   = out_D1;
+    _OUT_D2   = out_D2;
+    _OUT_D3   = out_D3;
+    _OUT_LH   = out_LH;
+    _INTR_REQ = intr_REQ;
+    _OUT_ACK  = out_ACK;
+
+    _flagSwapAC = flagSwapAC;
+
+    // InputStatus
+    _Buttons = pButtons;
+}
+
+void Cfunc_DigitalPeriodicPollingMethod(void)
+{
+    volatile int counter;
+    volatile int readCounter = 0;   // REQ変化を検知してからのカウンタ値
+    volatile int button = *_Buttons;    // ポインタ経由でアクセスすると処理全体で1us以上かかってしまう
+    char detectedREQ_L = 0;
+    char detectedREQ_H = 0;
+    
+    
+    counter = Out_MD::DIGITAL_PERIODICPOLLING_COUNTERMAX;
+    
+    // カウンタ>0の間だけ、真剣にポーリングする
+    while(counter--)
+    {
+                
+        if( _INTR_REQ->read() )
+        {
+            detectedREQ_H = 1;
+            
+            //RenewDigitalPadStatus(1);
+
+            // phase1出力
+            
+            // MD C
+            if(_flagSwapAC)
+            {
+                _OUT_ACK->write ( (button & 0x00200) ? 1 : 0 ); // Digital "A"
+            }
+            else
+            {
+                _OUT_ACK->write( (button & 0x00020) ? 1 : 0 ); // Digital "C"
+            }
+            // MD B
+            _OUT_LH->write ( (button & 0x00100) ? 1 : 0 ); // Digital "B"
+            // MD Right
+            _OUT_D3->write ( (button & 0x00400) ? 1 : 0 ); // Digital "Right"
+            // MD Left
+            _OUT_D2->write ( (button & 0x00800) ? 1 : 0 ); // Digital "Left"
+            // MD Down
+            _OUT_D1->write ( (button & 0x01000) ? 1 : 0 ); // Digital "Down"
+            // MD Up
+            _OUT_D0->write ( (button & 0x02000) ? 1 : 0 ); // Digital "Up"
+        }
+        else
+        {
+            detectedREQ_L = 1;
+            
+            //RenewDigitalPadStatus(0);
+
+            // phase0出力
+
+            
+            // サイバースティックのデジタルモードではStartボタンは読み取れない
+            // (カブトガニは可能)
+            // MD Start
+            _OUT_ACK->write ( ((button & 0x00010)&&(button & 0x00002)) ? 1 : 0 ); // Digital "D" & "Start"
+
+            // MD A
+            if(_flagSwapAC)
+            {
+                _OUT_LH->write( (button & 0x00020) ? 1 : 0 ); // Digital "C"
+            }
+            else
+            {
+                _OUT_LH->write ( (button & 0x00200) ? 1 : 0 ); // Digital "A"
+            }
+
+            _OUT_D3->write ( 0 );
+            _OUT_D2->write ( 0 );
+
+            // MD Down
+            _OUT_D1->write ( (button & 0x01000) ? 1 : 0 ); // Digital "Down"
+            // MD Up
+            _OUT_D0->write ( (button & 0x02000) ? 1 : 0 ); // Digital "Up"
+            
+        }
+
+        // ゲーム機からの読み取り要求開始から
+        // 一定時間たったら、ループ終了
+        if(detectedREQ_L && detectedREQ_H)
+        {
+            if(readCounter++ > 800) // だいたい1msのつもり
+            {
+                counter=0;
+                break;
+            }
+        }
+
+
+    }
+
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_MD/CFunc_Out_MD.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,13 @@
+void Cfunc_Out_MD_Initialize(
+    DigitalOut   *out_D0,
+    DigitalOut   *out_D1,
+    DigitalOut   *out_D2,
+    DigitalOut   *out_D3,
+    DigitalOut   *out_LH,
+    InterruptIn  *intr_REQ,
+    DigitalOut   *out_ACK,
+    volatile int *pButtons,
+    char         flagSwapAC
+);
+
+void Cfunc_DigitalPeriodicPollingMethod(void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_MD/Out_MD.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,755 @@
+#include "NiseKabuto.h"
+#include "CFunc_Out_MD.h"
+
+// 32Xスペハリのタイトルがおかしい問題
+// ・デジタルモードのとき、発生しない
+//   サイバースティック読み取りに原因??
+// ・Ack=Hのときにウェイトを入れても効果なし
+// ・Start押しっぱなし現象?
+// ⇒In_CSの読み取り中に割り込み禁止にすることで解決?
+
+// (Analog)ハングアップ問題;
+// この関数はメガドラからの要求の都度、呼ばれているのに、
+// _NowWritingが1のため、関数内に入らない問題
+// if(_AckCounter < 13) で直った?->だめ
+// (Analog)勝手にポーズ押しちゃう問題
+// 32Xスペハリ6面くらいまで進んだとき発生/何も操作しない状態で放置しても発生しない
+// ACK立ち上げ後のwait変えても効果なし
+// 入力クラスからは送られていない->メガドラへの送信フェーズずれた?
+//
+//  ⇒2件への対策として、Analog処理作り直し。データSetにTickerを使用しないようにする。
+//
+// (Analog)武者アレスタの動作がおかしい
+// サイバースティック読み取りルーチンの割り込み禁止のせいかも?
+
+//
+// Constructor
+//
+Out_MD::Out_MD(
+    PinName pn_D0, PinName pn_D1, PinName pn_D2, PinName pn_D3, 
+    PinName pn_LH, PinName pn_REQ, PinName pn_ACK,
+    InputStatus *inputStatus)
+      : _OUT_D0(pn_D0), _OUT_D1(pn_D1), _OUT_D2(pn_D2), _OUT_D3(pn_D3), _OUT_LH(pn_LH), _INTR_REQ(pn_REQ), _OUT_ACK(pn_ACK),
+        _DataBus(pn_D0, pn_D1, pn_D2, pn_D3)
+{
+    _InputStatus = inputStatus;
+    
+    Initialize();
+}
+
+//
+// Initialize
+//
+void Out_MD::Initialize()
+{
+    // Class Variable Setting
+    
+    // Pin Setting
+    _INTR_REQ.mode(PullUp);
+
+    // Reset Interrupt Setting
+    DisableModeChecker();
+    _INTR_REQ.fall(NULL);
+    _DigitalStateRenewTicker.detach();
+    _DigitalPeriodicPollingTicker.detach();
+    _InputMode = _InputStatus->InputDeviceType;
+    _SwapAC = 0;
+    _AnalogMUSHAMethod = 0;
+//  InitInterruptPriority();
+
+    switch(_InputMode)
+    {
+        //
+        // Input: CyberStick ANALOG mode
+        //
+        case NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG:
+            // Class Variable Setting
+            _TransferSpeed = TRANSFERSPEED_1_4__MICROSEC;   // もっとも遅い速度から開始
+        //  _TransferSpeed = TRANSFERSPEED_MAX__MICROSEC;   // 最速速度から開始
+            /*
+            if(
+                !((_InputStatus->Buttons) & 0x00003)    // Start+Selectが押されてる
+            )
+            {
+                _AnalogMUSHAMethod = 1;     // 武者アレスタ向けAnalog処理 有効
+            }
+            */
+
+            // Interrupt Setting
+            _INTR_REQ.fall(this, &Out_MD::ISR_Analog_ReqFall);
+
+            
+            // Initialize pin status
+            _OUT_D0  = 1;   
+            _OUT_D1  = 1;   
+            _OUT_D2  = 1;   
+            _OUT_D3  = 1;   
+            _OUT_LH  = 0;
+        //  _OUT_LH  = 1;   // 常にH版
+            _OUT_ACK = 1;   // output ACK = H
+            break;
+
+        //
+        // Input: CyberStick DIGITAL mode
+        // Input: MD6B
+        //
+        case NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL:
+        case NiseKabuto::CONFIG_INMODE_MD6B:
+        default:
+            if(
+                !((_InputStatus->Buttons) & 0x00020)    // Cが押されてる
+            )
+            {
+                _SwapAC = 1;
+            }
+
+            Cfunc_Out_MD_Initialize(
+                &_OUT_D0, &_OUT_D1, &_OUT_D2, &_OUT_D3,
+                &_OUT_LH, &_INTR_REQ, &_OUT_ACK,
+                &_ButtonStatus,
+                _SwapAC
+            );
+
+            EnableDigitalStateRenew();
+            RestartDigitalPeriodicPolling();
+            break;
+    }
+    
+    EnableModeChecker();
+}
+/*
+void Out_MD::InitInterruptPriority(void)
+{
+    // http://mbed.org/users/earlz/code/MbedConsole/file/370b9e559f92/main.cpp
+    
+    NVIC_SetPriority(NonMaskableInt_IRQn, 100 ); 
+    NVIC_SetPriority(MemoryManagement_IRQn, 100);
+    
+    NVIC_SetPriority(BusFault_IRQn, 100);
+    NVIC_SetPriority(UsageFault_IRQn, 100);
+    NVIC_SetPriority(SVCall_IRQn, 100);
+    NVIC_SetPriority(DebugMonitor_IRQn, 100);
+    NVIC_SetPriority(PendSV_IRQn, 100);
+    NVIC_SetPriority(SysTick_IRQn, 50);
+    NVIC_SetPriority(WDT_IRQn, 100);
+    NVIC_SetPriority(TIMER0_IRQn, 85);
+    NVIC_SetPriority(TIMER1_IRQn, 85);
+    NVIC_SetPriority(TIMER2_IRQn, 85);
+    NVIC_SetPriority(TIMER3_IRQn, 85);
+    NVIC_SetPriority(UART0_IRQn, 75);
+    NVIC_SetPriority(UART1_IRQn, 100);
+    NVIC_SetPriority(UART2_IRQn, 100);
+    NVIC_SetPriority(UART3_IRQn, 100);
+    
+    NVIC_SetPriority(PWM1_IRQn, 100);
+    NVIC_SetPriority(I2C0_IRQn, 100);
+    NVIC_SetPriority(I2C1_IRQn, 100);
+    NVIC_SetPriority(I2C2_IRQn, 100);
+    NVIC_SetPriority(SPI_IRQn, 100);
+    NVIC_SetPriority(SSP0_IRQn, 100);
+    NVIC_SetPriority(SSP1_IRQn, 100);
+    NVIC_SetPriority(PLL0_IRQn, 100);
+    NVIC_SetPriority(RTC_IRQn, 100);
+    NVIC_SetPriority(EINT0_IRQn, 100);
+    NVIC_SetPriority(EINT1_IRQn, 100);
+    
+    NVIC_SetPriority(EINT2_IRQn, 100);
+    NVIC_SetPriority(EINT3_IRQn, 0);    // 最高
+    NVIC_SetPriority(ADC_IRQn, 100);
+    NVIC_SetPriority(BOD_IRQn, 100);
+    NVIC_SetPriority(USB_IRQn, 100);
+    NVIC_SetPriority(CAN_IRQn, 100);
+    NVIC_SetPriority(DMA_IRQn, 100);
+    
+    NVIC_SetPriority(I2S_IRQn, 100);
+    NVIC_SetPriority(ENET_IRQn, 100);
+    NVIC_SetPriority(RIT_IRQn, 100);
+    NVIC_SetPriority(MCPWM_IRQn, 100);
+    NVIC_SetPriority(QEI_IRQn, 100);
+    NVIC_SetPriority(PLL1_IRQn, 100);
+    
+}
+*/
+
+
+//
+// Set output pin status
+//
+// Input:
+//   val: status of pins.  
+//   (MSB) ...|D3|D2|D1|D0| (LSB)
+//
+void Out_MD::SetPinValue(int val)
+{
+    // 意味ない
+    /*
+    _DataBus = val & 0x0f;
+    */
+    
+    _OUT_D0  = val & 0x01? 1 : 0;
+    _OUT_D1  = val & 0x02? 1 : 0;
+    _OUT_D2  = val & 0x04? 1 : 0;
+    _OUT_D3  = val & 0x08? 1 : 0;
+}
+
+
+
+
+
+//
+// 出力更新Ticker処理
+//
+void Out_MD::DigitalStateRenewMethod(void)
+{
+    
+    _ButtonStatus = _InputStatus->Buttons;
+
+    if( (_INTR_REQ) )
+    {
+        RenewDigitalPadStatus(1);
+    }
+    else
+    {
+        RenewDigitalPadStatus(0);
+    }
+
+}
+
+//
+// デジタルパッドの該当phaseのデータを出力
+//
+void Out_MD::RenewDigitalPadStatus(char phase)
+{
+
+    switch( phase )
+    {
+        case 0:
+            // phase0出力
+
+            // サイバースティックのデジタルモードではStartボタンは読み取れない
+            // (カブトガニは可能)
+            // MD Start
+            _OUT_ACK = ( (_ButtonStatus & 0x00010) ? 1 : 0 ); // Digital "D"
+
+            // MD A
+            if(_SwapAC)
+            {
+                _OUT_LH =( (_ButtonStatus & 0x00020) ? 1 : 0 ); // Digital "C"
+            }
+            else
+            {
+                _OUT_LH = ( (_ButtonStatus & 0x00200) ? 1 : 0 ); // Digital "A"
+            }
+            _OUT_D3 = ( 0 );
+            _OUT_D2 = ( 0 );
+
+            // MD Down
+            _OUT_D1 = ( (_ButtonStatus & 0x01000) ? 1 : 0 ); // Digital "Down"
+            // MD Up
+            _OUT_D0 = ( (_ButtonStatus & 0x02000) ? 1 : 0 ); // Digital "Up"
+            break;
+
+        case 1:
+            // phase1出力
+            
+            // MD C
+            if(_SwapAC)
+            {
+                _OUT_ACK = ( (_ButtonStatus & 0x00200) ? 1 : 0 ); // Digital "A"
+            }
+            else
+            {
+                _OUT_ACK =( (_ButtonStatus & 0x00020) ? 1 : 0 ); // Digital "C"
+            }
+            // MD B
+            _OUT_LH = ( (_ButtonStatus & 0x00100) ? 1 : 0 ); // Digital "B"
+            // MD Right
+            _OUT_D3 = ( (_ButtonStatus & 0x00400) ? 1 : 0 ); // Digital "Right"
+            // MD Left
+            _OUT_D2 = ( (_ButtonStatus & 0x00800) ? 1 : 0 ); // Digital "Left"
+            // MD Down
+            _OUT_D1 = ( (_ButtonStatus & 0x01000) ? 1 : 0 ); // Digital "Down"
+            // MD Up
+            _OUT_D0 = ( (_ButtonStatus & 0x02000) ? 1 : 0 ); // Digital "Up"
+            break;
+
+        default:
+            break;
+    }
+}
+
+
+
+//
+// 周期ポーリングの休みの間、デジタルパッド更新を行う/行わない
+//
+void Out_MD::EnableDigitalStateRenew(void)
+{
+    _DigitalStateRenewTicker.attach_us(
+        this, 
+        &Out_MD::DigitalStateRenewMethod, 
+        DIGITAL_STATE_RENEW_INTERVAL__MICROSEC
+    );
+}
+void Out_MD::DisableDigitalStateRenew(void)
+{
+    _DigitalStateRenewTicker.detach();
+}
+
+//
+// 周期ポーリングの開始(周期?のリセット)
+//
+void Out_MD::RestartDigitalPeriodicPolling(void)
+{
+    _DigitalPeriodicPollingTicker.detach();
+    
+    _DigitalPeriodicPollingTicker.attach_us(
+        this,
+        &Out_MD::DigitalPeriodicPollingMethod,
+        DIGITAL_PERIODICPOLLING_INTERVAL__MICROSEC
+    );
+}
+
+//
+// 周期ポーリング処理
+//
+void Out_MD::DigitalPeriodicPollingMethod(void)
+{
+    // 入力タイマ処理&休みの間の更新処理 止める
+    //  DisableInput();
+    //  DisableDigitalStateRenew();
+
+    // 割り込み禁止
+    __disable_irq();
+
+    Cfunc_DigitalPeriodicPollingMethod();
+
+    // 割り込み再開
+    __enable_irq();
+
+    
+    // 入力タイマ処理&休みの間の更新処理 再開
+    //  EnableDigitalStateRenew();
+    //  EnableInput();
+
+    RestartDigitalPeriodicPolling();
+
+}
+
+
+// 
+// InputStatusのデジタルモード・アナログモード切替を見張る
+//
+void Out_MD::EnableModeChecker(void)
+{
+    _ModeChecker.detach();
+    _ModeChecker.attach_us(
+        this,
+        &Out_MD::ModeCheckerMethod,
+        MODECHECK_INTERVAL__MICROSEC
+    );
+}
+
+void Out_MD::DisableModeChecker(void)
+{
+    _ModeChecker.detach();
+}
+
+void Out_MD::ModeCheckerMethod(void)
+{
+    // デジタル・アナログモードチェック
+    if(_InputStatus->InputDeviceType != _InputMode)
+    {
+        // モード変わってたら再Initialize
+        Initialize();
+    }
+}
+
+//
+// アナログスティック用:指定Phaseのデータを出力する
+//
+// 関数内部で_TransferSpeedを変化させている
+// 
+//
+void Out_MD::SetData_Analog_PhaseOf(char phase)
+{
+    // Get InputStatus
+    InputStatus *inp = _InputStatus;
+
+    // Set Data
+    switch(phase)
+    {
+        case 0:
+        // このとき、まだ1回目のAck立ち下げは行っていない
+            SetPinValue(
+                (((inp->Buttons) & 0x000c)) |       // E1E2
+                (((inp->Buttons) & 0x0003))         // FG
+            );
+            break;
+
+        case 1:
+        // 1回目のAck立ち下げ終了済み
+            SetPinValue(
+                (((inp->Buttons) & 0x0300) >> 6) |  // AB
+                (((inp->Buttons) & 0x0030) >> 4)    // CD
+            );
+            break;
+            
+        case 2:
+        // 2回目のAck立ち下げ終了済み
+            SetPinValue(
+                ((inp->Ch1) & 0x0f0) >> 4           // 2H
+//              0xff
+            );
+            // 最速モード
+            if(_INTR_REQ==1)
+            {
+                if(_TransferSpeed > TRANSFERSPEED_MAX__MICROSEC)
+                {
+                //  printf("MAX!!!");
+                    _TransferSpeed = TRANSFERSPEED_MAX__MICROSEC;
+                }
+            }
+            break;
+            
+        case 3:
+            SetPinValue(
+                ((inp->Ch0) & 0x0f0) >> 4           // 1H
+//              0xff
+            );
+            break;
+
+        case 4:
+            SetPinValue(
+                ((inp->Ch3) & 0x0f0) >> 4           // 4H
+            );
+
+            // 1/2倍速
+            if(_INTR_REQ==1)
+            {
+                if(_TransferSpeed > TRANSFERSPEED_1_2__MICROSEC)
+                {
+                //  printf("1/2!!!");
+                    _TransferSpeed = TRANSFERSPEED_1_2__MICROSEC;
+                }
+            }
+            break;
+
+        case 5:
+            SetPinValue(
+                ((inp->Ch2) & 0x0f0) >> 4           // 3H
+            );
+            break;
+
+        case 6:
+            SetPinValue(
+                (inp->Ch1) & 0x00f                  // 2L
+            );
+            // 1/3倍速
+            if(_INTR_REQ==1)
+            {
+                if(_TransferSpeed > TRANSFERSPEED_1_3__MICROSEC)
+                {
+                //  printf("1/3!!!");
+                    _TransferSpeed = TRANSFERSPEED_1_3__MICROSEC;
+                }
+            }
+            break;
+
+        case 7:
+            SetPinValue(
+                (inp->Ch0) & 0x00f                  // 1L
+            );
+            break;
+
+        case 8:
+            SetPinValue(
+                (inp->Ch3) & 0x00f                  // 4L
+            );
+
+            // 1/4倍速
+            // いらない気もする
+            if(_INTR_REQ==1)
+            {
+                if(_TransferSpeed >= TRANSFERSPEED_1_4__MICROSEC)
+                {
+                //  printf("1/4!!!");
+                    _TransferSpeed = TRANSFERSPEED_1_4__MICROSEC;
+                }
+            }
+            break;
+
+        case 9:
+            SetPinValue(
+                (inp->Ch2) & 0x00f                  // 3L
+                //カブトガニは固定値送ってるかも?
+                //0x0a
+            );
+            break;
+
+        case 10:
+            SetPinValue(0xff);
+            break;
+
+        case 11:
+            SetPinValue(
+                (((inp->Buttons) & 0x0300)  >> 6) |  // AB
+                (((inp->Buttons) & 0x00c0)) >>6     // A+A' B+B'
+            );
+            break;
+        
+        
+        default:
+            SetPinValue(0xff);
+            break;
+
+    }
+}
+
+//
+// ISR for REQ=L from Megadrive
+//
+void Out_MD::ISR_Analog_ReqFall()
+{
+    // 全体が間延び数現象の原因?
+    //  __disable_irq();    
+    
+    // デバッグ用:この関数が呼ばれるたび+1される
+    (_InputStatus->Temp[2])++;
+    
+    //
+    // from AJOY_SUB.DOC:
+    // --------------
+    //◆転送速度(各サイクルタイム)
+    //
+    //  ┌──────┬────┐
+    //  │ 最速モード │   50 │
+    //  │ 1/2倍速 │   96 │
+    //  │ 1/3倍速 │ 144 │
+    //  │ 1/4倍速 │ 192 │
+    //  └──────┴────┘
+    //      (単位:μsec)
+    // --------------
+    //  ジョイコンはデータ転送要求(割り込み)により
+    //  データ転送サイクルを6回繰り返す。
+    // --------------
+    //  
+    //  ↑ 以下のようなことを言いたかったのか?
+    //     ・サイバースティックは12回Ackが下がり、1回~11回目に
+    //       『◆アナログモード時のデータ』に沿ったデータを送る。
+    //       (12回目のデータは不明)
+    //     ・『データ転送サイクル』はAck2回分である(LHピンのLとHの組が1サイクル)
+    //     ・サイクルタイム=『データ転送サイクル』の周期
+    //
+    //  このように仮定すると、Ack1回分のデータは
+    //  サイクルタイム/2の間、保持していなければならないことになる。
+    //  なので、Ack1回分のデータを、サイクルタイム/2の周期で出力することとする。
+    //
+    // --------------
+    // AJOY.DOC
+    //※通信速度を最高速に設定した場合、アナログジョイスティックを
+    //  リセットしないかぎり、遅い速度への変更は行われない。
+    // --------------
+    // 本物は遅い方向には速度を変えさせない
+
+    char phase = 0;     // データPhase: 0からスタート
+    char savePhase;
+    int  us_Int1, us_Int2, us_Int3, us_Int4;
+
+    int time10, time1, time20, time2, time3, time4, time5, time6;
+
+    // 32Xスペハリ対策
+    // 待つ
+//  wait_us(40);
+    NiseKabuto::WaitUs(20);
+
+    // 現在の_TransferSpeedを元に、各時間を算出
+    us_Int1 = (int)(_TransferSpeed /12.5 );     // 速度MAX時:  4us
+    us_Int2 = (int)(_TransferSpeed / 8.3 );     // 速度MAX時:  6us
+    us_Int3 = (int)(_TransferSpeed / 4.17);     // 速度MAX時: 12us
+    us_Int4 = (int)(_TransferSpeed / 3.57);     // 速度MAX時: 14us
+
+    time10= us_Int1;
+    time20= us_Int4;
+
+    time1 = us_Int2;
+    time2 = us_Int3;
+    time3 = us_Int3;
+    time4 = us_Int1;
+    time5 = us_Int3;
+    time6 = us_Int1;
+    
+    // AckはHから開始
+    // LHはLから開始
+    _OUT_ACK = 1;
+    _OUT_LH = 0;
+    
+    
+    
+    // サイクルタイム6回分=phase0-12
+    
+    // 武者アレスタにおいて、サイクル2(phase2,3)のみ、値を送ると
+    // タイトル画面でボタンが押されてしまう不具合あり。
+    // このため、サイクル2は別のタイミングでデータを送付する。
+    // その直前のサイクル1も改める。
+
+
+
+    // サイクル1-6
+    for(int i=0; i<6; i++)
+    {
+        if(i==0)
+        {
+            // No1
+            _OUT_ACK = 1;
+            _OUT_LH = 0;
+            NiseKabuto::WaitUs(time10);
+
+            // No2
+            savePhase = phase;
+            SetData_Analog_PhaseOf(phase++);
+            _OUT_ACK = 1;
+            _OUT_LH = 0;
+            NiseKabuto::WaitUs(time20);
+        }
+        else
+        {
+            // No1
+            _OUT_ACK = 1;
+            _OUT_LH = 0;
+            NiseKabuto::WaitUs(time1-5);
+
+            // No2
+            savePhase = phase;
+            SetData_Analog_PhaseOf(phase++);
+            _OUT_ACK = 1;
+            _OUT_LH = 0;
+            NiseKabuto::WaitUs(time2);
+        }
+        
+        // No3
+        _OUT_ACK = 0;
+        _OUT_LH = 0;
+        NiseKabuto::WaitUs(time3);
+
+        // No4
+        _OUT_ACK = 1;
+        _OUT_LH = 1;
+        SetData_Analog_PhaseOf(phase++);
+        NiseKabuto::WaitUs(time4-3);
+
+        // No5
+        _OUT_ACK = 0;
+        _OUT_LH = 1;
+        NiseKabuto::WaitUs(time5);
+
+        // No6
+        _OUT_ACK = 1;
+        _OUT_LH = 1;
+        NiseKabuto::WaitUs(time6-1);
+        
+        // No7
+        _OUT_LH = 0;
+        SetData_Analog_PhaseOf(savePhase);
+    }
+/*  
+    // サイクル1-6
+    for(int i=0; i<6; i++)
+    {
+        if(i==0)
+        {
+            // No1
+            _OUT_ACK = 1;
+            _OUT_LH = 0;
+            NiseKabuto::WaitUs(time10-2);
+
+            // No2
+            savePhase = phase;
+            SetData_Analog_PhaseOf(phase++);
+            _OUT_ACK = 1;
+            _OUT_LH = 0;
+            NiseKabuto::WaitUs(time20-2);
+        }
+        else
+        {
+            // No1
+            _OUT_ACK = 1;
+            _OUT_LH = 0;
+            NiseKabuto::WaitUs(time1-3);
+
+            // No2
+            savePhase = phase;
+            SetData_Analog_PhaseOf(phase++);
+            _OUT_ACK = 1;
+            _OUT_LH = 0;
+            NiseKabuto::WaitUs(time2-2);
+        }
+        
+        // No3
+        _OUT_ACK = 0;
+        _OUT_LH = 0;
+        NiseKabuto::WaitUs(time3-1);
+
+        // No4
+        _OUT_ACK = 1;
+        _OUT_LH = 1;
+        SetData_Analog_PhaseOf(phase++);
+        NiseKabuto::WaitUs(time4-3);
+
+        // No5
+        _OUT_ACK = 0;
+        _OUT_LH = 1;
+        NiseKabuto::WaitUs(time5);
+
+        // No6
+        _OUT_ACK = 1;
+        _OUT_LH = 1;
+        NiseKabuto::WaitUs(time6-1);
+        
+        // No7
+        _OUT_LH = 0;
+        SetData_Analog_PhaseOf(savePhase);
+    }
+*/
+    _OUT_LH = 0;
+
+    // __enable_irq();  
+
+}
+
+
+
+
+
+
+
+void Out_MD::SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void))
+{
+    StartInputFunction = startInputFunction;
+    StopInputFunction  = stopInputFunction;
+}
+
+void Out_MD::EnableInput(void)
+{
+    if(_InputInstance && StartInputMethod)
+    {
+        (_InputInstance->*StartInputMethod)();
+    }
+    else if(StartInputFunction)
+    {
+        StartInputFunction();
+    }
+}
+
+void Out_MD::DisableInput(void)
+{
+    if(_InputInstance && StopInputMethod)
+    {
+        (_InputInstance->*StopInputMethod)();
+    }
+    else if(StopInputFunction)
+    {
+        StopInputFunction();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_MD/Out_MD.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,118 @@
+/** Class: Out_MD
+ *
+ * Used for writing to Megadrive analog joystick input mode
+ *
+ */
+
+#include "mbed.h"
+#include "InputStatus.h"
+
+class Out_MD
+{
+public:
+    /** Constructor: Out_MD
+     *
+     * Parameters:
+     * pn_D0  - DigitalOut for Megadrive's D0 (D-Sub 9pin connector's pin1)
+     * pn_D1  - DigitalOut for D1 (D-Sub9 pin2)
+     * pn_D2  - DigitalOut for D2 (D-Sub9 pin3)
+     * pn_D3  - DigitalOut for D3 (D-Sub9 pin4)
+     * pn_LH  - DigitalOut for L/H (D-Sub9 pin6)
+     * pn_REQ - InterruptIn for Req (D-Sub9 pin7)
+     * pn_ACK - DigitalOut for Ack (D-Sub9 pin9)
+     * inputStatus - The variable holds input status
+     */
+
+    Out_MD(
+        PinName pn_D0, PinName pn_D1, PinName pn_D2, PinName pn_D3, 
+        PinName pn_LH, PinName pn_REQ, PinName pn_ACK,
+        InputStatus *inputStatus
+    );
+/*   
+    void ShowReqInterval();
+*/
+    void SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void));
+    class CDummy;
+    template<class T>
+    void SetupInputControll(T* inputInstance, void (T::*startInputMethod)(void), void (T::*stopInputMethod)(void))
+    {
+        _InputInstance    = (CDummy*) inputInstance;
+        StartInputMethod = (void (CDummy::*)(void)) startInputMethod;
+        StopInputMethod  = (void (CDummy::*)(void)) stopInputMethod;
+    }
+
+    // Public constants
+    static const int DIGITAL_PERIODICPOLLING_COUNTERMAX         = 12000;//7300; // 周期ポーリングカウンタ最大値
+                                                                            // (ポーリングに使うカウンタ最大値)
+    
+
+private:
+    // Private constants
+    static const int REQUESTINTERVAL__MICROSEC      = 10000; // reading period 10msec
+    static const int TRANSFERSPEED_MAX__MICROSEC    = 50;    // from AJOY_SUB.DOC
+    static const int TRANSFERSPEED_1_2__MICROSEC    = 96;
+    static const int TRANSFERSPEED_1_3__MICROSEC    = 144;
+    static const int TRANSFERSPEED_1_4__MICROSEC    = 192;
+
+    static const int DIGITAL_PERIODICPOLLING_INTERVAL__MICROSEC = 7000;//10000; // 周期ポーリングの間隔
+                                                                            // (フレーム毎のゲーム機からのパッド読み取りの
+                                                                            //   前後のみ、集中してポーリングを行う)
+
+    static const int DIGITAL_STATE_RENEW_INTERVAL__MICROSEC     = 2000;     // 周期ポーリングの休みの間、デジタルパッド更新
+    static const int MODECHECK_INTERVAL__MICROSEC   = 2000;                 // InputStatusのデジタルモード・アナログモード切替を見張る間隔
+
+    // mbed pins
+    DigitalOut   _OUT_D0;
+    DigitalOut   _OUT_D1;
+    DigitalOut   _OUT_D2;
+    DigitalOut   _OUT_D3;
+    DigitalOut   _OUT_LH;
+    InterruptIn  _INTR_REQ;
+    DigitalOut   _OUT_ACK;
+    BusOut       _DataBus;
+
+    // Variables
+    InputStatus     *_InputStatus;
+    volatile char   _InputMode;
+    int             _TransferSpeed;
+    Ticker          _DigitalStateRenewTicker;
+    Ticker          _DigitalPeriodicPollingTicker;
+    Ticker          _ModeChecker;
+    volatile int    _ButtonStatus;
+    char            _SwapAC;            // Aボタン-Cボタンをスワップする?(マスターシステム向け)
+    char            _AnalogMUSHAMethod; // 武者アレスタ向けAnalog処理を使う?
+    
+    CDummy*         _InputInstance;
+
+    
+    // Private Method
+    void Initialize(void);
+//  void InitInterruptPriority(void);
+    void ISR_Analog_ReqFall(void);
+    void SetPinValue(int val);
+    void SetData_Analog_PhaseOf(char phase);
+
+    void DigitalStateRenewMethod(void);
+    void EnableDigitalStateRenew(void);
+    void DisableDigitalStateRenew(void);
+    void RenewDigitalPadStatus(char phase);
+
+    void RestartDigitalPeriodicPolling(void);
+    void DigitalPeriodicPollingMethod(void);
+
+    void EnableModeChecker(void);
+    void DisableModeChecker(void);
+    void ModeCheckerMethod(void);
+
+
+
+
+    void (CDummy::*StartInputMethod)(void);
+    void (CDummy::*StopInputMethod)(void);
+    void (*StartInputFunction)(void);
+    void (*StopInputFunction)(void);
+
+    void EnableInput(void);
+    void DisableInput(void);
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_PCE/Cfunc_PCEDigital.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,151 @@
+#include "mbed.h"
+#include "Cfunc_PCEDigital.h"
+
+// mbed pins
+DigitalOut  *_OUT_1Y;
+DigitalOut  *_OUT_2Y;
+DigitalOut  *_OUT_3Y;
+DigitalOut  *_OUT_4Y;
+//BusOut      *_OUT_BUS;
+InterruptIn *_INTR_DSEL;
+InterruptIn *_INTR_ST;
+
+// File local variables
+static volatile char    *_PhaseData;    //PhaseData[12]
+static volatile char    *_pRapidFireValue;
+static volatile char    *_pTemp;
+
+// Static variables
+static const int DIGITALPAD_PHASECOUNT_MAX = 10;
+
+// File local functions
+void DSelRiseISR(void);
+//void StrobeRiseISR(void);
+static void SetOutputPinsValue(char dat);
+
+
+
+void Cfunc_PCEDigital_Initialize(
+    DigitalOut  *out_1Y,
+    DigitalOut  *out_2Y,
+    DigitalOut  *out_3Y,
+    DigitalOut  *out_4Y,
+    //BusOut      *out_bus,
+    InterruptIn *intr_DSEL,
+    InterruptIn *intr_ST,
+    volatile char *pPhaseData,
+    volatile char *pRapidFireValue,
+    volatile char   *pTemp
+    /*
+    volatile char   *pCh0,
+    volatile char   *pCh1,
+    volatile char   *pCh2,
+    volatile int    *pButtons,
+    volatile char   *pInputDeviceType
+    */
+)
+{
+    // 入出力pin
+    _OUT_1Y     = out_1Y;
+    _OUT_2Y     = out_2Y;
+    _OUT_3Y     = out_3Y;
+    _OUT_4Y     = out_4Y;
+    //_OUT_BUS    = out_bus;
+    _INTR_DSEL  = intr_DSEL;
+    _INTR_ST    = intr_ST;
+
+    // PhaseDataポインタ
+    _PhaseData = pPhaseData;
+    
+    _pRapidFireValue = pRapidFireValue;
+    
+    _pTemp =pTemp;
+    
+    // Inetrrupt Setting
+//    _INTR_DSEL->rise(&DSelRiseISR);
+    _INTR_ST->rise(&DSelRiseISR);
+
+    // Initialize pin status
+    SetOutputPinsValue(0x00);
+    
+}
+
+
+void DSelRiseISR(void)
+{
+    //printf("I\r\n");
+    //////////////////////////////////////
+    char dselStatus =0;
+    //char loopCounter = 200;
+    int loopCounter = 200;
+
+    // Phase0(DSEL=1)の期間、待機
+    while( (_INTR_DSEL->read()) )
+    {
+        
+        loopCounter--;
+        if( loopCounter<0 )
+        {
+            break;
+        }
+        
+    }
+    
+    
+    // ただちにPhase1に移行
+    // Set data for current phase
+    SetOutputPinsValue(_PhaseData[1]);
+    
+    // 開始
+    for(int i=2; i< DIGITALPAD_PHASECOUNT_MAX; i++ )
+    {
+         loopCounter = 200;
+        
+        while( _INTR_DSEL->read()==dselStatus )
+        {
+            
+            loopCounter--;
+            if( loopCounter<0 )
+            {
+                break;
+            }
+            
+        }
+
+        // Set data for current phase
+        SetOutputPinsValue(_PhaseData[i]);
+
+    
+        dselStatus = !dselStatus;
+    }
+
+    loopCounter = 200;
+    while( _INTR_DSEL->read()==dselStatus )
+    {
+        loopCounter--;
+        if( loopCounter<0 )
+        {
+            break;
+        }
+    }
+    SetOutputPinsValue(_PhaseData[0]);
+
+    *_pRapidFireValue = !(*_pRapidFireValue);
+    //printf("O\r\n");
+    (*_pTemp)++;    // デバッグ用
+
+    //NVIC_EnableIRQ(TIMER3_IRQn); // Tickerルーチンが呼ばれなくなる問題
+    //LPC_TIM3->IR = 0xff;                    // clear interrupt flags
+    //LPC_TIM3->TCR = 1;           // Enable Timer 悪化
+}
+
+
+
+void SetOutputPinsValue(char dat)
+{
+    _OUT_1Y->write(  dat & 1       );
+    _OUT_2Y->write( (dat & 2) >> 1 );
+    _OUT_3Y->write( (dat & 4) >> 2 );
+    _OUT_4Y->write( (dat & 8) >> 3 );
+    //_OUT_BUS->write(dat);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_PCE/Cfunc_PCEDigital.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,21 @@
+#include "mbed.h"
+
+void Cfunc_PCEDigital_Initialize(
+    DigitalOut      *out_1Y,
+    DigitalOut      *out_2Y,
+    DigitalOut      *out_3Y,
+    DigitalOut      *out_4Y,
+    //BusOut            *out_bus,
+    InterruptIn *intr_DSEL,
+    InterruptIn *intr_ST,
+    volatile char *pPhaseData,
+    volatile char *pRapidFireValue,
+    volatile char   *pTemp
+    /*
+    volatile char   *pCh0,
+    volatile char   *pCh1,
+    volatile char   *pCh2,
+    volatile int    *pButtons,
+    volatile char   *pInputDeviceType
+    */
+);
--- /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();
+    }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_PCE/Out_PCE.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,128 @@
+/** Class: Out_PCE
+ *
+ * Output class for PC-Engine Analog/Digital stick
+ *
+ */
+
+// ゲームごとによって微妙なタイミングの差異があると思われる。
+// XHE-3実機があればもっと調査できたかもしれない。
+
+#include "mbed.h"
+#include "InputStatus.h"
+
+class Out_PCE
+{
+public:
+    /** Constructor: Out_PCE
+     *
+     * Parameters:
+     * pn_1Y        - DigitalOut for 1Y(Up/trigI)     (PCE pad connector's pin2)
+     * pn_2Y        - DigitalOut for 2Y(Right/trigII) (pin3)
+     * pn_3Y        - DigitalOut for 3Y(Down/Select)  (pin4)
+     * pn_4Y        - DigitalOut for 4Y(Left/Run)     (pin5)
+     * pn_DSEL      - InterruptIn for DATASEL         (pin6)
+     * pn_ST        - InterruptIn for /STROBE         (pin7)
+     * pn_POWDETECT - InterruptIn for PowerDetect     (pin1)
+     * inputStatus  - Input status
+     */
+
+    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
+    );
+     
+private:
+    // Private constants
+    // ---- Analog ----
+    static const int TRANSFERSPEED_MAX__MICROSEC    = 50;    // from AJOY_SUB.DOC
+    static const int TRANSFERSPEED_1_2__MICROSEC    = 96;
+    static const int TRANSFERSPEED_1_3__MICROSEC    = 144;
+    static const int TRANSFERSPEED_1_4__MICROSEC    = 192;
+    static const int MODECHECKPERIOD__MICROSEC      = 5000;
+    // ---- Digital ----
+    static const int DIGITALPAD_PHASECOUNT_MAX              = 10;
+    static const int DIGITALPAD_STATERENEWINTERVAL__MICROSEC= 5000;
+    
+    // mbed pins
+    DigitalOut   _OUT_1Y;
+    DigitalOut   _OUT_2Y;
+    DigitalOut   _OUT_3Y;
+    DigitalOut   _OUT_4Y;
+    InterruptIn  _INTR_DSEL;
+    InterruptIn  _INTR_ST;
+    InterruptIn  _INTR_POWDETECT;
+
+    // Variable
+    volatile char   _OutputMode;
+    InputStatus     *_InputStatus;
+    volatile char   _NowWriting;
+    volatile char   _DataSelectStatus;
+
+    volatile char   _PhaseCounter;
+    Ticker          _PhaseChangeTicker;
+    int             _TransferSpeed;
+
+    volatile char   _Buttons;
+    volatile char   _Ch0;
+    volatile char   _Ch1;
+    volatile char   _Ch2;
+
+    volatile char   _RapidFireValue;
+    volatile char   _PhaseData[12];
+
+    Ticker          _PCEPowerCheckTicker;
+    volatile int    _PCEActiveCounter;  // 不要?
+
+    Ticker          _DigitalPadPhase0SetTicker;
+    
+    Ticker          _ModeCheckTicker;
+    
+    // Private Method
+    void Initialize(void);
+    void InitializePowerChecker(void);
+    void SetOutputPinsValue(char dat);
+    void SetOutputPinsValue2(char dat);
+    void RenewPins(void);
+    
+    void DSelFallISR(void);
+    void DSelRiseISR(void);
+    void StrobeFallISR(void);
+    void StrobeRiseISR(void);
+    
+    void AttachTicker(void);
+    void DetachTicker(void);
+    void ChangePhase(void);
+
+    void Enable_DigitalPadPhase0SetTicker(void);
+    void Digital_TickerMethod(void);
+    void Digital_SetDataOfPhase(char phaseCounter);
+//    void InitInterruptPriority(void);
+    void ModeChecker(void);
+
+//
+// for InputControll
+//
+public:
+    void SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void));
+    class CDummy;
+    template<class T>
+    void SetupInputControll(T* inputInstance, void (T::*startInputMethod)(void), void (T::*stopInputMethod)(void))
+    {
+        _InputInstance    = (CDummy*) inputInstance;
+        StartInputMethod = (void (CDummy::*)(void)) startInputMethod;
+        StopInputMethod  = (void (CDummy::*)(void)) stopInputMethod;
+    }
+
+private:
+    CDummy*         _InputInstance;
+    void (CDummy::*StartInputMethod)(void);
+    void (CDummy::*StopInputMethod)(void);
+    void (*StartInputFunction)(void);
+    void (*StopInputFunction)(void);
+    void EnableInput(void);
+    void DisableInput(void);
+
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_PS3USB/Out_PS3USB.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,170 @@
+#include "NiseKabuto.h"
+
+//
+// Constructor
+//
+Out_PS3USB::Out_PS3USB(InputStatus *inputStatus)
+{
+//  wait(1);
+    _InputStatus = inputStatus;
+    _MyJS = new USBJoystick();
+    Initialize();
+}
+
+//
+// Initialize
+//
+void Out_PS3USB::Initialize()
+{
+
+    // Pin Setting
+
+    // Class Variable Setting
+    
+    // Interrupt Setting
+    _USBUpdateTicker.attach_us(this, &Out_PS3USB::USBUpdate, USBUPDATEINTERVAL__MSEC*1000);
+}
+
+
+//
+// USB Joystick Update Method
+//
+void Out_PS3USB::USBUpdate()
+{
+    int16_t x;
+    int16_t y;
+    int16_t z;
+    int16_t rz;
+    uint32_t buttons;
+    uint8_t button_hat;
+    
+    int in_Buttons;
+    
+    in_Buttons = _InputStatus->Buttons;
+    
+    // Dボタンが押されている/押されていないで送る情報を変える
+    
+    if( (in_Buttons & 0x0010) )
+    {
+        // Dボタン押されてない
+        
+        x =  (int)(0x80 + _InputStatus->Ch1)& 0xff; // x
+        y =  (int)(0x80 + _InputStatus->Ch0)& 0xff; // y
+        z =  (int)(0x80 + 0x80)     & 0xff;         // z
+        rz = (int)(0x80 + _InputStatus->Ch2)& 0xff; // rz
+
+        buttons = 
+            ((in_Buttons & 0x0020)? 0: 0x0001) |    // button   □
+            ((in_Buttons & 0x0100)? 0: 0x0002) |    //          ×
+            ((in_Buttons & 0x0200)? 0: 0x0004) |    //          ○
+                                            0  |    //          △
+            ((in_Buttons & 0x0008)? 0: 0x0010) |    //          L1
+            ((in_Buttons & 0x0004)? 0: 0x0020) |    //          R1
+                                            0  |    //          L2
+                                            0  |    //          R2
+            ((in_Buttons & 0x0001)? 0: 0x0100) |    //          SELECT
+            ((in_Buttons & 0x0002)? 0: 0x0200) |    //          START
+                                            0  |    //          L3
+                                            0  |    //          R3
+                                            0  ;    //          PS button
+
+        button_hat = 0;
+
+    }
+    else
+    {
+        // Dボタン押されてる
+        
+        x =  (int)(0x80 + 0x80)& 0xff;                  // x
+        y =  (int)(0x80 + 0x80)& 0xff;                  // y
+        z =  (int)(0x80 + _InputStatus->Ch2) & 0xff;    // z
+        rz = (int)(0x80 + 0x80)& 0xff;                  // rz
+
+        buttons = 
+                                            0  |    // button   □
+                                            0  |    //          ×
+                                            0  |    //          ○
+            ((in_Buttons & 0x0100)? 0: 0x0008) |    //          △
+                                            0  |    //          L1
+                                            0  |    //          R1
+            ((in_Buttons & 0x0008)? 0: 0x0040) |    //          L2
+            ((in_Buttons & 0x0004)? 0: 0x0080) |    //          R2
+                                            0  |    //          SELECT
+                                            0  |    //          START
+            ((in_Buttons & 0x0200)? 0: 0x0400) |    //          L3
+            ((in_Buttons & 0x0020)? 0: 0x0800) |    //          R3
+            ((in_Buttons & 0x0002)? 0: 0x1000) ;    //          PS button
+
+        button_hat =
+            (( (_InputStatus->Ch0<0x20) )? 0x01: 0) |   // hat  up
+            (( (_InputStatus->Ch0>0xe0) )? 0x02: 0) |   //      down
+            (( (_InputStatus->Ch1<0x10) )? 0x04: 0) |   //      left
+            (( (_InputStatus->Ch1>0xe0) )? 0x08: 0) ;   //      right
+    }
+    
+    _MyJS->update(x, y, z, rz, buttons, button_hat);
+    
+    /*
+    _MyJS->update(  //int16_t x, int16_t y, int16_t z, int16_t rz, uint32_t buttons, uint8_t button_hat
+        (int)(0x80 + _InputStatus->Ch1)& 0xff,  // x
+        (int)(0x80 + _InputStatus->Ch0)& 0xff,  // y
+        (int)(0x80 + 0x80)     & 0xff,          // z
+        (int)(0x80 + _InputStatus->Ch2)& 0xff,  // rz
+
+        ((_InputStatus->Buttons & 0x0020)? 0: 0x0001) |                                 // button   □
+        ((_InputStatus->Buttons & 0x0100)? 0: 0x0002) |                                 //          ×
+        ((_InputStatus->Buttons & 0x0200)? 0: 0x0004) |                                 //          ○
+        ((!(_InputStatus->Buttons & 0x0010) && !(_InputStatus->Buttons & 0x0100))? 0x0008: 0) | //          △
+        ((_InputStatus->Buttons & 0x0008)? 0: 0x0010) |                                 //          L1
+        ((_InputStatus->Buttons & 0x0004)? 0: 0x0020) |                                 //          R2
+        ((!(_InputStatus->Buttons & 0x0010) && !(_InputStatus->Buttons & 0x0008))? 0x0040: 0) | //          L2
+        ((!(_InputStatus->Buttons & 0x0010) && !(_InputStatus->Buttons & 0x0004))? 0x0080: 0) | //          R2
+        ((_InputStatus->Buttons & 0x0001)? 0: 0x0100) |                                 //          SELECT
+        ((_InputStatus->Buttons & 0x0002)? 0: 0x0200) |                                 //          START
+        ((!(_InputStatus->Buttons & 0x0010) && (_InputStatus->Ch2<0x20))? 0x0400: 0)        |   //          L3?
+        ((!(_InputStatus->Buttons & 0x0010) && (_InputStatus->Ch2>0xe0))? 0x0800: 0)        |   //          R3?
+        ((!(_InputStatus->Buttons & 0x0010) && !(_InputStatus->Buttons & 0x0002))? 0x1000: 0),  //          PS button
+
+        ((!(_InputStatus->Buttons & 0x0010) && (_InputStatus->Ch0<0x20))? 0x01: 0) |    // hat  up
+        ((!(_InputStatus->Buttons & 0x0010) && (_InputStatus->Ch0>0xe0))? 0x02: 0) |    //      down
+        ((!(_InputStatus->Buttons & 0x0010) && (_InputStatus->Ch1<0x10))? 0x04: 0) |    //      left
+        ((!(_InputStatus->Buttons & 0x0010) && (_InputStatus->Ch1>0xe0))? 0x08: 0)      //      right
+    );
+    */
+}
+
+
+
+
+
+void Out_PS3USB::SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void))
+{
+    StartInputFunction = startInputFunction;
+    StopInputFunction  = stopInputFunction;
+}
+
+void Out_PS3USB::EnableInput(void)
+{
+    if(_InputInstance && StartInputMethod)
+    {
+        (_InputInstance->*StartInputMethod)();
+    }
+    else if(StartInputFunction)
+    {
+        StartInputFunction();
+    }
+}
+
+void Out_PS3USB::DisableInput(void)
+{
+    if(_InputInstance && StopInputMethod)
+    {
+        (_InputInstance->*StopInputMethod)();
+    }
+    else if(StopInputFunction)
+    {
+        StopInputFunction();
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_PS3USB/Out_PS3USB.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,63 @@
+/** Class: Out_PS3USB
+ *
+ * Output class for PlayStation3 USB Joystick
+ *
+ */
+
+#include "mbed.h"
+#include "InputStatus.h"
+#include "USBJoystick.h"
+
+class Out_PS3USB
+{
+public:
+    /** Constructor: Out_PS3USB
+     *
+     * Parameters:
+     * inputStatus  - Input status
+     */
+
+    Out_PS3USB(InputStatus *inputStatus);
+
+private:
+    // Private constants
+    static const int USBUPDATEINTERVAL__MSEC = 10;
+    
+    // mbed pins
+
+    // Variable
+    InputStatus *_InputStatus;
+    USBJoystick *_MyJS;
+    Ticker      _USBUpdateTicker;
+    
+    // Private Method
+    void Initialize(void);
+    void USBUpdate(void);
+//    void InitInterruptPriority(void);
+
+
+
+// for InputControll
+public:
+    void SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void));
+    class CDummy;
+    template<class T>
+    void SetupInputControll(T* inputInstance, void (T::*startInputMethod)(void), void (T::*stopInputMethod)(void))
+    {
+        _InputInstance    = (CDummy*) inputInstance;
+        StartInputMethod = (void (CDummy::*)(void)) startInputMethod;
+        StopInputMethod  = (void (CDummy::*)(void)) stopInputMethod;
+    }
+
+private:
+    CDummy*         _InputInstance;
+    void (CDummy::*StartInputMethod)(void);
+    void (CDummy::*StopInputMethod)(void);
+    void (*StartInputFunction)(void);
+    void (*StopInputFunction)(void);
+    void EnableInput(void);
+    void DisableInput(void);
+
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_PS3USB/USBHID/USBDevice.lib	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/samux/code/USBDevice/#ac5cca60029a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_PS3USB/USBHID/USBJoystick.cpp	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,254 @@
+/* Copyright (c) 2010-2011 mbed.org, MIT License
+* Modified Mouse code for Joystick - WH 2012
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+* and associated documentation files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all copies or
+* substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "stdint.h"
+#include "USBJoystick.h"
+
+bool USBJoystick::update(int16_t x, int16_t y, int16_t z, int16_t rz, uint32_t buttons, uint8_t stick)
+{
+    HID_REPORT report;
+    int idx = 0;
+    
+    _x = x;
+    _y = y;
+    _z = z;
+    _rz = rz;
+    _buttons = buttons;
+    _stick = stick;
+
+    unsigned char hatswitch;
+    if (_stick & JOYSTICK_UP) {
+        hatswitch = 0;
+        if (_stick & JOYSTICK_RIGHT) hatswitch = 1;
+        if (_stick & JOYSTICK_LEFT) hatswitch = 7;
+    } else if (_stick & JOYSTICK_RIGHT) {
+        hatswitch = 2;
+        if (_stick & JOYSTICK_DOWN) hatswitch = 3;
+    } else if (_stick & JOYSTICK_DOWN) {
+        hatswitch = 4;
+        if (_stick & JOYSTICK_LEFT) hatswitch = 5;
+    } else if (_stick & JOYSTICK_LEFT) {
+        hatswitch = 6;
+    } else {
+        hatswitch = 0xf;
+    }
+
+   // Fill the report according to the Joystick Descriptor
+    report.data[idx++] = _buttons & 0xff;
+    report.data[idx++] = (_buttons>>8) & 0xff;
+    report.data[idx++] = hatswitch & 0x0f;
+    report.data[idx++] = _x + 0x80;
+    report.data[idx++] = _y + 0x80;
+    report.data[idx++] = _z + 0x80;
+    report.data[idx++] = _rz + 0x80;
+
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.length = idx; 
+
+    return send(&report);
+}
+ 
+bool USBJoystick::update() 
+{
+    HID_REPORT report;
+    int idx = 0;
+
+    unsigned char hatswitch;
+    if (_stick & JOYSTICK_UP) {
+        hatswitch = 0;
+        if (_stick & JOYSTICK_RIGHT) hatswitch = 1;
+        if (_stick & JOYSTICK_LEFT) hatswitch = 7;
+    } else if (_stick & JOYSTICK_RIGHT) {
+        hatswitch = 2;
+        if (_stick & JOYSTICK_DOWN) hatswitch = 3;
+    } else if (_stick & JOYSTICK_DOWN) {
+        hatswitch = 4;
+        if (_stick & JOYSTICK_LEFT) hatswitch = 5;
+    } else if (_stick & JOYSTICK_LEFT) {
+        hatswitch = 6;
+    } else {
+        hatswitch = 0xf;
+    }
+
+   // Fill the report according to the Joystick Descriptor
+    report.data[idx++] = _buttons & 0xff;
+    report.data[idx++] = (_buttons>>8) & 0xff;
+    report.data[idx++] = hatswitch & 0x0f;
+    report.data[idx++] = _x + 0x80;
+    report.data[idx++] = _y + 0x80;
+    report.data[idx++] = _z + 0x80;
+    report.data[idx++] = _rz + 0x80;
+
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.data[idx++] = 0;
+    report.length = idx; 
+
+    return send(&report);
+}
+
+
+
+void USBJoystick::_init() 
+{
+    _x = 0;
+    _y = 0;
+    _z = 0;
+    _rz = 0;
+    _buttons = 0;
+    _stick = 0;
+}
+
+
+uint8_t * USBJoystick::reportDesc() 
+{
+    static uint8_t reportDescriptor[] = 
+    {
+        0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+        0x09, 0x05, // USAGE (Gamepad)
+        0xa1, 0x01, // COLLECTION (Application)
+
+        0x15, 0x00, //   LOGICAL_MINIMUM (0)
+        0x25, 0x01, //   LOGICAL_MAXIMUM (1)
+        0x35, 0x00, //   PHYSICAL_MINIMUM (0)
+        0x45, 0x01, //   PHYSICAL_MAXIMUM (1)
+        0x75, 0x01, //   REPORT_SIZE (1)
+        0x95, 0x0d, //   REPORT_COUNT (13)
+        0x05, 0x09, //   USAGE_PAGE (Button)
+        0x19, 0x01, //   USAGE_MINIMUM (Button 1)
+        0x29, 0x0d, //   USAGE_MAXIMUM (Button 13)
+        0x81, 0x02, //   INPUT (Data,Var,Abs)
+        0x95, 0x03, //   REPORT_COUNT (3)
+        0x81, 0x01, //   INPUT (Cnst,Ary,Abs)
+        0x05, 0x01, //   USAGE_PAGE (Generic Desktop)
+        0x25, 0x07, //   LOGICAL_MAXIMUM (7)
+        0x46, 0x3b, 0x01, //   PHYSICAL_MAXIMUM (315)
+        0x75, 0x04, //   REPORT_SIZE (4)
+        0x95, 0x01, //   REPORT_COUNT (1)
+        0x65, 0x14, //   UNIT (Eng Rot:Angular Pos)
+        0x09, 0x39, //   USAGE (Hat switch)
+        0x81, 0x42, //   INPUT (Data,Var,Abs,Null)
+        0x65, 0x00, //   UNIT (None)
+        0x95, 0x01, //   REPORT_COUNT (1)
+        0x81, 0x01, //   INPUT (Cnst,Ary,Abs)
+
+        0x26, 0xff, 0x00, //   LOGICAL_MAXIMUM (255)
+        0x46, 0xff, 0x00, //   PHYSICAL_MAXIMUM (255)
+        0x09, 0x30, //   USAGE (X)
+        0x09, 0x31, //   USAGE (Y)
+        0x09, 0x32, //   USAGE (Z)
+        0x09, 0x35, //   USAGE (Rz)
+        0x75, 0x08, //   REPORT_SIZE (8)
+        0x95, 0x04, //   REPORT_COUNT (4)
+        0x81, 0x02, //   INPUT (Data,Var,Abs)
+
+        0x06, 0x00, 0xff, //   USAGE_PAGE (Vendor Specific)
+        0x09, 0x20, //   Unknown
+        0x09, 0x21, //   Unknown
+        0x09, 0x22, //   Unknown
+        0x09, 0x23, //   Unknown
+        0x09, 0x24, //   Unknown
+        0x09, 0x25, //   Unknown
+        0x09, 0x26, //   Unknown
+        0x09, 0x27, //   Unknown
+        0x09, 0x28, //   Unknown
+        0x09, 0x29, //   Unknown
+        0x09, 0x2a, //   Unknown
+        0x09, 0x2b, //   Unknown
+        0x95, 0x0c, //   REPORT_COUNT (12)
+        0x81, 0x02, //   INPUT (Data,Var,Abs)
+        0x0a, 0x21, 0x26, //   Unknown
+        0x95, 0x08, //   REPORT_COUNT (8)
+        0xb1, 0x02, //   FEATURE (Data,Var,Abs)
+
+        0xc0, // END_COLLECTION
+        
+    /*  
+        USAGE_PAGE(1),      0x01,
+        USAGE(1),           0x04,
+        COLLECTION(1),      0x01,
+        USAGE(1),           0x01,
+        COLLECTION(1),      0x00,
+
+        USAGE_PAGE(1),      0x09,
+        USAGE_MINIMUM(1),       0x01,
+        USAGE_MAXIMUM(1),       0x0C,
+        LOGICAL_MINIMUM(1),     0x00,
+        LOGICAL_MAXIMUM(1),     0x01,
+        PHYSICAL_MINIMUM(1),    0x00,
+        PHYSICAL_MAXIMUM(1),    0x01,
+        REPORT_SIZE(1),     0x01,
+        REPORT_COUNT(1),    0x0C,
+        INPUT(1),           0x02,
+
+        USAGE_PAGE(1),      0x01,
+        USAGE(1),           0x39,
+        LOGICAL_MINIMUM(1),     0x00,
+        LOGICAL_MAXIMUM(1),     0x07,
+        PHYSICAL_MINIMUM(1),    0x00,
+        PHYSICAL_MAXIMUM(2),    0x3B, 0x01,
+        UNIT(1),            0x14,
+        REPORT_SIZE(1),     0x04,
+        REPORT_COUNT(1),    0x01,
+        INPUT(1),           0x42,
+
+        USAGE_PAGE(1),      0x01,
+        USAGE(1),           0x30,
+        USAGE(1),           0x31,
+        USAGE(1),           0x32,
+        USAGE(1),           0x35,
+        LOGICAL_MINIMUM(1),     0x00,
+        LOGICAL_MAXIMUM(2),     0xff, 0x00,
+        PHYSICAL_MINIMUM(1),    0x00,
+        PHYSICAL_MAXIMUM(2),    0xff, 0x00,
+        UNIT(2),            0x00, 0x00,
+        REPORT_SIZE(1),     0x08,
+        REPORT_COUNT(1),    0x04,
+        INPUT(1),           0x02,
+
+        END_COLLECTION(0),
+        END_COLLECTION(0),
+    */
+    };
+
+      reportLength = sizeof(reportDescriptor);
+      return reportDescriptor;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_PS3USB/USBHID/USBJoystick.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,77 @@
+/* USBJoystick.h */
+/* USB device example: Joystick*/
+/* Copyright (c) 2011 ARM Limited. All rights reserved. */
+/* Modified Mouse code for Joystick - WH 2012 */
+
+// PS3向け改修版
+
+#ifndef USBJOYSTICK_H
+#define USBJOYSTICK_H
+
+#include "USBHID.h"
+
+#define REPORT_ID_JOYSTICK  4
+
+#define JOYSTICK_UP    (1<<0)
+#define JOYSTICK_DOWN  (1<<1)
+#define JOYSTICK_LEFT  (1<<2)
+#define JOYSTICK_RIGHT (1<<3)
+
+class USBJoystick: public USBHID
+{
+    private:
+        int8_t      _x;
+        int8_t      _y;
+        int8_t      _z;
+        int8_t      _rz;
+        uint32_t        _buttons;
+        uint8_t     _stick; 
+        
+        void _init();
+
+   public:
+        /**
+         *   Constructor
+         *
+         * @param vendor_id Your vendor_id (default: 0x1234)
+         * @param product_id Your product_id (default: 0x0002)
+         * @param product_release Your product_release (default: 0x0001)
+         */
+         USBJoystick(uint16_t vendor_id = 0x1234, uint16_t product_id = 0x0100, uint16_t product_release = 0x0001): 
+             USBHID(0, 0, vendor_id, product_id, product_release, false)
+             { 
+                 _init();
+                 connect();
+             };
+         
+         /**
+         * Write a state of the mouse
+         *
+         * @param x  x-axis position
+         * @param y  y-axis position
+         * @param z  z-axis position
+         * @param rz rotate-z position
+         * @param buttons buttons state
+         * @param stick rest of buttons, and hat state 0 (up), 1 (right, 2 (down), 3 (left) or 4 (neutral)
+         * @returns true if there is no error, false otherwise
+         */
+         bool update(int16_t x, int16_t y, int16_t z, int16_t rz, uint32_t buttons, uint8_t stick);
+
+         /**
+         * Write a state of the mouse
+         *
+         * @returns true if there is no error, false otherwise
+         */
+         bool update();
+
+         
+         /*
+         * To define the report descriptor. Warning: this method has to store the length of the report descriptor in reportLength.
+         *
+         * @returns pointer to the report descriptor
+         */
+         virtual uint8_t * reportDesc();
+
+};
+
+#endif
\ No newline at end of file
--- /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();
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Out_SSMulCon/Out_SSMulCon.h	Sat Jul 27 14:05:47 2013 +0000
@@ -0,0 +1,113 @@
+/** Class: Out_SSMulCon
+ *
+ * Output class for Sega Saturn's Sega Multi Controller
+ *
+ */
+
+/*
+注意書き・特殊操作
+
+・入力デバイス:サイバースティックアナログモードのとき
+  - サターンからはマルコンアナログモードに見える
+  - G(SELECT)を押しながら上下左右スティック・・・十字キー操作
+  - G(SELECT)を押しながらスロットル操作    ・・・LRキー操作
+
+・入力デバイス:サイバースティックデジタルモードのとき
+  - サターンからはマルコンデジタルモードに見える
+  - DボタンがStartキーになる
+
+・入力デバイス:ファイティングパッド6Bのとき
+  - サターンからはマルコンデジタルモードに見える
+  - modeキー押しながらトリガ・・・連射
+  - modeキー左右・・・LRキー操作
+
+*/
+
+#include "mbed.h"
+#include "InputStatus.h"
+
+class Out_SSMulCon
+{
+public:
+    /** Constructor: Out_SSMulcon
+     *
+     * Parameters:
+     * pn_D0        - DigitalOut for D0 (SS pad connector's pin3)
+     * pn_D1        - DigitalOut for D1 (pin2)
+     * pn_D2        - DigitalOut for D2 (pin8)
+     * pn_D3        - DigitalOut for D3 (pin7)
+     * pn_TL        - InterruptIn for TL - L=DataEnable (pin4)
+     * pn_TR        - InterruptIn for TR - Clock (pin5)
+     * pn_TH        - DigitalOut for TH (pin6)
+     * inputStatus  - Input status
+     */
+
+    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
+    );
+     
+private:
+    // Private constants
+    static const char OUTPUTMODE_ANALOG  = 0;
+    static const char OUTPUTMODE_DIGITAL = 1;
+    static const char OUTPUTMODE_6B      = 2;
+    
+    // mbed pins
+    DigitalOut   _OUT_D0;
+    DigitalOut   _OUT_D1;
+    DigitalOut   _OUT_D2;
+    DigitalOut   _OUT_D3;
+    InterruptIn  _INTR_TL;
+    InterruptIn  _INTR_TR;
+    DigitalOut   _OUT_TH;
+
+    // Variable
+    InputStatus     *_InputStatus;
+    char            _OutputMode;
+    volatile char   _NowWriting;
+    volatile char   _PhaseCounter;
+    volatile char   _RapidFireValue;
+    
+    
+    // Private Method
+    void Initialize(void);
+    void InitializePinStatus(void);
+    void SetPinStatus(void);
+    void SetD3D2D1D0(char d3, char d2, char d1, char d0);
+    void SetBus(char data);
+
+    void StrobeFallISR(void);
+    void StrobeRiseISR(void);
+    void ClockFallISR(void);
+    void ClockRiseISR(void);
+    
+    void RenewOutputMode(void);
+
+
+
+// for InputControll
+public:
+    void SetupInputControll(void (*startInputFunction)(void), void (*stopInputFunction)(void));
+    class CDummy;
+    template<class T>
+    void SetupInputControll(T* inputInstance, void (T::*startInputMethod)(void), void (T::*stopInputMethod)(void))
+    {
+        _InputInstance    = (CDummy*) inputInstance;
+        StartInputMethod = (void (CDummy::*)(void)) startInputMethod;
+        StopInputMethod  = (void (CDummy::*)(void)) stopInputMethod;
+    }
+
+private:
+    CDummy*         _InputInstance;
+    void (CDummy::*StartInputMethod)(void);
+    void (CDummy::*StopInputMethod)(void);
+    void (*StartInputFunction)(void);
+    void (*StopInputFunction)(void);
+    void EnableInput(void);
+    void DisableInput(void);
+
+};
+
+