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  byte readReg(byte rg, EmuTime::param time);
63  byte peekReg(byte rg, EmuTime::param time) const;
64  byte readStatus(EmuTime::param time);
65  byte peekStatus(EmuTime::param time) const;
66 
67  // for ADPCM
68  void setStatus(byte flags);
69  void resetStatus(byte flags);
70  byte peekRawStatus() const;
71 
72  template<typename Archive>
73  void serialize(Archive& ar, unsigned version);
74 
75 private:
76  // SoundDevice
77  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  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  inline bool isActive() const;
144  inline void slotOn (KeyPart part);
145  inline void slotOff(KeyPart part);
146 
147  inline unsigned calc_phase(int lfo_pm);
148  inline unsigned calc_envelope(int lfo_am);
149  inline int calc_slot_car(int lfo_pm, int lfo_am, int fm);
150  inline int calc_slot_mod(int lfo_pm, int lfo_am);
151  inline int calc_slot_tom(int lfo_pm, int lfo_am);
152  inline int calc_slot_snare(int lfo_pm, int lfo_am, int whitenoise);
153  inline int calc_slot_cym(int lfo_am, int a, int b);
154  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  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
openmsx::MSXAudio
MSXAudio
Definition: MSXAudio.cc:145
DACSound16S.hh
openmsx::Y8950::RELEASE
Definition: Y8950.hh:107
openmsx::Y8950::peekReg
byte peekReg(byte rg, EmuTime::param time) const
Definition: Y8950.cc:1193
openmsx::Y8950::peekStatus
byte peekStatus(EmuTime::param time) const
Definition: Y8950.cc:1223
openmsx.hh
openmsx::Y8950::STATUS_T1
static constexpr int STATUS_T1
Definition: Y8950.hh:52
openmsx::Y8950::setEnabled
void setEnabled(bool enabled, EmuTime::param time)
Definition: Y8950.cc:807
openmsx::Y8950::R04_IRQ_RESET
static constexpr int R04_IRQ_RESET
Definition: Y8950.hh:45
openmsx::ResampledSoundDevice
Definition: ResampledSoundDevice.hh:15
openmsx::Y8950::serialize
void serialize(Archive &ar, unsigned version)
Definition: Y8950.cc:1344
openmsx::YM2413Okazaki::tll
constexpr TllTable tll
Definition: YM2413Okazaki.cc:229
openmsx::Y8950::readReg
byte readReg(byte rg, EmuTime::param time)
Definition: Y8950.cc:1175
openmsx::Y8950::readStatus
byte readStatus(EmuTime::param time)
Definition: Y8950.cc:1216
openmsx::DeviceConfig
Definition: DeviceConfig.hh:19
openmsx::IRQHelper
IntHelper< IRQSource > IRQHelper
Definition: IRQHelper.hh:135
openmsx::Y8950::EnvPhaseIndex
FixedPoint< EG_DP_BITS - EG_BITS > EnvPhaseIndex
Definition: Y8950.hh:105
openmsx::Y8950::clearRam
void clearRam()
Definition: Y8950.cc:578
openmsx::Y8950::reset
void reset(EmuTime::param time)
Definition: Y8950.cc:584
openmsx::Y8950::resetStatus
void resetStatus(byte flags)
Definition: Y8950.cc:1242
openmsx::MSXAudio
Definition: MSXAudio.hh:14
Y8950Adpcm.hh
openmsx::Y8950::setStatus
void setStatus(byte flags)
Definition: Y8950.cc:1234
openmsx::Y8950::R04_ST1
static constexpr int R04_ST1
Definition: Y8950.hh:31
Y8950KeyboardConnector.hh
openmsx::Y8950::STATUS_PCM_BSY
static constexpr int STATUS_PCM_BSY
Definition: Y8950.hh:48
openmsx::Y8950::R04_MASK_BUF_RDY
static constexpr int R04_MASK_BUF_RDY
Definition: Y8950.hh:37
openmsx::Y8950::CLOCK_FREQ
static constexpr int CLOCK_FREQ
Definition: Y8950.hh:26
openmsx::Y8950::R04_ST2
static constexpr int R04_ST2
Definition: Y8950.hh:33
openmsx::Y8950::EG_DP_BITS
static constexpr int EG_DP_BITS
Definition: Y8950.hh:104
openmsx::Y8950::writeReg
void writeReg(byte rg, byte data, EmuTime::param time)
Definition: Y8950.cc:932
openmsx::DACSound16S
DACSound16S
Definition: DACSound16S.cc:73
openmsx::Y8950::FINISH
Definition: Y8950.hh:107
openmsx::Y8950::SUSTAIN
Definition: Y8950.hh:107
openmsx::SimpleDebuggable::write
void write(unsigned address, byte value) override
Definition: SimpleDebuggable.cc:44
openmsx::Debuggable::Debuggable
Debuggable()=default
openmsx::Y8950::~Y8950
~Y8950()
Definition: Y8950.cc:573
openmsx::Y8950::STATUS_BUF_RDY
static constexpr int STATUS_BUF_RDY
Definition: Y8950.hh:50
openmsx::SL
constexpr Y8950::EnvPhaseIndex SL[16]
Definition: Y8950.cc:687
openmsx::Y8950::STATUS_T2
static constexpr int STATUS_T2
Definition: Y8950.hh:51
SimpleDebuggable.hh
openmsx::Y8950Adpcm
Y8950Adpcm
Definition: Y8950Adpcm.cc:557
FixedPoint.hh
openmsx::Y8950::EG_BITS
static constexpr int EG_BITS
Definition: Y8950.hh:101
openmsx::Y8950::STATUS_EOS
static constexpr int STATUS_EOS
Definition: Y8950.hh:49
openmsx::Y8950::R04_MASK_EOS
static constexpr int R04_MASK_EOS
Definition: Y8950.hh:39
EmuTime.hh
openmsx::Y8950KeyboardConnector
Y8950KeyboardConnector
Definition: Y8950KeyboardConnector.cc:64
openmsx::EmuTimerCallback
Definition: EmuTimer.hh:11
openmsx::Y8950::Y8950
Y8950(const std::string &name, const DeviceConfig &config, unsigned sampleRam, EmuTime::param time, MSXAudio &audio)
Definition: Y8950.cc:509
IRQHelper.hh
openmsx::Y8950::R04_MASK_T1
static constexpr int R04_MASK_T1
Definition: Y8950.hh:43
openmsx::Y8950::DECAY
Definition: Y8950.hh:107
openmsx::Y8950::CLOCK_FREQ_DIV
static constexpr int CLOCK_FREQ_DIV
Definition: Y8950.hh:27
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::Y8950::R04_MASK_T2
static constexpr int R04_MASK_T2
Definition: Y8950.hh:41
openmsx::Y8950::peekRawStatus
byte peekRawStatus() const
Definition: Y8950.cc:1250
EmuTimer.hh
openmsx::Y8950::ATTACK
Definition: Y8950.hh:107
openmsx::SimpleDebuggable::read
byte read(unsigned address) override
Definition: SimpleDebuggable.cc:34
openmsx::Y8950
Definition: Y8950.hh:23
openmsx::FixedPoint< EG_DP_BITS - EG_BITS >
openmsx::Y8950::EnvelopeState
EnvelopeState
Definition: Y8950.hh:107
ResampledSoundDevice.hh