1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3
4 /*
5
6 NewBrain
7 Grundy Business Systems Ltd.
8
9 32K RAM
10 28K ROM
11
12 Z80 @ 2MHz
13 COP420 @ 2MHz
14
15 Z80 @ 4MHz (416): INT/NMI=+5V, WAIT=EXTBUSRQ|BUSAKD, RESET=_FDC RESET,
16 NEC 765AC @ 4 MHz (418)
17 MC6850 ACIA (459)
18 Z80CTC (458)
19 ADC0809 (427)
20 DAC0808 (461)
21
22 Models according to the Software Technical Manual:
23
24 Model M: 'Page Register', Expansion Port onto Z80 bus, Video, ACIA/CTC, User Port
25 Model A: Expansion Port, Video, no User Port but has software driver serial port - s/w Printer, s/w V24
26 Model V: ACIA/CTC, User Port
27
28 */
29
30 /*
31
32 TODO:
33
34 - COPINT @ 84Hz instead of 50Hz? (with clock 3240506 is 50Hz)
35 - CLKINT arrives too late and COP reads the VFD data before CPU writes it
36 - VFD does not receive data from main CPU
37 - bitmapped video
38 - accurate video timing
39 - cassette motor control seems to have a COP cpu problem
40 - EIM
41 - floppy
42 - CP/M 2.2 ROMs
43 - localized ROM sets
44 - Micropage ROM/RAM card
45 - Z80 PIO board
46 - peripheral (PI) box
47 - sound card
48
49 */
50
51 #include "emu.h"
52 #include "includes/newbrain.h"
53 #include "speaker.h"
54 #include "screen.h"
55
56 #include "newbrain.lh"
57 #include "newbraina.lh"
58
59
60
61 //**************************************************************************
62 // MACROS / CONSTANTS
63 //**************************************************************************
64
65 #define LOG_COP (1 << 1U)
66 #define LOG_VFD (1 << 2U)
67 #define VERBOSE 0
68 #include "logmacro.h"
69
70
71
72 //**************************************************************************
73 // IMPLEMENTATION
74 //**************************************************************************
75
76 //-------------------------------------------------
77 // check_interrupt -
78 //-------------------------------------------------
79
check_interrupt()80 void newbrain_state::check_interrupt()
81 {
82 int level = ((!m_clk && !m_clkint) || !m_copint) ? ASSERT_LINE : CLEAR_LINE;
83
84 m_maincpu->set_input_line(INPUT_LINE_IRQ0, level);
85 }
86
87
88 //-------------------------------------------------
89 // mreq_r - memory request read
90 //-------------------------------------------------
91
mreq_r(offs_t offset)92 uint8_t newbrain_state::mreq_r(offs_t offset)
93 {
94 bool romov = 1, raminh = 0;
95 int exrm = 0;
96 uint8_t data = m_exp->mreq_r(offset, 0xff, romov, exrm, raminh);
97
98 int rom0 = 1, rom1 = 1, rom2 = 1;
99 int a15_14_13 = romov ? (offset >> 13) : exrm;
100 if (!m_pwrup) a15_14_13 = 7;
101 int a15g = BIT(a15_14_13, 2);
102
103 switch (a15_14_13)
104 {
105 case 5: rom0 = 0; break;
106 case 6: rom1 = 0; break;
107 case 7: rom2 = 0; break;
108 }
109
110 if (!a15g && !raminh)
111 {
112 data = m_ram->pointer()[offset];
113 }
114
115 if (!rom0)
116 {
117 data = m_rom->base()[0x0000 + (offset & 0x1fff)];
118 }
119
120 if (!rom1)
121 {
122 data = m_rom->base()[0x2000 + (offset & 0x1fff)];
123 }
124
125 if (!rom2)
126 {
127 data = m_rom->base()[0x4000 + (offset & 0x1fff)];
128 }
129
130 return data;
131 }
132
133
134 //-------------------------------------------------
135 // mreq_w - memory request write
136 //-------------------------------------------------
137
mreq_w(offs_t offset,uint8_t data)138 void newbrain_state::mreq_w(offs_t offset, uint8_t data)
139 {
140 bool romov = 1, raminh = 0;
141 int exrm = 0;
142 m_exp->mreq_w(offset, data, romov, exrm, raminh);
143
144 int a15_14_13 = romov ? (offset >> 13) : exrm;
145 if (!m_pwrup) a15_14_13 = 7;
146 int a15g = BIT(a15_14_13, 2);
147
148 if (!a15g && !raminh)
149 {
150 m_ram->pointer()[offset] = data;
151 }
152 }
153
154
155 //-------------------------------------------------
156 // iorq_r - I/O request read
157 //-------------------------------------------------
158
iorq_r(offs_t offset)159 uint8_t newbrain_state::iorq_r(offs_t offset)
160 {
161 bool prtov = 0;
162 uint8_t data = m_exp->iorq_r(offset, 0xff, prtov);
163
164 if (!prtov)
165 {
166 switch ((offset >> 2) & 0x07)
167 {
168 case 1: // EXP1
169 switch (offset & 0x03)
170 {
171 case 0: // CLCLK
172 clclk();
173 break;
174
175 case 2: // COP
176 data = m_cop->microbus_rd();
177 break;
178 }
179 break;
180
181 case 5: // UST
182 if (BIT(offset, 1))
183 {
184 data = ust_b_r();
185 }
186 else
187 {
188 data = ust_a_r();
189 }
190 break;
191 }
192 }
193
194 return data;
195 }
196
197
198 //-------------------------------------------------
199 // iorq_w - I/O request write
200 //-------------------------------------------------
201
iorq_w(offs_t offset,uint8_t data)202 void newbrain_state::iorq_w(offs_t offset, uint8_t data)
203 {
204 bool prtov = 0;
205 m_exp->iorq_w(offset, 0xff, prtov);
206
207 if (!prtov)
208 {
209 switch ((offset >> 2) & 0x07)
210 {
211 case 1: // EXP1
212 switch (offset & 0x03)
213 {
214 case 0: // CLCLK
215 clclk();
216 break;
217
218 case 2: // COP
219 m_cop->microbus_wr(data);
220 break;
221
222 case 3: // ENRG1
223 enrg_w(data);
224 break;
225 }
226 break;
227
228 case 2: // TVL
229 tvl(data, BIT(offset, 6));
230 break;
231
232 case 3: // TVTL
233 tvtl_w(data);
234 break;
235 }
236 }
237 }
238
239
240 //-------------------------------------------------
241 // clclk - clear clock interrupt
242 //-------------------------------------------------
243
clclk()244 void newbrain_state::clclk()
245 {
246 LOG("%s %s CLCLK\n", machine().time().as_string(), machine().describe_context());
247
248 m_clkint = 1;
249 check_interrupt();
250 }
251
252
253 //-------------------------------------------------
254 // enrg_w -
255 //-------------------------------------------------
256
enrg_w(uint8_t data)257 void newbrain_state::enrg_w(uint8_t data)
258 {
259 /*
260
261 bit signal
262
263 0 _CLK
264 1
265 2 TVP
266 3
267 4 _RTSD
268 5 DO
269 6
270 7 PO
271
272 */
273
274 LOG("%s %s ENRG %02x\n", machine().time().as_string(), machine().describe_context(), data);
275
276 // clock enable
277 int clk = BIT(data, 0);
278
279 if (m_clk != clk) {
280 m_clk = clk;
281 check_interrupt();
282 }
283
284 // TV enable
285 m_tvp = BIT(data, 2);
286
287 // V24
288 m_rs232_v24->write_rts(BIT(data, 4));
289 m_rs232_v24->write_txd(BIT(data, 5));
290
291 // printer
292 m_rs232_prn->write_txd(BIT(data, 7));
293 }
294
295
296 //-------------------------------------------------
297 // ust_r -
298 //-------------------------------------------------
299
ust_a_r()300 uint8_t newbrain_state::ust_a_r()
301 {
302 /*
303
304 bit signal
305
306 0 +5V
307 1 PWRUP
308 2
309 3
310 4
311 5 _CLKINT
312 6
313 7 _COPINT
314
315 */
316
317 uint8_t data = 0x5d;
318
319 // powered up
320 data |= m_pwrup << 1;
321
322 // interrupts
323 data |= m_clkint << 5;
324 data |= m_copint << 7;
325
326 return data;
327 }
328
329
330 //-------------------------------------------------
331 // user_r -
332 //-------------------------------------------------
333
ust_b_r()334 uint8_t newbrain_state::ust_b_r()
335 {
336 /*
337
338 bit signal
339
340 0 RDDK
341 1 _CTSD
342 2
343 3
344 4
345 5 TPIN
346 6
347 7 _CTSP
348
349 */
350
351 uint8_t data = 0x5c;
352
353 // V24
354 data |= m_rs232_v24->rxd_r();
355 data |= m_rs232_v24->cts_r() << 1;
356
357 // tape
358 data |= tpin() << 5;
359
360 // printer
361 data |= m_rs232_prn->cts_r() << 7;
362
363 return data;
364 }
365
366
367 //-------------------------------------------------
368 // cop_in_r -
369 //-------------------------------------------------
370
cop_in_r()371 uint8_t newbrain_state::cop_in_r()
372 {
373 /*
374
375 bit description
376
377 IN0 K8 (CD4076 Q2)
378 IN1 _RD
379 IN2 _COP
380 IN3 _WR
381
382 */
383
384 uint8_t data = 0xe;
385
386 // keyboard
387 data |= BIT(m_403_q, 2);
388
389 LOGMASKED(LOG_COP, "%s %s IN %01x\n", machine().time().as_string(), machine().describe_context(), data);
390
391 return data;
392 }
393
394
395 //-------------------------------------------------
396 // cop_g_r -
397 //-------------------------------------------------
398
cop_g_r()399 uint8_t newbrain_state::cop_g_r()
400 {
401 /*
402
403 bit description
404
405 G0
406 G1 K9 (CD4076 Q1)
407 G2 K7 (CD4076 Q0)
408 G3 K3 (CD4076 Q3)
409
410 */
411
412 uint8_t data = 0;
413
414 // keyboard
415 data |= BIT(m_403_q, 1) << 1;
416 data |= BIT(m_403_q, 0) << 2;
417 data |= BIT(m_403_q, 3) << 3;
418
419 LOGMASKED(LOG_COP, "%s %s G %01x\n", machine().time().as_string(), machine().describe_context(), data);
420
421 return data;
422 }
423
424
425 //-------------------------------------------------
426 // cop_g_w -
427 //-------------------------------------------------
428
429 // m_cop_g1 and m_cop_g3, when activated, have 20 zeros and a 1 in a continuous sequence.
430 // m_cop_k6 randomly alternates between 0 and 1, spending more time at 1.
431 // The outcome is the cassette is unreadable.
432 // Therefore the motors are left permanently on until the above issues can be fixed.
tm()433 void newbrain_state::tm()
434 {
435 // cassette_state tm1 = (!m_cop_g1 && !m_cop_k6) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED;
436 // cassette_state tm2 = (!m_cop_g3 && !m_cop_k6) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED;
437
438 // m_cassette1->change_state(tm1, CASSETTE_MASK_MOTOR);
439 // m_cassette2->change_state(tm2, CASSETTE_MASK_MOTOR);
440 }
441
cop_g_w(uint8_t data)442 void newbrain_state::cop_g_w(uint8_t data)
443 {
444 /*
445
446 bit description
447
448 G0 _COPINT
449 G1 _TM1
450 G2
451 G3 _TM2
452
453 */
454
455 int copint = !BIT(data, 0);
456
457 LOGMASKED(LOG_COP, "%s %s COPINT %u\n", machine().time().as_string(), machine().describe_context(), copint);
458
459 if (m_copint != copint)
460 {
461 m_copint = copint;
462 check_interrupt();
463 }
464
465 m_cop_g1 = BIT(data, 1);
466 m_cop_g3 = BIT(data, 3);
467 tm();
468 }
469
470
471 //-------------------------------------------------
472 // cop_d_w -
473 //-------------------------------------------------
474
cop_d_w(uint8_t data)475 void newbrain_state::cop_d_w(uint8_t data)
476 {
477 /*
478 bit description
479
480 D0 inverted to K4 -> CD4024 pin 2 (reset)
481 D1 TDO
482 D2 inverted to K6 -> CD4024 pin 1 (clock), CD4076 pin 7 (clock), inverted to DS8881 pin 3 (enable)
483 D3 not connected
484
485 */
486
487 int k4 = !BIT(data, 0);
488 int k6 = !BIT(data, 2);
489
490 LOGMASKED(LOG_COP, "%s %s K4 %u K6 %u\n", machine().time().as_string(), machine().describe_context(), k4, k6);
491
492 m_cop_tdo = BIT(data, 1);
493 m_cassette1->output(m_cop_tdo ? -1.0 : +1.0);
494 m_cassette2->output(m_cop_tdo ? -1.0 : +1.0);
495
496 if (k4) {
497 m_405_q = 0;
498
499 LOGMASKED(LOG_COP, "%s %s keylatch reset\n", machine().time().as_string(), machine().describe_context());
500 } else if (m_cop_k6 && !k6) {
501 m_405_q++;
502 m_405_q &= 0x7f;
503
504 LOGMASKED(LOG_COP, "%s %s keylatch %u\n", machine().time().as_string(), machine().describe_context(), m_405_q);
505 }
506
507 if (!m_cop_k6 && k6) {
508 m_403_d = m_y[m_405_q & 0x0f]->read() & 0x0f;
509
510 LOGMASKED(LOG_COP, "%s %s keydata %01x\n", machine().time().as_string(), machine().describe_context(), m_403_d);
511 }
512
513 if (k6) {
514 m_403_q = m_403_d;
515 } else {
516 m_403_q = 0xf;
517
518 LOGMASKED(LOG_COP, "%s %s keydata disabled\n", machine().time().as_string(), machine().describe_context());
519
520 // COP to VFD serial format, bits 15..0
521 // A B J I x H G2 C x F G1 E K L M D
522 uint16_t value = bitswap<16>(m_402_q, 11, 7, 1, 13, 10, 3, 2, 12, 9, 5, 6, 4, 0, 8, 14, 15) & 0x3fff;
523 m_digits[m_405_q & 0x0f] = value;
524
525 LOGMASKED(LOG_VFD, "%s %s vfd segment %u 402.Q %04x data %04x\n", machine().time().as_string(), machine().describe_context(), m_405_q & 0x0f, m_402_q, value);
526 }
527
528 m_cop_k6 = k6;
529 tm();
530 }
531
532
533 //-------------------------------------------------
534 // k1_w -
535 //-------------------------------------------------
536
WRITE_LINE_MEMBER(newbrain_state::k1_w)537 WRITE_LINE_MEMBER( newbrain_state::k1_w )
538 {
539 LOGMASKED(LOG_VFD, "%s %s SO %u\n", machine().time().as_string(), machine().describe_context(), state);
540
541 m_cop_so = state;
542 }
543
544
545 //-------------------------------------------------
546 // k2_w -
547 //-------------------------------------------------
548
WRITE_LINE_MEMBER(newbrain_state::k2_w)549 WRITE_LINE_MEMBER( newbrain_state::k2_w )
550 {
551 LOGMASKED(LOG_VFD, "%s %s SK %u\n", machine().time().as_string(), machine().describe_context(), state);
552
553 if (state)
554 {
555 m_402_q <<= 1;
556 m_402_q = (m_402_q & 0xfffe) | m_cop_so;
557 }
558 }
559
560
561 //-------------------------------------------------
562 // tdi_r -
563 //-------------------------------------------------
564
tpin()565 int newbrain_state::tpin()
566 {
567 return (m_cassette1->input() > +0.04) || (m_cassette2->input() > +0.04);
568 }
569
READ_LINE_MEMBER(newbrain_state::tdi_r)570 READ_LINE_MEMBER( newbrain_state::tdi_r )
571 {
572 return tpin() ^ m_cop_tdo;
573 }
574
575
576
577 //**************************************************************************
578 // ADDRESS MAPS
579 //**************************************************************************
580
581 //-------------------------------------------------
582 // ADDRESS_MAP( newbrain_mreq )
583 //-------------------------------------------------
584
newbrain_mreq(address_map & map)585 void newbrain_state::newbrain_mreq(address_map &map)
586 {
587 map.unmap_value_high();
588 map(0x0000, 0xffff).rw(FUNC(newbrain_state::mreq_r), FUNC(newbrain_state::mreq_w));
589 }
590
591
592 //-------------------------------------------------
593 // ADDRESS_MAP( newbrain_iorq )
594 //-------------------------------------------------
595
newbrain_iorq(address_map & map)596 void newbrain_state::newbrain_iorq(address_map &map)
597 {
598 map.unmap_value_high();
599 map(0x0000, 0xffff).rw(FUNC(newbrain_state::iorq_r), FUNC(newbrain_state::iorq_w));
600 }
601
602
603
604 //**************************************************************************
605 // INPUT PORTS
606 //**************************************************************************
607
608 //-------------------------------------------------
609 // INPUT_PORTS( newbrain )
610 //-------------------------------------------------
611
612 static INPUT_PORTS_START( newbrain )
613 PORT_START("Y0")
614 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_CODE(KEYCODE_ESC)615 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("STOP") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
616 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
617 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
618
619 PORT_START("Y1")
620 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
621 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
622 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
623 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
624
625 PORT_START("Y2")
626 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
627 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8')
628 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
629 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
630
631 PORT_START("Y3")
632 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
633 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9')
634 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
635 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
636
637 PORT_START("Y4")
638 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
639 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0')
640 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
641 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
642
643 PORT_START("Y5")
644 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
645 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('(') PORT_CHAR('[')
646 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
647 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
648
649 PORT_START("Y6")
650 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
651 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(')') PORT_CHAR(']')
652 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
653 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
654
655 PORT_START("Y7")
656 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
657 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("* \xC2\xA3") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('*') PORT_CHAR(0x00A3)
658 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
659 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
660
661 PORT_START("Y8")
662 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
663 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("VIDEO TEXT") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT)) // Vd
664 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
665 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
666
667 PORT_START("Y9")
668 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
669 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
670 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
671 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
672
673 PORT_START("Y10")
674 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
675 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('@')
676 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
677 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
678
679 PORT_START("Y11")
680 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
681 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('-') PORT_CHAR('\\')
682 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
683 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
684
685 PORT_START("Y12")
686 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
687 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('+') PORT_CHAR('^')
688 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
689 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("INSERT") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
690
691 PORT_START("Y13")
692 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
693 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("NEW LINE") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) // NL
694 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
695 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
696
697 PORT_START("Y14")
698 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
699 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
700 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
701 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("HOME") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME)) // CH
702
703 PORT_START("Y15")
704 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // SH
705 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("GRAPHICS") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) // GR
706 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("REPEAT") // RPT
707 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("CONTROL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) // GL
708 INPUT_PORTS_END
709
710
711
712 //**************************************************************************
713 // MACHINE INITIALIZATION
714 //**************************************************************************
715
716 int newbrain_state::get_reset_t()
717 {
718 return RES_K(220) * CAP_U(10) * 1000; // t = R128 * C125 = 2.2s
719 }
720
get_pwrup_t()721 int newbrain_state::get_pwrup_t()
722 {
723 return RES_K(560) * CAP_U(10) * 1000; // t = R129 * C127 = 5.6s
724 }
725
726
727 //-------------------------------------------------
728 // machine_start -
729 //-------------------------------------------------
730
machine_start()731 void newbrain_state::machine_start()
732 {
733 m_digits.resolve();
734
735 // set power up timer
736 timer_set(attotime::from_usec(get_pwrup_t()), TIMER_ID_PWRUP);
737
738 // state saving
739 save_item(NAME(m_clk));
740 save_item(NAME(m_tvp));
741 save_item(NAME(m_pwrup));
742 save_item(NAME(m_clkint));
743 save_item(NAME(m_copint));
744 save_item(NAME(m_cop_so));
745 save_item(NAME(m_cop_tdo));
746 save_item(NAME(m_cop_g1));
747 save_item(NAME(m_cop_g3));
748 save_item(NAME(m_cop_k6));
749 save_item(NAME(m_405_q));
750 save_item(NAME(m_403_q));
751 save_item(NAME(m_402_q));
752
753 // patch COP ROM to read VFD data
754 //memregion(COP420_TAG)->base()[0x20a] = 0xc6;
755 }
756
757
758 //-------------------------------------------------
759 // machine_reset -
760 //-------------------------------------------------
761
machine_reset()762 void newbrain_state::machine_reset()
763 {
764 m_maincpu->reset();
765 m_cop->reset();
766
767 m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
768 m_cop->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
769
770 enrg_w(0);
771
772 timer_set(attotime::from_usec(get_reset_t()), TIMER_ID_RESET);
773 }
774
775
776 //-------------------------------------------------
777 // device_timer - handler timer events
778 //-------------------------------------------------
779
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)780 void newbrain_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
781 {
782 switch (id)
783 {
784 case TIMER_ID_RESET:
785 LOG("%s %s RESET 1\n", machine().time().as_string(), machine().describe_context());
786
787 m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
788 m_cop->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
789 break;
790
791 case TIMER_ID_PWRUP:
792 LOG("%s %s PWRUP 1\n", machine().time().as_string(), machine().describe_context());
793
794 m_pwrup = 1;
795 break;
796
797 case TIMER_ID_CLKINT:
798 LOG("%s CLKINT\n", machine().time().as_string());
799
800 m_clkint = 0;
801 check_interrupt();
802 break;
803 }
804 }
805
806
807
808 //**************************************************************************
809 // MACHINE DRIVERS
810 //**************************************************************************
811
812 //-------------------------------------------------
813 // machine_config( newbrain )
814 //-------------------------------------------------
815
newbrain(machine_config & config)816 void newbrain_state::newbrain(machine_config &config)
817 {
818 // basic system hardware
819 Z80(config, m_maincpu, XTAL(16'000'000)/4);
820 m_maincpu->set_addrmap(AS_PROGRAM, &newbrain_state::newbrain_mreq);
821 m_maincpu->set_addrmap(AS_IO, &newbrain_state::newbrain_iorq);
822
823 COP420(config, m_cop, XTAL(16'000'000)/4);
824 m_cop->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, true);
825 m_cop->read_g().set(FUNC(newbrain_state::cop_g_r));
826 m_cop->write_g().set(FUNC(newbrain_state::cop_g_w));
827 m_cop->write_d().set(FUNC(newbrain_state::cop_d_w));
828 m_cop->read_in().set(FUNC(newbrain_state::cop_in_r));
829 m_cop->write_so().set(FUNC(newbrain_state::k1_w));
830 m_cop->write_sk().set(FUNC(newbrain_state::k2_w));
831 m_cop->read_si().set(FUNC(newbrain_state::tdi_r));
832
833 // video hardware
834 newbrain_video(config);
835
836 // devices
837 NEWBRAIN_EXPANSION_SLOT(config, m_exp, XTAL(16'000'000)/4, newbrain_expansion_cards, "eim");
838
839 SPEAKER(config, "mono").front_center();
840
841 CASSETTE(config, m_cassette1);
842 m_cassette1->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
843 m_cassette1->add_route(ALL_OUTPUTS, "mono", 0.05);
844
845 CASSETTE(config, m_cassette2);
846 m_cassette2->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
847 m_cassette2->add_route(ALL_OUTPUTS, "mono", 0.05);
848
849 RS232_PORT(config, RS232_V24_TAG, default_rs232_devices, nullptr);
850 RS232_PORT(config, RS232_PRN_TAG, default_rs232_devices, nullptr);
851
852 // internal ram
853 RAM(config, RAM_TAG).set_default_size("32K");
854 }
855
856
857 //-------------------------------------------------
858 // machine_config( newbrain_ad )
859 //-------------------------------------------------
860
newbrain_ad(machine_config & config)861 void newbrain_state::newbrain_ad(machine_config &config)
862 {
863 newbrain(config);
864 config.set_default_layout(layout_newbrain);
865 }
866
867
868 //-------------------------------------------------
869 // machine_config( newbrain_a )
870 //-------------------------------------------------
871
newbrain_a(machine_config & config)872 void newbrain_state::newbrain_a(machine_config &config)
873 {
874 newbrain(config);
875 config.set_default_layout(layout_newbraina);
876 }
877
878
879 //-------------------------------------------------
880 // machine_config( newbrain_md )
881 //-------------------------------------------------
882
newbrain_md(machine_config & config)883 void newbrain_state::newbrain_md(machine_config &config)
884 {
885 newbrain(config);
886 config.set_default_layout(layout_newbrain);
887 }
888
889
890
891 //**************************************************************************
892 // ROMS
893 //**************************************************************************
894
895 //-------------------------------------------------
896 // ROM( newbrain )
897 //-------------------------------------------------
898
899 ROM_START( newbrain )
900 ROM_REGION( 0x6000, Z80_TAG, 0 )
901 ROM_DEFAULT_BIOS( "rom20" )
902
903 ROM_SYSTEM_BIOS( 0, "issue1", "Issue 1 (v?)" )
904 ROMX_LOAD( "aben.ic6", 0x0000, 0x2000, CRC(308f1f72) SHA1(a6fd9945a3dca47636887da2125fde3f9b1d4e25), ROM_BIOS(0) )
905 ROMX_LOAD( "cd iss 1.ic7", 0x2000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(0) )
906 ROMX_LOAD( "ef iss 1.ic8", 0x4000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(0) )
907
908 ROM_SYSTEM_BIOS( 1, "issue2", "Issue 2 (v1.9)" )
909 ROMX_LOAD( "aben19.ic6", 0x0000, 0x2000, CRC(d0283eb1) SHA1(351d248e69a77fa552c2584049006911fb381ff0), ROM_BIOS(1) )
910 ROMX_LOAD( "cdi2.ic7", 0x2000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(1) )
911 ROMX_LOAD( "ef iss 1.ic8", 0x4000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(1) )
912
913 ROM_SYSTEM_BIOS( 2, "issue3", "Issue 3 (v1.91)" )
914 ROMX_LOAD( "aben191.ic6", 0x0000, 0x2000, CRC(b7be8d89) SHA1(cce8d0ae7aa40245907ea38b7956c62d039d45b7), ROM_BIOS(2) )
915 ROMX_LOAD( "cdi3.ic7", 0x2000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(2) )
916 ROMX_LOAD( "ef iss 1.ic8", 0x4000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6), ROM_BIOS(2) )
917
918 ROM_SYSTEM_BIOS( 3, "series2", "Series 2 (v?)" )
919 ROMX_LOAD( "abs2.ic6", 0x0000, 0x2000, CRC(9a042acb) SHA1(80d83a2ea3089504aa68b6cf978d80d296cd9bda), ROM_BIOS(3) )
920 ROMX_LOAD( "cds2.ic7", 0x2000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a), ROM_BIOS(3) )
921 ROMX_LOAD( "efs2.ic8", 0x4000, 0x2000, CRC(b222d798) SHA1(c0c816b4d4135b762f2c5f1b24209d0096f22e56), ROM_BIOS(3) )
922
923 ROM_SYSTEM_BIOS( 4, "rom20", "? (v2.0)" )
924 ROMX_LOAD( "aben20.rom", 0x0000, 0x2000, CRC(3d76d0c8) SHA1(753b4530a518ad832e4b81c4e5430355ba3f62e0), ROM_BIOS(4) )
925 ROMX_LOAD( "cd20tci.rom", 0x2000, 0x4000, CRC(f65b2350) SHA1(1ada7fbf207809537ec1ffb69808524300622ada), ROM_BIOS(4) )
926
927 ROM_REGION( 0x400, COP420_TAG, 0 )
928 ROM_LOAD( "cop420-guw.ic419", 0x000, 0x400, CRC(a1388ee7) SHA1(5822e16aa794545600bf7a9dbee2ef467ca2a3e0) ) // COP420-GUW/N
929
930 ROM_REGION( 0x1000, "chargen", 0 )
931 ROM_LOAD( "char eprom iss 1.ic453", 0x0000, 0x1000, CRC(6a38b7a2) SHA1(29f3e672fc41792ac2f2b405e571d79235193561) ) // 8248R7
932 ROM_END
933
934
935 //-------------------------------------------------
936 // ROM( newbraina )
937 //-------------------------------------------------
938
939 #define rom_newbraina rom_newbrain
940
941
942 //-------------------------------------------------
943 // ROM( newbrainmd )
944 //-------------------------------------------------
945
946 ROM_START( newbrainmd )
947 ROM_REGION( 0x10000, Z80_TAG, 0 )
948 ROM_LOAD( "cdmd.rom", 0x2000, 0x2000, CRC(6b4d9429) SHA1(ef688be4e75aced61f487c928258c8932a0ae00a) )
949 ROM_LOAD( "efmd.rom", 0x4000, 0x2000, CRC(20dd0b49) SHA1(74b517ca223cefb588e9f49e72ff2d4f1627efc6) )
950
951 ROM_REGION( 0x400, COP420_TAG, 0 )
952 ROM_LOAD( "cop420-guw.ic419", 0x000, 0x400, CRC(a1388ee7) SHA1(5822e16aa794545600bf7a9dbee2ef467ca2a3e0) ) // COP420-GUW/N
953
954 ROM_REGION( 0x1000, "chargen", 0 )
955 ROM_LOAD( "char eprom iss 1.ic453", 0x0000, 0x1000, CRC(6a38b7a2) SHA1(29f3e672fc41792ac2f2b405e571d79235193561) ) // 8248R7
956 ROM_END
957
958
959
960 //**************************************************************************
961 // SYSTEM DRIVERS
962 //**************************************************************************
963
964 // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
965 COMP( 1981, newbrain, 0, 0, newbrain_ad, newbrain, newbrain_state, empty_init, "Grundy Business Systems Ltd", "NewBrain AD", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND )
966 COMP( 1981, newbraina, newbrain, 0, newbrain_a, newbrain, newbrain_state, empty_init, "Grundy Business Systems Ltd", "NewBrain A", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND )
967 COMP( 1981, newbrainmd, newbrain, 0, newbrain_md, newbrain, newbrain_state, empty_init, "Grundy Business Systems Ltd", "NewBrain MD", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND )
968