Annotation of nono/vm/mfp.cpp, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.