First Release
Diff: In_CyberStick/In_CyberStick.cpp
- 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; +}