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