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