|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.