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

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

unix.superglobalmegacorp.com

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