openMSX
YM2151.hh
Go to the documentation of this file.
1 /*
2  **
3  ** File: ym2151.h - header file for software implementation of YM2151
4  ** FM Operator Type-M(OPM)
5  **
6  ** (c) 1997-2002 Jarek Burczynski (s0246@poczta.onet.pl, bujar@mame.net)
7  ** Some of the optimizing ideas by Tatsuyuki Satoh
8  **
9  ** Version 2.150 final beta May, 11th 2002
10  **
11  **
12  ** I would like to thank following people for making this project possible:
13  **
14  ** Beauty Planets - for making a lot of real YM2151 samples and providing
15  ** additional informations about the chip. Also for the time spent making
16  ** the samples and the speed of replying to my endless requests.
17  **
18  ** Shigeharu Isoda - for general help, for taking time to scan his YM2151
19  ** Japanese Manual first of all, and answering MANY of my questions.
20  **
21  ** Nao - for giving me some info about YM2151 and pointing me to Shigeharu.
22  ** Also for creating fmemu (which I still use to test the emulator).
23  **
24  ** Aaron Giles and Chris Hardy - they made some samples of one of my favourite
25  ** arcade games so I could compare it to my emulator.
26  **
27  ** Bryan McPhail and Tim (powerjaw) - for making some samples.
28  **
29  ** Ishmair - for the datasheet and motivation.
30  */
31 
32 // YM2164/OPP specifics info from http://map.grauw.nl/resources/sound/yamaha_ym2164.php
33 
34 #ifndef YM2151_HH
35 #define YM2151_HH
36 
37 #include "ResampledSoundDevice.hh"
38 #include "EmuTimer.hh"
39 #include "EmuTime.hh"
40 #include "IRQHelper.hh"
41 #include "openmsx.hh"
42 #include <string>
43 #include <memory>
44 
45 namespace openmsx {
46 
47 class DeviceConfig;
48 
49 class YM2151 final : public ResampledSoundDevice, private EmuTimerCallback
50 {
51 public:
52  enum class Variant : char {
53  YM2151, // aka OPM
54  YM2164, // aka OPP
55  };
56 
57  YM2151(const std::string& name, static_string_view desc,
58  const DeviceConfig& config, EmuTime::param time, Variant variant);
59  ~YM2151();
60 
61  void reset(EmuTime::param time);
62  void writeReg(byte r, byte v, EmuTime::param time);
63  [[nodiscard]] byte readStatus() const;
64 
65  template<typename Archive>
66  void serialize(Archive& ar, unsigned version);
67 
68 private:
69  // a single operator
70  struct YM2151Operator {
71  template<typename Archive>
72  void serialize(Archive& ar, unsigned version);
73 
74  int* connect; // operator output 'direction'
75  int* mem_connect; // where to put the delayed sample (MEM)
76 
77  unsigned phase; // accumulated operator phase
78  unsigned freq; // operator frequency count
79  int dt1; // current DT1 (detune 1 phase inc/decrement) value
80  unsigned mul; // frequency count multiply
81  unsigned dt1_i; // DT1 index * 32
82  unsigned dt2; // current DT2 (detune 2) value
83 
84  int mem_value; // delayed sample (MEM) value
85 
86  // channel specific data
87  // note: each operator number 0 contains channel specific data
88  unsigned fb_shift; // feedback shift value for operators 0 in each channel
89  int fb_out_curr; // operator feedback value (used only by operators 0)
90  int fb_out_prev; // previous feedback value (used only by operators 0)
91  unsigned kc; // channel KC (copied to all operators)
92  unsigned kc_i; // just for speedup
93  unsigned pms; // channel PMS
94  unsigned ams; // channel AMS
95 
96  unsigned AMmask; // LFO Amplitude Modulation enable mask
97  unsigned state; // Envelope state: 4-attack(AR)
98  // 3-decay(D1R)
99  // 2-sustain(D2R)
100  // 1-release(RR)
101  // 0-off
102  unsigned tl; // Total attenuation Level
103  int volume; // current envelope attenuation level
104  unsigned d1l; // envelope switches to sustain state after
105 
106  unsigned key; // 0=last key was KEY OFF, 1=last key was KEY ON
107 
108  unsigned ks; // key scale
109  unsigned ar; // attack rate
110  unsigned d1r; // decay rate
111  unsigned d2r; // sustain rate
112  unsigned rr; // release rate
113 
114  byte eg_sh_ar; // (attack state)
115  byte eg_sel_ar; // (attack state)
116  byte eg_sh_d1r; // (decay state)
117  byte eg_sel_d1r; // (decay state)
118  // reaching this level
119  byte eg_sh_d2r; // (sustain state)
120  byte eg_sel_d2r; // (sustain state)
121  byte eg_sh_rr; // (release state)
122  byte eg_sel_rr; // (release state)
123  };
124 
125  void setConnect(YM2151Operator* om1, int cha, int v);
126 
127  // SoundDevice
128  void generateChannels(float** bufs, unsigned num) override;
129 
130  void callback(byte flag) override;
131  void setStatus(byte flags);
132  void resetStatus(byte flags);
133 
134  // operator methods
135  void envelopeKONKOFF(YM2151Operator* op, int v);
136  static void refreshEG(YM2151Operator* op);
137  [[nodiscard]] int opCalc(YM2151Operator* op, unsigned env, int pm);
138  [[nodiscard]] int opCalc1(YM2151Operator* op, unsigned env, int pm);
139  [[nodiscard]] inline unsigned volumeCalc(YM2151Operator* op, unsigned AM);
140  inline void keyOn(YM2151Operator* op, unsigned keySet);
141  inline void keyOff(YM2151Operator* op, unsigned keyClear);
142 
143  // general chip mehods
144  void chanCalc(unsigned chan);
145  void chan7Calc();
146 
147  void advanceEG();
148  void advance();
149 
150  [[nodiscard]] bool checkMuteHelper();
151 
152  IRQHelper irq;
153 
154  // Timers (see EmuTimer class for details about timing)
155  const std::unique_ptr<EmuTimer> timer1;
156  const std::unique_ptr<EmuTimer> timer2;
157 
158  YM2151Operator oper[32]; // the 32 operators
159 
160  unsigned pan[16]; // channels output masks (0xffffffff = enable)
161 
162  unsigned eg_cnt; // global envelope generator counter
163  unsigned eg_timer; // global envelope generator counter
164  // works at frequency = chipclock/64/3
165  unsigned lfo_phase; // accumulated LFO phase (0 to 255)
166  unsigned lfo_timer; // LFO timer
167  unsigned lfo_overflow; // LFO generates new output when lfo_timer
168  // reaches this value
169  unsigned lfo_counter; // LFO phase increment counter
170  unsigned lfo_counter_add;// step of lfo_counter
171  unsigned lfa; // LFO current AM output
172  int lfp; // LFO current PM output
173 
174  unsigned noise; // noise enable/period register
175  // bit 7 - noise enable, bits 4-0 - noise period
176  unsigned noise_rng; // 17 bit noise shift register
177  int noise_p; // current noise 'phase'
178  unsigned noise_f; // current noise period
179 
180  unsigned csm_req; // CSM KEY ON / KEY OFF sequence request
181 
182  unsigned irq_enable; // IRQ enable for timer B (bit 3) and timer A
183  // (bit 2); bit 7 - CSM mode (keyon to all
184  // slots, everytime timer A overflows)
185  unsigned status; // chip status (BUSY, IRQ Flags)
186 
187  int chanout[8];
188  int m2, c1, c2; // Phase Modulation input for operators 2,3,4
189  int mem; // one sample delay memory
190 
191  word timer_A_val;
192 
193  byte lfo_wsel; // LFO waveform (0-saw, 1-square, 2-triangle,
194  // 3-random noise)
195  byte amd; // LFO Amplitude Modulation Depth
196  signed char pmd; // LFO Phase Modulation Depth
197 
198  byte test; // TEST register
199  byte ct; // output control pins (bit1-CT2, bit0-CT1)
200 
201  byte regs[256]; // only used for serialization ATM
202  const Variant variant; // Whether we're emulating YM2151 or YM2164
203 };
204 
205 } // namespace openmsx
206 
207 #endif
byte readStatus() const
Definition: YM2151.cc:1548
void writeReg(byte r, byte v, EmuTime::param time)
Definition: YM2151.cc:649
void reset(EmuTime::param time)
Definition: YM2151.cc:929
void serialize(Archive &ar, unsigned version)
Definition: YM2151.cc:1613
YM2151(const std::string &name, static_string_view desc, const DeviceConfig &config, EmuTime::param time, Variant variant)
Definition: YM2151.cc:872
static_string_view
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
IntHelper< IRQSource > IRQHelper
Definition: IRQHelper.hh:122