openMSX
Y8950.hh
Go to the documentation of this file.
1#ifndef Y8950_HH
2#define Y8950_HH
3
4#include "Y8950Adpcm.hh"
7#include "DACSound16S.hh"
8#include "SimpleDebuggable.hh"
9#include "IRQHelper.hh"
10#include "EmuTimer.hh"
11#include "EmuTime.hh"
12#include "FixedPoint.hh"
13#include "openmsx.hh"
14#include <string>
15#include <memory>
16
17namespace openmsx {
18
19class MSXAudio;
20class DeviceConfig;
21class Y8950Periphery;
22
23class Y8950 final : private ResampledSoundDevice, private EmuTimerCallback
24{
25public:
26 static constexpr int CLOCK_FREQ = 3579545;
27 static constexpr int CLOCK_FREQ_DIV = 72;
28
29 // Bitmask for register 0x04
30 // Timer1 Start.
31 static constexpr int R04_ST1 = 0x01;
32 // Timer2 Start.
33 static constexpr int R04_ST2 = 0x02;
34 // not used
35 //static constexpr int R04 = 0x04;
36 // Mask 'Buffer Ready'.
37 static constexpr int R04_MASK_BUF_RDY = 0x08;
38 // Mask 'End of sequence'.
39 static constexpr int R04_MASK_EOS = 0x10;
40 // Mask Timer2 flag.
41 static constexpr int R04_MASK_T2 = 0x20;
42 // Mask Timer1 flag.
43 static constexpr int R04_MASK_T1 = 0x40;
44 // IRQ RESET.
45 static constexpr int R04_IRQ_RESET = 0x80;
46
47 // Bitmask for status register
48 static constexpr int STATUS_PCM_BSY = 0x01;
49 static constexpr int STATUS_EOS = R04_MASK_EOS;
50 static constexpr int STATUS_BUF_RDY = R04_MASK_BUF_RDY;
51 static constexpr int STATUS_T2 = R04_MASK_T2;
52 static constexpr int STATUS_T1 = R04_MASK_T1;
53
54 Y8950(const std::string& name, const DeviceConfig& config,
55 unsigned sampleRam, EmuTime::param time, MSXAudio& audio);
56 ~Y8950();
57
58 void setEnabled(bool enabled, EmuTime::param time);
59 void clearRam();
60 void reset(EmuTime::param time);
61 void writeReg(byte rg, byte data, EmuTime::param time);
62 [[nodiscard]] byte readReg(byte rg, EmuTime::param time);
63 [[nodiscard]] byte peekReg(byte rg, EmuTime::param time) const;
64 [[nodiscard]] byte readStatus(EmuTime::param time) const;
65 [[nodiscard]] byte peekStatus(EmuTime::param time) const;
66
67 // for ADPCM
68 void setStatus(byte flags);
69 void resetStatus(byte flags);
70 [[nodiscard]] byte peekRawStatus() const;
71
72 template<typename Archive>
73 void serialize(Archive& ar, unsigned version);
74
75private:
76 // SoundDevice
77 [[nodiscard]] float getAmplificationFactorImpl() const override;
78 void generateChannels(float** bufs, unsigned num) override;
79
80 inline void keyOn_BD();
81 inline void keyOn_SD();
82 inline void keyOn_TOM();
83 inline void keyOn_HH();
84 inline void keyOn_CYM();
85 inline void keyOff_BD();
86 inline void keyOff_SD();
87 inline void keyOff_TOM();
88 inline void keyOff_HH();
89 inline void keyOff_CYM();
90 inline void setRythmMode(int data);
91 void update_key_status();
92
93 [[nodiscard]] bool checkMuteHelper();
94
95 void changeStatusMask(byte newMask);
96
97 void callback(byte flag) override;
98
99public:
100 // Dynamic range of envelope
101 static constexpr int EG_BITS = 9;
102
103 // Bits for envelope phase incremental counter
104 static constexpr int EG_DP_BITS = 23;
106
108
109private:
110 enum KeyPart { KEY_MAIN = 1, KEY_RHYTHM = 2 };
111
112 class Patch {
113 public:
114 Patch();
115 void reset();
116
117 void setKeyScaleRate(bool value) {
118 KR = value ? 9 : 11;
119 }
120 void setFeedbackShift(byte value) {
121 FB = value ? 8 - value : 0;
122 }
123
124 template<typename Archive>
125 void serialize(Archive& ar, unsigned version);
126
127 bool AM, PM, EG;
128 byte KR; // 0,1 transformed to 9,11
129 byte ML; // 0-15
130 byte KL; // 0-3
131 byte TL; // 0-63
132 byte FB; // 0,1-7 transformed to 0,7-1
133 byte AR; // 0-15
134 byte DR; // 0-15
135 byte SL; // 0-15
136 byte RR; // 0-15
137 };
138
139 class Slot {
140 public:
141 void reset();
142
143 [[nodiscard]] inline bool isActive() const;
144 inline void slotOn (KeyPart part);
145 inline void slotOff(KeyPart part);
146
147 [[nodiscard]] inline unsigned calc_phase(int lfo_pm);
148 [[nodiscard]] inline unsigned calc_envelope(int lfo_am);
149 [[nodiscard]] inline int calc_slot_car(int lfo_pm, int lfo_am, int fm);
150 [[nodiscard]] inline int calc_slot_mod(int lfo_pm, int lfo_am);
151 [[nodiscard]] inline int calc_slot_tom(int lfo_pm, int lfo_am);
152 [[nodiscard]] inline int calc_slot_snare(int lfo_pm, int lfo_am, int whitenoise);
153 [[nodiscard]] inline int calc_slot_cym(int lfo_am, int a, int b);
154 [[nodiscard]] inline int calc_slot_hat(int lfo_am, int a, int b, int whitenoise);
155
156 inline void updateAll(unsigned freq);
157 inline void updatePG(unsigned freq);
158 inline void updateTLL(unsigned freq);
159 inline void updateRKS(unsigned freq);
160 inline void updateEG();
161
162 template<typename Archive>
163 void serialize(Archive& ar, unsigned version);
164
165 // OUTPUT
166 int feedback;
167 int output; // Output value of slot
168
169 // for Phase Generator (PG)
170 unsigned phase; // Phase
171 unsigned dPhase; // Phase increment amount
172
173 // for Envelope Generator (EG)
174 const EnvPhaseIndex* dPhaseARTableRks;
175 const EnvPhaseIndex* dPhaseDRTableRks;
176 int tll; // Total Level + Key scale level
177 EnvelopeState eg_mode; // Current state
178 EnvPhaseIndex eg_phase; // Phase
179 EnvPhaseIndex eg_dPhase;// Phase increment amount
180
181 Patch patch;
182 byte key;
183 };
184
185 class Channel {
186 public:
187 Channel();
188 void reset();
189 inline void setFreq(unsigned freq);
190 inline void keyOn (KeyPart part);
191 inline void keyOff(KeyPart part);
192
193 template<typename Archive>
194 void serialize(Archive& ar, unsigned version);
195
196 Slot slot[2];
197 unsigned freq; // combined F-Number and Block
198 bool alg;
199 };
200
201 MSXMotherBoard& motherBoard;
202 Y8950Periphery& periphery;
203 Y8950Adpcm adpcm;
204 Y8950KeyboardConnector connector;
205 DACSound16S dac13; // 13-bit (exponential) DAC
206
207 struct Debuggable final : SimpleDebuggable {
208 Debuggable(MSXMotherBoard& motherBoard, const std::string& name);
209 [[nodiscard]] byte read(unsigned address, EmuTime::param time) override;
210 void write(unsigned address, byte value, EmuTime::param time) override;
211 } debuggable;
212
213 const std::unique_ptr<EmuTimer> timer1; // 80us timer
214 const std::unique_ptr<EmuTimer> timer2; // 320us timer
215 IRQHelper irq;
216
217 byte reg[0x100];
218
219 Channel ch[9];
220
221 unsigned pm_phase; // Pitch Modulator
222 unsigned am_phase; // Amp Modulator
223
224 // Noise Generator
225 int noise_seed;
226 unsigned noiseA_phase;
227 unsigned noiseB_phase;
228 unsigned noiseA_dPhase;
229 unsigned noiseB_dPhase;
230
231 byte status; // STATUS Register
232 byte statusMask; // bit=0 -> masked
233 bool rythm_mode;
234 bool am_mode;
235 bool pm_mode;
236 bool enabled;
237};
238
239} // namespace openmsx
240
241#endif
Debuggable(const Debuggable &)=delete
byte read(unsigned address) override
void write(unsigned address, byte value) override
static constexpr int STATUS_BUF_RDY
Definition: Y8950.hh:50
static constexpr int STATUS_T1
Definition: Y8950.hh:52
void reset(EmuTime::param time)
Definition: Y8950.cc:551
static constexpr int EG_DP_BITS
Definition: Y8950.hh:104
byte peekRawStatus() const
Definition: Y8950.cc:1212
byte readStatus(EmuTime::param time) const
Definition: Y8950.cc:1178
void setEnabled(bool enabled, EmuTime::param time)
Definition: Y8950.cc:774
static constexpr int CLOCK_FREQ_DIV
Definition: Y8950.hh:27
Y8950(const std::string &name, const DeviceConfig &config, unsigned sampleRam, EmuTime::param time, MSXAudio &audio)
Definition: Y8950.cc:476
static constexpr int R04_MASK_T2
Definition: Y8950.hh:41
static constexpr int R04_MASK_BUF_RDY
Definition: Y8950.hh:37
static constexpr int STATUS_PCM_BSY
Definition: Y8950.hh:48
static constexpr int R04_IRQ_RESET
Definition: Y8950.hh:45
static constexpr int R04_MASK_EOS
Definition: Y8950.hh:39
FixedPoint< EG_DP_BITS - EG_BITS > EnvPhaseIndex
Definition: Y8950.hh:105
byte peekReg(byte rg, EmuTime::param time) const
Definition: Y8950.cc:1155
static constexpr int R04_ST2
Definition: Y8950.hh:33
void serialize(Archive &ar, unsigned version)
Definition: Y8950.cc:1306
void clearRam()
Definition: Y8950.cc:545
void resetStatus(byte flags)
Definition: Y8950.cc:1204
static constexpr int R04_MASK_T1
Definition: Y8950.hh:43
static constexpr int R04_ST1
Definition: Y8950.hh:31
void writeReg(byte rg, byte data, EmuTime::param time)
Definition: Y8950.cc:896
static constexpr int CLOCK_FREQ
Definition: Y8950.hh:26
static constexpr int EG_BITS
Definition: Y8950.hh:101
byte readReg(byte rg, EmuTime::param time)
Definition: Y8950.cc:1140
void setStatus(byte flags)
Definition: Y8950.cc:1196
static constexpr int STATUS_EOS
Definition: Y8950.hh:49
byte peekStatus(EmuTime::param time) const
Definition: Y8950.cc:1185
static constexpr int STATUS_T2
Definition: Y8950.hh:51
This file implemented 3 utility functions:
Definition: Autofire.cc:9
constexpr Y8950::EnvPhaseIndex SL[16]
Definition: Y8950.cc:654
IntHelper< IRQSource > IRQHelper
Definition: IRQHelper.hh:122