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

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

unix.superglobalmegacorp.com

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