openMSX
AY8910.hh
Go to the documentation of this file.
1 #ifndef AY8910_HH
2 #define AY8910_HH
3 
5 #include "FloatSetting.hh"
6 #include "SimpleDebuggable.hh"
7 #include "TclCallback.hh"
8 #include "openmsx.hh"
9 
10 namespace openmsx {
11 
12 class AY8910Periphery;
13 class DeviceConfig;
14 
19 class AY8910 final : public ResampledSoundDevice
20 {
21 public:
22  AY8910(const std::string& name, AY8910Periphery& periphery,
23  const DeviceConfig& config, EmuTime::param time);
24  ~AY8910();
25 
26  byte readRegister(unsigned reg, EmuTime::param time);
27  byte peekRegister(unsigned reg, EmuTime::param time) const;
28  void writeRegister(unsigned reg, byte value, EmuTime::param time);
29  void reset(EmuTime::param time);
30 
31  template<typename Archive>
32  void serialize(Archive& ar, unsigned version);
33 
34 private:
35  class Generator {
36  public:
37  inline void setPeriod(int value);
38  inline unsigned getNextEventTime() const;
39  inline void advanceFast(unsigned duration);
40 
41  template<typename Archive>
42  void serialize(Archive& ar, unsigned version);
43 
44  protected:
45  Generator() = default;
46  inline void reset();
47 
53  int period;
58  int count;
59  };
60 
61  class ToneGenerator : public Generator {
62  public:
63  ToneGenerator();
64 
65  inline void reset();
66 
70  inline void advance(int duration);
71 
72  inline void doNextEvent(AY8910& ay8910);
73 
76  bool getOutput() const { return output; }
77 
78  template<typename Archive>
79  void serialize(Archive& ar, unsigned version);
80 
81  private:
82  int getDetune(AY8910& ay8910);
83 
86  unsigned vibratoCount;
87  unsigned detuneCount;
88 
91  bool output;
92  };
93 
94  class NoiseGenerator : public Generator {
95  public:
96  NoiseGenerator();
97 
98  inline void reset();
102  inline void advance(int duration);
103 
104  inline void doNextEvent();
105 
108  bool getOutput() const { return random & 1; }
109 
110  template<typename Archive>
111  void serialize(Archive& ar, unsigned version);
112 
113  private:
114  int random;
115  };
116 
117  class Amplitude {
118  public:
119  explicit Amplitude(const DeviceConfig& config);
120  const unsigned* getEnvVolTable() const;
121  inline unsigned getVolume(unsigned chan) const;
122  inline void setChannelVolume(unsigned chan, unsigned value);
123  inline void setMasterVolume(int volume);
124  inline bool followsEnvelope(unsigned chan) const;
125 
126  private:
127  unsigned volTable[16];
128  unsigned envVolTable[32];
129  unsigned vol[3];
130  bool envChan[3];
131  const bool isAY8910;
132  };
133 
134  class Envelope {
135  public:
136  explicit inline Envelope(const unsigned* envVolTable);
137  inline void reset();
138  inline void setPeriod(int value);
139  inline void setShape(unsigned shape);
140  inline bool isChanging() const;
141  inline void advance(int duration);
142  inline unsigned getVolume() const;
143 
144  inline unsigned getNextEventTime() const;
145  inline void advanceFast(unsigned duration);
146  inline void doNextEvent();
147 
148  template<typename Archive>
149  void serialize(Archive& ar, unsigned version);
150 
151  private:
152  inline void doSteps(int steps);
153 
154  const unsigned* envVolTable;
155  int period;
156  int count;
157  int step;
158  int attack;
159  bool hold, alternate, holding;
160  };
161 
162  // SoundDevice
163  void generateChannels(int** bufs, unsigned num) override;
164 
165  // Observer<Setting>
166  void update(const Setting& setting) override;
167 
168  void wrtReg(unsigned reg, byte value, EmuTime::param time);
169 
170  AY8910Periphery& periphery;
171 
172  struct Debuggable final : SimpleDebuggable {
173  Debuggable(MSXMotherBoard& motherBoard, const std::string& name);
174  byte read(unsigned address, EmuTime::param time) override;
175  void write(unsigned address, byte value, EmuTime::param time) override;
176  } debuggable;
177 
178  FloatSetting vibratoPercent;
179  FloatSetting vibratoFrequency;
180  FloatSetting detunePercent;
181  FloatSetting detuneFrequency;
182  TclCallback directionsCallback;
183  ToneGenerator tone[3];
184  NoiseGenerator noise;
185  Amplitude amplitude;
186  Envelope envelope;
187  byte regs[16];
188  const bool isAY8910;
189  bool doDetune;
190  bool detuneInitialized;
191 };
192 
193 SERIALIZE_CLASS_VERSION(AY8910::Generator, 2);
194 SERIALIZE_CLASS_VERSION(AY8910::ToneGenerator, 2);
195 SERIALIZE_CLASS_VERSION(AY8910::NoiseGenerator, 2);
196 
197 } // namespace openmsx
198 
199 #endif // AY8910_HH
A Setting with a floating point value.
Definition: FloatSetting.hh:10
This class implements the AY-3-8910 sound chip.
Definition: AY8910.hh:19
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
void serialize(Archive &ar, unsigned version)
Definition: AY8910.cc:967
void advance(octet_iterator &it, distance_type n, octet_iterator end)
SERIALIZE_CLASS_VERSION(CassettePlayer, 2)
byte peekRegister(unsigned reg, EmuTime::param time) const
Definition: AY8910.cc:548
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
byte readRegister(unsigned reg, EmuTime::param time)
Definition: AY8910.cc:523
AY8910(const std::string &name, AY8910Periphery &periphery, const DeviceConfig &config, EmuTime::param time)
Definition: AY8910.cc:462
void reset(EmuTime::param time)
Definition: AY8910.cc:510
Models the general purpose I/O ports of the AY8910.
void writeRegister(unsigned reg, byte value, EmuTime::param time)
Definition: AY8910.cc:567