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