First Release
Out_MD/Out_MD.cpp
- Committer:
- sankichi
- Date:
- 2013-07-27
- Revision:
- 1:6c392ebcd4d4
- Parent:
- 0:e1265f6b3565
File content as of revision 1:6c392ebcd4d4:
#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(); } }