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 
17 namespace openmsx {
18 
19 class MSXAudio;
20 class DeviceConfig;
21 class Y8950Periphery;
22 
23 class Y8950 final : private ResampledSoundDevice, private EmuTimerCallback
24 {
25 public:
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 
75 private:
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 
99 public:
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 
109 private:
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