Annotation of nono/vm/adpcm.cpp, revision 1.1.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.