1 // license:BSD-3-Clause
2 // copyright-holders:Antoine Mine
3 /**********************************************************************
4 
5   Copyright (C) Antoine Mine' 2008
6 
7    Hewlett Packard HP48 S/SX & G/GX/G+ and HP49 G
8 
9 **********************************************************************/
10 
11 #include "emu.h"
12 #include "includes/hp48.h"
13 
14 #include "cpu/saturn/saturn.h"
15 #include "machine/nvram.h"
16 
17 #include "screen.h"
18 
19 
20 /***************************************************************************
21     DEBUGGING
22 ***************************************************************************/
23 
24 
25 #define VERBOSE          0
26 #define VERBOSE_SERIAL   0
27 
28 #define LOG(x)  do { if (VERBOSE) logerror x; } while (0)
29 #define LOG_SERIAL(x)  do { if (VERBOSE_SERIAL) logerror x; } while (0)
30 
31 
32 
33 /***************************************************************************
34     TYPE DEFINITIONS
35 ***************************************************************************/
36 
37 /* state field in hp48_module */
38 #define HP48_MODULE_UNCONFIGURED 0
39 #define HP48_MODULE_MASK_KNOWN   1
40 #define HP48_MODULE_CONFIGURED   2
41 
42 /***************************************************************************
43     GLOBAL VARIABLES & CONSTANTS
44 ***************************************************************************/
45 
46 /* current HP48 model */
47 
48 #define HP48_G_SERIES ((m_model==HP48_G) || (m_model==HP48_GX) || (m_model==HP48_GP))
49 #define HP48_S_SERIES ((m_model==HP48_S) || (m_model==HP48_SX))
50 #define HP48_X_SERIES ((m_model==HP48_SX) || (m_model==HP48_GX))
51 #define HP48_GX_MODEL ((m_model==HP48_GX) || (m_model==HP48_GP))
52 #define HP49_G_MODEL  ((m_model==HP49_G))
53 
54 static const char *const hp48_module_names[6] =
55 { "HDW (I/O)", "NCE2 (RAM)", "CE1", "CE2", "NCE3", "NCE1 (ROM)" };
56 
57 /* values returned by C=ID */
58 static const uint8_t hp48_module_mask_id[6] = { 0x00, 0x03, 0x05, 0x07, 0x01, 0x00 };
59 static const uint8_t hp48_module_addr_id[6] = { 0x19, 0xf4, 0xf6, 0xf8, 0xf2, 0x00 };
60 
61 
62 
63 
64 
65 /***************************************************************************
66     FUNCTIONS
67 ***************************************************************************/
68 
pulse_irq(int irq_line)69 void hp48_state::pulse_irq(int irq_line)
70 {
71 	m_maincpu->set_input_line(irq_line, ASSERT_LINE);
72 	m_maincpu->set_input_line(irq_line, CLEAR_LINE);
73 }
74 
75 
76 /* ---------------- serial --------------------- */
77 
78 #define RS232_DELAY attotime::from_usec(300)
79 
80 /* end of receive event */
TIMER_CALLBACK_MEMBER(hp48_state::rs232_byte_recv_cb)81 TIMER_CALLBACK_MEMBER(hp48_state::rs232_byte_recv_cb)
82 {
83 	LOG_SERIAL(("%f hp48_state::rs232_byte_recv_cb: end of receive, data=%02x\n", machine().time().as_double(), param));
84 
85 	m_io[0x14] = param & 0xf; /* receive zone */
86 	m_io[0x15] = param >> 4;
87 	m_io[0x11] &= ~2; /* clear byte receiving */
88 	m_io[0x11] |= 1;  /* set byte received */
89 
90 	/* interrupt */
91 	if (m_io[0x10] & 2)
92 	{
93 		pulse_irq(SATURN_IRQ_LINE);
94 	}
95 }
96 
97 /* outside world initiates a receive event */
rs232_start_recv_byte(uint8_t data)98 void hp48_state::rs232_start_recv_byte(uint8_t data)
99 {
100 	LOG_SERIAL(("%f hp48_state::rs232_start_recv_byte: start receiving, data=%02x\n", machine().time().as_double(), data));
101 
102 	m_io[0x11] |= 2;  /* set byte receiving */
103 
104 	/* interrupt */
105 	if (m_io[0x10] & 1)
106 	{
107 		pulse_irq(SATURN_IRQ_LINE);
108 	}
109 
110 	/* schedule end of reception */
111 	machine().scheduler().timer_set(RS232_DELAY, timer_expired_delegate(FUNC(hp48_state::rs232_byte_recv_cb),this), data);
112 }
113 
114 
115 /* end of send event */
TIMER_CALLBACK_MEMBER(hp48_state::rs232_byte_sent_cb)116 TIMER_CALLBACK_MEMBER(hp48_state::rs232_byte_sent_cb)
117 {
118 	LOG_SERIAL(("%f hp48_state::rs232_byte_sent_cb: end of send, data=%02x\n", machine().time().as_double(), param));
119 
120 	m_io[0x12] &= ~3; /* clear byte sending and buffer full */
121 
122 	/* interrupt */
123 	if (m_io[0x10] & 4)
124 	{
125 		pulse_irq(SATURN_IRQ_LINE);
126 	}
127 }
128 
129 /* CPU initiates a send event */
rs232_send_byte()130 void hp48_state::rs232_send_byte()
131 {
132 	uint8_t data = HP48_IO_8(0x16); /* byte to send */
133 
134 	LOG_SERIAL(("%s %f hp48_state::rs232_send_byte: start sending, data=%02x\n", machine().describe_context(), machine().time().as_double(), data));
135 
136 	/* set byte sending and send buffer full */
137 	m_io[0x12] |= 3;
138 
139 	/* schedule transmission */
140 	machine().scheduler().timer_set(RS232_DELAY, timer_expired_delegate(FUNC(hp48_state::rs232_byte_sent_cb),this), data);
141 }
142 
143 
144 
145 
146 /* ------ Saturn's IN / OUT registers ---------- */
147 
148 
149 /* CPU sets OUT register (keyboard + beeper) */
reg_out(uint32_t data)150 void hp48_state::reg_out(uint32_t data)
151 {
152 	LOG(("%s %f hp48_state::reg_out: %03x\n", machine().describe_context(), machine().time().as_double(), data));
153 
154 	/* bits 0-8: keyboard lines */
155 	m_out = data & 0x1ff;
156 
157 	/* bits 9-10: unused */
158 
159 	/* bit 11: beeper */
160 	m_dac->write(BIT(data, 11));
161 }
162 
get_in()163 int hp48_state::get_in()
164 {
165 	int in = 0;
166 
167 	/* regular keys */
168 	if (BIT(m_out, 0)) in |= ioport("LINE0")->read();
169 	if (BIT(m_out, 1)) in |= ioport("LINE1")->read();
170 	if (BIT(m_out, 2)) in |= ioport("LINE2")->read();
171 	if (BIT(m_out, 3)) in |= ioport("LINE3")->read();
172 	if (BIT(m_out, 4)) in |= ioport("LINE4")->read();
173 	if (BIT(m_out, 5)) in |= ioport("LINE5")->read();
174 	if (BIT(m_out, 6)) in |= ioport("LINE6")->read();
175 	if (BIT(m_out, 7)) in |= ioport("LINE7")->read();
176 	if (BIT(m_out, 8)) in |= ioport("LINE8")->read();
177 
178 	/* on key */
179 	in |= ioport("ON")->read();
180 
181 	return in;
182 }
183 
184 /* CPU reads IN register (keyboard) */
reg_in()185 uint32_t hp48_state::reg_in()
186 {
187 	int in = get_in();
188 	LOG(("%s %f hp48_state::reg_in: %04x\n", machine().describe_context(), machine().time().as_double(), in));
189 	return in;
190 }
191 
192 /* key detect */
update_kdn()193 void hp48_state::update_kdn()
194 {
195 	int in = get_in();
196 
197 	/* interrupt on raising edge */
198 	if (in && !m_kdn)
199 	{
200 		LOG(("%f hp48_state::update_kdn: interrupt\n", machine().time().as_double()));
201 		m_io[0x19] |= 8; // service request
202 		pulse_irq(SATURN_WAKEUP_LINE);
203 		pulse_irq(SATURN_IRQ_LINE);
204 	}
205 
206 	m_kdn = (in != 0);
207 }
208 
209 /* periodic keyboard polling, generates an interrupt */
TIMER_CALLBACK_MEMBER(hp48_state::kbd_cb)210 TIMER_CALLBACK_MEMBER(hp48_state::kbd_cb)
211 {
212 	/* NMI for ON key */
213 	if (ioport( "ON" )->read())
214 	{
215 		LOG(("%f hp48_state::kbd_cb: keyboard interrupt, on key\n", machine().time().as_double()));
216 		m_io[0x19] |= 8; // set service request
217 		pulse_irq(SATURN_WAKEUP_LINE);
218 		pulse_irq(SATURN_NMI_LINE);
219 		return;
220 	}
221 
222 	/* regular keys */
223 	update_kdn();
224 }
225 
226 /* RSI opcode */
WRITE_LINE_MEMBER(hp48_state::rsi)227 WRITE_LINE_MEMBER( hp48_state::rsi )
228 {
229 	LOG(("%s %f hp48_state::rsi\n", machine().describe_context(), machine().time().as_double()));
230 
231 	// enables interrupts on key repeat (normally, there is only one interrupt, when the key is pressed)
232 	m_kdn = 0;
233 }
234 
235 
236 /* ------------- annonciators ------------ */
237 
update_annunciators()238 void hp48_state::update_annunciators()
239 {
240 	/* bit 0: left shift
241 	   bit 1: right shift
242 	   bit 2: alpha
243 	   bit 3: alert
244 	   bit 4: busy
245 	   bit 5: transmit
246 	   bit 7: master enable
247 	*/
248 	int markers = HP48_IO_8(0xb);
249 	m_lshift0   = (markers & 0x81) == 0x81;
250 	m_rshift0   = (markers & 0x82) == 0x82;
251 	m_alpha0    = (markers & 0x84) == 0x84;
252 	m_alert0    = (markers & 0x88) == 0x88;
253 	m_busy0     = (markers & 0x90) == 0x90;
254 	m_transmit0 = (markers & 0xb0) == 0xb0;
255 }
256 
257 
258 /* ------------- I/O registers ----------- */
259 
260 /* Some part of the I/O registers are simple r/w registers. We store them in hp48_io.
261    Special cases are registers that:
262    - have a different meaning on read and write
263    - perform some action on read / write
264  */
265 
io_w(offs_t offset,uint8_t data)266 void hp48_state::io_w(offs_t offset, uint8_t data)
267 {
268 	LOG(("%s %f hp48_state::io_w: off=%02x data=%x\n", machine().describe_context(), machine().time().as_double(), offset, data));
269 
270 	switch (offset)
271 	{
272 	/* CRC register */
273 	case 0x04: m_crc = (m_crc & 0xfff0) | data; break;
274 	case 0x05: m_crc = (m_crc & 0xff0f) | (data << 4); break;
275 	case 0x06: m_crc = (m_crc & 0xf0ff) | (data << 8); break;
276 	case 0x07: m_crc = (m_crc & 0x0fff) | (data << 12); break;
277 
278 	/* annunciators */
279 	case 0x0b:
280 	case 0x0c:
281 		m_io[offset] = data;
282 		update_annunciators();
283 		break;
284 
285 	/* cntrl ROM */
286 	case 0x29:
287 	{
288 		int old_cntrl = m_io[offset] & 8;
289 		m_io[offset] = data;
290 		if (old_cntrl != (data & 8))
291 		{
292 			apply_modules();
293 		}
294 		break;
295 	}
296 
297 	/* timers */
298 	case 0x37: m_timer1 = data; break;
299 	case 0x38: m_timer2 = (m_timer2 & 0xfffffff0) | data; break;
300 	case 0x39: m_timer2 = (m_timer2 & 0xffffff0f) | (data << 4); break;
301 	case 0x3a: m_timer2 = (m_timer2 & 0xfffff0ff) | (data << 8); break;
302 	case 0x3b: m_timer2 = (m_timer2 & 0xffff0fff) | (data << 12); break;
303 	case 0x3c: m_timer2 = (m_timer2 & 0xfff0ffff) | (data << 16); break;
304 	case 0x3d: m_timer2 = (m_timer2 & 0xff0fffff) | (data << 20); break;
305 	case 0x3e: m_timer2 = (m_timer2 & 0xf0ffffff) | (data << 24); break;
306 	case 0x3f: m_timer2 = (m_timer2 & 0x0fffffff) | (data << 28); break;
307 
308 	/* cards */
309 	case 0x0e:
310 		LOG(("%s: card control write %02x\n", machine().describe_context(), data));
311 
312 		/* bit 0: software interrupt */
313 		if (data & 1)
314 		{
315 			LOG(("%f hp48_state::io_w: software interrupt requested\n", machine().time().as_double()));
316 			pulse_irq(SATURN_IRQ_LINE);
317 			data &= ~1;
318 		}
319 
320 		/* XXX not implemented
321 		    bit 1: card test?
322 		 */
323 
324 		m_io[0x0e] = data;
325 		break;
326 
327 	case 0x0f:
328 		LOG(("%s: card info write %02x\n", machine().describe_context(), data));
329 		m_io[0x0f] = data;
330 		break;
331 
332 	/* serial */
333 	case 0x13:
334 		m_io[0x11] &= ~4; /* clear error status */
335 		break;
336 	case 0x16:
337 		/* first nibble of sent data */
338 		m_io[offset] = data;
339 		break;
340 	case 0x17:
341 		/* second nibble of sent data */
342 		m_io[offset] = data;
343 		rs232_send_byte();
344 		break;
345 
346 	/* XXX not implemented:
347 
348 	   - 0x0d: RS232c speed:
349 	      bits 0-2: speed
350 	            000 = 1200 bauds
351 	        010 = 2400 bauds
352 	        100 = 4800 bauds
353 	        110 = 9600 bauds
354 	          bit 3: ?
355 
356 	       - 0x1a: I/R input
357 	          bit 0: irq
358 	      bit 1: irq enable
359 	      bit 2: 1=RS232c mode 0=direct mode
360 	      bit 3: receiving
361 
362 	   - 0x1c: I/R output control
363 	      bit 0: buffer full
364 	      bit 1: transmitting
365 	      bit 2: irq enable on buffer empty
366 	      bit 3: led on (direct mode)
367 	                 on HP49 G, flash ROM write enable
368 
369 	   - 0x1d: I/R output buffer
370 	*/
371 
372 	default: m_io[offset] = data;
373 	}
374 
375 }
376 
377 
io_r(offs_t offset)378 uint8_t hp48_state::io_r(offs_t offset)
379 {
380 	uint8_t data = 0;
381 
382 	switch (offset)
383 	{
384 	/* CRC register */
385 	case 0x04: data = m_crc & 0xf; break;
386 	case 0x05: data = (m_crc >> 4) & 0xf; break;
387 	case 0x06: data = (m_crc >> 8) & 0xf; break;
388 	case 0x07: data = (m_crc >> 12) & 0xf; break;
389 
390 	/* battery test */
391 	case 0x08:
392 		data = 0;
393 		if (m_io[0x9] & 8) /* test enable */
394 		{
395 			/* XXX not implemented:
396 			   bit 3: battery in port 2
397 			   bit 2: battery in port 1
398 			 */
399 			switch (ioport("BATTERY")->read())
400 			{
401 			case 1: data = 2; break; /* low */
402 			case 2: data = 3; break; /* low | critical */
403 			}
404 		}
405 		break;
406 
407 	/* remaining lines in main bitmap */
408 	case 0x28:
409 	case 0x29:
410 	{
411 		int last_line = HP48_IO_8(0x28) & 0x3f; /* last line of main bitmap before menu */
412 		int cur_line = m_screen->vpos();
413 		if (last_line <= 1) last_line = 0x3f;
414 		data = (cur_line >= 0 && cur_line <= last_line) ? last_line - cur_line : 0;
415 		if (offset == 0x29)
416 		{
417 			data >>= 4;
418 			data |= HP48_IO_4(0x29) & 0xc;
419 		}
420 		else
421 		{
422 			data &= 0xf;
423 		}
424 		break;
425 	}
426 
427 	/* timers */
428 	case 0x37: data = m_timer1; break;
429 	case 0x38: data = m_timer2 & 0xf; break;
430 	case 0x39: data = (m_timer2 >> 4) & 0xf; break;
431 	case 0x3a: data = (m_timer2 >> 8) & 0xf; break;
432 	case 0x3b: data = (m_timer2 >> 12) & 0xf; break;
433 	case 0x3c: data = (m_timer2 >> 16) & 0xf; break;
434 	case 0x3d: data = (m_timer2 >> 20) & 0xf; break;
435 	case 0x3e: data = (m_timer2 >> 24) & 0xf; break;
436 	case 0x3f: data = (m_timer2 >> 28) & 0xf; break;
437 
438 	/* serial */
439 	case 0x15:
440 	{
441 		m_io[0x11] &= ~1;  /* clear byte received */
442 		data = m_io[offset];
443 		break;
444 	}
445 
446 	/* cards */
447 	case 0x0e: /* detection */
448 		data = m_io[0x0e];
449 		LOG(( "%s: card control read %02x\n", machine().describe_context(), data ));
450 		break;
451 	case 0x0f: /* card info */
452 		data = 0;
453 		if ( HP48_G_SERIES )
454 		{
455 			if (m_port[1].found() && m_port[1]->port_size() > 0)
456 			{
457 				data |= 1;
458 				if (m_port[1]->port_write())
459 					data |= 4;
460 			}
461 			if (m_port[0].found() && m_port[0]->port_size() > 0)
462 			{
463 				data |= 2;
464 				if (m_port[0]->port_write())
465 					data |= 8;
466 			}
467 		}
468 		else
469 		{
470 			if (m_port[0].found() && m_port[0]->port_size() > 0)
471 			{
472 				data |= 1;
473 				if (m_port[0]->port_write())
474 					data |= 4;
475 			}
476 			if (m_port[1].found() && m_port[1]->port_size() > 0)
477 			{
478 				data |= 2;
479 				if (m_port[1]->port_write())
480 					data |= 8;
481 			}
482 		}
483 		LOG(( "%s: card info read %02x\n", machine().describe_context(), data ));
484 		break;
485 
486 
487 	default: data = m_io[offset];
488 	}
489 
490 	LOG(("%s %f hp48_state::io_r: off=%02x data=%x\n", machine().describe_context(), machine().time().as_double(), offset, data));
491 	return data;
492 }
493 
494 
495 /* ---------- bank switcher --------- */
496 
bank_r(offs_t offset)497 uint8_t hp48_state::bank_r(offs_t offset)
498 {
499 	/* HP48 GX
500 	   bit 0: ignored
501 	   bits 2-5: bank number
502 	   bit 6: enable
503 	*/
504 
505 	/* HP49 G
506 	   bit 0: ignored
507 	   bits 1-2: select bank 0x00000-0x3ffff
508 	   bits 3-6: select bank 0x40000-0x7ffff
509 	 */
510 	offset &= 0x7e;
511 	if ( m_bank_switch != offset )
512 	{
513 		LOG(( "%s %f hp48_state::bank_r: off=%03x\n", machine().describe_context(), machine().time().as_double(), offset ));
514 		m_bank_switch = offset;
515 		apply_modules();
516 	}
517 	return 0;
518 }
519 
520 
hp49_bank_w(offs_t offset,uint8_t data)521 void hp48_state::hp49_bank_w(offs_t offset, uint8_t data)
522 {
523 	offset &= 0x7e;
524 	if ( m_bank_switch != offset )
525 	{
526 		LOG(("%s %f hp49_bank_w: off=%03x\n", machine().describe_context(), machine().time().as_double(), offset));
527 		m_bank_switch = offset;
528 		apply_modules();
529 	}
530 }
531 
532 
533 
534 /* ---------------- timers --------------- */
535 
TIMER_CALLBACK_MEMBER(hp48_state::timer1_cb)536 TIMER_CALLBACK_MEMBER(hp48_state::timer1_cb)
537 {
538 	if (!(m_io[0x2f] & 1)) return; /* timer enable */
539 
540 	m_timer1 = (m_timer1 - 1) & 0xf;
541 
542 	/* wake-up on carry */
543 	if ((m_io[0x2e] & 4) && (m_timer1 == 0xf))
544 	{
545 		LOG(("wake-up on timer1\n"));
546 		m_io[0x2e] |= 8;                                      /* set service request */
547 		m_io[0x18] |= 4;                                      /* set service request */
548 		pulse_irq(SATURN_WAKEUP_LINE);
549 	}
550 	/* interrupt on carry */
551 	if ((m_io[0x2e] & 2) && (m_timer1 == 0xf))
552 	{
553 		LOG(("generate timer1 interrupt\n"));
554 		m_io[0x2e] |= 8; /* set service request */
555 		m_io[0x18] |= 4; /* set service request */
556 		pulse_irq(SATURN_NMI_LINE);
557 	}
558 }
559 
TIMER_CALLBACK_MEMBER(hp48_state::timer2_cb)560 TIMER_CALLBACK_MEMBER(hp48_state::timer2_cb)
561 {
562 	if (!(m_io[0x2f] & 1)) return; /* timer enable */
563 
564 	m_timer2 = (m_timer2 - 1) & 0xffffffff;
565 
566 	/* wake-up on carry */
567 	if ((m_io[0x2f] & 4) && (m_timer2 == 0xffffffff))
568 	{
569 		LOG(("wake-up on timer2\n"));
570 		m_io[0x2f] |= 8;                                      /* set service request */
571 		m_io[0x18] |= 4;                                      /* set service request */
572 		pulse_irq(SATURN_WAKEUP_LINE);
573 	}
574 	/* interrupt on carry */
575 	if ((m_io[0x2f] & 2) && (m_timer2 == 0xffffffff))
576 	{
577 		LOG(("generate timer2 interrupt\n"));
578 		m_io[0x2f] |= 8;                                      /* set service request */
579 		m_io[0x18] |= 4;                                      /* set service request */
580 		pulse_irq(SATURN_NMI_LINE);
581 	}
582 }
583 
584 
585 
586 
587 /* --------- memory controller ----------- */
588 
589 /*
590    Clark (S series) and York (G series) CPUs have 6 daisy-chained modules
591 
592 
593    <-- highest --------- priority ------------- lowest -->
594 
595    CPU ---------------------------------------------------
596             |      |      |          |          |        |
597            HDW    NCE2   CE1        CE2        NCE3     NCE1
598 
599 
600    However, controller usage is different in both series:
601 
602 
603       controller    48 S series     48 G series         49 G series
604                     (Clark CPU)     (York CPU)          (York CPU)
605 
606          HDW        32B I/O RAM    32B I/O RAM         32B I/O RAM
607         NCE2         32KB RAM      32/128KB RAM        256KB RAM
608          CE1           port1       bank switcher       bank switcher
609          CE2           port2          port1             128KB RAM
610         NCE3          unused          port2             128KB RAM
611         NCE1         256KB ROM      512KB ROM         2MB flash ROM
612 
613 
614    - NCE1 (ROM) cannot be configured, it is always visible at addresses
615    00000-7ffff not covered by higher priority modules.
616 
617    - only the address of HDW (I/O) can be configured, its size is constant
618    (64 nibbles)
619 
620    - other modules can have their address & size set
621 
622  */
623 
624 
625 /* remap all modules according to hp48_modules */
apply_modules()626 void hp48_state::apply_modules()
627 {
628 	int nce3_enable = 1;
629 	address_space& space = m_maincpu->space(AS_PROGRAM);
630 
631 	m_io_addr = 0x100000;
632 
633 	/* NCE1 (ROM) is a bit special, so treat it separately */
634 	space.unmap_readwrite(0, 0xfffff);
635 	if (HP49_G_MODEL)
636 	{
637 		int bank_lo = (m_bank_switch >> 5) & 3;
638 		int bank_hi = (m_bank_switch >> 1) & 15;
639 		LOG(("hp48_state::apply_modules: low ROM bank is %i\n", bank_lo));
640 		LOG(("hp48_state::apply_modules: high ROM bank is %i\n", bank_hi));
641 		space.install_read_bank(0x00000, 0x3ffff, 0x80000, "bank5");
642 		space.install_read_bank(0x40000, 0x7ffff, 0x80000, "bank6");
643 		if (m_rom)
644 		{
645 			membank("bank5")->set_base(m_rom + bank_lo * 0x40000);
646 			membank("bank6")->set_base(m_rom + bank_hi * 0x40000);
647 		}
648 	}
649 	else if (HP48_G_SERIES)
650 	{
651 		/* port 2 bank switch */
652 		if (m_port[1].found() && m_port[1]->port_size() > 0)
653 		{
654 			int off = (m_bank_switch << 16) % m_port[1]->port_size();
655 			LOG(("hp48_state::apply_modules: port 2 offset is %i\n", off));
656 			m_modules[HP48_NCE3].data = m_port[1]->port_data() + off;
657 		}
658 
659 		/* ROM A19 (hi 256 KB) / NCE3 (port 2) control switch */
660 		if (m_io[0x29] & 8)
661 		{
662 			/* A19 */
663 			LOG(("hp48_state::apply_modules: A19 enabled, NCE3 disabled\n"));
664 			nce3_enable = 0;
665 			space.install_read_bank(0, 0xfffff, "bank5");
666 		}
667 		else
668 		{
669 			/* NCE3 */
670 			nce3_enable = m_bank_switch >> 6;
671 			LOG(("hp48_apply_modules: A19 disabled, NCE3 %s\n", nce3_enable ? "enabled" : "disabled"));
672 			space.install_read_bank(0, 0x7ffff, 0x80000, "bank5");
673 		}
674 		if (m_rom)
675 		{
676 			membank("bank5")->set_base(m_rom);
677 		}
678 	}
679 	else
680 	{
681 		space.install_read_bank(0, 0x7ffff, 0x80000, "bank5");
682 		if (m_rom)
683 		{
684 			membank("bank5")->set_base(m_rom);
685 		}
686 	}
687 
688 
689 	/* from lowest to highest priority */
690 	for (int i = 4; i >= 0; i--)
691 	{
692 		uint32_t select_mask = m_modules[i].mask;
693 		uint32_t nselect_mask = ~select_mask & 0xfffff;
694 		uint32_t base = m_modules[i].base;
695 		uint32_t off_mask = m_modules[i].off_mask;
696 		uint32_t mirror = nselect_mask & ~off_mask;
697 		uint32_t end = base + (off_mask & nselect_mask);
698 		char bank[10];
699 		sprintf(bank,"bank%d",i);
700 
701 		if (m_modules[i].state != HP48_MODULE_CONFIGURED) continue;
702 		if ((i == 4) && !nce3_enable) continue;
703 
704 		/* our code assumes that the 20-bit select_mask is all 1s followed by all 0s */
705 		if (nselect_mask & (nselect_mask + 1))
706 		{
707 			logerror("hp48_apply_modules: invalid mask %05x for module %s\n", select_mask, hp48_module_names[i]);
708 			continue;
709 		}
710 
711 		if (m_modules[i].data)
712 		{
713 			space.install_read_bank(base, end, mirror, bank);
714 		}
715 		else
716 		{
717 			if (!m_modules[i].read.isnull())
718 			{
719 				space.install_read_handler(base, end, 0, mirror, 0, m_modules[i].read);
720 			}
721 		}
722 
723 		if (m_modules[i].isnop)
724 		{
725 			space.nop_write(base, end | mirror);
726 		}
727 		else
728 		{
729 			if (m_modules[i].data)
730 			{
731 				space.install_write_bank(base, end, mirror, bank);
732 			}
733 			else
734 			{
735 				if (!m_modules[i].write.isnull())
736 				{
737 					space.install_write_handler(base, end, 0, mirror, 0, m_modules[i].write);
738 				}
739 			}
740 		}
741 
742 		LOG(("hp48_apply_modules: module %s configured at %05x-%05x, mirror %05x\n", hp48_module_names[i], base, end, mirror));
743 
744 		if (m_modules[i].data)
745 		{
746 			membank(bank)->set_base(m_modules[i].data);
747 		}
748 
749 		if (i == 0)
750 		{
751 			m_io_addr = base;
752 		}
753 	}
754 }
755 
756 
757 /* reset the configuration */
reset_modules()758 void hp48_state::reset_modules()
759 {
760 	/* fixed size for HDW */
761 	m_modules[HP48_HDW].state = HP48_MODULE_MASK_KNOWN;
762 	m_modules[HP48_HDW].mask = 0xfffc0;
763 	/* unconfigure NCE2, CE1, CE2, NCE3 */
764 	for (int i = 1; i < 5; i++)
765 	{
766 		m_modules[i].state = HP48_MODULE_UNCONFIGURED;
767 	}
768 
769 	/* fixed configuration for NCE1 */
770 	m_modules[HP48_NCE1].state = HP48_MODULE_CONFIGURED;
771 	m_modules[HP48_NCE1].base = 0;
772 	m_modules[HP48_NCE1].mask = 0;
773 
774 	apply_modules();
775 }
776 
777 
778 /* RESET opcode */
WRITE_LINE_MEMBER(hp48_state::mem_reset)779 WRITE_LINE_MEMBER( hp48_state::mem_reset )
780 {
781 	LOG(("%s %f hp48_state::mem_reset\n", machine().describe_context(), machine().time().as_double()));
782 	reset_modules();
783 }
784 
785 
786 /* CONFIG opcode */
mem_config(uint32_t data)787 void hp48_state::mem_config(uint32_t data)
788 {
789 	LOG(("%s %f hp48_state::mem_config: %05x\n", machine().describe_context(), machine().time().as_double(), data));
790 
791 	/* find the highest priority unconfigured module (except non-configurable NCE1)... */
792 	for (int i = 0; i < 5; i++)
793 	{
794 		/* ... first call sets the address mask */
795 		if (m_modules[i].state == HP48_MODULE_UNCONFIGURED)
796 		{
797 			m_modules[i].mask = data & 0xff000;
798 			m_modules[i].state = HP48_MODULE_MASK_KNOWN;
799 			break;
800 		}
801 
802 		/* ... second call sets the base address */
803 		if (m_modules[i].state == HP48_MODULE_MASK_KNOWN)
804 		{
805 			m_modules[i].base = data & m_modules[i].mask;
806 			m_modules[i].state = HP48_MODULE_CONFIGURED;
807 			LOG(("hp48_mem_config: module %s configured base=%05x, mask=%05x\n", hp48_module_names[i], m_modules[i].base, m_modules[i].mask));
808 			apply_modules();
809 			break;
810 		}
811 	}
812 }
813 
814 
815 /* UNCFG opcode */
mem_unconfig(uint32_t data)816 void hp48_state::mem_unconfig(uint32_t data)
817 {
818 	LOG(("%s %f hp48_state::mem_unconfig: %05x\n", machine().describe_context(), machine().time().as_double(), data));
819 
820 	/* find the highest priority fully configured module at address v (except NCE1)... */
821 	for (int i = 0; i < 5; i++)
822 	{
823 		/* ... and unconfigure it */
824 		if (m_modules[i].state == HP48_MODULE_CONFIGURED && (m_modules[i].base == (data & m_modules[i].mask)))
825 		{
826 			m_modules[i].state = i > 0 ? HP48_MODULE_UNCONFIGURED : HP48_MODULE_MASK_KNOWN;
827 			LOG(("hp48_mem_unconfig: module %s\n", hp48_module_names[i]));
828 			apply_modules();
829 			break;
830 		}
831 	}
832 }
833 
834 
835 /* C=ID opcode */
mem_id()836 uint32_t hp48_state::mem_id()
837 {
838 	int data = 0; /* 0 = everything is configured */
839 
840 	/* find the highest priority unconfigured module (except NCE1)... */
841 	for (int i = 0; i < 5; i++)
842 	{
843 		/* ... mask need to be configured */
844 		if (m_modules[i].state == HP48_MODULE_UNCONFIGURED)
845 		{
846 			data = hp48_module_mask_id[i] | (m_modules[i].mask & ~0xff);
847 			break;
848 		}
849 
850 		/* ... address need to be configured */
851 		if (m_modules[i].state == HP48_MODULE_MASK_KNOWN)
852 		{
853 			data = hp48_module_addr_id[i] | (m_modules[i].base & ~0x3f);
854 			break;
855 		}
856 	}
857 
858 	LOG(("%s %f mem_id = %02x\n", machine().describe_context(), machine().time().as_double(), data));
859 
860 	return data; /* everything is configured */
861 }
862 
863 
864 
865 /* --------- CRC ---------- */
866 
867 /* each memory read by the CPU updates the internal CRC state */
mem_crc(offs_t offset,uint32_t data)868 void hp48_state::mem_crc(offs_t offset, uint32_t data)
869 {
870 	/* no CRC for I/O RAM */
871 	if (offset >= m_io_addr && offset < m_io_addr + 0x40) return;
872 
873 	m_crc = (m_crc >> 4) ^ (((m_crc ^ data) & 0xf) * 0x1081);
874 }
875 
876 
877 
878 /* ------ utilities ------- */
879 
880 
881 /* decodes size bytes into 2*size nibbles (least significant first) */
decode_nibble(uint8_t * dst,uint8_t * src,int size)882 void hp48_state::decode_nibble(uint8_t* dst, uint8_t* src, int size)
883 {
884 	for (int i = size - 1; i >= 0; i--)
885 	{
886 		dst[2 * i + 1] = src[i] >> 4;
887 		dst[2 * i] = src[i] & 0xf;
888 	}
889 }
890 
891 /* inverse of decode_nibble  */
encode_nibble(uint8_t * dst,uint8_t * src,int size)892 void hp48_state::encode_nibble(uint8_t* dst, uint8_t* src, int size)
893 {
894 	for (int i = 0; i < size; i++)
895 	{
896 		dst[i] = (src[2 * i] & 0xf) | (src[2 * i + 1] << 4);
897 	}
898 }
899 
900 /***************************************************************************
901     MACHINES
902 ***************************************************************************/
903 
init_hp48()904 void hp48_state::init_hp48()
905 {
906 	LOG(( "hp48: driver init called\n" ));
907 	for (int i = 0; i < 6; i++)
908 	{
909 		m_modules[i].off_mask = 0x00fff;  /* 2 KB */
910 		m_modules[i].read     = read8sm_delegate(*this);
911 		m_modules[i].write    = write8sm_delegate(*this);
912 		m_modules[i].data     = nullptr;
913 		m_modules[i].isnop    = 0;
914 	}
915 	m_rom = nullptr;
916 }
917 
machine_reset()918 void hp48_state::machine_reset()
919 {
920 	LOG(("hp48: machine reset called\n"));
921 	m_bank_switch = 0;
922 	reset_modules();
923 	update_annunciators();
924 }
925 
base_machine_start(hp48_models model)926 void hp48_state::base_machine_start(hp48_models model)
927 {
928 	LOG(( "hp48_state::machine_start: model %i\n", model ));
929 
930 	m_model = model;
931 
932 	/* internal RAM */
933 	uint32_t ram_size =
934 		HP49_G_MODEL  ? (512 * 1024) :
935 		HP48_GX_MODEL ? (128 * 1024) : (32 * 1024);
936 
937 	uint8_t *ram = auto_alloc_array(machine(), uint8_t, 2 * ram_size);
938 	subdevice<nvram_device>("nvram")->set_base(ram, 2 * ram_size);
939 
940 
941 	/* ROM load */
942 	uint32_t rom_size =
943 		HP49_G_MODEL  ? (2048 * 1024) :
944 		HP48_S_SERIES ?  (256 * 1024) : (512 * 1024);
945 	m_rom = auto_alloc_array(machine(), uint8_t, 2 * rom_size);
946 	decode_nibble(m_rom, memregion("maincpu")->base(), rom_size);
947 
948 	/* init state */
949 	memset(ram, 0, 2 * ram_size);
950 	memset(m_io, 0, sizeof(m_io));
951 	m_out = 0;
952 	m_kdn = 0;
953 	m_crc = 0;
954 	m_timer1 = 0;
955 	m_timer2 = 0;
956 	m_bank_switch = 0;
957 
958 	/* I/O RAM */
959 	m_modules[HP48_HDW].off_mask = 0x0003f;  /* 32 B */
960 	m_modules[HP48_HDW].read     = read8sm_delegate(*this, FUNC(hp48_state::io_r));
961 	m_modules[HP48_HDW].write    = write8sm_delegate(*this, FUNC(hp48_state::io_w));
962 
963 	/* internal RAM */
964 	if (HP49_G_MODEL)
965 	{
966 		m_modules[HP48_NCE2].off_mask = 2 * 256 * 1024 - 1;
967 		m_modules[HP48_NCE2].data     = ram;
968 		m_modules[HP48_CE2].off_mask  = 2 * 128 * 1024 - 1;
969 		m_modules[HP48_CE2].data      = ram + 2 * 256 * 1024;
970 		m_modules[HP48_NCE3].off_mask = 2 * 128 * 1024 - 1;
971 		m_modules[HP48_NCE3].data     = ram + 2 * (128+256) * 1024;
972 	}
973 	else
974 	{
975 		m_modules[HP48_NCE2].off_mask = 2 * ram_size - 1;
976 		m_modules[HP48_NCE2].data     = ram;
977 	}
978 
979 	/* bank switcher */
980 	if (HP48_G_SERIES)
981 	{
982 		m_modules[HP48_CE1].off_mask = 0x00fff;  /* 2 KB */
983 		m_modules[HP48_CE1].read     = read8sm_delegate(*this, FUNC(hp48_state::bank_r));
984 		m_modules[HP48_CE1].write    = HP49_G_MODEL ? write8sm_delegate(*this, FUNC(hp48_state::hp49_bank_w)) : write8sm_delegate(*this);
985 	}
986 
987 	/* timers */
988 	m_1st_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hp48_state::timer1_cb), this));
989 	m_1st_timer->adjust(attotime::from_hz(16), 0, attotime::from_hz(16));
990 
991 	m_2nd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hp48_state::timer2_cb), this));
992 	m_2nd_timer->adjust(attotime::from_hz(8192), 0, attotime::from_hz(8192));
993 
994 	/* 1ms keyboard polling */
995 	m_kbd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hp48_state::kbd_cb), this));
996 	m_kbd_timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1));
997 
998 	m_lshift0.resolve();
999 	m_rshift0.resolve();
1000 	m_alpha0.resolve();
1001 	m_alert0.resolve();
1002 	m_busy0.resolve();
1003 	m_transmit0.resolve();
1004 
1005 	/* save state */
1006 	save_item(NAME(m_out));
1007 	save_item(NAME(m_kdn));
1008 	save_item(NAME(m_io_addr));
1009 	save_item(NAME(m_crc));
1010 	save_item(NAME(m_timer1));
1011 	save_item(NAME(m_timer2));
1012 	save_item(NAME(m_bank_switch));
1013 	for (int i = 0; i < 6; i++)
1014 	{
1015 		save_item(m_modules[i].state, "globals/m_modules[i].state", i);
1016 		save_item(m_modules[i].base, "globals/m_modules[i].base", i);
1017 		save_item(m_modules[i].mask, "globals/m_modules[i].mask", i);
1018 	}
1019 	save_item(NAME(m_io) );
1020 	machine().save().register_postload(save_prepost_delegate(FUNC(hp48_state::update_annunciators), this));
1021 	machine().save().register_postload(save_prepost_delegate(FUNC(hp48_state::apply_modules), this));
1022 
1023 }
1024 
MACHINE_START_MEMBER(hp48_state,hp48s)1025 MACHINE_START_MEMBER(hp48_state,hp48s)
1026 {
1027 	base_machine_start(HP48_S);
1028 }
1029 
MACHINE_START_MEMBER(hp48_state,hp48sx)1030 MACHINE_START_MEMBER(hp48_state,hp48sx)
1031 {
1032 	base_machine_start(HP48_SX);
1033 }
1034 
MACHINE_START_MEMBER(hp48_state,hp48g)1035 MACHINE_START_MEMBER(hp48_state,hp48g)
1036 {
1037 	base_machine_start(HP48_G);
1038 }
1039 
MACHINE_START_MEMBER(hp48_state,hp48gx)1040 MACHINE_START_MEMBER(hp48_state,hp48gx)
1041 {
1042 	base_machine_start(HP48_GX);
1043 }
1044 
MACHINE_START_MEMBER(hp48_state,hp48gp)1045 MACHINE_START_MEMBER(hp48_state,hp48gp)
1046 {
1047 	base_machine_start(HP48_GP);
1048 }
1049 
MACHINE_START_MEMBER(hp48_state,hp49g)1050 MACHINE_START_MEMBER(hp48_state,hp49g)
1051 {
1052 	base_machine_start(HP49_G);
1053 }
1054