Annotation of nono/vm/adpcm.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2022 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: //
        !             8: // ADPCM (MSM6258V)
        !             9: //
        !            10: 
        !            11: #include "adpcm.h"
        !            12: #include "dmac.h"
        !            13: #include "mpu.h"
        !            14: #include "pio.h"
        !            15: #include "scheduler.h"
        !            16: 
        !            17: // グローバル参照用
        !            18: ADPCMDevice *gADPCM;
        !            19: 
        !            20: // コンストラクタ
        !            21: ADPCMDevice::ADPCMDevice()
        !            22:        : inherited("ADPCM")
        !            23: {
        !            24:        devaddr = baseaddr;
        !            25:        devlen  = 0x2000;
        !            26: 
        !            27:        event.func = ToEventCallback(&ADPCMDevice::EventCallback);
        !            28:        event.Regist("ADPCM");
        !            29: }
        !            30: 
        !            31: // デストラクタ
        !            32: ADPCMDevice::~ADPCMDevice()
        !            33: {
        !            34:        gADPCM = NULL;
        !            35: }
        !            36: 
        !            37: // リセット
        !            38: void
        !            39: ADPCMDevice::ResetHard(bool poweron)
        !            40: {
        !            41:        playing = false;
        !            42:        dack = false;
        !            43: 
        !            44:        // ?
        !            45:        clk = 8000'000;
        !            46:        div = 512;
        !            47: }
        !            48: 
        !            49: uint64
        !            50: ADPCMDevice::Read(uint32 offset)
        !            51: {
        !            52:        uint8 data;
        !            53: 
        !            54:        gMPU->AddCycle(18);     // InsideOut p.135
        !            55: 
        !            56:        switch (offset) {
        !            57:         case 0:        // STAT
        !            58:                data = 0x40;
        !            59:                if (playing) {
        !            60:                        data |= STAT_PLAY;
        !            61:                }
        !            62:                putlog(1, "STAT -> $%02x", data);
        !            63:                break;
        !            64:         case 1:        // DATA
        !            65:                putlog(0, "Read $%06x (NOT IMPLEMENTED)", gMPU->GetPaddr());
        !            66:                data = 0xff;
        !            67:                break;
        !            68:         default:
        !            69:                __unreachable();
        !            70:        }
        !            71: 
        !            72:        return data;
        !            73: }
        !            74: 
        !            75: uint64
        !            76: ADPCMDevice::Write(uint32 offset, uint32 data)
        !            77: {
        !            78:        gMPU->AddCycle(22);     // InsideOut p.135
        !            79: 
        !            80:        switch (offset) {
        !            81:         case 0:        // CMD
        !            82:                putlog(1, "CMD  <- $%02x", data);
        !            83:                if ((data & REC_START)) {
        !            84:                        putlog(0, "Start recording (NOT IMPLEMENTED)");
        !            85:                }
        !            86:                if ((data & PLAY_START)) {
        !            87:                        putlog(0, "Start playing (NOT IMPLEMENTED)");
        !            88:                        StartPlay();
        !            89:                }
        !            90:                if ((data & STOP)) {
        !            91:                        putlog(0, "Stop (NOT IMPLEMENTED)");
        !            92:                        playing = false;
        !            93:                }
        !            94:                break;
        !            95:         case 1:        // DATA
        !            96:                // 未実装だけど再生中の書き込みは来るのは分かっているので抑えておく
        !            97:                if ((playing && loglevel >= 2) || playing == false) {
        !            98:                        putlogn("DATA <- $%02x (NOT IMPLEMENTED)", data);
        !            99:                }
        !           100:                break;
        !           101:         default:
        !           102:                __unreachable();
        !           103:        }
        !           104: 
        !           105:        return 0;
        !           106: }
        !           107: 
        !           108: uint64
        !           109: ADPCMDevice::Peek(uint32 offset)
        !           110: {
        !           111:        // XXX 未実装
        !           112:        return 0xff;
        !           113: }
        !           114: 
        !           115: // 再生開始
        !           116: void
        !           117: ADPCMDevice::StartPlay()
        !           118: {
        !           119:        // PPI で設定されているサンプリングレートをここで読み出す。
        !           120:        // XXX パンは未対応
        !           121:        switch (gPPI->GetADPCMRate()) {
        !           122:         case 0:
        !           123:                div = 1024;
        !           124:                break;
        !           125:         case 1:
        !           126:         case 3:                // %11 は %01 と同じになる (Inside p295)
        !           127:                div = 768;
        !           128:                break;
        !           129:         case 2:
        !           130:                div = 512;
        !           131:                break;
        !           132:         default:
        !           133:                __unreachable();
        !           134:        }
        !           135: 
        !           136:        playing = true;
        !           137:        gDMAC->AssertREQ(3);
        !           138: 
        !           139:        event.time = div / clk;
        !           140:        gScheduler->StartEvent(event);
        !           141: }
        !           142: 
        !           143: // イベント
        !           144: void
        !           145: ADPCMDevice::EventCallback(Event& ev)
        !           146: {
        !           147:        // XXX 適当
        !           148:        if (playing) {
        !           149:                gDMAC->AssertREQ(3);
        !           150:        }
        !           151: }
        !           152: 
        !           153: // DACK 信号をアサートする (DMAC から呼ばれる)
        !           154: void
        !           155: ADPCMDevice::AssertDACK(bool tc_)
        !           156: {
        !           157:        dack = true;
        !           158:        // DRQ を下げる
        !           159:        gDMAC->NegateREQ(0);
        !           160: }
        !           161: 
        !           162: // DACK 信号をネゲートする (DMAC から呼ばれる)
        !           163: void
        !           164: ADPCMDevice::NegateDACK()
        !           165: {
        !           166:        dack = false;
        !           167: }
        !           168: 
        !           169: // クロック切り替え。OPM から呼ばれる。
        !           170: // CT1 = %0 で 8MHz、%1 で 4MHz。
        !           171: void
        !           172: ADPCMDevice::SetClock(bool ct1)
        !           173: {
        !           174:        if (ct1) {
        !           175:                clk = 4000'000;
        !           176:        } else {
        !           177:                clk = 8000'000;
        !           178:        }
        !           179: }

unix.superglobalmegacorp.com

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