1 // license:BSD-3-Clause
2 // copyright-holders:Frank Palazzolo, Jarek Burczynski, Aaron Giles, Jonathan Gevaryahu, Couriersud
3 #ifndef MAME_SOUND_TMS5110_H
4 #define MAME_SOUND_TMS5110_H
5 
6 #pragma once
7 
8 
9 /* HACK: if defined, uses impossibly perfect 'straight line' interpolation */
10 #undef TMS5110_PERFECT_INTERPOLATION_HACK
11 
12 /* clock rate = 80 * output sample rate,     */
13 /* usually 640000 for 8000 Hz sample rate or */
14 /* usually 800000 for 10000 Hz sample rate.  */
15 
16 class tms5110_device : public device_t, public device_sound_interface
17 {
18 public:
19 	/* TMS5110 commands */
20 													/* CTL8  CTL4  CTL2  CTL1  |   PDC's  */
21 													/* (MSB)             (LSB) | required */
22 	static constexpr uint8_t CMD_RESET        = 0;  /*    0     0     0     x  |     1    */
23 	static constexpr uint8_t CMD_LOAD_ADDRESS = 2;  /*    0     0     1     x  |     2    */
24 	static constexpr uint8_t CMD_OUTPUT       = 4;  /*    0     1     0     x  |     3    */
25 	static constexpr uint8_t CMD_SPKSLOW      = 6;  /*    0     1     1     x  |     1    */
26 	/* Note: TMS5110_CMD_SPKSLOW is undocumented on the datasheets, it only appears
27 	   on the patents. It might not actually work properly on some of the real
28 	   chips as manufactured. Acts the same as CMD_SPEAK, but makes the
29 	   interpolator take two A cycles wherever it would normally only take one,
30 	   effectively making speech of any given word take 1.5x as long as normal. */
31 	static constexpr uint8_t CMD_READ_BIT    =  8;  /*    1     0     0     x  |     1    */
32 	static constexpr uint8_t CMD_SPEAK       = 10;  /*    1     0     1     x  |     1    */
33 	static constexpr uint8_t CMD_READ_BRANCH = 12;  /*    1     1     0     x  |     1    */
34 	static constexpr uint8_t CMD_TEST_TALK   = 14;  /*    1     1     1     x  |     3    */
35 
36 	tms5110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
37 
m0()38 	auto m0() { return m_m0_cb.bind(); }
m1()39 	auto m1() { return m_m1_cb.bind(); }
addr()40 	auto addr() { return m_addr_cb.bind(); }
data()41 	auto data() { return m_data_cb.bind(); }
romclk()42 	auto romclk() { return m_romclk_cb.bind(); }
43 
44 	void ctl_w(uint8_t data);
45 	uint8_t ctl_r();
46 	void pdc_w(int state);
47 
48 	// this is only used by cvs.cpp
49 	// it is not related at all to the speech generation and conflicts with the new ROM controller interface.
50 	int romclk_hack_r();
51 
52 protected:
53 	tms5110_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int variant);
54 
55 	// device-level overrides
56 	virtual void device_start() override;
57 	virtual void device_reset() override;
58 	virtual void device_clock_changed() override;
59 
60 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
61 
62 	// sound stream update overrides
63 	virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
64 
TALK_STATUS()65 	uint8_t TALK_STATUS() const { return m_SPEN | m_TALKD; }
66 
67 	uint8_t m_SPEN;             /* set on speak command, cleared on stop command or reset command */
68 	uint8_t m_TALK;             /* set on SPEN & RESETL4(pc12->pc0 transition), cleared on stop command or reset command */
69 	uint8_t m_TALKD;            /* TALK(TCON) value, latched every RESETL4 */
70 	sound_stream *m_stream;
71 
72 private:
73 	void new_int_write(uint8_t rc, uint8_t m0, uint8_t m1, uint8_t addr);
74 	void new_int_write_addr(uint8_t addr);
75 	uint8_t new_int_read();
76 	void register_for_save_states();
77 	int extract_bits(int count);
78 	void perform_dummy_read();
79 	int32_t lattice_filter();
80 	void process(int16_t *buffer, unsigned int size);
81 	void PDC_set(int data);
82 	void parse_frame();
83 
OLD_FRAME_SILENCE_FLAG()84 	uint8_t &OLD_FRAME_SILENCE_FLAG() { return m_OLDE; } // 1 if E=0, 0 otherwise.
OLD_FRAME_UNVOICED_FLAG()85 	uint8_t &OLD_FRAME_UNVOICED_FLAG() { return m_OLDP; } // 1 if P=0 (unvoiced), 0 if voiced
86 
NEW_FRAME_STOP_FLAG()87 	bool NEW_FRAME_STOP_FLAG() const { return m_new_frame_energy_idx == 0x0F; } // 1 if this is a stop (Energy = 0x0F) frame
NEW_FRAME_SILENCE_FLAG()88 	bool NEW_FRAME_SILENCE_FLAG() const { return m_new_frame_energy_idx == 0; } // ditto as above
NEW_FRAME_UNVOICED_FLAG()89 	bool NEW_FRAME_UNVOICED_FLAG() const { return m_new_frame_pitch_idx == 0; } // ditto as above
90 
91 	// internal state
92 	/* table */
93 	optional_region_ptr<uint8_t> m_table;
94 
95 	/* coefficient tables */
96 	const int m_variant;                /* Variant of the 5110 - see tms5110.h */
97 
98 	/* coefficient tables */
99 	const struct tms5100_coeffs *m_coeff;
100 
101 	/* these contain global status bits */
102 	uint8_t m_PDC;
103 	uint8_t m_CTL_pins;
104 	uint8_t m_state;
105 
106 	/* Rom interface */
107 	uint32_t m_address;
108 	uint8_t  m_next_is_address;
109 	uint8_t  m_schedule_dummy_read;
110 	uint8_t  m_addr_bit;
111 	/* read byte */
112 	uint8_t  m_CTL_buffer;
113 
114 	/* callbacks */
115 	devcb_write_line   m_m0_cb;      // the M0 line
116 	devcb_write_line   m_m1_cb;      // the M1 line
117 	devcb_write8       m_addr_cb;    // Write to ADD1,2,4,8 - 4 address bits
118 	devcb_read_line    m_data_cb;    // Read one bit from ADD8/Data - voice data
119 	// On a real chip rom_clk is running all the time
120 	// Here, we only use it to properly emulate the protocol.
121 	// Do not rely on it to be a timed signal.
122 	devcb_write_line   m_romclk_cb;  // rom clock - Only used to drive the data lines
123 
124 	/* these contain data describing the current and previous voice frames */
125 	uint8_t m_OLDE;
126 	uint8_t m_OLDP;
127 
128 	uint8_t m_new_frame_energy_idx;
129 	uint8_t m_new_frame_pitch_idx;
130 	uint8_t m_new_frame_k_idx[10];
131 
132 
133 	/* these are all used to contain the current state of the sound generation */
134 #ifndef TMS5110_PERFECT_INTERPOLATION_HACK
135 	int16_t m_current_energy;
136 	int16_t m_current_pitch;
137 	int16_t m_current_k[10];
138 #else
139 	uint8_t m_old_frame_energy_idx;
140 	uint8_t m_old_frame_pitch_idx;
141 	uint8_t m_old_frame_k_idx[10];
142 	uint8_t m_old_zpar;
143 	uint8_t m_old_uv_zpar;
144 
145 	int32_t m_current_energy;
146 	int32_t m_current_pitch;
147 	int32_t m_current_k[10];
148 #endif
149 
150 	uint16_t m_previous_energy; /* needed for lattice filter to match patent */
151 
152 	uint8_t m_subcycle;         /* contains the current subcycle for a given PC: 0 is A' (only used on SPKSLOW mode on 51xx), 1 is A, 2 is B */
153 	uint8_t m_subc_reload;      /* contains 1 for normal speech, 0 when SPKSLOW is active */
154 	uint8_t m_PC;               /* current parameter counter (what param is being interpolated), ranges from 0 to 12 */
155 	/* NOTE: the interpolation period counts 1,2,3,4,5,6,7,0 for divide by 8,8,8,4,4,2,2,1 */
156 	uint8_t m_IP;               /* the current interpolation period */
157 	uint8_t m_inhibit;          /* If 1, interpolation is inhibited until the DIV1 period */
158 	uint8_t m_uv_zpar;          /* If 1, zero k5 thru k10 coefficients */
159 	uint8_t m_zpar;             /* If 1, zero ALL parameters. */
160 	uint8_t m_pitch_zero;       /* circuit 412; pitch is forced to zero under certain circumstances */
161 	uint16_t m_pitch_count;     /* pitch counter; provides chirp rom address */
162 
163 	int32_t m_u[11];
164 	int32_t m_x[10];
165 
166 	uint16_t m_RNG;             /* the random noise generator configuration is: 1 + x + x^3 + x^4 + x^13 TODO: no it isn't */
167 	int16_t m_excitation_data;
168 
169 	/* The TMS51xx has two different ways of providing output data: the
170 	   analog speaker pins (which were usually used) and the Digital I/O pin.
171 	   The internal DAC used to feed the analog pins is only 8 bits, and has the
172 	   funny clipping/clamping logic, while the digital pin gives full 10 bit
173 	   resolution of the output data.
174 	   TODO: add a way to set/reset this other than the FORCE_DIGITAL define
175 	 */
176 	uint8_t m_digital_select;
177 
178 	int32_t m_speech_rom_bitnum;
179 
180 	uint8_t m_romclk_hack_timer_started;
181 	uint8_t m_romclk_hack_state;
182 
183 	emu_timer *m_romclk_hack_timer;
184 };
185 
186 
187 class tms5100_device : public tms5110_device
188 {
189 public:
190 	tms5100_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
191 };
192 
193 
194 class tmc0281_device : public tms5110_device
195 {
196 public:
197 	tmc0281_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
198 };
199 
200 
201 class tms5100a_device : public tms5110_device
202 {
203 public:
204 	tms5100a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
205 };
206 
207 
208 class tmc0281d_device : public tms5110_device
209 {
210 public:
211 	tmc0281d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
212 };
213 
214 
215 class cd2801_device : public tms5110_device
216 {
217 public:
218 	cd2801_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
219 };
220 
221 
222 class cd2802_device : public tms5110_device
223 {
224 public:
225 	cd2802_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
226 };
227 
228 
229 class tms5110a_device : public tms5110_device
230 {
231 public:
232 	tms5110a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
233 };
234 
235 
236 class m58817_device : public tms5110_device
237 {
238 public:
239 	m58817_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
240 
241 	uint8_t status_r();
242 };
243 
244 
DECLARE_DEVICE_TYPE(TMS5110,tms5110_device)245 DECLARE_DEVICE_TYPE(TMS5110,  tms5110_device)
246 DECLARE_DEVICE_TYPE(TMS5100,  tms5100_device)
247 DECLARE_DEVICE_TYPE(TMC0281,  tmc0281_device)
248 DECLARE_DEVICE_TYPE(TMS5100A, tms5100a_device)
249 DECLARE_DEVICE_TYPE(TMC0281D, tmc0281d_device)
250 DECLARE_DEVICE_TYPE(CD2801,   cd2801_device)
251 DECLARE_DEVICE_TYPE(CD2802,   cd2802_device)
252 DECLARE_DEVICE_TYPE(TMS5110A, tms5110a_device)
253 DECLARE_DEVICE_TYPE(M58817,   m58817_device)
254 
255 
256 
257 /* PROM controlled TMS5110 interface */
258 
259 class tmsprom_device : public device_t
260 {
261 public:
262 	tmsprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
263 
264 	void set_region(const char *region) { m_prom.set_tag(region); }
265 	void set_rom_size(uint32_t rom_size) { m_rom_size = rom_size; }
266 	void set_pdc_bit(uint8_t pdc_bit) { m_pdc_bit = pdc_bit; }
267 	void set_ctl1_bit(uint8_t ctl1_bit) { m_ctl1_bit = ctl1_bit; }
268 	void set_ctl2_bit(uint8_t ctl2_bit) { m_ctl2_bit = ctl2_bit; }
269 	void set_ctl4_bit(uint8_t ctl4_bit) { m_ctl4_bit = ctl4_bit; }
270 	void set_ctl8_bit(uint8_t ctl8_bit) { m_ctl8_bit = ctl8_bit; }
271 	void set_reset_bit(uint8_t reset_bit) { m_reset_bit = reset_bit; }
272 	void set_stop_bit(uint8_t stop_bit) { m_stop_bit = stop_bit; }
273 	auto pdc() { return m_pdc_cb.bind(); }
274 	auto ctl() { return m_ctl_cb.bind(); }
275 
276 	void m0_w(int state);
277 	int data_r();
278 
279 	/* offset is rom # */
280 	void rom_csq_w(offs_t offset, uint8_t data);
281 	void bit_w(uint8_t data);
282 	void enable_w(int state);
283 
284 protected:
285 	// device-level overrides
286 	virtual void device_start() override;
287 
288 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
289 
290 private:
291 	void register_for_save_states();
292 	void update_prom_cnt();
293 
294 	// internal state
295 	/* Rom interface */
296 	uint32_t m_address;
297 	/* ctl lines */
298 	uint8_t  m_m0;
299 	uint8_t  m_enable;
300 	uint32_t  m_base_address;
301 	uint8_t  m_bit;
302 
303 	int m_prom_cnt;
304 
305 	required_region_ptr<uint8_t> m_rom;
306 	required_region_ptr<uint8_t> m_prom;
307 	uint32_t m_rom_size;                /* individual rom_size */
308 	uint8_t m_pdc_bit;                  /* bit # of pdc line */
309 	/* virtual bit 8: constant 0, virtual bit 9:constant 1 */
310 	uint8_t m_ctl1_bit;                 /* bit # of ctl1 line */
311 	uint8_t m_ctl2_bit;                 /* bit # of ctl2 line */
312 	uint8_t m_ctl4_bit;                 /* bit # of ctl4 line */
313 	uint8_t m_ctl8_bit;                 /* bit # of ctl8 line */
314 	uint8_t m_reset_bit;                /* bit # of rom reset */
315 	uint8_t m_stop_bit;                 /* bit # of stop */
316 	devcb_write_line m_pdc_cb;      /* tms pdc func */
317 	devcb_write8 m_ctl_cb;          /* tms ctl func */
318 
319 	emu_timer *m_romclk_timer;
320 };
321 
322 DECLARE_DEVICE_TYPE(TMSPROM, tmsprom_device)
323 
324 #endif // MAME_SOUND_TMS5110_H
325