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

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "mfp.h"
1.1.1.7   root        8: #include "interrupt.h"
                      9: #include "keyboard.h"
1.1.1.4   root       10: #include "mpu680x0.h"
1.1       root       11: 
1.1.1.3   root       12: std::unique_ptr<MFPDevice> gMFP;
1.1       root       13: 
                     14: // コンストラクタ
                     15: MFPDevice::MFPDevice()
                     16: {
                     17:        logname = "mfp";
                     18:        devname = "MFP";
                     19:        devaddr = baseaddr;
                     20:        devlen  = 0x2000;
1.1.1.7   root       21:        monitor_size = nnSize(77, 26);
1.1       root       22: 
                     23:        for (int ch = 0; ch < countof(event); ch++) {
                     24:                event[ch].dev = this;
                     25:                event[ch].func = (DeviceCallback_t)&MFPDevice::TimerCallback;
                     26:                event[ch].code = ch;
1.1.1.2   root       27:                event[ch].SetName(string_format("MFP Timer-%c", ch + 'A'));
1.1       root       28:        }
1.1.1.4   root       29: 
                     30:        // キーボード周りは x68kkbd.cpp のコメント参照
                     31:        key_event.dev = this;
                     32:        key_event.func = (DeviceCallback_t)&MFPDevice::KeyCallback;
                     33:        key_event.time = 3750_usec;
                     34:        key_event.SetName("MFP USART");
1.1       root       35: }
                     36: 
                     37: // デストラクタ
                     38: MFPDevice::~MFPDevice()
                     39: {
                     40: }
                     41: 
1.1.1.8 ! root       42: // デバイスリセット
1.1.1.6   root       43: void
                     44: MFPDevice::ResetHard()
                     45: {
                     46:        // All internal registers are cleared expect the TxDR, UDR, and TSR.
                     47:        mfp.aer = 0;
                     48:        mfp.ddr = 0;
                     49:        mfp.ier.w = 0;
                     50:        mfp.ipr.w = 0;
                     51:        mfp.isr.w = 0;
                     52:        mfp.imr.w = 0;
                     53:        for (int i = 0; i < countof(mfp.tcr); i++) {
                     54:                mfp.tcr[i] = 0;
                     55:        }
                     56:        mfp.scr = 0;
                     57:        mfp.ucr = 0;
                     58:        mfp.rsr = 0;
                     59:        // XXX TSR は変化しないがたぶんバッファはクリアされるので BE は立つ
                     60:        // ということかな。
                     61:        mfp.tsr = MFP::TSR_BE;
1.1       root       62: 
1.1.1.6   root       63:        // All timers are stopped.
1.1       root       64:        for (int ch = 0; ch < countof(event); ch++) {
1.1.1.3   root       65:                event[ch].Stop();
1.1       root       66:        }
1.1.1.4   root       67:        key_event.Stop();
1.1       root       68: 
1.1.1.6   root       69:        // USART RX and TX are disabled.
                     70:        // SO line is placed in HighZ.
                     71:        // The interrupt channels are disabled, and
                     72:        // any pending interrupts are cleared.
                     73:        // GPIO lines are placed in HighZ.
                     74:        // timer outputs are driven low.
                     75:        // External signals are nagated.
                     76:        // VR is initialized to $00 (not $0f).
1.1.1.7   root       77:        mfp.vr_vec = 0;
                     78:        mfp.vr_s   = 0;
1.1.1.6   root       79: 
1.1.1.4   root       80:        // 信号線
                     81:        rr = false;
1.1.1.3   root       82: }
                     83: 
1.1       root       84: uint64
1.1.1.8 ! root       85: MFPDevice::Read(uint32 offset)
1.1       root       86: {
                     87:        uint8 data;
                     88: 
1.1.1.6   root       89:        gMPU->AddCycle(24);     // InsideOut p.135
                     90: 
1.1.1.8 ! root       91:        switch (offset) {
1.1       root       92:         case MFP::GPIP:
                     93:                data = mfp.gpip;
                     94:                break;
                     95:         case MFP::AER:
                     96:                data = mfp.aer;
                     97:                break;
                     98:         case MFP::DDR:
                     99:                data = mfp.ddr;
                    100:                break;
                    101:         case MFP::IERA:
                    102:                data = mfp.ier.a;
                    103:                break;
                    104:         case MFP::IERB:
                    105:                data = mfp.ier.b;
                    106:                break;
                    107:         case MFP::IPRA:
                    108:                data = mfp.ipr.a;
                    109:                break;
                    110:         case MFP::IPRB:
                    111:                data = mfp.ipr.b;
                    112:                break;
                    113:         case MFP::ISRA:
                    114:                data = mfp.isr.a;
                    115:                break;
                    116:         case MFP::ISRB:
                    117:                data = mfp.isr.b;
                    118:                break;
                    119:         case MFP::IMRA:
                    120:                data = mfp.imr.a;
                    121:                break;
                    122:         case MFP::IMRB:
                    123:                data = mfp.imr.b;
                    124:                break;
                    125:         case MFP::VR:
1.1.1.7   root      126:                data = mfp.GetVR();
1.1       root      127:                break;
                    128:         case MFP::TACR:
                    129:                data = mfp.tcr[0];
                    130:                break;
                    131:         case MFP::TBCR:
                    132:                data = mfp.tcr[1];
                    133:                break;
                    134:         case MFP::TCDCR:
                    135:                data = (mfp.tcr[2] << 4) | mfp.tcr[3];
                    136:                break;
                    137:         case MFP::TADR:
                    138:                data = GetTDR(0);
                    139:                break;
                    140:         case MFP::TBDR:
                    141:                data = GetTDR(1);
                    142:                break;
                    143:         case MFP::TCDR:
                    144:                data = GetTDR(2);
                    145:                break;
                    146:         case MFP::TDDR:
                    147:                data = GetTDR(3);
                    148:                break;
                    149:         case MFP::SCR:
                    150:                data = mfp.scr;
                    151:                break;
                    152:         case MFP::UCR:
                    153:                data = mfp.ucr;
                    154:                break;
                    155:         case MFP::RSR:
                    156:                data = mfp.rsr;
                    157:                break;
                    158:         case MFP::TSR:
                    159:                data = mfp.tsr;
                    160:                break;
                    161:         case MFP::UDR:
                    162:                data = mfp.udr;
                    163:                break;
1.1.1.4   root      164:         default:
                    165:                data = 0xff;
                    166:                break;
1.1       root      167:        }
                    168:        return data;
                    169: }
                    170: 
                    171: uint64
1.1.1.8 ! root      172: MFPDevice::Write(uint32 offset, uint32 data)
1.1       root      173: {
1.1.1.6   root      174:        gMPU->AddCycle(24);     // InsideOut p.135
                    175: 
1.1.1.8 ! root      176:        switch (offset) {
1.1       root      177:         case MFP::GPIP:
                    178:                putlog(0, "GPIP <- $%02x 未実装書き込み", data);
                    179:                mfp.gpip = data;
                    180:                break;
                    181:         case MFP::AER:
                    182:                putlog(0, "AER <- $%02x 未実装書き込み", data);
                    183:                mfp.aer = data;
                    184:                break;
                    185:         case MFP::DDR:
                    186:                if (data != 0) {
                    187:                        putlog(0, "DDR <- $%02x 未実装書き込み", data);
                    188:                }
                    189:                mfp.ddr = data;
                    190:                break;
                    191:         case MFP::IERA:
                    192:                putlog(2, "IERA <- $%02x", data);
                    193:                mfp.ier.a = data;
                    194:                break;
                    195:         case MFP::IERB:
                    196:                putlog(2, "IERB <- $%02x", data);
                    197:                mfp.ier.b = data;
                    198:                break;
                    199:         case MFP::IPRA:
                    200:                putlog(2, "IPRA <- $%02x", data);
                    201:                mfp.ipr.a = data;
1.1.1.7   root      202:                ChangeInterrupt();
1.1       root      203:                break;
                    204:         case MFP::IPRB:
                    205:                putlog(2, "IPRB <- $%02x", data);
                    206:                mfp.ipr.b = data;
1.1.1.7   root      207:                ChangeInterrupt();
1.1       root      208:                break;
                    209:         case MFP::ISRA:
                    210:                putlog(2, "ISRA <- $%02x", data);
                    211:                mfp.isr.a = data;
                    212:                break;
                    213:         case MFP::ISRB:
                    214:                putlog(2, "ISRB <- $%02x", data);
                    215:                mfp.isr.b = data;
                    216:                break;
                    217:         case MFP::IMRA:
                    218:                putlog(2, "IMRA <- $%02x", data);
                    219:                mfp.imr.a = data;
1.1.1.7   root      220:                ChangeInterrupt();
1.1       root      221:                break;
                    222:         case MFP::IMRB:
                    223:                putlog(2, "IMRB <- $%02x", data);
                    224:                mfp.imr.b = data;
1.1.1.7   root      225:                ChangeInterrupt();
1.1       root      226:                break;
                    227:         case MFP::VR:
1.1.1.7   root      228:                mfp.vr_vec = data & 0xf0;
                    229:                mfp.vr_s   = data & 0x08;
                    230:                putlog(2, "VR <- $%02x", mfp.GetVR());
1.1       root      231:                break;
                    232:         case MFP::TACR:
                    233:                putlog(2, "TACR <- $%02x", data);
                    234:                SetTCR(0, data);
                    235:                break;
                    236:         case MFP::TBCR:
                    237:                putlog(2, "TBCR <- $%02x", data);
                    238:                SetTCR(1, data);
                    239:                break;
                    240:         case MFP::TCDCR:
                    241:                putlog(2, "TCDCR <- $%02x", data);
                    242:                SetTCR(2, data >> 4);
                    243:                SetTCR(3, data & 7);
                    244:                break;
                    245:         case MFP::TADR:
                    246:                putlog(2, "TADR <- $%02x", data);
                    247:                SetTDR(0, data);
                    248:                break;
                    249:         case MFP::TBDR:
                    250:                putlog(2, "TBDR <- $%02x", data);
                    251:                SetTDR(1, data);
                    252:                break;
                    253:         case MFP::TCDR:
                    254:                putlog(2, "TCDR <- $%02x", data);
                    255:                SetTDR(2, data);
                    256:                break;
                    257:         case MFP::TDDR:
                    258:                putlog(2, "TDDR <- $%02x", data);
                    259:                SetTDR(3, data);
                    260:                break;
                    261:         case MFP::SCR:
                    262:                putlog(0, "SCR <- $%02x 未実装書き込み", data);
                    263:                mfp.scr = data;
                    264:                break;
                    265:         case MFP::UCR:
1.1.1.4   root      266:                putlog(2, "UCR <- $%02x", data);
                    267:                SetUCR(data);
1.1       root      268:                break;
                    269:         case MFP::RSR:
1.1.1.4   root      270:                putlog(2, "RSR <- $%02x", data);
                    271:                SetRSR(data);
1.1       root      272:                break;
                    273:         case MFP::TSR:
                    274:                putlog(0, "TSR <- $%02x 未実装書き込み", data);
                    275:                mfp.tsr = (mfp.tsr & 0xf0) | (data & 0x0f);
                    276:                break;
                    277:         case MFP::UDR:
1.1.1.4   root      278:                if (data == 0x40 || data == 0x41) {
                    279:                        // MSCTRL だけ頻度が高いのでログレベルを上げておく
                    280:                        putlog(3, "UDR <- $%02x", data);
                    281:                } else {
                    282:                        putlog(2, "UDR <- $%02x", data);
                    283:                }
                    284:                SetUDR(data);
                    285:                break;
                    286:         default:
1.1       root      287:                break;
                    288:        }
                    289:        return 0;
                    290: }
                    291: 
                    292: uint64
1.1.1.8 ! root      293: MFPDevice::Peek(uint32 offset)
1.1       root      294: {
                    295:        uint8 data;
                    296: 
1.1.1.8 ! root      297:        switch (offset) {
1.1       root      298:         case MFP::GPIP:
                    299:                data = mfp.gpip;
                    300:                break;
                    301:         case MFP::AER:
                    302:                data = mfp.aer;
                    303:                break;
                    304:         case MFP::DDR:
                    305:                data = mfp.ddr;
                    306:                break;
                    307:         case MFP::IERA:
                    308:                data = mfp.ier.a;
                    309:                break;
                    310:         case MFP::IERB:
                    311:                data = mfp.ier.b;
                    312:                break;
                    313:         case MFP::IPRA:
                    314:                data = mfp.ipr.a;
                    315:                break;
                    316:         case MFP::IPRB:
                    317:                data = mfp.ipr.b;
                    318:                break;
                    319:         case MFP::ISRA:
                    320:                data = mfp.isr.a;
                    321:                break;
                    322:         case MFP::ISRB:
                    323:                data = mfp.isr.b;
                    324:                break;
                    325:         case MFP::IMRA:
                    326:                data = mfp.imr.a;
                    327:                break;
                    328:         case MFP::IMRB:
                    329:                data = mfp.imr.b;
                    330:                break;
                    331:         case MFP::VR:
1.1.1.7   root      332:                data = mfp.GetVR();
1.1       root      333:                break;
                    334:         case MFP::TACR:
                    335:                data = mfp.tcr[0];
                    336:                break;
                    337:         case MFP::TBCR:
                    338:                data = mfp.tcr[1];
                    339:                break;
                    340:         case MFP::TCDCR:
                    341:                data = (mfp.tcr[2] << 4) | mfp.tcr[3];
                    342:                break;
                    343:         case MFP::TADR:
                    344:                data = GetTDR(0);
                    345:                break;
                    346:         case MFP::TBDR:
                    347:                data = GetTDR(1);
                    348:                break;
                    349:         case MFP::TCDR:
                    350:                data = GetTDR(2);
                    351:                break;
                    352:         case MFP::TDDR:
                    353:                data = GetTDR(3);
                    354:                break;
                    355:         case MFP::SCR:
                    356:                data = mfp.scr;
                    357:                break;
                    358:         case MFP::UCR:
                    359:                data = mfp.ucr;
                    360:                break;
                    361:         case MFP::RSR:
                    362:                data = mfp.rsr;
                    363:                break;
                    364:         case MFP::TSR:
                    365:                data = mfp.tsr;
                    366:                break;
                    367:         case MFP::UDR:
                    368:                data = mfp.udr;
                    369:                break;
1.1.1.4   root      370:         default:
                    371:                data = 0xff;
1.1       root      372:        }
                    373:        return data;
                    374: }
                    375: 
1.1.1.5   root      376: void
                    377: MFPDevice::MonitorUpdate(TextScreen& monitor)
1.1       root      378: {
                    379:        int x;
                    380:        int y;
                    381: 
                    382:        monitor.Clear();
                    383: 
                    384:        // 0         1         2         3         4         5         6
1.1.1.7   root      385:        // 01234567890123456789012345678901234567890123456789012345678901234567890
                    386:        // $e88001(GPIP):$00   $e88007(IERA):$00   $e88019(TACR):$00   $e88027
1.1       root      387:        //                 IER    IMR  IPR  ISR           Mode        TDR Cnt
                    388:        // An:MPSC TxEmpty Enable Mask Pend Serv  Timer-A Delay(50us) 255 255
                    389: 
1.1.1.7   root      390: #define A(x)   (baseaddr + (x * 2) + 1)
                    391: 
                    392:        // レジスタ生値
                    393:        // 1列目(GPIP 関連と VR)
                    394:        x = 0;
                    395:        y = 0;
                    396:        monitor.Print(x, y++, "$%06x(GPIP):$%02x", A(MFP::GPIP), mfp.gpip);
                    397:        monitor.Print(x, y++, "$%06x(AER): $%02x", A(MFP::AER),  mfp.aer);
                    398:        monitor.Print(x, y++, "$%06x(DDR): $%02x", A(MFP::DDR),  mfp.ddr);
                    399:        monitor.Print(x, y++, "$%06x(VR):  $%02x", A(MFP::VR),   mfp.GetVR());
                    400:        // 2列目(割り込み関連)
                    401:        x = 20;
                    402:        y = 0;
                    403:        monitor.Print(x, y++, "$%06x(IERA):$%02x", A(MFP::IERA), mfp.ier.a);
                    404:        monitor.Print(x, y++, "$%06x(IERB):$%02x", A(MFP::IERB), mfp.ier.b);
                    405:        monitor.Print(x, y++, "$%06x(IPRA):$%02x", A(MFP::IPRA), mfp.ipr.a);
                    406:        monitor.Print(x, y++, "$%06x(IPRB):$%02x", A(MFP::IPRB), mfp.ipr.b);
                    407:        monitor.Print(x, y++, "$%06x(ISRA):$%02x", A(MFP::ISRA), mfp.isr.a);
                    408:        monitor.Print(x, y++, "$%06x(ISRB):$%02x", A(MFP::ISRB), mfp.isr.b);
                    409:        monitor.Print(x, y++, "$%06x(IMRA):$%02x", A(MFP::IMRA), mfp.imr.a);
                    410:        monitor.Print(x, y++, "$%06x(IMRB):$%02x", A(MFP::IMRB), mfp.imr.b);
                    411:        // 3列目(タイマー関連)
                    412:        x = 40;
                    413:        y = 0;
                    414:        monitor.Print(x, y++, "$%06x(TACR): $%02x", A(MFP::TACR), mfp.tcr[0]);
                    415:        monitor.Print(x, y++, "$%06x(TBCR): $%02x", A(MFP::TBCR), mfp.tcr[1]);
                    416:        monitor.Print(x, y++, "$%06x(TCDCR):$%02x", A(MFP::TCDCR),
                    417:                (mfp.tcr[2] << 4) | mfp.tcr[3]);
                    418:        monitor.Print(x, y++, "$%06x(TADR): $%02x", A(MFP::TADR), GetTDR(0));
                    419:        monitor.Print(x, y++, "$%06x(TBDR): $%02x", A(MFP::TBDR), GetTDR(1));
                    420:        monitor.Print(x, y++, "$%06x(TCDR): $%02x", A(MFP::TCDR), GetTDR(2));
                    421:        monitor.Print(x, y++, "$%06x(TDDR): $%02x", A(MFP::TDDR), GetTDR(3));
                    422:        // 4列目(USART 関連)
                    423:        x = 61;
                    424:        y = 0;
                    425:        monitor.Print(x, y++, "$%06x(SCR):$%02x", A(MFP::SCR), mfp.scr);
                    426:        monitor.Print(x, y++, "$%06x(UCR):$%02x", A(MFP::UCR), mfp.ucr);
                    427:        monitor.Print(x, y++, "$%06x(RSR):$%02x", A(MFP::RSR), mfp.rsr);
                    428:        monitor.Print(x, y++, "$%06x(TSR):$%02x", A(MFP::TSR), mfp.tsr);
                    429:        monitor.Print(x, y, "$%06x(UDR):", A(MFP::UDR));
                    430:        if ((int16)mfp.udr >= 0) {
                    431:                monitor.Print(x + 13, y, "$%02x", mfp.udr);
                    432:        } else {
                    433:                monitor.Print(x + 13, y, "---");
                    434:        }
                    435: 
1.1       root      436:        // 割り込み関連
1.1.1.7   root      437:        y = 9;
                    438:        monitor.Print(0, y++, "<Interrupt>     %-6s %-4s %-4s %-4s",
                    439:                "IER", "IMR", "IPR", "ISR");
1.1       root      440:        for (int i = 15; i >= 0; i--, y++) {
                    441:                uint16 mask = (1 << i);
                    442:                monitor.Print(0, y, "%c%d:%-12s %-6s %-4s %-4s %-4s",
                    443:                        i >= 8 ? 'A' : 'B',
                    444:                        (i % 8),
                    445:                        intrname[i],
                    446:                        (mfp.ier.w & mask) ? "Enable" : "",
                    447:                        (mfp.imr.w & mask) ? ""       : "Mask", // %0 でマスクする
                    448:                        (mfp.ipr.w & mask) ? "Pend"   : "",
                    449:                        (mfp.isr.w & mask) ? "Serv"   : "");
                    450:        }
                    451: 
                    452:        // タイマー関連
                    453:        x = 39;
1.1.1.7   root      454:        y = 9;
                    455:        monitor.Print(x, y++, "<Timer> Mode       TDR Ini");
1.1       root      456:        for (int ch = 0; ch < 4; ch++) {
                    457:                monitor.Print(x, y, "Timer-%c", ch + 'A');
                    458:                if (mfp.tcr[ch] == 0) {
                    459:                        monitor.Print(x + 8, y, "Stopped");
                    460:                } else if (mfp.tcr[ch] == 8) {
                    461:                        monitor.Print(x + 8, y, "Event");
                    462:                } else if (mfp.tcr[ch] > 8) {
                    463:                        monitor.Print(x + 8, y, "Pulse(%s)", prescale_str[mfp.tcr[ch] - 8]);
                    464:                } else {
                    465:                        monitor.Print(x + 8, y, "Delay(%s)", prescale_str[mfp.tcr[ch]]);
                    466:                }
                    467: 
                    468:                monitor.Print(x + 19, y, "%3d", GetTDR(ch));
1.1.1.7   root      469:                monitor.Print(x + 23, y, "%3d", mfp.initial_tdr[ch]);
                    470:                y++;
1.1       root      471:        }
                    472: 
                    473:        // GPIP 関連
                    474:        x = 39;
1.1.1.7   root      475:        y = 9 + 8;
                    476:        monitor.Puts(x, y++, "<GPIP>    GPIP AER DDR");
1.1       root      477:        for (int i = 7; i >= 0; i--, y++) {
                    478:                uint mask = (1 << i);
                    479:                monitor.Print(x, y, "b%d %-6s  %d   %d   %s", i, gpipname[i],
                    480:                        (mfp.gpip & mask) ? 1 : 0,
                    481:                        (mfp.aer & mask) ? 1 : 0,
                    482:                        (mfp.ddr & mask) ? "OUT" : "IN");
                    483:        }
                    484: }
                    485: 
                    486: /*static*/ const char *
                    487: MFPDevice::intrname[] = {
                    488:        "RTC Alarm",
                    489:        "EXPON",
                    490:        "POW SW",
                    491:        "FM IRQ",
                    492:        "Timer-D",
                    493:        "Timer-C",
                    494:        "V-Disp",
                    495:        "---",
                    496:        "Timer-B",
                    497:        "MPSC TxErr",
                    498:        "MPSC TxEmpty",
                    499:        "MPSC RxErr",
                    500:        "MPSC RxFull",
                    501:        "Timer-A",
                    502:        "CRTC IRQ",
                    503:        "H-Sync",
                    504: };
                    505: 
                    506: /*static*/ const char *
                    507: MFPDevice::gpipname[] = {
                    508:        "ALARM",
                    509:        "EXPON",
                    510:        "POW SW",
                    511:        "FMIRQ",
                    512:        "V-Disp",
                    513:        "------",
                    514:        "CIRQ",
                    515:        "H-Sync",
                    516: };
                    517: 
                    518: // TxCR の設定値から分周期間というかメインカウンタ1回分の時間を返す
                    519: /*static*/ const int
                    520: MFPDevice::prescale_ns[8] = {
                    521:        0,
                    522:        1000,   // /4
                    523:        2500,   // /10
                    524:        4000,   // /16
                    525:        12500,  // /50
                    526:        16000,  // /64
                    527:        25000,  // /100
                    528:        50000,  // /200
                    529: };
                    530: 
                    531: /*static*/ const char *
                    532: MFPDevice::prescale_str[8] = {
                    533:        "",
                    534:        "1us",
                    535:        "2.5us",
                    536:        "4us",
                    537:        "12.5us",
                    538:        "16us",
                    539:        "25us",
                    540:        "50us",
                    541: };
                    542: 
1.1.1.7   root      543: // タイマーのチャンネルから MFP 割り込みチャンネル番号に変換する
1.1       root      544: /*static*/ const int
1.1.1.4   root      545: MFPDevice::timer_vector[4] = {
                    546:        MFP::INTR_TIMER_A,
                    547:        MFP::INTR_TIMER_B,
                    548:        MFP::INTR_TIMER_C,
                    549:        MFP::INTR_TIMER_D,
                    550: };
1.1       root      551: 
                    552: // TxCR をセットする
                    553: void
                    554: MFPDevice::SetTCR(int ch, uint32 data)
                    555: {
                    556:        uint32 prev;
                    557: 
                    558:        prev = mfp.tcr[ch];
                    559:        data &= 0x0f;
                    560: 
                    561:        mfp.tcr[ch] = data;
1.1.1.7   root      562:        if (data == 0) {
                    563:                if (prev == 0) {
                    564:                        // 0 -> 0 なら何も起きない
                    565:                        return;
                    566:                } else if (prev < 8) {
                    567:                        // タイマー停止
                    568:                        putlog(1, "Timer-%c 停止", ch + 'A');
                    569: 
                    570:                        // ここで TDR を確定させる。
                    571:                        // タイマー動作中の TDR の参照はイベント終了時刻から現在値を逆算
                    572:                        // していたが、イベントを停止すると求められなくなるので、イベント
                    573:                        // 停止前に求めておく。
                    574:                        uint64 period = prescale_ns[prev];
                    575:                        uint64 now = gMPU->GetVirtTime();
                    576:                        mfp.tdr[ch] = ((event[ch].vtime - now) + period - 1) / period;
                    577: 
                    578:                        // でイベント停止
                    579:                        event[ch].Stop();
                    580:                        return;
                    581:                } else if (prev == 8) {
                    582:                        // イベントカウントモードから停止しても何も起きないはず
                    583:                } else {
                    584:                        // パルス幅測定モード (未実装)
                    585:                }
1.1       root      586:                return;
1.1.1.7   root      587: 
                    588:        } else if (data < 8) {
                    589:                // タイマー開始
                    590: 
                    591:                // TDR をリロード(?)
                    592:                mfp.tdr[ch] = mfp.initial_tdr[ch];
                    593:                // タイマースタート
                    594:                uint64 period = prescale_ns[mfp.tcr[ch]];
                    595:                event[ch].time = period * (mfp.tdr[ch] ?: 256);
                    596:                event[ch].Start();
                    597: 
                    598:                putlog(1, "Timer-%c ディレイモード開始(%u x %u.%uusec)",
                    599:                        ch + 'A',
                    600:                        mfp.initial_tdr[ch],
                    601:                        (uint)period / 1000,
                    602:                        (uint)(period / 100) % 10);
                    603:                return;
                    604: 
                    605:        } else if (data == 8) {
1.1       root      606:                // イベントカウントモード
                    607: 
                    608:                // TDR をロードする
                    609:                mfp.initial_tdr[ch] = mfp.tdr[ch];
                    610:                putlog(1, "Timer-%c イベントカウントモード", ch + 'A');
                    611:                return;
                    612: 
                    613:        } else {
1.1.1.7   root      614:                putlog(0, "T%cCR パルス幅測定モード $%02x 未実装",
                    615:                        ch + 'A', data);
                    616:                return;
1.1       root      617:        }
                    618: }
                    619: 
                    620: // TxDR の読み出し
1.1.1.7   root      621: // (副作用はないので Peek 系からも呼び出してよい)
1.1       root      622: uint8
1.1.1.3   root      623: MFPDevice::GetTDR(int ch) const
1.1       root      624: {
1.1.1.7   root      625:        uint8 tcr = mfp.tcr[ch];
1.1       root      626: 
1.1.1.7   root      627:        if (tcr == 0) {
                    628:                // 停止中なら tdr に現在値が保持されている
1.1       root      629:                return mfp.tdr[ch];
                    630: 
1.1.1.7   root      631:        } else if (tcr < 8) {
                    632:                // ディレイモード動作中なら現在値は保持していないので、
                    633:                // プリスケーラと終了時刻から算出。
                    634: 
                    635:                uint64 period = prescale_ns[tcr];
                    636:                uint64 now = gMPU->GetVirtTime();
                    637:                return ((event[ch].vtime - now) + period - 1) / period;
1.1       root      638: 
1.1.1.7   root      639:        } else {
                    640:                // イベントモード、パルス幅測定モードは未対応
                    641:                return mfp.tdr[ch];
1.1       root      642: 
1.1.1.7   root      643:        }
1.1       root      644: }
                    645: 
                    646: // TxDR への書き込み
                    647: void
                    648: MFPDevice::SetTDR(int ch, uint32 data)
                    649: {
1.1.1.7   root      650:        uint8& tcr = mfp.tcr[ch];
1.1       root      651: 
1.1.1.7   root      652:        if (tcr == 0) {
                    653:                // 停止中の書き込みは両方更新
                    654:                mfp.tdr[ch] = data;
                    655:                mfp.initial_tdr[ch] = data;
                    656: 
                    657:        } else if (tcr < 8) {
                    658:                // ディレイモード動作中の書き込み
                    659:                // メインカウンタは影響を受けず、次回値を更新するだけ。
                    660:                mfp.initial_tdr[ch] = data;
1.1       root      661: 
1.1.1.7   root      662:        } else {
                    663:                // イベントモード、パルス幅測定モードは未対応
                    664:                putlog(0, "T%cDR サポートしてないモード中の書き込み $%02x",
                    665:                        ch + 'A', data);
1.1       root      666:        }
                    667: }
                    668: 
                    669: // イベントコールバック
                    670: void
1.1.1.6   root      671: MFPDevice::TimerCallback(Event& ev)
1.1       root      672: {
1.1.1.6   root      673:        int& ch = ev.code;
1.1       root      674: 
1.1.1.7   root      675:        // TDR がゼロになったところで呼ばれるので、TDR をリロードする
                    676:        mfp.tdr[ch] = mfp.initial_tdr[ch];
1.1       root      677: 
1.1.1.7   root      678:        // 割り込みを上げる
                    679:        SetInterrupt(timer_vector[ch]);
                    680: 
                    681:        // 次のイベントをセット
                    682:        // XXX 1回のイベントで複数のタイムアウトパルスを跨ぐ状況は考慮してない
                    683: 
                    684:        // period が1メインパルス期間
                    685:        // time が1タイムアウトパルス期間
                    686:        uint64 period = prescale_ns[mfp.tcr[ch]];
                    687:        uint64 time = period * (mfp.tdr[ch] ?: 256);
                    688:        // 次のタイムアウトパルスは、今回のタイムアウト時刻から数える
                    689:        // (現在時刻はそれを通り過ぎた任意の時刻なので)
                    690:        uint64 now = gMPU->GetVirtTime();
                    691:        ev.time = ev.vtime + time - now;
                    692:        ev.Start();
1.1       root      693: }
                    694: 
                    695: // VDisp 入力
                    696: void
                    697: MFPDevice::SetVDisp(bool vdisp)
                    698: {
                    699:        // TAI への入力はイベントカウントモードの時のみ
                    700:        if (mfp.tcr[0] == 8) {
                    701:                // AER が示す方向と同じエッジ方向の時
                    702:                bool aer = (mfp.aer & (1 << MFP::GPIP_VDISP));
                    703:                if (aer == vdisp) {
                    704:                        // カウンタを減算
1.1.1.7   root      705:                        mfp.tdr[0]--;
                    706:                        if (mfp.tdr[0] == 0) {
1.1       root      707:                                // 0 になったらリロード
1.1.1.7   root      708:                                mfp.tdr[0] = mfp.initial_tdr[0];
1.1       root      709: 
1.1.1.7   root      710:                                SetInterrupt(MFP::INTR_TIMER_A);
1.1       root      711:                        }
                    712:                }
                    713:        }
                    714: 
                    715:        // GPIP への入力
                    716:        SetGPIP(MFP::GPIP_VDISP, vdisp);
                    717: }
                    718: 
                    719: // GPIP への入力。
                    720: // num はビット番号(0..7)。
                    721: void
                    722: MFPDevice::SetGPIP(int num, bool val)
                    723: {
                    724:        bool aer = (mfp.aer & (1 << num));
                    725:        bool old = (mfp.gpip & (1 << num));
                    726: 
                    727:        // 立ち上がりか立ち下がりで割り込みを上げる (AER による)
                    728:        // AER OLD VAL   Interrupt
                    729:        //   0   0   0   0
                    730:        //   0   0   1   0
                    731:        //   0   1   0   1
                    732:        //   0   1   1   0
                    733:        //   1   0   0   0
                    734:        //   1   0   1   1
                    735:        //   1   1   0   0
                    736:        //   1   1   1   0
1.1.1.3   root      737:        if ((old != val) && (aer == val)) {
1.1       root      738:                // XXX ここで割り込みを上げる
                    739:        }
                    740: 
                    741:        if (val) {
                    742:                mfp.gpip |= (1 << num);
                    743:        } else {
                    744:                mfp.gpip &= ~(1 << num);
                    745:        }
                    746: }
1.1.1.4   root      747: 
                    748: // UCR への書き込み
                    749: void
                    750: MFPDevice::SetUCR(uint32 data)
                    751: {
                    752:        mfp.ucr = data;
                    753: 
                    754:        if ((mfp.ucr & MFP::UCR_CLK) == 0) {
                    755:                putlog(0, "UCR CLK=0 未実装");
                    756:        }
                    757:        if (((mfp.ucr & MFP::UCR_WL) >> 5) != 0) {
                    758:                putlog(0, "UCR WL=%d 未実装", (mfp.ucr >> 5) & 3);
                    759:        }
                    760:        if (((mfp.ucr & MFP::UCR_ST) >> 3) != 1) {
                    761:                putlog(0, "UCR ST=%d 未実装", (mfp.ucr >> 3) & 3);
                    762:        }
                    763: }
                    764: 
                    765: // RSR への書き込み
                    766: void
                    767: MFPDevice::SetRSR(uint32 data)
                    768: {
                    769:        uint32 old = mfp.rsr;
                    770: 
                    771:        mfp.rsr = data;
                    772: 
                    773:        if ((old & MFP::RSR_RE) == 0 && (mfp.rsr & MFP::RSR_RE)) {
                    774:                // RE 0 -> 1
                    775:                rr = true;
                    776:        }
                    777:        if ((old & MFP::RSR_RE) && (mfp.rsr & MFP::RSR_RE) == 0) {
                    778:                // RE 1 -> 0
                    779:                rr = false;
                    780:                mfp.rsr &= 0x0f;        // 上位4ビットのステータスを %0 に
                    781:        }
                    782: }
                    783: 
                    784: // UDR への書き込み
                    785: void
                    786: MFPDevice::SetUDR(uint32 data)
                    787: {
                    788:        if ((mfp.tsr & MFP::TSR_TE)) {
                    789:                gKeyboard->Command(data);
                    790:        }
                    791: }
                    792: 
                    793: // システムポート#4 の KEY CTRL の状態を受け取る。
                    794: void
                    795: MFPDevice::SetKeyCtrl(bool val)
                    796: {
                    797:        key_ctrl = val;
                    798:        putlog(1, "KEYCTRL = %d", key_ctrl);
                    799: }
                    800: 
                    801: // RR (Receiver Ready) 線の状態を返す。true なら Ready。
                    802: // これはシステムポート#4 の KEY CTRL の状態も加味したもの。
                    803: bool
                    804: MFPDevice::IsRR() const
                    805: {
                    806:        return rr && key_ctrl;
                    807: }
                    808: 
                    809: // キーボードからデータを受信
                    810: void
                    811: MFPDevice::Rx(uint32 data)
                    812: {
                    813:        // Ready を下げる
                    814:        rr = false;
                    815: 
                    816:        key_event.code = data;
                    817:        key_event.Start();
                    818: }
                    819: 
                    820: // キーボードからのデータが受信し終わった頃に呼ばれるイベント。
                    821: void
1.1.1.6   root      822: MFPDevice::KeyCallback(Event& ev)
1.1.1.4   root      823: {
                    824:        // Ready を元に戻す
                    825:        rr = true;
                    826: 
1.1.1.6   root      827:        mfp.udr = ev.code;
1.1.1.4   root      828:        mfp.rsr |= MFP::RSR_BF;
                    829: 
1.1.1.7   root      830:        SetInterrupt(MFP::INTR_RXFULL);
                    831: }
                    832: 
                    833: // 必要なら割り込みを上げる。
                    834: // ch は MFP 内の割り込みチャンネル番号。MFP::INTR_*
                    835: void
                    836: MFPDevice::SetInterrupt(uint ch)
                    837: {
                    838:        assertmsg(ch < 16, "ch=%u", ch);
                    839:        __assume(ch < 16);
                    840: 
                    841:        uint b = (1U << ch);
                    842: 
                    843:        // IER で割り込みが無効なら何もしない
                    844:        if ((mfp.ier.w & b) == 0) {
                    845:                return;
1.1.1.4   root      846:        }
1.1.1.7   root      847: 
                    848:        // IPR にペンディングを立てる
                    849:        mfp.ipr.w |= b;
                    850: 
                    851:        // 割り込み信号線の状態を変える
                    852:        ChangeInterrupt();
                    853: }
                    854: 
                    855: // 割り込み信号線の状態を変える
                    856: void
                    857: MFPDevice::ChangeInterrupt()
                    858: {
                    859:        // ペンディングの割り込みがあればアサートされる、
                    860:        // IPR をクリアするか IMR をクリアすると /IRQ はネゲートされる。
                    861:        bool irq = ((mfp.ipr.w & mfp.imr.w) != 0);
                    862:        gInterrupt->ChangeINT(this, irq);
                    863: }
                    864: 
                    865: // 割り込みアクノリッジ
                    866: int
                    867: MFPDevice::InterruptAcknowledge()
                    868: {
                    869:        uint32 pending = mfp.ipr.w;
                    870: 
                    871:        // ch はこの時点で IPR に立ってる一番優先度の高いチャンネルのビット
                    872:        // XXX IPR にビット立ってなかったらどうなる?
                    873:        int ch = 31 - __builtin_clz(pending);
                    874:        uint b = (1U << ch);
                    875: 
                    876:        // MPU にベクタを引き渡したので Pending をクリア
                    877:        mfp.ipr.w &= ~b;
                    878:        ChangeInterrupt();
                    879: 
                    880:        // ソフトウェア EOI なら In Service を立てる
                    881:        if (mfp.vr_s) {
                    882:                mfp.isr.w |= b;
                    883:        }
                    884: 
                    885:        return mfp.vr_vec + ch;
1.1.1.4   root      886: }

unix.superglobalmegacorp.com

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