1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol, Curt Coder
3 /************************************************\
4 * Multitech Micro Professor 1                    *
5 *                                                *
6 *     CPU: Z80 @ 1.79 MHz                        *
7 *     ROM: 4-kilobyte ROM monitor                *
8 *     RAM: 4 kilobytes                           *
9 *   Input: Hex keypad                            *
10 * Storage: Cassette tape                         *
11 *   Video: 6x 7-segment LED display              *
12 *   Sound: Speaker                               *
13 \************************************************/
14 
15 /*
16 
17     Keys:
18         0-9,A-F : hexadecimal numbers
19         ADR : enter an address to work with. After the 4 digits are entered,
20               the data at that address shows, and you can modify the data.
21         +   : Enter the data into memory, and increment the address by 1.
22         GO  : execute the program located at the current address.
23 
24     Pasting:
25         0-F : as is
26         +   : ^
27         -   : V
28         ADDR : -
29         DATA : =
30         GO : X
31         PC : P
32 
33     Test Paste:
34         -1800=11^22^33^44^55^66^77^88^99^-1800
35         Now press up-arrow to confirm the data has been entered.
36 
37     TODO:
38 
39     - remove halt callback
40     - crt board
41     - speech board
42     - printers
43     - clickable artwork
44     - video board (has 6845)
45     - mpf1p has 49-key keyboard
46     - computer can't keep up with paste
47     - paste only set up for mpf1
48 
49 */
50 
51 #include "emu.h"
52 #include "includes/mpf1.h"
53 #include "speaker.h"
54 
55 #include "mpf1.lh"
56 #include "mpf1b.lh"
57 #include "mpf1p.lh"
58 
59 /* Address Maps */
60 
mpf1_map(address_map & map)61 void mpf1_state::mpf1_map(address_map &map)
62 {
63 	map.unmap_value_high();
64 	map(0x0000, 0x0fff).rom();
65 	map(0x1800, 0x1fff).ram();
66 }
67 
mpf1_step(address_map & map)68 void mpf1_state::mpf1_step(address_map &map)
69 {
70 	map(0x0000, 0xffff).r(FUNC(mpf1_state::step_r));
71 }
72 
mpf1b_map(address_map & map)73 void mpf1_state::mpf1b_map(address_map &map)
74 {
75 	map.unmap_value_high();
76 	map(0x0000, 0x0fff).rom();
77 	map(0x1800, 0x1fff).ram();
78 	map(0x2000, 0x2fff).rom();
79 	map(0x5000, 0x6fff).rom();
80 }
81 
mpf1p_map(address_map & map)82 void mpf1_state::mpf1p_map(address_map &map)
83 {
84 	map(0x0000, 0x1fff).rom();
85 	map(0x6000, 0x6fff).rom();
86 	map(0xf000, 0xffff).ram();
87 }
88 
mpf1_io_map(address_map & map)89 void mpf1_state::mpf1_io_map(address_map &map)
90 {
91 	map.unmap_value_high();
92 	map.global_mask(0xff);
93 	map(0x00, 0x03).mirror(0x3c).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write));
94 	map(0x40, 0x43).mirror(0x3c).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
95 	map(0x80, 0x83).mirror(0x3c).rw(Z80PIO_TAG, FUNC(z80pio_device::read), FUNC(z80pio_device::write));
96 }
97 
mpf1b_io_map(address_map & map)98 void mpf1_state::mpf1b_io_map(address_map &map)
99 {
100 	map.unmap_value_high();
101 	map.global_mask(0xff);
102 	map(0x00, 0x03).mirror(0x3c).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write));
103 	map(0x40, 0x43).mirror(0x3c).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
104 	map(0x80, 0x83).mirror(0x3c).rw(Z80PIO_TAG, FUNC(z80pio_device::read), FUNC(z80pio_device::write));
105 	map(0xfe, 0xfe).mirror(0x01).rw(TMS5220_TAG, FUNC(tms5220_device::status_r), FUNC(tms5220_device::data_w));
106 }
107 
mpf1p_io_map(address_map & map)108 void mpf1_state::mpf1p_io_map(address_map &map)
109 {
110 	map.unmap_value_high();
111 	map.global_mask(0xff);
112 	map(0x00, 0x03).mirror(0x3c).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write));
113 	map(0x40, 0x43).mirror(0x3c).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
114 	map(0x80, 0x83).mirror(0x3c).rw(Z80PIO_TAG, FUNC(z80pio_device::read), FUNC(z80pio_device::write));
115 }
116 
117 /* Input Ports */
118 
INPUT_CHANGED_MEMBER(mpf1_state::trigger_nmi)119 INPUT_CHANGED_MEMBER( mpf1_state::trigger_nmi )
120 {
121 	m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? CLEAR_LINE : ASSERT_LINE);
122 }
123 
INPUT_CHANGED_MEMBER(mpf1_state::trigger_irq)124 INPUT_CHANGED_MEMBER( mpf1_state::trigger_irq )
125 {
126 	m_maincpu->set_input_line(INPUT_LINE_IRQ0, newval ? CLEAR_LINE : ASSERT_LINE);
127 }
128 
INPUT_CHANGED_MEMBER(mpf1_state::trigger_res)129 INPUT_CHANGED_MEMBER( mpf1_state::trigger_res )
130 {
131 	m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? CLEAR_LINE : ASSERT_LINE);
132 }
133 
134 static INPUT_PORTS_START( mpf1 )
135 	PORT_START("PC0")
PORT_CODE(KEYCODE_3)136 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("3 HL") PORT_CODE(KEYCODE_3) PORT_CHAR('3')
137 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("7 HL'") PORT_CODE(KEYCODE_7) PORT_CHAR('7')
138 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("B I*IF") PORT_CODE(KEYCODE_B) PORT_CHAR('B')
139 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F *PNC'") PORT_CODE(KEYCODE_F) PORT_CHAR('F')
140 	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
141 
142 	PORT_START("PC1")
143 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("2 DE") PORT_CODE(KEYCODE_2) PORT_CHAR('2')
144 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("6 DE'") PORT_CODE(KEYCODE_6) PORT_CHAR('6')
145 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A SP") PORT_CODE(KEYCODE_A) PORT_CHAR('A')
146 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("E SZ*H'") PORT_CODE(KEYCODE_E) PORT_CHAR('E')
147 	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
148 
149 	PORT_START("PC2")
150 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("1 BC") PORT_CODE(KEYCODE_1) PORT_CHAR('1')
151 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("5 BC'") PORT_CODE(KEYCODE_5) PORT_CHAR('5')
152 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9 IY") PORT_CODE(KEYCODE_9) PORT_CHAR('9')
153 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D *PNC") PORT_CODE(KEYCODE_D) PORT_CHAR('D')
154 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("STEP") PORT_CODE(KEYCODE_F1)
155 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TAPE RD") PORT_CODE(KEYCODE_F5)
156 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
157 
158 	PORT_START("PC3")
159 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0 AF") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
160 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 AF'") PORT_CODE(KEYCODE_4) PORT_CHAR('4')
161 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8 IX") PORT_CODE(KEYCODE_8) PORT_CHAR('8')
162 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C SZ*H") PORT_CODE(KEYCODE_C) PORT_CHAR('C')
163 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GO") PORT_CODE(KEYCODE_X) PORT_CHAR('X')
164 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TAPE WR") PORT_CODE(KEYCODE_F6)
165 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
166 
167 	PORT_START("PC4")
168 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CBR") PORT_CODE(KEYCODE_N)
169 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PC") PORT_CODE(KEYCODE_P) PORT_CHAR('P')
170 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("REG") PORT_CODE(KEYCODE_COMMA)
171 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ADDR") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
172 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("DEL") PORT_CODE(KEYCODE_SLASH)
173 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RELA") PORT_CODE(KEYCODE_RCONTROL)
174 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
175 
176 	PORT_START("PC5")
177 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SBR") PORT_CODE(KEYCODE_H)
178 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_DOWN) PORT_CHAR('V')
179 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("DATA") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=')
180 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("+") PORT_CODE(KEYCODE_UP) PORT_CHAR('^')
181 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INS") PORT_CODE(KEYCODE_COLON)
182 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MOVE") PORT_CODE(KEYCODE_QUOTE)
183 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
184 
185 	PORT_START("SPECIAL")
186 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("USER KEY") PORT_CODE(KEYCODE_U)
187 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MONI") PORT_CODE(KEYCODE_M) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_nmi, 0)
188 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INTR") PORT_CODE(KEYCODE_I) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_irq, 0)
189 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F3) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_res, 0)
190 INPUT_PORTS_END
191 
192 static INPUT_PORTS_START( mpf1b )
193 	PORT_START("PC0")
194 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("3 /") PORT_CODE(KEYCODE_3) PORT_CHAR('3')
195 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("7 >") PORT_CODE(KEYCODE_7) PORT_CHAR('7')
196 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("B STOP") PORT_CODE(KEYCODE_B) PORT_CHAR('B')
197 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F LET") PORT_CODE(KEYCODE_F) PORT_CHAR('F')
198 	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
199 
200 	PORT_START("PC1")
201 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("2 *") PORT_CODE(KEYCODE_2) PORT_CHAR('2')
202 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("6 <") PORT_CODE(KEYCODE_6) PORT_CHAR('6')
203 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("A CALL") PORT_CODE(KEYCODE_A) PORT_CHAR('A')
204 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("E INPUT") PORT_CODE(KEYCODE_E) PORT_CHAR('E')
205 	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
206 
207 	PORT_START("PC2")
208 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("1 -") PORT_CODE(KEYCODE_1) PORT_CHAR('1')
209 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("5 =") PORT_CODE(KEYCODE_5) PORT_CHAR('5')
210 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("9 P") PORT_CODE(KEYCODE_9) PORT_CHAR('9')
211 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("D PRINT") PORT_CODE(KEYCODE_D) PORT_CHAR('D')
212 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CONT") PORT_CODE(KEYCODE_F1)
213 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("LOAD") PORT_CODE(KEYCODE_F5)
214 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
215 
216 	PORT_START("PC3")
217 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("0 +") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
218 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 * *") PORT_CODE(KEYCODE_4) PORT_CHAR('4')
219 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("8 M") PORT_CODE(KEYCODE_8) PORT_CHAR('8')
220 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("C NEXT") PORT_CODE(KEYCODE_C) PORT_CHAR('C')
221 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RUN") PORT_CODE(KEYCODE_X) PORT_CHAR('X')
222 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SAVE") PORT_CODE(KEYCODE_F6)
223 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
224 
225 	PORT_START("PC4")
226 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("IF/\xE2\x88\xA7") PORT_CODE(KEYCODE_PGUP)
227 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TO/\xE2\x86\x93") PORT_CODE(KEYCODE_T) PORT_CODE(KEYCODE_DOWN)
228 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("THEN/\xE2\x88\xA8") PORT_CODE(KEYCODE_PGDN)
229 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GOTO") PORT_CODE(KEYCODE_G)
230 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RET/\xE2\x89\x81") PORT_CODE(KEYCODE_R)
231 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("GOSUB") PORT_CODE(KEYCODE_O)
232 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
233 
234 	PORT_START("PC5")
235 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("FOR/\xE2\x86\x91") PORT_CODE(KEYCODE_H) PORT_CODE(KEYCODE_UP)
236 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("LIST") PORT_CODE(KEYCODE_L)
237 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("NEW") PORT_CODE(KEYCODE_N)
238 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER)
239 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CLR/\xE2\x86\x92") PORT_CODE(KEYCODE_INSERT) PORT_CODE(KEYCODE_RIGHT)
240 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("DEL/\xE2\x86\x90") PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_LEFT)
241 	PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
242 
243 	PORT_START("SPECIAL")
244 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT)
245 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("MONI") PORT_CODE(KEYCODE_M) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_nmi, 0)
246 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INTR") PORT_CODE(KEYCODE_I) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_irq, 0)
247 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F3) PORT_CHANGED_MEMBER(DEVICE_SELF, mpf1_state, trigger_res, 0)
248 INPUT_PORTS_END
249 
250 /* Intel 8255A Interface */
251 
252 TIMER_CALLBACK_MEMBER(mpf1_state::led_refresh)
253 {
254 	for (int digit = 0; digit < 6; digit++)
255 		if (BIT(m_lednum, 5 - digit))
256 			m_digits[digit] = param;
257 }
258 
ppi_pa_r()259 uint8_t mpf1_state::ppi_pa_r()
260 {
261 	uint8_t data = 0x7f;
262 
263 	/* bit 0 to 5, keyboard rows 0 to 5 */
264 	for (int row = 0; row < 6; row++)
265 		if (!BIT(m_lednum, row))
266 			data &= m_pc[row]->read();
267 
268 	/* bit 6, user key */
269 	data &= m_special->read() & 1 ? 0xff : 0xbf;
270 
271 	/* bit 7, tape input */
272 	data |= ((m_cassette)->input() > 0) ? 0x80 : 0;
273 
274 	return data;
275 }
276 
ppi_pb_w(uint8_t data)277 void mpf1_state::ppi_pb_w(uint8_t data)
278 {
279 	/* swap bits around for the mame 7-segment emulation */
280 	uint8_t led_data = bitswap<8>(data, 6, 1, 2, 0, 7, 5, 4, 3);
281 
282 	/* timer to update segments */
283 	m_led_refresh_timer->adjust(attotime::from_usec(70), led_data);
284 }
285 
ppi_pc_w(uint8_t data)286 void mpf1_state::ppi_pc_w(uint8_t data)
287 {
288 	/* bits 0-5, led select and keyboard latch */
289 	m_lednum = data & 0x3f;
290 	m_led_refresh_timer->adjust(attotime::never);
291 
292 	/* bit 6, monitor break control */
293 	m_break = BIT(data, 6);
294 
295 	if (m_break)
296 	{
297 		m_m1 = 0;
298 		m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
299 	}
300 
301 	/* bit 7, tape output, tone and led */
302 	m_leds[0] = !BIT(data, 7);
303 	m_speaker->level_w(BIT(data, 7));
304 	m_cassette->output( BIT(data, 7) ? 1.0 : -1.0);
305 }
306 
step_r(offs_t offset)307 uint8_t mpf1_state::step_r(offs_t offset)
308 {
309 	if (!m_break)
310 	{
311 		m_m1++;
312 
313 		if (m_m1 == 5)
314 			m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
315 	}
316 
317 	return m_program->read_byte(offset);
318 }
319 
320 /* Z80 Daisy Chain */
321 
322 static const z80_daisy_config mpf1_daisy_chain[] =
323 {
324 	{ Z80CTC_TAG },
325 	{ Z80PIO_TAG },
326 	{ nullptr }
327 };
328 
329 /* Machine Initialization */
330 
TIMER_DEVICE_CALLBACK_MEMBER(mpf1_state::check_halt_callback)331 TIMER_DEVICE_CALLBACK_MEMBER(mpf1_state::check_halt_callback)
332 {
333 	// halt-LED; the red one, is turned on when the processor is halted
334 	// TODO: processor seems to halt, but restarts(?) at 0x0000 after a while -> fix
335 	int64_t led_halt = m_maincpu->state_int(Z80_HALT);
336 	m_leds[1] = led_halt;
337 }
338 
machine_start()339 void mpf1_state::machine_start()
340 {
341 	m_led_refresh_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mpf1_state::led_refresh),this));
342 	m_digits.resolve();
343 	m_leds.resolve();
344 
345 	/* register for state saving */
346 	save_item(NAME(m_break));
347 	save_item(NAME(m_m1));
348 	save_item(NAME(m_lednum));
349 }
350 
machine_reset()351 void mpf1_state::machine_reset()
352 {
353 	m_lednum = 0;
354 }
355 
356 /* Machine Drivers */
357 
mpf1(machine_config & config)358 void mpf1_state::mpf1(machine_config &config)
359 {
360 	/* basic machine hardware */
361 	Z80(config, m_maincpu, XTAL(3'579'545)/2);
362 	m_maincpu->set_addrmap(AS_PROGRAM, &mpf1_state::mpf1_map);
363 	m_maincpu->set_addrmap(AS_OPCODES, &mpf1_state::mpf1_step);
364 	m_maincpu->set_addrmap(AS_IO, &mpf1_state::mpf1_io_map);
365 	m_maincpu->set_daisy_config(mpf1_daisy_chain);
366 
367 	/* devices */
368 	z80pio_device& pio(Z80PIO(config, Z80PIO_TAG, XTAL(3'579'545)/2));
369 	pio.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
370 
371 	Z80CTC(config, m_ctc, XTAL(3'579'545)/2);
372 	m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
373 
374 	i8255_device &ppi(I8255A(config, I8255A_TAG));
375 	ppi.in_pa_callback().set(FUNC(mpf1_state::ppi_pa_r));
376 	ppi.out_pb_callback().set(FUNC(mpf1_state::ppi_pb_w));
377 	ppi.out_pc_callback().set(FUNC(mpf1_state::ppi_pc_w));
378 
379 	CASSETTE(config, m_cassette);
380 	m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED);
381 
382 	/* video hardware */
383 	config.set_default_layout(layout_mpf1);
384 
385 	/* sound hardware */
386 	SPEAKER(config, "mono").front_center();
387 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
388 
389 	TIMER(config, "halt_timer").configure_periodic(FUNC(mpf1_state::check_halt_callback), attotime::from_hz(1));
390 }
391 
mpf1b(machine_config & config)392 void mpf1_state::mpf1b(machine_config &config)
393 {
394 	/* basic machine hardware */
395 	Z80(config, m_maincpu, XTAL(3'579'545)/2);
396 	m_maincpu->set_addrmap(AS_PROGRAM, &mpf1_state::mpf1b_map);
397 	m_maincpu->set_addrmap(AS_OPCODES, &mpf1_state::mpf1_step);
398 	m_maincpu->set_addrmap(AS_IO, &mpf1_state::mpf1b_io_map);
399 	m_maincpu->set_daisy_config(mpf1_daisy_chain);
400 
401 	/* devices */
402 	z80pio_device& pio(Z80PIO(config, Z80PIO_TAG, XTAL(3'579'545)/2));
403 	pio.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
404 
405 	Z80CTC(config, m_ctc, XTAL(3'579'545)/2);
406 	m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
407 
408 	i8255_device &ppi(I8255A(config, I8255A_TAG));
409 	ppi.in_pa_callback().set(FUNC(mpf1_state::ppi_pa_r));
410 	ppi.out_pb_callback().set(FUNC(mpf1_state::ppi_pb_w));
411 	ppi.out_pc_callback().set(FUNC(mpf1_state::ppi_pc_w));
412 
413 	CASSETTE(config, m_cassette);
414 	m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED);
415 
416 	/* video hardware */
417 	config.set_default_layout(layout_mpf1b);
418 
419 	/* sound hardware */
420 	SPEAKER(config, "mono").front_center();
421 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
422 
423 	TMS5220(config, TMS5220_TAG, 680000L).add_route(ALL_OUTPUTS, "mono", 0.50);
424 
425 	TIMER(config, "halt_timer").configure_periodic(FUNC(mpf1_state::check_halt_callback), attotime::from_hz(1));
426 }
427 
mpf1p(machine_config & config)428 void mpf1_state::mpf1p(machine_config &config)
429 {
430 	/* basic machine hardware */
431 	Z80(config, m_maincpu, 2500000);
432 	m_maincpu->set_addrmap(AS_PROGRAM, &mpf1_state::mpf1p_map);
433 	m_maincpu->set_addrmap(AS_OPCODES, &mpf1_state::mpf1_step);
434 	m_maincpu->set_addrmap(AS_IO, &mpf1_state::mpf1p_io_map);
435 	m_maincpu->set_daisy_config(mpf1_daisy_chain);
436 
437 	/* video hardware */
438 	config.set_default_layout(layout_mpf1p);
439 
440 	/* devices */
441 	z80pio_device& pio(Z80PIO(config, Z80PIO_TAG, 2500000));
442 	pio.out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
443 
444 	Z80CTC(config, m_ctc, 2500000);
445 	m_ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
446 
447 	i8255_device &ppi(I8255A(config, I8255A_TAG));
448 	ppi.in_pa_callback().set(FUNC(mpf1_state::ppi_pa_r));
449 	ppi.out_pb_callback().set(FUNC(mpf1_state::ppi_pb_w));
450 	ppi.out_pc_callback().set(FUNC(mpf1_state::ppi_pc_w));
451 
452 	CASSETTE(config, m_cassette);
453 	m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED);
454 
455 	/* sound hardware */
456 	SPEAKER(config, "mono").front_center();
457 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
458 
459 	TIMER(config, "halt_timer").configure_periodic(FUNC(mpf1_state::check_halt_callback), attotime::from_hz(1));
460 }
461 
462 /* ROMs */
463 
464 ROM_START( mpf1 )
465 	ROM_REGION( 0x10000, Z80_TAG, 0 )
CRC(b60249ce)466 	ROM_LOAD( "mpf.u6", 0x0000, 0x1000, CRC(b60249ce) SHA1(78e0e8874d1497fabfdd6378266d041175e3797f) )
467 ROM_END
468 
469 ROM_START( mpf1b )
470 	ROM_REGION( 0x10000, Z80_TAG, 0 )
471 	ROM_LOAD( "c55167.u6", 0x0000, 0x1000, CRC(28b06dac) SHA1(99cfbab739d71a914c39302d384d77bddc4b705b) )
472 	ROM_LOAD( "basic.u7", 0x2000, 0x1000, CRC(d276ed6b) SHA1(a45fb98961be5e5396988498c6ed589a35398dcf) )
473 	ROM_LOAD( "ssb-mpf.u", 0x5000, 0x1000, CRC(f926334f) SHA1(35847f8164eed4c0794a8b74e5d7fa972b10eb90) )
474 	ROM_LOAD( "prt-mpf.u5", 0x6000, 0x1000, CRC(730f2fb0) SHA1(f31536ee9dbb9babb9ce16a7490db654ca0b5749) )
475 ROM_END
476 
477 ROM_START( mpf1p )
478 	ROM_REGION( 0x10000, Z80_TAG, 0 )
479 	ROM_LOAD( "mpf1pmon.bin", 0x0000, 0x2000, BAD_DUMP CRC(91ace7d3) SHA1(22e3c16a81ac09f37741ad1b526a4456b2ba9493) ) // A9 stuck low when dumped
480 	ROM_LOAD( "prt-mpf-ip.u5", 0x6000, 0x1000, CRC(4dd2a4eb) SHA1(6a3e7daa7834d67fd572261ed4a9a62c4594fe3f) )
481 ROM_END
482 
483 /* System Drivers */
484 
485 void mpf1_state::init_mpf1()
486 {
487 	m_program = &m_maincpu->space(AS_PROGRAM);
488 }
489 
490 COMP( 1979, mpf1,  0,    0, mpf1, mpf1,  mpf1_state, init_mpf1, "Multitech", "Micro Professor 1",      0 )
491 COMP( 1979, mpf1b, mpf1, 0, mpf1b,mpf1b, mpf1_state, init_mpf1, "Multitech", "Micro Professor 1B",     0 )
492 COMP( 1982, mpf1p, mpf1, 0, mpf1p,mpf1b, mpf1_state, init_mpf1, "Multitech", "Micro Professor 1 Plus", MACHINE_NOT_WORKING )
493