1 // license:BSD-3-Clause
2 // copyright-holders:Jonathan Gevaryahu
3 /******************************************************************************
4 *
5 *  Pacific Educational Systems 'PES' Speech box
6 *  Part number VPU-1 V1
7 *  By Kevin 'kevtris' Horton and Jonathan Gevaryahu AKA Lord Nightmare
8 *
9 *  Pacific Educational Systems, 915 Woodhall Drive, Victoria, Canada.
10 *
11 *  RE work done by Kevin Horton and Jonathan Gevaryahu
12 *
13 *  DONE:
14 *  compiles correctly
15 *  rom loads correctly
16 *  interface with tms5220 is done
17 *  rts and cts bits are stored in struct
18 *  serial is attached to terminal
19 *
20 *  TODO:
21 *  serial receive clear should happen after delay of one cpu cycle, not ASSERT and then CLEAR immediately after
22 *  figure out how to attach serial to external socket
23 *
24 ***********************************************************************
25 This is almost as simple as hardware gets from the digital side:
26 Hardware consists of:
27 10.245Mhz xtal
28 80c31 cpu/mcu
29 27c64 rom (holds less than 256 bytes of code)
30 unpopulated 6164 sram, which isn't used
31 TSP5220C speech chip (aka tms5220c)
32 mc145406 RS232 driver/receiver (+-24v to 0-5v converter for serial i/o)
33 74hc573b1 octal tri-state D-latch (part of bus interface for ROM)
34 74hc74b1 dual d-flipflop with set/reset, positive edge trigger (?)
35 74hc02b1 quad 2-input NOR gate (wired up to decode address 0, and data 0 and 1 to produce /RS and /WS)
36 mc14520b dual 4-bit binary up counter (used as a chopper for the analog filter)
37 Big messy analog section to allow voice output to be filtered extensively by a 4th order filter
38 
39 Address map:
40 80C31 ADDR:
41   0000-1FFF: ROM
42   2000-3FFF: open bus (would be ram)
43   4000-ffff: open bus
44 80C31 IO:
45   00 W: d0 and d1 are the /RS and /WS bits
46   port 1.x: tms5220 bus
47   port 2.x: unused
48   port 3.0: RxD serial receive
49   port 3.1: TxD serial send
50   port 3.2: read, from /INT on tms5220c
51   port 3.3: read, from /READY on tms5220c
52   port 3.4: read, from the serial RTS line
53   port 3.5: read/write, to the serial CTS line, inverted (effectively /CTS)
54   port 3.6: write, /WR (general) and /WE (pin 27) for unpopulated 6164 SRAM
55   port 3.7: write, /RD (general) and /OE (pin 22) for unpopulated 6164 SRAM
56 
57 
58 Current status:
59 - bios 0 : working. Hold down various letters for fragments of sound. g makes a beep. Status is reflected on the screen (eg space,@,`).
60 - bios 1 : working as above, however it does not get the tms5220 status and it does not write to the screen.
61 
62 */
63 
64 #include "emu.h"
65 #include "cpu/mcs51/mcs51.h"
66 #include "sound/tms5220.h"
67 #include "machine/terminal.h"
68 #include "speaker.h"
69 
70 
71 class pes_state : public driver_device
72 {
73 public:
pes_state(const machine_config & mconfig,device_type type,const char * tag)74 	pes_state(const machine_config &mconfig, device_type type, const char *tag)
75 		: driver_device(mconfig, type, tag)
76 		, m_maincpu(*this, "maincpu")
77 		, m_terminal(*this, "terminal")
78 		, m_speech(*this, "tms5220")
79 	{ }
80 
81 	void pes(machine_config &config);
82 
83 private:
84 
85 	u8 m_term_data;
86 	u8 m_port3;
87 	virtual void machine_reset() override;
88 	void port3_w(u8 data);
89 	u8 port3_r();
90 	void kbd_put(u8 data);
91 	void io_map(address_map &map);
92 	void prg_map(address_map &map);
93 	required_device<i80c31_device> m_maincpu;
94 	required_device<generic_terminal_device> m_terminal;
95 	required_device<tms5220_device> m_speech;
96 };
97 
98 
99 
100 /* Devices */
kbd_put(u8 data)101 void pes_state::kbd_put(u8 data)
102 {
103 	m_maincpu->set_input_line(MCS51_RX_LINE, ASSERT_LINE);
104 	m_maincpu->set_input_line(MCS51_RX_LINE, CLEAR_LINE);
105 	m_term_data = data;
106 }
107 
108 
109 /* Port Handlers */
port3_w(u8 data)110 void pes_state::port3_w(u8 data)
111 {
112 	m_port3 = data;
113 #if 0
114 	logerror("port3 write: control data written: %02X; ", data);
115 	logerror("RXD: %d; ", BIT(data,0));
116 	logerror("TXD: %d; ", BIT(data,1));
117 	logerror("/INT: %d; ", BIT(data,2));
118 	logerror("/RDY: %d; ", BIT(data,3));
119 	logerror("RTS: %d; ", BIT(data,4));
120 	logerror("CTS: %d; ", BIT(data,5));
121 	logerror("WR: %d; ", BIT(data,6));
122 	logerror("RD: %d;\n", BIT(data,7));
123 #endif
124 	// todo: poke serial handler here somehow?
125 }
126 
port3_r()127 u8 pes_state::port3_r()
128 {
129 	uint8_t data = m_port3 & 0xE3; // return last written state with rts, /rdy and /int masked out
130 	// check rts state; if virtual fifo is nonzero, rts is set, otherwise it is cleared
131 	//data |= 0x10; // set RTS bit
132 	data |= (m_speech->intq_r()<<2);
133 	data |= (m_speech->readyq_r()<<3);
134 	return data;
135 }
136 
137 
138 /* Reset */
machine_reset()139 void pes_state::machine_reset()
140 {
141 	m_port3 = 0; // reset the openbus state of port 3
142 	m_speech->reset(); // reset the 5220
143 }
144 
145 
146 /******************************************************************************
147  Address Maps
148 ******************************************************************************/
149 
prg_map(address_map & map)150 void pes_state::prg_map(address_map &map)
151 {
152 	map.unmap_value_high();
153 	map(0x0000, 0x1fff).rom(); /* 27C64 ROM */
154 	// map(0x2000, 0x3fff).ram(); /* 6164 8k SRAM, not populated */
155 }
156 
io_map(address_map & map)157 void pes_state::io_map(address_map &map)
158 {
159 	map(0x0000, 0x0000).w(m_speech, FUNC(tms5220_device::combined_rsq_wsq_w)); // /WS(0) and /RS(1)
160 }
161 
162 /******************************************************************************
163  Input Ports
164 ******************************************************************************/
INPUT_PORTS_START(pes)165 static INPUT_PORTS_START( pes )
166 INPUT_PORTS_END
167 
168 /******************************************************************************
169  Machine Drivers
170 ******************************************************************************/
171 
172 void pes_state::pes(machine_config &config)
173 {
174 	/* basic machine hardware */
175 	I80C31(config, m_maincpu, XTAL(10'245'000));
176 	m_maincpu->set_addrmap(AS_PROGRAM, &pes_state::prg_map);
177 	m_maincpu->set_addrmap(AS_IO, &pes_state::io_map);
178 	m_maincpu->port_in_cb<1>().set(m_speech, FUNC(tms5220_device::status_r));
179 	m_maincpu->port_out_cb<1>().set(m_speech, FUNC(tms5220_device::data_w));
180 	m_maincpu->port_in_cb<3>().set(FUNC(pes_state::port3_r));
181 	m_maincpu->port_out_cb<3>().set(FUNC(pes_state::port3_w));
182 	m_maincpu->serial_tx_cb().set(m_terminal, FUNC(generic_terminal_device::write));
183 	m_maincpu->serial_rx_cb().set([this] () { return m_term_data; });
184 
185 	/* sound hardware */
186 	SPEAKER(config, "mono").front_center();
187 	TMS5220C(config, m_speech, 720000); /* 720Khz clock, 9khz sample-rate, adjustable with 10-turn trimpot */
188 	m_speech->add_route(ALL_OUTPUTS, "mono", 1.0);
189 
190 	GENERIC_TERMINAL(config, m_terminal, 0);
191 	m_terminal->set_keyboard_callback(FUNC(pes_state::kbd_put));
192 }
193 
194 /******************************************************************************
195  ROM Definitions
196 ******************************************************************************/
197 ROM_START( pes )
198 	ROM_REGION( 0x10000, "maincpu", 0 )
199 	ROM_DEFAULT_BIOS("kevbios")
200 	ROM_SYSTEM_BIOS( 0, "orig", "PES box with original firmware v2.5")
201 	ROMX_LOAD( "vpu_2-5.bin",   0x0000, 0x2000, CRC(b27cfdf7) SHA1(c52acf9c080823de5ef26ac55abe168ad53a7d38), ROM_BIOS(0)) // original firmware, rather buggy, 4800bps serial, buggy RTS/CTS flow control, no buffer
202 	ROM_SYSTEM_BIOS( 1, "kevbios", "PES box with kevtris' rewritten firmware")
203 	ROMX_LOAD( "pes.bin",   0x0000, 0x2000, CRC(22c1c4ec) SHA1(042e139cd0cf6ffafcd88904f1636c6fa1b38f25), ROM_BIOS(1)) // rewritten firmware by kevtris, 4800bps serial, RTS/CTS plus XON/XOFF flow control, 64 byte buffer
204 ROM_END
205 
206 /******************************************************************************
207  Drivers
208 ******************************************************************************/
209 
210 //    YEAR  NAME  PARENT  COMPAT  MACHINE  INPUT  CLASS      INIT        COMPANY                        FULLNAME             FLAGS
211 COMP( 1987, pes,  0,      0,      pes,     pes,   pes_state, empty_init, "Pacific Educational Systems", "VPU-01 Speech box", 0 )
212