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

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

unix.superglobalmegacorp.com

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