|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2017 [email protected] ! 4: // ! 5: ! 6: #include "mfp.h" ! 7: #include "mpu.h" ! 8: #include "mystring.h" ! 9: #include "scheduler.h" ! 10: ! 11: MFPDevice *gMFP; ! 12: ! 13: // コンストラクタ ! 14: MFPDevice::MFPDevice() ! 15: { ! 16: logname = "mfp"; ! 17: devname = "MFP"; ! 18: devaddr = baseaddr; ! 19: devlen = 0x2000; ! 20: monitor.Init(65, 17); ! 21: ! 22: for (int ch = 0; ch < countof(event); ch++) { ! 23: event[ch].dev = this; ! 24: event[ch].func = (DeviceCallback_t)&MFPDevice::TimerCallback; ! 25: event[ch].code = ch; ! 26: event[ch].name = string_format("MFP Timer-%c", ch + 'A'); ! 27: } ! 28: } ! 29: ! 30: // デストラクタ ! 31: MFPDevice::~MFPDevice() ! 32: { ! 33: } ! 34: ! 35: // MPU の RESET 命令によるリセット ! 36: void ! 37: MFPDevice::ResetSoft() ! 38: { ! 39: // TxDR, UDR, TSR はクリアされない ! 40: ! 41: // ? ! 42: mfp.tsr = 0x80; ! 43: ! 44: // それ以外のすべてのレジスタはクリア? ! 45: mfp.vr = 0; ! 46: ! 47: // タイマーはすべてストップなのでイベントを削除 ! 48: for (int ch = 0; ch < countof(event); ch++) { ! 49: gScheduler->DelEvent(&event[ch]); ! 50: } ! 51: ! 52: // ペンディング割り込みクリア ! 53: ! 54: } ! 55: ! 56: uint64 ! 57: MFPDevice::Read8(uint32 addr) ! 58: { ! 59: uint8 data; ! 60: ! 61: if (addr % 2 == 0) ! 62: return (uint64)-1; ! 63: ! 64: int n = (addr - baseaddr) / 2; ! 65: switch (n) { ! 66: case MFP::GPIP: ! 67: data = mfp.gpip; ! 68: break; ! 69: case MFP::AER: ! 70: data = mfp.aer; ! 71: break; ! 72: case MFP::DDR: ! 73: data = mfp.ddr; ! 74: break; ! 75: case MFP::IERA: ! 76: data = mfp.ier.a; ! 77: break; ! 78: case MFP::IERB: ! 79: data = mfp.ier.b; ! 80: break; ! 81: case MFP::IPRA: ! 82: data = mfp.ipr.a; ! 83: break; ! 84: case MFP::IPRB: ! 85: data = mfp.ipr.b; ! 86: break; ! 87: case MFP::ISRA: ! 88: data = mfp.isr.a; ! 89: break; ! 90: case MFP::ISRB: ! 91: data = mfp.isr.b; ! 92: break; ! 93: case MFP::IMRA: ! 94: data = mfp.imr.a; ! 95: break; ! 96: case MFP::IMRB: ! 97: data = mfp.imr.b; ! 98: break; ! 99: case MFP::VR: ! 100: data = mfp.vr; ! 101: break; ! 102: case MFP::TACR: ! 103: data = mfp.tcr[0]; ! 104: break; ! 105: case MFP::TBCR: ! 106: data = mfp.tcr[1]; ! 107: break; ! 108: case MFP::TCDCR: ! 109: data = (mfp.tcr[2] << 4) | mfp.tcr[3]; ! 110: break; ! 111: case MFP::TADR: ! 112: data = GetTDR(0); ! 113: break; ! 114: case MFP::TBDR: ! 115: data = GetTDR(1); ! 116: break; ! 117: case MFP::TCDR: ! 118: data = GetTDR(2); ! 119: break; ! 120: case MFP::TDDR: ! 121: data = GetTDR(3); ! 122: break; ! 123: case MFP::SCR: ! 124: data = mfp.scr; ! 125: break; ! 126: case MFP::UCR: ! 127: data = mfp.ucr; ! 128: break; ! 129: case MFP::RSR: ! 130: data = mfp.rsr; ! 131: break; ! 132: case MFP::TSR: ! 133: data = mfp.tsr; ! 134: break; ! 135: case MFP::UDR: ! 136: data = mfp.udr; ! 137: break; ! 138: default: ! 139: return (uint64)-1; ! 140: } ! 141: return data; ! 142: } ! 143: ! 144: uint64 ! 145: MFPDevice::Read16(uint32 addr) ! 146: { ! 147: return (0xff00 | Read8(addr + 1)); ! 148: } ! 149: ! 150: uint64 ! 151: MFPDevice::Write8(uint32 addr, uint32 data) ! 152: { ! 153: if (addr % 2 == 0) ! 154: return (uint64)-1; ! 155: ! 156: int n = (addr - baseaddr) / 2; ! 157: switch (n) { ! 158: case MFP::GPIP: ! 159: putlog(0, "GPIP <- $%02x 未実装書き込み", data); ! 160: mfp.gpip = data; ! 161: break; ! 162: case MFP::AER: ! 163: putlog(0, "AER <- $%02x 未実装書き込み", data); ! 164: mfp.aer = data; ! 165: break; ! 166: case MFP::DDR: ! 167: if (data != 0) { ! 168: putlog(0, "DDR <- $%02x 未実装書き込み", data); ! 169: } ! 170: mfp.ddr = data; ! 171: break; ! 172: case MFP::IERA: ! 173: putlog(2, "IERA <- $%02x", data); ! 174: mfp.ier.a = data; ! 175: break; ! 176: case MFP::IERB: ! 177: putlog(2, "IERB <- $%02x", data); ! 178: mfp.ier.b = data; ! 179: break; ! 180: case MFP::IPRA: ! 181: putlog(2, "IPRA <- $%02x", data); ! 182: mfp.ipr.a = data; ! 183: break; ! 184: case MFP::IPRB: ! 185: putlog(2, "IPRB <- $%02x", data); ! 186: mfp.ipr.b = data; ! 187: break; ! 188: case MFP::ISRA: ! 189: putlog(2, "ISRA <- $%02x", data); ! 190: mfp.isr.a = data; ! 191: break; ! 192: case MFP::ISRB: ! 193: putlog(2, "ISRB <- $%02x", data); ! 194: mfp.isr.b = data; ! 195: break; ! 196: case MFP::IMRA: ! 197: putlog(2, "IMRA <- $%02x", data); ! 198: mfp.imr.a = data; ! 199: break; ! 200: case MFP::IMRB: ! 201: putlog(2, "IMRB <- $%02x", data); ! 202: mfp.imr.b = data; ! 203: break; ! 204: case MFP::VR: ! 205: mfp.vr = data & 0xf0; ! 206: putlog(2, "VR <- $%02x", mfp.vr); ! 207: break; ! 208: case MFP::TACR: ! 209: putlog(2, "TACR <- $%02x", data); ! 210: SetTCR(0, data); ! 211: break; ! 212: case MFP::TBCR: ! 213: putlog(2, "TBCR <- $%02x", data); ! 214: SetTCR(1, data); ! 215: break; ! 216: case MFP::TCDCR: ! 217: putlog(2, "TCDCR <- $%02x", data); ! 218: SetTCR(2, data >> 4); ! 219: SetTCR(3, data & 7); ! 220: break; ! 221: case MFP::TADR: ! 222: putlog(2, "TADR <- $%02x", data); ! 223: SetTDR(0, data); ! 224: break; ! 225: case MFP::TBDR: ! 226: putlog(2, "TBDR <- $%02x", data); ! 227: SetTDR(1, data); ! 228: break; ! 229: case MFP::TCDR: ! 230: putlog(2, "TCDR <- $%02x", data); ! 231: SetTDR(2, data); ! 232: break; ! 233: case MFP::TDDR: ! 234: putlog(2, "TDDR <- $%02x", data); ! 235: SetTDR(3, data); ! 236: break; ! 237: case MFP::SCR: ! 238: putlog(0, "SCR <- $%02x 未実装書き込み", data); ! 239: mfp.scr = data; ! 240: break; ! 241: case MFP::UCR: ! 242: putlog(0, "UCR <- $%02x 未実装書き込み", data); ! 243: mfp.ucr = data & 0xfe; ! 244: break; ! 245: case MFP::RSR: ! 246: putlog(0, "RSR <- $%02x 未実装書き込み", data); ! 247: mfp.rsr = data; ! 248: break; ! 249: case MFP::TSR: ! 250: putlog(0, "TSR <- $%02x 未実装書き込み", data); ! 251: mfp.tsr = (mfp.tsr & 0xf0) | (data & 0x0f); ! 252: break; ! 253: case MFP::UDR: ! 254: putlog(0, "UDR <- $%02x 未実装書き込み", data); ! 255: mfp.udr = data; ! 256: break; ! 257: default: ! 258: return (uint64)-1; ! 259: } ! 260: return 0; ! 261: } ! 262: ! 263: uint64 ! 264: MFPDevice::Write16(uint32 addr, uint32 data) ! 265: { ! 266: return Write8(addr + 1, data); ! 267: } ! 268: ! 269: uint64 ! 270: MFPDevice::Peek8(uint32 addr) ! 271: { ! 272: uint8 data; ! 273: ! 274: if (addr % 2 == 0) { ! 275: return (uint64)-1; ! 276: } ! 277: int n = (addr - baseaddr) / 2; ! 278: switch (n) { ! 279: case MFP::GPIP: ! 280: data = mfp.gpip; ! 281: break; ! 282: case MFP::AER: ! 283: data = mfp.aer; ! 284: break; ! 285: case MFP::DDR: ! 286: data = mfp.ddr; ! 287: break; ! 288: case MFP::IERA: ! 289: data = mfp.ier.a; ! 290: break; ! 291: case MFP::IERB: ! 292: data = mfp.ier.b; ! 293: break; ! 294: case MFP::IPRA: ! 295: data = mfp.ipr.a; ! 296: break; ! 297: case MFP::IPRB: ! 298: data = mfp.ipr.b; ! 299: break; ! 300: case MFP::ISRA: ! 301: data = mfp.isr.a; ! 302: break; ! 303: case MFP::ISRB: ! 304: data = mfp.isr.b; ! 305: break; ! 306: case MFP::IMRA: ! 307: data = mfp.imr.a; ! 308: break; ! 309: case MFP::IMRB: ! 310: data = mfp.imr.b; ! 311: break; ! 312: case MFP::VR: ! 313: data = mfp.vr; ! 314: break; ! 315: case MFP::TACR: ! 316: data = mfp.tcr[0]; ! 317: break; ! 318: case MFP::TBCR: ! 319: data = mfp.tcr[1]; ! 320: break; ! 321: case MFP::TCDCR: ! 322: data = (mfp.tcr[2] << 4) | mfp.tcr[3]; ! 323: break; ! 324: case MFP::TADR: ! 325: data = GetTDR(0); ! 326: break; ! 327: case MFP::TBDR: ! 328: data = GetTDR(1); ! 329: break; ! 330: case MFP::TCDR: ! 331: data = GetTDR(2); ! 332: break; ! 333: case MFP::TDDR: ! 334: data = GetTDR(3); ! 335: break; ! 336: case MFP::SCR: ! 337: data = mfp.scr; ! 338: break; ! 339: case MFP::UCR: ! 340: data = mfp.ucr; ! 341: break; ! 342: case MFP::RSR: ! 343: data = mfp.rsr; ! 344: break; ! 345: case MFP::TSR: ! 346: data = mfp.tsr; ! 347: break; ! 348: case MFP::UDR: ! 349: data = mfp.udr; ! 350: break; ! 351: default: ! 352: data = 0xff; ! 353: break; ! 354: } ! 355: return data; ! 356: } ! 357: ! 358: bool ! 359: MFPDevice::MonitorUpdate() ! 360: { ! 361: int x; ! 362: int y; ! 363: ! 364: monitor.Clear(); ! 365: ! 366: // 0 1 2 3 4 5 6 ! 367: // 012345678901234567890123456789012345678901234567890123456789012345 ! 368: // IER IMR IPR ISR Mode TDR Cnt ! 369: // An:MPSC TxEmpty Enable Mask Pend Serv Timer-A Delay(50us) 255 255 ! 370: ! 371: // 割り込み関連 ! 372: monitor.Print(0, 0, " %-12s %-6s %-4s %-4s %-4s", ! 373: "", "IER", "IMR", "IPR", "ISR"); ! 374: y = 1; ! 375: for (int i = 15; i >= 0; i--, y++) { ! 376: uint16 mask = (1 << i); ! 377: monitor.Print(0, y, "%c%d:%-12s %-6s %-4s %-4s %-4s", ! 378: i >= 8 ? 'A' : 'B', ! 379: (i % 8), ! 380: intrname[i], ! 381: (mfp.ier.w & mask) ? "Enable" : "", ! 382: (mfp.imr.w & mask) ? "" : "Mask", // %0 でマスクする ! 383: (mfp.ipr.w & mask) ? "Pend" : "", ! 384: (mfp.isr.w & mask) ? "Serv" : ""); ! 385: } ! 386: ! 387: // タイマー関連 ! 388: x = 39; ! 389: y = 1; ! 390: for (int ch = 0; ch < 4; ch++) { ! 391: y = ch + 1; ! 392: monitor.Print(x, y, "Timer-%c", ch + 'A'); ! 393: if (mfp.tcr[ch] == 0) { ! 394: monitor.Print(x + 8, y, "Stopped"); ! 395: } else if (mfp.tcr[ch] == 8) { ! 396: monitor.Print(x + 8, y, "Event"); ! 397: } else if (mfp.tcr[ch] > 8) { ! 398: monitor.Print(x + 8, y, "Pulse(%s)", prescale_str[mfp.tcr[ch] - 8]); ! 399: } else { ! 400: monitor.Print(x + 8, y, "Delay(%s)", prescale_str[mfp.tcr[ch]]); ! 401: } ! 402: ! 403: monitor.Print(x + 19, y, "%3d", GetTDR(ch)); ! 404: monitor.Print(x + 23, y, "%3d", mfp.tdr[ch]); ! 405: } ! 406: ! 407: // GPIP 関連 ! 408: x = 39; ! 409: y = 8; ! 410: monitor.Print(x, y++, "GPIP Name GPIP AER DDR"); ! 411: for (int i = 7; i >= 0; i--, y++) { ! 412: uint mask = (1 << i); ! 413: monitor.Print(x, y, "b%d %-6s %d %d %s", i, gpipname[i], ! 414: (mfp.gpip & mask) ? 1 : 0, ! 415: (mfp.aer & mask) ? 1 : 0, ! 416: (mfp.ddr & mask) ? "OUT" : "IN"); ! 417: } ! 418: ! 419: return true; ! 420: } ! 421: ! 422: /*static*/ const char * ! 423: MFPDevice::intrname[] = { ! 424: "RTC Alarm", ! 425: "EXPON", ! 426: "POW SW", ! 427: "FM IRQ", ! 428: "Timer-D", ! 429: "Timer-C", ! 430: "V-Disp", ! 431: "---", ! 432: "Timer-B", ! 433: "MPSC TxErr", ! 434: "MPSC TxEmpty", ! 435: "MPSC RxErr", ! 436: "MPSC RxFull", ! 437: "Timer-A", ! 438: "CRTC IRQ", ! 439: "H-Sync", ! 440: }; ! 441: ! 442: /*static*/ const char * ! 443: MFPDevice::gpipname[] = { ! 444: "ALARM", ! 445: "EXPON", ! 446: "POW SW", ! 447: "FMIRQ", ! 448: "V-Disp", ! 449: "------", ! 450: "CIRQ", ! 451: "H-Sync", ! 452: }; ! 453: ! 454: // TxCR の設定値から分周期間というかメインカウンタ1回分の時間を返す ! 455: /*static*/ const int ! 456: MFPDevice::prescale_ns[8] = { ! 457: 0, ! 458: 1000, // /4 ! 459: 2500, // /10 ! 460: 4000, // /16 ! 461: 12500, // /50 ! 462: 16000, // /64 ! 463: 25000, // /100 ! 464: 50000, // /200 ! 465: }; ! 466: ! 467: /*static*/ const char * ! 468: MFPDevice::prescale_str[8] = { ! 469: "", ! 470: "1us", ! 471: "2.5us", ! 472: "4us", ! 473: "12.5us", ! 474: "16us", ! 475: "25us", ! 476: "50us", ! 477: }; ! 478: ! 479: // タイマーのチャンネルからベクタ(ビット番号) に変換する ! 480: /*static*/ const int ! 481: MFPDevice::timer_vector[4] = { 13, 8, 5, 4 }; ! 482: ! 483: // このタイマーで割り込みを上げる必要があるかどうかを返す ! 484: bool ! 485: MFPDevice::IsTimerIntrEnable(uint ch) const ! 486: { ! 487: assert(ch < 4); ! 488: __assume(ch < 4); ! 489: ! 490: // 割り込みが無効なら false ! 491: if ((mfp.ier.w & (1 << timer_vector[ch])) == 0) { ! 492: return false; ! 493: } ! 494: ! 495: // 割り込みがマスクされていれば false ! 496: if ((mfp.imr.w & (1 << timer_vector[ch])) == 0) { ! 497: return false; ! 498: } ! 499: ! 500: // そうでなければ、割り込みを上げる必要がある ! 501: return true; ! 502: } ! 503: ! 504: // TxCR をセットする ! 505: void ! 506: MFPDevice::SetTCR(int ch, uint32 data) ! 507: { ! 508: uint32 prev; ! 509: ! 510: prev = mfp.tcr[ch]; ! 511: data &= 0x0f; ! 512: ! 513: mfp.tcr[ch] = data; ! 514: if (mfp.tcr[ch] > 0x08) { ! 515: putlog(0, "T%cCR サポートしていないモード $%02x", ! 516: ch + 'A', mfp.tcr[ch]); ! 517: return; ! 518: } ! 519: if (mfp.tcr[ch] == 8) { ! 520: // イベントカウントモード ! 521: ! 522: // TDR をロードする ! 523: mfp.initial_tdr[ch] = mfp.tdr[ch]; ! 524: putlog(1, "Timer-%c イベントカウントモード", ch + 'A'); ! 525: return; ! 526: ! 527: } else if (mfp.tcr[ch] == 0) { ! 528: // タイマー停止 ! 529: if (prev != 0) { ! 530: putlog(1, "Timer-%c 停止", ch + 'A'); ! 531: } ! 532: mfp.timer_start[ch] = 0; ! 533: gScheduler->DelEvent(&event[ch]); ! 534: return; ! 535: ! 536: } else { ! 537: // タイマー開始 ! 538: int scale = prescale_ns[mfp.tcr[ch]]; ! 539: if (prev == 0) { ! 540: // タイマー停止中に開始 ! 541: // ここで initial_tdr にロード ! 542: mfp.initial_tdr[ch] = mfp.tdr[ch] ?: 256; ! 543: mfp.timer_start[ch] = gScheduler->GetVirtTime(); ! 544: } else { ! 545: // タイマー動作中に(再)開始 ! 546: ! 547: // タイマー動作中に TxCR に書き込むと、TxDR は影響を受けずに、 ! 548: // プリスケーラのカウンタがリセットされる。 ! 549: // 例えば、TCR = 0x01 (プリスケール 10)、TDR = 0x05 で、 ! 550: // プリスケールカウントが12回進行した時点で TCR に再び 0x01 ! 551: // (プリスケール10) が書き込まれた場合、以下のようになるはず。 ! 552: // ! 553: // time -> ! 554: // prescale cnt| 0 1 2 3 4 5 6 7 8 9 0 1 2 ! 555: // main count | 5 ----------------> 4 --> ! 556: // * ここで TCR 書き込み ! 557: // TCR書き込み後のprescale cnt | 0 1 2 3 4 5 6 7 8 9 0 1 ! 558: // TCR書き込み後のmain count | 4 ----------------> 3 -> ! 559: uint64 ellapsed; ! 560: uint deccount; ! 561: ! 562: // タイマー開始時からの経過時間 ! 563: ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch]; ! 564: ! 565: // タイマー開始時から今までのメインカウンタ減算回数 ! 566: deccount = ellapsed / scale; ! 567: ! 568: // 再設定 ! 569: mfp.initial_tdr[ch] -= deccount; ! 570: mfp.timer_start[ch] += gScheduler->GetVirtTime(); ! 571: } ! 572: ! 573: // 割り込みを上げる必要があれば、カウントダウン終了時にイベントを ! 574: // 起こす。 ! 575: // 割り込みを上げる必要がない場合は、TxDR を読み出す時に正しい値が ! 576: // 算出できるだけでよくて、それは timer_start 等により行えているので ! 577: // 他には何もしなくてよい。Timer-B 対策。 ! 578: if (IsTimerIntrEnable(ch)) { ! 579: event[ch].time = mfp.initial_tdr[ch] * scale; ! 580: gScheduler->AddEvent(&event[ch]); ! 581: } ! 582: ! 583: putlog(1, "Timer-%c ディレイモード開始(%d.%d x %d usec)", ! 584: ch + 'A', ! 585: scale / 1000, ! 586: (scale / 100) % 10, ! 587: mfp.initial_tdr[ch]); ! 588: } ! 589: } ! 590: ! 591: // TxDR の読み出し ! 592: // タイマーデータレジスタの現在値は保持しておらず、 ! 593: // タイマー開始時刻と減算量が分かっているので読み出しのたびに求める。 ! 594: // この操作に副作用はないので Peek/Monitor でも使用可能。 ! 595: uint8 ! 596: MFPDevice::GetTDR(int ch) ! 597: { ! 598: uint64 ellapsed; ! 599: uint64 count; ! 600: uint32 data; ! 601: ! 602: // イベントカウントモードなら initial_tdr が読める? ! 603: if (mfp.tcr[ch] == 8) { ! 604: return mfp.initial_tdr[ch]; ! 605: } ! 606: ! 607: // タイマー停止中なら TxDR と同じでよい? ! 608: if (mfp.tcr[ch] == 0) { ! 609: return mfp.tdr[ch]; ! 610: } ! 611: ! 612: // タイマー開始時からの経過時間 ! 613: ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch]; ! 614: ! 615: // タイマー開始時から現在までのメインカウンタ減算回数 ! 616: count = ellapsed / prescale_ns[mfp.tcr[ch]]; ! 617: ! 618: // カウント終了時に割り込みが上がる設定になっていれば ! 619: // count は必ず 0 から initail_tdr-1 までの範囲だが、 ! 620: // カウント終了時に割り込みが上がる設定になっていない場合は ! 621: // 経過時間とそれに伴い count はひたすら増える。 ! 622: // そのため initial_tdr で modulo する。 ! 623: count %= mfp.initial_tdr[ch]; ! 624: ! 625: // count は減算回数だが、 ! 626: // TxDR レジスタの読み出し値は減算カウンタの現在値。 ! 627: // TxDR = 10 で開始して count = 0 のうちは TxDR 読み出しは 10。 ! 628: // TxDR = 10 で開始して count = 1 のうちは TxDR 読み出しは 9。 ! 629: // : ! 630: // TxDR = 10 で開始して count = 9 のうちは TxDR 読み出しは 1。 ! 631: data = mfp.initial_tdr[ch] - count; ! 632: ! 633: return data; ! 634: } ! 635: ! 636: // TxDR への書き込み ! 637: void ! 638: MFPDevice::SetTDR(int ch, uint32 data) ! 639: { ! 640: uint64 ellapsed; ! 641: uint64 scale; ! 642: uint64 period; ! 643: uint64 timer_end; ! 644: ! 645: mfp.tdr[ch] = data; ! 646: ! 647: // イベントカウントモードなら即ロード ! 648: if (mfp.tcr[ch] == 8) { ! 649: mfp.initial_tdr[ch] = mfp.tdr[ch]; ! 650: } ! 651: ! 652: // カウント終了時に割り込みが上がる設定になっていれば、 ! 653: // そのイベントコールバックで tdr を initial_tdr にロードするが、 ! 654: // 割り込みが上がらない設定の場合、そのままでは tdr をリロードする ! 655: // 機会がない。そのためこのケースでは書き込み時点の次のカウント終了 ! 656: // 時にイベントを起こす必要がある。 ! 657: // ! 658: // TCR=1(プリスケール10)、TDR=5 で 38カウント目に TDR がセットされた ! 659: // 場合、ここから 12カウント目がリロードタイミング。 ! 660: // ! 661: // pre | 0 ... 0 ... 0 ... 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ! 662: // main| 5 --> 4 --> 3 --> 2 ------------->* ! 663: // |<--------------------->| ! 664: // イベントを起こすまでの時間 ! 665: if (IsTimerIntrEnable(ch) == false) { ! 666: // タイマー開始時から現在までの経過時間 ! 667: ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch]; ! 668: // プリスケールカウント時間 (上でいう1カウントの時間) ! 669: scale = prescale_ns[mfp.tcr[ch]]; ! 670: // 1タイマー期間(上でいう50カウントに相当する時間) ! 671: period = scale * mfp.initial_tdr[ch]; ! 672: // タイマー開始時から次のタイムアップ時刻までの時間 ! 673: timer_end = ((ellapsed + period - 1) / period) * period; ! 674: // タイムアップ時刻 ! 675: timer_end = mfp.timer_start[ch] + timer_end; ! 676: // 現在から次のタイムアップ時刻まで ! 677: event[ch].time = timer_end - gScheduler->GetVirtTime(); ! 678: gScheduler->AddEvent(&event[ch]); ! 679: ! 680: putlog(3, "Timer-%c TDR 更新予約 %d.%09d", ch + 'A', ! 681: (int)(event[ch].time / (1000 * 1000 * 1000)), ! 682: (int)(event[ch].time % (1000 * 1000 * 1000))); ! 683: } ! 684: } ! 685: ! 686: // イベントコールバック ! 687: void ! 688: MFPDevice::TimerCallback(int arg) ! 689: { ! 690: int ch = arg; ! 691: int prevtdr; ! 692: uint64 ellapsed; ! 693: uint64 scale; ! 694: uint64 period; ! 695: uint64 timer_end; ! 696: ! 697: // タイムアップした時刻を計算。現在時刻ではない。 ! 698: // 現在時刻はタイムアップした直後の命令境界の時刻なので。 ! 699: ! 700: // タイマー開始時から現在までの経過時間 ! 701: ellapsed = gScheduler->GetVirtTime() - mfp.timer_start[ch]; ! 702: // 1プリスケール期間 ! 703: scale = prescale_ns[mfp.tcr[ch]]; ! 704: // 1タイマー期間 ! 705: period = scale * mfp.initial_tdr[ch]; ! 706: // タイマー開始時から直近のタイムアップ時刻まで ! 707: timer_end = (ellapsed / period) * period; ! 708: ! 709: // TxDR がゼロになったので TxDR をリロード ! 710: prevtdr = mfp.initial_tdr[ch]; ! 711: mfp.initial_tdr[ch] = mfp.tdr[ch] ?: 256; ! 712: // 今タイムアップ時刻を次のタイマー起点に更新 ! 713: mfp.timer_start[ch] += timer_end; ! 714: ! 715: // 割り込み有効なら ! 716: if (IsTimerIntrEnable(ch)) { ! 717: // 1タイマー期間を新しい TDR で再計算 ! 718: period = prescale_ns[mfp.tcr[ch]] * mfp.initial_tdr[ch]; ! 719: // イベント再設定 ! 720: event[ch].time = period; ! 721: gScheduler->AddEvent(&event[ch]); ! 722: ! 723: // 割り込みを上げる ! 724: gMPU->Interrupt(6, mfp.vr + timer_vector[ch]); ! 725: } ! 726: ! 727: if (mfp.initial_tdr[ch] != prevtdr) { ! 728: putlog(1, "Timer-%c ディレイモード更新(%u.%u x %u usec)", ! 729: ch + 'A', ! 730: (uint)(scale / 1000), ! 731: (uint)((scale / 100) % 10), ! 732: (uint)mfp.initial_tdr[ch]); ! 733: } ! 734: } ! 735: ! 736: // VDisp 入力 ! 737: void ! 738: MFPDevice::SetVDisp(bool vdisp) ! 739: { ! 740: // TAI への入力はイベントカウントモードの時のみ ! 741: if (mfp.tcr[0] == 8) { ! 742: // AER が示す方向と同じエッジ方向の時 ! 743: bool aer = (mfp.aer & (1 << MFP::GPIP_VDISP)); ! 744: if (aer == vdisp) { ! 745: // カウンタを減算 ! 746: mfp.initial_tdr[0]--; ! 747: if (mfp.initial_tdr[0] == 0) { ! 748: // 0 になったらリロード ! 749: mfp.initial_tdr[0] = mfp.tdr[0]; ! 750: ! 751: // XXX ここで割り込みを上げる ! 752: } ! 753: } ! 754: } ! 755: ! 756: // GPIP への入力 ! 757: SetGPIP(MFP::GPIP_VDISP, vdisp); ! 758: } ! 759: ! 760: // GPIP への入力。 ! 761: // num はビット番号(0..7)。 ! 762: void ! 763: MFPDevice::SetGPIP(int num, bool val) ! 764: { ! 765: bool aer = (mfp.aer & (1 << num)); ! 766: bool old = (mfp.gpip & (1 << num)); ! 767: ! 768: // 立ち上がりか立ち下がりで割り込みを上げる (AER による) ! 769: // AER OLD VAL Interrupt ! 770: // 0 0 0 0 ! 771: // 0 0 1 0 ! 772: // 0 1 0 1 ! 773: // 0 1 1 0 ! 774: // 1 0 0 0 ! 775: // 1 0 1 1 ! 776: // 1 1 0 0 ! 777: // 1 1 1 0 ! 778: if ((old != val) & (aer == val)) { ! 779: // XXX ここで割り込みを上げる ! 780: } ! 781: ! 782: if (val) { ! 783: mfp.gpip |= (1 << num); ! 784: } else { ! 785: mfp.gpip &= ~(1 << num); ! 786: } ! 787: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.