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