summaryrefslogtreecommitdiffstats
path: root/src/devices/sound/s14001a.h
blob: a7294559fb475aab7265866d00e93c7f8cc40530 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// license:BSD-3-Clause
// copyright-holders:Ed Bernard, Jonathan Gevaryahu, hap
// thanks-to:Kevin Horton
/*
    SSi TSI S14001A speech IC emulator
*/

#ifndef MAME_SOUND_S14001A_H
#define MAME_SOUND_S14001A_H

#define MCFG_S14001A_BSY_HANDLER(_devcb) \
	downcast<s14001a_device &>(*device).set_bsy_handler(DEVCB_##_devcb);

#define MCFG_S14001A_EXT_READ_HANDLER(_devcb) \
	downcast<s14001a_device &>(*device).set_ext_read_handler(DEVCB_##_devcb);


class s14001a_device : public device_t, public device_sound_interface
{
public:
	s14001a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	// configuration helpers
	template <class Object> devcb_base &set_bsy_handler(Object &&cb) { return m_bsy_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_ext_read_handler(Object &&cb) { return m_ext_read_handler.set_callback(std::forward<Object>(cb)); }

	DECLARE_READ_LINE_MEMBER(busy_r);   // /BUSY (pin 40)
	DECLARE_READ_LINE_MEMBER(romen_r);  // ROM /EN (pin 9)
	DECLARE_WRITE_LINE_MEMBER(start_w); // START (pin 10)
	DECLARE_WRITE8_MEMBER(data_w);      // 6-bit word

	void set_clock(uint32_t clock);       // set new CLK frequency
	void set_clock(const XTAL &xtal) { set_clock(xtal.value()); }
	void force_update();                // update stream, eg. before external ROM bankswitch

protected:
	// device-level overrides
	virtual void device_start() override;

	// sound stream update overrides
	virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;

private:
	uint8_t readmem(uint16_t offset, bool phase);
	bool Clock(); // called once to toggle external clock twice

	// emulator helper functions
	void ClearStatistics();
	void GetStatistics(uint32_t &uNPitchPeriods, uint32_t &uNVoiced, uint32_t &uNControlWords);
	void SetPrintLevel(uint32_t uPrintLevel) { m_uPrintLevel = uPrintLevel; }

	enum class states : u8
	{
		IDLE = 0,
		WORDWAIT,
		CWARMSB,    // read 8 CWAR MSBs
		CWARLSB,    // read 4 CWAR LSBs from rom d7-d4
		DARMSB,     // read 8 DAR  MSBs
		CTRLBITS,   // read Stop, Voiced, Silence, Length, XRepeat
		PLAY,
		DELAY
	};

	required_region_ptr<uint8_t> m_SpeechRom;
	sound_stream * m_stream;

	devcb_write_line m_bsy_handler;
	devcb_read8 m_ext_read_handler;

	// internal state
	bool m_bPhase1; // 1 bit internal clock

	// registers
	states m_uStateP1;          // 3 bits
	states m_uStateP2;

	uint16_t m_uDAR13To05P1;      // 9 MSBs of delta address register
	uint16_t m_uDAR13To05P2;      // incrementing uDAR05To13 advances ROM address by 8 bytes

	uint16_t m_uDAR04To00P1;      // 5 LSBs of delta address register
	uint16_t m_uDAR04To00P2;      // 3 address ROM, 2 mux 8 bits of data into 2 bit delta
								// carry indicates end of quarter pitch period (32 cycles)

	uint16_t m_uCWARP1;           // 12 bits Control Word Address Register (syllable)
	uint16_t m_uCWARP2;

	bool m_bStopP1;
	bool m_bStopP2;
	bool m_bVoicedP1;
	bool m_bVoicedP2;
	bool m_bSilenceP1;
	bool m_bSilenceP2;
	uint8_t m_uLengthP1;          // 7 bits, upper three loaded from ROM length
	uint8_t m_uLengthP2;          // middle two loaded from ROM repeat and/or uXRepeat
								// bit 0 indicates mirror in voiced mode
								// bit 1 indicates internal silence in voiced mode
								// incremented each pitch period quarter

	uint8_t m_uXRepeatP1;         // 2 bits, loaded from ROM repeat
	uint8_t m_uXRepeatP2;
	uint8_t m_uDeltaOldP1;        // 2 bit old delta
	uint8_t m_uDeltaOldP2;
	uint8_t m_uOutputP1;          // 4 bits audio output, calculated during phase 1

	// derived signals
	bool m_bDAR04To00CarryP2;
	bool m_bPPQCarryP2;
	bool m_bRepeatCarryP2;
	bool m_bLengthCarryP2;
	uint16_t m_RomAddrP1;         // rom address

	// output pins
	uint8_t m_uOutputP2;          // output changes on phase2
	uint16_t m_uRomAddrP2;        // address pins change on phase 2
	bool m_bBusyP1;             // busy changes on phase 1

	// input pins
	bool m_bStart;
	uint8_t m_uWord;              // 6 bit word number to be spoken

	// emulator variables
	// statistics
	uint32_t m_uNPitchPeriods;
	uint32_t m_uNVoiced;
	uint32_t m_uNControlWords;

	// diagnostic output
	uint32_t m_uPrintLevel;
};

DECLARE_DEVICE_TYPE(S14001A, s14001a_device)

#endif // MAME_SOUND_S14001A_H