First Release
Embed:
(wiki syntax)
Show/hide line numbers
C_Out_FC.cpp
00001 #include "mbed.h" 00002 #include "NiseKabuto.h" // InputDeviceType 00003 #include "C_Out_FC.h" 00004 00005 // mbed pins 00006 DigitalOut led2_FC(LED2); 00007 DigitalOut led3_FC(LED3); 00008 InterruptIn *_INTR_LATCH; 00009 DigitalOut *_OUT_DATA; 00010 InterruptIn *_INTR_CLOCK; 00011 InterruptIn *_INTR_POWDETECT; 00012 00013 // File local variables 00014 static volatile int *_pButtons; //PhaseData[12] 00015 static volatile char *_pCh0; 00016 static volatile char *_pCh1; 00017 static volatile char *_pCh2; 00018 static volatile char *_pInputDeviceType; 00019 static volatile char _Flag_NowOutput; 00020 static volatile char _PhaseCounter; 00021 static volatile char _SpeedType; 00022 static FunctionPointer *_fp_EnableInput; 00023 static FunctionPointer *_fp_DisableInput; 00024 static volatile char _RapidFireValue; 00025 static Ticker _RapidStateTicker; 00026 00027 // Const variables 00028 static const int DIGITALPAD_SPEED_STARFORCE = 120; 00029 static const int DIGITALPAD_SPEED_RECCA = 75; 00030 static const int RAPIDFIRE_PER_SEC = 15; // 高橋名人連射速度-1 00031 00032 // File local functions 00033 static void ISR_Rise_LATCH_STARFORCE(void); // 遅い読み取りルーチン for スターフォース 00034 static void ISR_Rise_LATCH(void); // フツー 00035 static void ISR_Rise_LATCH_RECCA(void); // 速い読み取りルーチン for サマーカーニバル'92 烈火 00036 //static void ISR_Rise_POWERDETECT(void); 00037 static void RenewData(void); 00038 static char CheckSpeedType(void); 00039 static int CheckOneReadTime(void); 00040 static void ConfigureSpeed(void); 00041 static void RapidStateTickerMethod(void); 00042 00043 void C_Out_FC_Initialize( 00044 InterruptIn *intr_LATCH, 00045 DigitalOut *out_DATA, 00046 InterruptIn *intr_CLOCK, 00047 InterruptIn *intr_POWDETECT, 00048 volatile int *pButtons, 00049 volatile char *pCh0, 00050 volatile char *pCh1, 00051 volatile char *pCh2, 00052 volatile char *pInputDeviceType, 00053 FunctionPointer *pFunc_InputEnable, 00054 FunctionPointer *pFunc_InputDisable 00055 ) 00056 { 00057 // 入出力pin 00058 _INTR_LATCH = intr_LATCH; 00059 _OUT_DATA = out_DATA; 00060 _INTR_CLOCK = intr_CLOCK; 00061 _INTR_POWDETECT = intr_POWDETECT; 00062 00063 // 割り込み設定 00064 //_INTR_POWDETECT->rise(&ISR_Rise_POWERDETECT); // 電源ON/OFFでスピード切り替え判定を行う場合 00065 00066 led2_FC.write(0); // 初期:フツー 00067 led3_FC.write(1); // 00068 _INTR_LATCH->rise(&ISR_Rise_LATCH); // 00069 00070 // 出力速度設定 00071 ConfigureSpeed(); 00072 00073 // ポインタ 00074 _pButtons = pButtons; 00075 _pCh0 = pCh0; 00076 _pCh1 = pCh1; 00077 _pCh2 = pCh2; 00078 _pInputDeviceType = pInputDeviceType; 00079 _fp_EnableInput = pFunc_InputEnable; 00080 _fp_DisableInput = pFunc_InputDisable; 00081 00082 _Flag_NowOutput = 0; 00083 _RapidFireValue = 1; 00084 00085 //_pTemp = pTemp; 00086 00087 // 連射ステータス変更設定 00088 _RapidStateTicker.attach_us(&RapidStateTickerMethod, (int)(1000000/(RAPIDFIRE_PER_SEC*2))); 00089 00090 // Initialize pin status 00091 _PhaseCounter = 0; 00092 RenewData(); 00093 } 00094 00095 void ISR_Rise_LATCH(void) 00096 { 00097 int loopCounter; 00098 00099 // 止める 00100 if( 00101 (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG || 00102 (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL 00103 ) 00104 { 00105 (*_fp_DisableInput).call(); 00106 } 00107 00108 // この関数開始時点で、phase0読み取り(DATAの立下り1回分)は 00109 // 終了しているものと仮定する 00110 // (mbedのピン割り込み時の反応速度は7usくらい) 00111 // 00112 // ただしMetalMaxでは。Latch立ち上がりから初回DATA立下りの間が 00113 // 6.5-7.0usくらいで微妙なので、 00114 // 絶対にphase0から開始することを保証するため、ちょっと待つ 00115 wait_us(1); 00116 00117 00118 // Phase1に移行 00119 _PhaseCounter=1; 00120 RenewData(); 00121 00122 // Lの間待つ 00123 while( !(_INTR_CLOCK->read()) ) 00124 { 00125 loopCounter = 400; 00126 00127 loopCounter--; 00128 if( !loopCounter ) 00129 { 00130 break; 00131 } 00132 } 00133 00134 // 開始 00135 for(int i=1; i<8; i++ ) 00136 { 00137 00138 // Hの間待つ 00139 loopCounter = 5000; 00140 while( _INTR_CLOCK->read() ) 00141 { 00142 loopCounter--; 00143 if( !loopCounter ) 00144 { 00145 break; 00146 } 00147 } 00148 00149 // Set data for current phase 00150 _PhaseCounter++; 00151 RenewData(); 00152 00153 // Lの間待つ 00154 loopCounter = 200; 00155 while( !(_INTR_CLOCK->read()) ) 00156 { 00157 loopCounter--; 00158 if( !loopCounter ) 00159 { 00160 break; 00161 } 00162 } 00163 } 00164 00165 _PhaseCounter = 0; 00166 RenewData(); 00167 00168 // 再開 00169 if( 00170 (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG || 00171 (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL 00172 ) 00173 { 00174 (*_fp_EnableInput).call(); 00175 } 00176 00177 } 00178 00179 void ISR_Rise_LATCH_RECCA(void) 00180 { 00181 // おまじない(Phase0を長引かせる) 00182 wait_us(2); 00183 00184 // Phase1に移行 00185 _PhaseCounter=1; 00186 RenewData(); 00187 00188 // 開始 00189 for(int i=1; i<8; i++ ) 00190 { 00191 wait_us(6); 00192 00193 // Set data for current phase 00194 _PhaseCounter++; 00195 RenewData(); 00196 } 00197 00198 _PhaseCounter = 0; 00199 RenewData(); 00200 00201 } 00202 00203 // 遅い読み取りルーチン 00204 void ISR_Rise_LATCH_STARFORCE(void) 00205 { 00206 int loopCounter; 00207 00208 // 止める 00209 if( 00210 (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG || 00211 (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL 00212 ) 00213 { 00214 (*_fp_DisableInput).call(); 00215 } 00216 00217 // Hの間待つ 00218 loopCounter = 5000; 00219 while( _INTR_CLOCK->read() ) 00220 { 00221 loopCounter--; 00222 if( !loopCounter ) 00223 { 00224 break; 00225 } 00226 } 00227 00228 00229 // Phase1に移行 00230 _PhaseCounter=1; 00231 RenewData(); 00232 00233 // Lの間待つ 00234 while( !(_INTR_CLOCK->read()) ) 00235 { 00236 loopCounter = 400; 00237 00238 loopCounter--; 00239 if( !loopCounter ) 00240 { 00241 break; 00242 } 00243 } 00244 00245 // 開始 00246 for(int i=1; i<8; i++ ) 00247 { 00248 00249 // Hの間待つ 00250 loopCounter = 5000; 00251 while( _INTR_CLOCK->read() ) 00252 { 00253 loopCounter--; 00254 if( !loopCounter ) 00255 { 00256 break; 00257 } 00258 } 00259 00260 // Set data for current phase 00261 _PhaseCounter++; 00262 RenewData(); 00263 00264 // Lの間待つ 00265 loopCounter = 200; 00266 while( !(_INTR_CLOCK->read()) ) 00267 { 00268 loopCounter--; 00269 if( !loopCounter ) 00270 { 00271 break; 00272 } 00273 } 00274 } 00275 00276 _PhaseCounter = 0; 00277 RenewData(); 00278 00279 // 再開 00280 if( 00281 (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG || 00282 (*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_DIGITAL 00283 ) 00284 { 00285 (*_fp_EnableInput).call(); 00286 } 00287 00288 } 00289 00290 00291 00292 00293 void RenewData(void) 00294 { 00295 switch(_PhaseCounter) 00296 { 00297 case 0: 00298 // 00299 // A 00300 // 00301 if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ) 00302 { 00303 _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0); // Digital B 00304 } 00305 else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B 00306 { 00307 // Zが押されてたら連射、押されてなかったらCの結果 00308 if( ((*_pButtons) & 0x010000) ) // Z 00309 { 00310 // 真:押されてない 00311 _OUT_DATA->write(((*_pButtons) & 0x0020) ? 1 : 0); // Digital C 00312 } 00313 else 00314 { 00315 // 偽:押されてる 00316 _OUT_DATA->write(_RapidFireValue&1); 00317 } 00318 } 00319 else 00320 { 00321 _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0); // Digital B 00322 } 00323 break; 00324 00325 case 1: 00326 // 00327 // B 00328 // 00329 if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ) 00330 { 00331 _OUT_DATA->write(((*_pButtons) & 0x0200) ? 1 : 0); // Digital A 00332 } 00333 else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B 00334 { 00335 // Yが押されてたら連射、押されてなかったらBの結果 00336 if( ((*_pButtons) & 0x020000) ) // Y 00337 { 00338 // 真:押されてない 00339 _OUT_DATA->write(((*_pButtons) & 0x0100) ? 1 : 0); // Digital B 00340 } 00341 else 00342 { 00343 // 偽:押されてる 00344 _OUT_DATA->write(_RapidFireValue&1); 00345 } 00346 } 00347 else 00348 { 00349 _OUT_DATA->write(((*_pButtons) & 0x0200) ? 1 : 0); // Digital A 00350 } 00351 break; 00352 00353 case 2: 00354 // 00355 // Select 00356 // 00357 if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ) 00358 { 00359 _OUT_DATA->write(((*_pButtons) & 0x0001) ? 1 : 0); // G(Sel,Mode) 00360 } 00361 else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B 00362 { 00363 _OUT_DATA->write(((*_pButtons) & 0x0001) ? 1 : 0); // G(Sel,Mode) 00364 } 00365 else 00366 { 00367 _OUT_DATA->write(((*_pButtons) & 0x0020) ? 1 : 0); // Digital C 00368 } 00369 break; 00370 00371 case 3: 00372 // 00373 // Start 00374 // 00375 if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ) 00376 { 00377 _OUT_DATA->write( 00378 ( ((*_pButtons) & 0x0002) ? 1 : 0) & // F(Start) 00379 ( (*_pCh2)>0xf0? 0:1 ) // スロットル引く 00380 00381 ); 00382 //_OUT_DATA->write( ((*_pButtons) & 0x0002) ? 1 : 0) ); 00383 00384 } 00385 else if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_MD6B) //2:MD6B 00386 { 00387 _OUT_DATA->write(((*_pButtons) & 0x0002) ? 1 : 0); // F(Start) 00388 } 00389 else 00390 { 00391 _OUT_DATA->write(((*_pButtons) & 0x0010) ? 1 : 0); // Digital C 00392 } 00393 break; 00394 00395 case 4: 00396 // 00397 // Up 00398 // 00399 // ch1>0xf0? 0:1, // 右 00400 // ch1<0x0f? 0:1, // 左 00401 // ch0>0xf0? 0:1, // 下 00402 // ch0<0x0f? 0:1 // 上 00403 // ch2>0xf0? 0:1, // スロットル引く 00404 00405 if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ) 00406 { 00407 _OUT_DATA->write((*_pCh0)<0x40? 0:1); 00408 } 00409 else 00410 { 00411 _OUT_DATA->write(((*_pButtons) & 0x2000) ? 1 : 0); 00412 } 00413 break; 00414 00415 case 5: 00416 // 00417 // Down 00418 // 00419 if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ) 00420 { 00421 _OUT_DATA->write((*_pCh0)>0xb0? 0:1); 00422 } 00423 else 00424 { 00425 _OUT_DATA->write(((*_pButtons) & 0x1000) ? 1 : 0); 00426 } 00427 break; 00428 00429 case 6: 00430 // 00431 // Left 00432 // 00433 if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ) 00434 { 00435 _OUT_DATA->write((*_pCh1)<0x40? 0:1); 00436 } 00437 else 00438 { 00439 _OUT_DATA->write(((*_pButtons) & 0x0800) ? 1 : 0); 00440 } 00441 break; 00442 00443 case 7: 00444 // 00445 // Right 00446 // 00447 if((*_pInputDeviceType) == NiseKabuto::CONFIG_INMODE_CYBERSTICK_ANALOG) //サイバースティック(アナログ) 00448 { 00449 _OUT_DATA->write((*_pCh1)>0xb0? 0:1); 00450 } 00451 else 00452 { 00453 _OUT_DATA->write(((*_pButtons) & 0x0400) ? 1 : 0); 00454 } 00455 break; 00456 00457 default: 00458 _OUT_DATA->write(1); // H 00459 } 00460 } 00461 00462 // 00463 // ファミコンからの読み取り処理の長さを得る(1回分) 00464 // 00465 // return: 00466 // 0 = 読み取りが行えない(烈火の可能性がある) 00467 // 0以外 = 読み取り処理長さ[us] 00468 int CheckOneReadTime(void) 00469 { 00470 int retVal = 0; 00471 char stat = 1; 00472 int intLoopCounter; // ZanacはGunnac&MMに比べて2倍 00473 Timer t; 00474 00475 // Latch = Hまで待つ 00476 intLoopCounter = 500000; 00477 while( !(_INTR_LATCH->read()) ) 00478 { 00479 intLoopCounter--; 00480 if( !intLoopCounter ) 00481 { 00482 stat = 0; 00483 break; 00484 } 00485 } 00486 00487 if(stat) 00488 { 00489 // 時刻計測開始 00490 t.start(); 00491 00492 // Clockが8回Lになることを確認 00493 for(int i=0; i<8; i++ ) 00494 { 00495 intLoopCounter = 1000; 00496 while( _INTR_CLOCK->read() ) 00497 { 00498 intLoopCounter--; 00499 if( !intLoopCounter ) 00500 { 00501 stat = 0; 00502 break; 00503 } 00504 } 00505 00506 intLoopCounter = 100; 00507 while( !(_INTR_CLOCK->read()) ) 00508 { 00509 intLoopCounter--; 00510 if( !intLoopCounter ) 00511 { 00512 break; 00513 } 00514 } 00515 } 00516 } 00517 00518 if(stat) 00519 { 00520 t.stop(); 00521 retVal = t.read_us(); 00522 } 00523 00524 return retVal; 00525 } 00526 00527 00528 00529 // 00530 // SpeedTypeを判定する 00531 // 00532 // return: 00533 // 0 = 普通モード(普通のゲーム) 00534 // 1 = 高速モード(烈火) 00535 // 2 = 低速モード(スターフォース) 00536 // よくわからないときは0を返す 00537 char CheckSpeedType(void) 00538 { 00539 char retVal = 0; 00540 int readTime[8]; 00541 char counter_recca = 0; 00542 char counter_starforce = 0; 00543 00544 // Dataは常にH 00545 _OUT_DATA->write(1); 00546 00547 // 8回くらいチェックする 00548 for(int i=0; i<8; i++ ) 00549 { 00550 readTime[i] = CheckOneReadTime(); 00551 printf("readTime[%d]: %d\r\n",i,readTime[i]); 00552 } 00553 00554 // 個別の結果判定 00555 for(int i=0; i<8; i++ ) 00556 { 00557 if( readTime[i]>DIGITALPAD_SPEED_STARFORCE ) 00558 { 00559 counter_starforce++; 00560 } 00561 else if( readTime[i]<DIGITALPAD_SPEED_RECCA ) 00562 { 00563 counter_recca++; 00564 } 00565 else 00566 { 00567 } 00568 } 00569 00570 // 判定 00571 if(counter_starforce >= 4) 00572 { 00573 retVal = 2; 00574 } 00575 else if(counter_recca >= 4) 00576 { 00577 retVal = 1; 00578 } 00579 00580 return retVal; 00581 } 00582 00583 // 00584 // Configure speed setting 00585 // 00586 void ConfigureSpeed(void) 00587 { 00588 char speed; 00589 00590 // ISR登録解除 00591 _INTR_LATCH->rise(0); 00592 00593 // ちょっと待つ 00594 wait_ms(500); 00595 00596 speed = CheckSpeedType(); 00597 00598 // Interrupt Setting 00599 if( speed==1 ) 00600 { 00601 led2_FC.write(1); 00602 led3_FC.write(1); 00603 _INTR_LATCH->rise(&ISR_Rise_LATCH_RECCA); 00604 } 00605 else if( speed==2 ) 00606 { 00607 led2_FC.write(0); 00608 led3_FC.write(0); 00609 _INTR_LATCH->rise(&ISR_Rise_LATCH_STARFORCE); 00610 } 00611 else 00612 { 00613 led2_FC.write(0); 00614 led3_FC.write(1); 00615 _INTR_LATCH->rise(&ISR_Rise_LATCH); 00616 } 00617 00618 } 00619 00620 // 00621 // ISR for POWERDETECT L->H 00622 // 00623 void ISR_Rise_POWERDETECT(void) 00624 { 00625 ConfigureSpeed(); 00626 } 00627 00628 void RapidStateTickerMethod(void) 00629 { 00630 _RapidFireValue = !_RapidFireValue; 00631 } 00632
Generated on Thu Jul 14 2022 14:49:55 by 1.7.2