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