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

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: 
1.1.1.3 ! root       56: busdata
1.1       root       57: ADPCMDevice::Read(uint32 offset)
                     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.2   root       74:                VMPANIC("corrupted offset=%d", 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       root       81:        return data;
                     82: }
                     83: 
1.1.1.3 ! root       84: busdata
1.1       root       85: ADPCMDevice::Write(uint32 offset, uint32 data)
                     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: 
1.1.1.3 ! root      112:        // InsideOut p.135
        !           113:        const busdata wait = busdata::Wait(22 * 40_nsec);
        !           114:        return wait;
1.1       root      115: }
                    116: 
1.1.1.3 ! root      117: busdata
1.1       root      118: ADPCMDevice::Peek(uint32 offset)
                    119: {
                    120:        // XXX 未実装
                    121:        return 0xff;
                    122: }
                    123: 
                    124: // 再生開始
                    125: void
                    126: ADPCMDevice::StartPlay()
                    127: {
                    128:        // PPI で設定されているサンプリングレートをここで読み出す。
                    129:        // XXX パンは未対応
1.1.1.2   root      130:        int rate = ppi->GetADPCMRate();
                    131:        switch (rate) {
1.1       root      132:         case 0:
                    133:                div = 1024;
                    134:                break;
                    135:         case 1:
                    136:         case 3:                // %11 は %01 と同じになる (Inside p295)
                    137:                div = 768;
                    138:                break;
                    139:         case 2:
                    140:                div = 512;
                    141:                break;
                    142:         default:
1.1.1.2   root      143:                VMPANIC("corrupted ADPCM rate=%d", rate);
1.1       root      144:        }
                    145: 
                    146:        playing = true;
1.1.1.2   root      147:        dmac->AssertREQ(3);
1.1       root      148: 
                    149:        event.time = div / clk;
1.1.1.2   root      150:        scheduler->StartEvent(event);
1.1       root      151: }
                    152: 
                    153: // イベント
                    154: void
                    155: ADPCMDevice::EventCallback(Event& ev)
                    156: {
                    157:        // XXX 適当
                    158:        if (playing) {
1.1.1.2   root      159:                dmac->AssertREQ(3);
1.1       root      160:        }
                    161: }
                    162: 
                    163: // DACK 信号をアサートする (DMAC から呼ばれる)
                    164: void
                    165: ADPCMDevice::AssertDACK(bool tc_)
                    166: {
                    167:        dack = true;
                    168:        // DRQ を下げる
1.1.1.2   root      169:        dmac->NegateREQ(0);
1.1       root      170: }
                    171: 
                    172: // DACK 信号をネゲートする (DMAC から呼ばれる)
                    173: void
                    174: ADPCMDevice::NegateDACK()
                    175: {
                    176:        dack = false;
                    177: }
                    178: 
                    179: // クロック切り替え。OPM から呼ばれる。
                    180: // CT1 = %0 で 8MHz、%1 で 4MHz。
                    181: void
                    182: ADPCMDevice::SetClock(bool ct1)
                    183: {
                    184:        if (ct1) {
                    185:                clk = 4000'000;
                    186:        } else {
                    187:                clk = 8000'000;
                    188:        }
                    189: }

unix.superglobalmegacorp.com

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