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