openMSX
MSXTurboRPCM.cc
Go to the documentation of this file.
1#include "MSXTurboRPCM.hh"
2#include "MSXMotherBoard.hh"
3#include "MSXMixer.hh"
4#include "narrow.hh"
5#include "serialize.hh"
6#include "unreachable.hh"
7
8namespace openmsx {
9
11 : MSXDevice(config)
12 , mixer(getMotherBoard().getMSXMixer())
13 , connector(getPluggingController(), "pcminput")
14 , dac("PCM", "Turbo-R PCM", config)
15 , reference(getCurrentTime())
16{
18}
19
21{
22 hardwareMute(false);
23}
24
25void MSXTurboRPCM::reset(EmuTime::param time)
26{
27 reference.reset(time);
28 status = 0;
29 DValue = 0x80; // TODO correct initial value?
30 hold = 0x80; // avoid UMR
31 dac.reset(time);
32 hardwareMute(false);
33}
34
35byte MSXTurboRPCM::readIO(word port, EmuTime::param time)
36{
37 return peekIO(port, time);
38}
39
40byte MSXTurboRPCM::peekIO(word port, EmuTime::param time) const
41{
42 switch (port & 0x01) {
43 case 0:
44 // bit 0-1 15.75kHz counter
45 // bit 2-7 not used
46 return reference.getTicksTill(time) & 0x03;
47 case 1:
48 // bit 0 BUFF 0->D/A TODO check this bit
49 // 1->A/D
50 // bit 1 MUTE mute ALL sound 0->muted
51 // bit 2 FILT filter 0->standard signal
52 // 1->filtered signal
53 // bit 3 SEL select 0->D/A
54 // 1->Mic/Jack
55 // bit 4 SMPL sample/hold 0->sample
56 // 1->hold
57 // bit 5-6 not used
58 // bit 7 COMP comparator result 0->greater
59 // 1->smaller
60 return (getComp(time) ? 0x80 : 0x00) | (status & 0x1F);
61 default: // unreachable, avoid warning
62 UNREACHABLE; return 0;
63 }
64}
65
66void MSXTurboRPCM::writeIO(word port, byte value, EmuTime::param time)
67{
68 switch (port & 0x01) {
69 case 0:
70 // While playing: sample value
71 // recording: compare value
72 // Resets counter
73 reference.advance(time);
74 DValue = value;
75 if (status & 0x02) {
76 dac.writeDAC(DValue, time);
77 }
78 break;
79
80 case 1:
81 // bit 0 BUFF
82 // bit 1 MUTE mute _all_ sound 0->no sound
83 // bit 2 FILT filter 1->filter on
84 // bit 3 SEL select 1->Mic/Jack 0->D/A
85 // bit 4 SMPL sample/hold 1->hold
86 // bit 5-7 not used
87 byte change = status ^ value;
88 status = value;
89
90 if ((change & 0x01) && ((status & 0x01) == 0)) {
91 dac.writeDAC(DValue, time);
92 }
93 // TODO status & 0x08
94 if ((change & 0x10) && (status & 0x10)) {
95 hold = getSample(time);
96 }
97 hardwareMute(!(status & 0x02));
98 break;
99 }
100}
101
102byte MSXTurboRPCM::getSample(EmuTime::param time) const
103{
104 return (status & 0x04)
105 ? narrow<byte>((connector.readSample(time) / 256) + 0x80)
106 : 0x80; // TODO check
107}
108
109bool MSXTurboRPCM::getComp(EmuTime::param time) const
110{
111 // TODO also when D/A ??
112 byte sample = (status & 0x10) ? hold : getSample(time);
113 return sample >= DValue;
114}
115
116void MSXTurboRPCM::hardwareMute(bool mute)
117{
118 if (mute == hwMute) return;
119
120 hwMute = mute;
121 if (hwMute) {
122 mixer.mute();
123 } else {
124 mixer.unmute();
125 }
126}
127
128
129template<typename Archive>
130void MSXTurboRPCM::serialize(Archive& ar, unsigned /*version*/)
131{
132 ar.template serializeBase<MSXDevice>(*this);
133 ar.serialize("audioConnector", connector,
134 "reference", reference,
135 "status", status,
136 "DValue", DValue,
137 "hold", hold,
138 "DAC", dac);
139
140 hardwareMute(!(status & 0x02)); // restore hwMute
141}
144
145} // namespace openmsx
int16_t readSample(EmuTime::param time) const
constexpr void reset(EmuTime::param e)
Reset the clock to start ticking at the given time.
Definition: Clock.hh:102
constexpr void advance(EmuTime::param e)
Advance this clock in time until the last tick which is not past the given time.
Definition: Clock.hh:110
constexpr unsigned getTicksTill(EmuTime::param e) const
Calculate the number of ticks for this clock until the given time.
Definition: Clock.hh:58
void reset(EmuTime::param time)
Definition: DACSound16S.cc:29
void writeDAC(uint8_t value, EmuTime::param time)
Definition: DACSound8U.cc:17
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:36
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:125
void mute()
TODO This methods (un)mute the sound.
Definition: MSXMixer.cc:609
MSXTurboRPCM(const DeviceConfig &config)
Definition: MSXTurboRPCM.cc:10
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition: MSXTurboRPCM.cc:66
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: MSXTurboRPCM.cc:35
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXTurboRPCM.cc:40
void serialize(Archive &ar, unsigned version)
~MSXTurboRPCM() override
Definition: MSXTurboRPCM.cc:20
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXTurboRPCM.cc:25
This file implemented 3 utility functions:
Definition: Autofire.cc:9
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1021
#define UNREACHABLE
Definition: unreachable.hh:38