|
|
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:
56: uint64
57: ADPCMDevice::Read(uint32 offset)
58: {
59: uint8 data;
60:
1.1.1.2 ! root 61: mpu->AddCycle(18); // InsideOut p.135
1.1 root 62:
63: switch (offset) {
64: case 0: // STAT
65: data = 0x40;
66: if (playing) {
67: data |= STAT_PLAY;
68: }
69: putlog(1, "STAT -> $%02x", data);
70: break;
71: case 1: // DATA
1.1.1.2 ! root 72: putlog(0, "Read $%06x (NOT IMPLEMENTED)", mpu->GetPaddr());
1.1 root 73: data = 0xff;
74: break;
75: default:
1.1.1.2 ! root 76: VMPANIC("corrupted offset=%d", offset);
1.1 root 77: }
78:
79: return data;
80: }
81:
82: uint64
83: ADPCMDevice::Write(uint32 offset, uint32 data)
84: {
1.1.1.2 ! root 85: mpu->AddCycle(22); // InsideOut p.135
1.1 root 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:
112: return 0;
113: }
114:
115: uint64
116: ADPCMDevice::Peek(uint32 offset)
117: {
118: // XXX 未実装
119: return 0xff;
120: }
121:
122: // 再生開始
123: void
124: ADPCMDevice::StartPlay()
125: {
126: // PPI で設定されているサンプリングレートをここで読み出す。
127: // XXX パンは未対応
1.1.1.2 ! root 128: int rate = ppi->GetADPCMRate();
! 129: switch (rate) {
1.1 root 130: case 0:
131: div = 1024;
132: break;
133: case 1:
134: case 3: // %11 は %01 と同じになる (Inside p295)
135: div = 768;
136: break;
137: case 2:
138: div = 512;
139: break;
140: default:
1.1.1.2 ! root 141: VMPANIC("corrupted ADPCM rate=%d", rate);
1.1 root 142: }
143:
144: playing = true;
1.1.1.2 ! root 145: dmac->AssertREQ(3);
1.1 root 146:
147: event.time = div / clk;
1.1.1.2 ! root 148: scheduler->StartEvent(event);
1.1 root 149: }
150:
151: // イベント
152: void
153: ADPCMDevice::EventCallback(Event& ev)
154: {
155: // XXX 適当
156: if (playing) {
1.1.1.2 ! root 157: dmac->AssertREQ(3);
1.1 root 158: }
159: }
160:
161: // DACK 信号をアサートする (DMAC から呼ばれる)
162: void
163: ADPCMDevice::AssertDACK(bool tc_)
164: {
165: dack = true;
166: // DRQ を下げる
1.1.1.2 ! root 167: dmac->NegateREQ(0);
1.1 root 168: }
169:
170: // DACK 信号をネゲートする (DMAC から呼ばれる)
171: void
172: ADPCMDevice::NegateDACK()
173: {
174: dack = false;
175: }
176:
177: // クロック切り替え。OPM から呼ばれる。
178: // CT1 = %0 で 8MHz、%1 で 4MHz。
179: void
180: ADPCMDevice::SetClock(bool ct1)
181: {
182: if (ct1) {
183: clk = 4000'000;
184: } else {
185: clk = 8000'000;
186: }
187: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.