|
|
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: if (inherited::Init() == false) {
33: return false;
34: }
35:
36: dmac = GetDMACDevice();
37: ppi = GetPPIDevice();
38:
1.1.1.4 ! root 39: event.func = ToEventCallback(&ADPCMDevice::EventCallback);
! 40: event.SetName("ADPCM");
! 41: scheduler->RegistEvent(event);
! 42:
1.1.1.2 root 43: return true;
1.1 root 44: }
45:
46: // リセット
47: void
48: ADPCMDevice::ResetHard(bool poweron)
49: {
50: playing = false;
51: dack = false;
52:
53: // ?
54: clk = 8000'000;
55: div = 512;
56: }
57:
1.1.1.3 root 58: busdata
1.1.1.4 ! root 59: ADPCMDevice::ReadPort(uint32 offset)
1.1 root 60: {
1.1.1.3 root 61: busdata data;
1.1 root 62:
63: switch (offset) {
64: case 0: // STAT
65: data = 0x40;
66: if (playing) {
67: data |= STAT_PLAY;
68: }
1.1.1.3 root 69: putlog(1, "STAT -> $%02x", data.Data());
1.1 root 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.4 ! root 76: VMPANIC("corrupted offset=%u", offset);
1.1 root 77: }
78:
1.1.1.3 root 79: // InsideOut p.135
80: const busdata wait = busdata::Wait(18 * 40_nsec);
81: data |= wait;
82:
1.1.1.4 ! root 83: data |= BusData::Size1;
1.1 root 84: return data;
85: }
86:
1.1.1.3 root 87: busdata
1.1.1.4 ! root 88: ADPCMDevice::WritePort(uint32 offset, uint32 data)
1.1 root 89: {
90: switch (offset) {
91: case 0: // CMD
92: putlog(1, "CMD <- $%02x", data);
93: if ((data & REC_START)) {
94: putlog(0, "Start recording (NOT IMPLEMENTED)");
95: }
96: if ((data & PLAY_START)) {
97: putlog(0, "Start playing (NOT IMPLEMENTED)");
98: StartPlay();
99: }
100: if ((data & STOP)) {
101: putlog(0, "Stop (NOT IMPLEMENTED)");
102: playing = false;
103: }
104: break;
105: case 1: // DATA
106: // 未実装だけど再生中の書き込みは来るのは分かっているので抑えておく
107: if ((playing && loglevel >= 2) || playing == false) {
108: putlogn("DATA <- $%02x (NOT IMPLEMENTED)", data);
109: }
110: break;
111: default:
1.1.1.4 ! root 112: VMPANIC("corrupted offset=%u", offset);
1.1 root 113: }
114:
1.1.1.3 root 115: // InsideOut p.135
116: const busdata wait = busdata::Wait(22 * 40_nsec);
1.1.1.4 ! root 117:
! 118: busdata r = wait;
! 119: r |= BusData::Size1;
! 120: return r;
1.1 root 121: }
122:
1.1.1.3 root 123: busdata
1.1.1.4 ! root 124: ADPCMDevice::PeekPort(uint32 offset)
1.1 root 125: {
126: // XXX 未実装
127: return 0xff;
128: }
129:
1.1.1.4 ! root 130: bool
! 131: ADPCMDevice::PokePort(uint32 offset, uint32 data)
! 132: {
! 133: return false;
! 134: }
! 135:
1.1 root 136: // 再生開始
137: void
138: ADPCMDevice::StartPlay()
139: {
140: // PPI で設定されているサンプリングレートをここで読み出す。
141: // XXX パンは未対応
1.1.1.4 ! root 142: uint rate = ppi->GetADPCMRate();
1.1.1.2 root 143: switch (rate) {
1.1 root 144: case 0:
145: div = 1024;
146: break;
147: case 1:
148: case 3: // %11 は %01 と同じになる (Inside p295)
149: div = 768;
150: break;
151: case 2:
152: div = 512;
153: break;
154: default:
1.1.1.4 ! root 155: VMPANIC("corrupted ADPCM rate=%u", rate);
1.1 root 156: }
157:
158: playing = true;
1.1.1.2 root 159: dmac->AssertREQ(3);
1.1 root 160:
161: event.time = div / clk;
1.1.1.2 root 162: scheduler->StartEvent(event);
1.1 root 163: }
164:
165: // イベント
166: void
167: ADPCMDevice::EventCallback(Event& ev)
168: {
169: // XXX 適当
170: if (playing) {
1.1.1.2 root 171: dmac->AssertREQ(3);
1.1 root 172: }
173: }
174:
175: // DACK 信号をアサートする (DMAC から呼ばれる)
176: void
177: ADPCMDevice::AssertDACK(bool tc_)
178: {
179: dack = true;
180: // DRQ を下げる
1.1.1.2 root 181: dmac->NegateREQ(0);
1.1 root 182: }
183:
184: // DACK 信号をネゲートする (DMAC から呼ばれる)
185: void
186: ADPCMDevice::NegateDACK()
187: {
188: dack = false;
189: }
190:
191: // クロック切り替え。OPM から呼ばれる。
192: // CT1 = %0 で 8MHz、%1 で 4MHz。
193: void
194: ADPCMDevice::SetClock(bool ct1)
195: {
196: if (ct1) {
197: clk = 4000'000;
198: } else {
199: clk = 8000'000;
200: }
201: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.