First Release
Revision 0:e1265f6b3565, committed 2013-07-27
- Comitter:
- sankichi
- Date:
- Sat Jul 27 14:05:47 2013 +0000
- Child:
- 1:6c392ebcd4d4
- Commit message:
- First Release
Changed in this revision
--- /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); + +}; + +