openMSX
MSXTurboRPCM.cc
Go to the documentation of this file.
1 #include "MSXTurboRPCM.hh"
2 #include "MSXMotherBoard.hh"
3 #include "MSXMixer.hh"
4 #include "serialize.hh"
5 #include "unreachable.hh"
6 
7 namespace openmsx {
8 
10  : MSXDevice(config)
11  , mixer(getMotherBoard().getMSXMixer())
12  , connector(getPluggingController(), "pcminput")
13  , dac("PCM", "Turbo-R PCM", config)
14  , reference(getCurrentTime())
15  , hwMute(false)
16 {
18 }
19 
21 {
22  hardwareMute(false);
23 }
24 
25 void 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 
35 byte MSXTurboRPCM::readIO(word port, EmuTime::param time)
36 {
37  return peekIO(port, time);
38 }
39 
40 byte 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 
66 void 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 
102 byte MSXTurboRPCM::getSample(EmuTime::param time) const
103 {
104  return (status & 0x04)
105  ? (connector.readSample(time) / 256) + 0x80
106  : 0x80; // TODO check
107 }
108 
109 bool 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 
116 void 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 
129 template<typename Archive>
130 void 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:16
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:33
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:126
void mute()
TODO This methods (un)mute the sound.
Definition: MSXMixer.cc:548
MSXTurboRPCM(const DeviceConfig &config)
Definition: MSXTurboRPCM.cc:9
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:998
#define UNREACHABLE
Definition: unreachable.hh:38