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

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

unix.superglobalmegacorp.com

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