First Release
Diff: Out_MD/Out_MD.cpp
- Revision:
- 0:e1265f6b3565
--- /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(); + } +} +