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

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

unix.superglobalmegacorp.com

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