First Release

Dependencies:   USBDevice

Revision:
0:e1265f6b3565
--- /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;
+}