|
|
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.