1 // license:BSD-3-Clause
2 // copyright-holders:AJR
3 /***********************************************************************************************************************************
4
5 The Visual 500 and 550 are the graphical members of the third series of display terminals released by Visual Technology.
6 While they appear to use the same character generators as the text-mode-only Visual 300 and 330 and have similar detachable
7 keyboards, they uniquely feature high-definition green-screen (P39 phosphor) monitors and support Tektronix 4010/4014-
8 compatible graphics at a resolution of 768 x 555 pixels.
9
10 The VT100-compatible Visual 550 was released first, and conforms to the ANSI X3.64 standard (like the Visual 300).
11 The Visual 500 instead emulates the ADM3A, D200, Hazeltine 1500 and VT52 terminals (like the Visual 330).
12
13 ***********************************************************************************************************************************/
14
15 #include "emu.h"
16 //include "bus/rs232/rs232.h"
17 #include "cpu/z80/z80.h"
18 #include "machine/com8116.h"
19 #include "machine/input_merger.h"
20 #include "machine/nvram.h"
21 #include "machine/i8251.h"
22 #include "machine/i8255.h"
23 #include "machine/v102_kbd.h"
24 #include "machine/z80sio.h"
25 #include "video/scn2674.h"
26 #include "video/upd7220.h"
27 #include "screen.h"
28
29 class v550_state : public driver_device
30 {
31 public:
v550_state(const machine_config & mconfig,device_type type,const char * tag)32 v550_state(const machine_config &mconfig, device_type type, const char *tag)
33 : driver_device(mconfig, type, tag)
34 , m_maincpu(*this, "maincpu")
35 , m_screen(*this, "screen")
36 , m_chargen(*this, "chargen")
37 , m_usart(*this, "usart")
38 { }
39
40 void v550(machine_config &config);
41
42 private:
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)43 u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { return 0; }
44
45 void mem_map(address_map &map);
46 void io_map(address_map &map);
47 void pvtc_char_map(address_map &map);
48 void pvtc_attr_map(address_map &map);
49
50 virtual void machine_start() override;
51
52 required_device<cpu_device> m_maincpu;
53 required_device<screen_device> m_screen;
54 required_region_ptr<u8> m_chargen;
55 required_device<i8251_device> m_usart;
56 };
57
58
mem_map(address_map & map)59 void v550_state::mem_map(address_map &map)
60 {
61 map(0x0000, 0x7bff).rom().region("maincpu", 0);
62 map(0x7c00, 0x7fff).ram().share("nvram"); // actually 4 bits wide
63 map(0x8000, 0x87ff).ram();
64 }
65
io_map(address_map & map)66 void v550_state::io_map(address_map &map)
67 {
68 map.global_mask(0xff);
69 map(0x00, 0x01).rw("gdc", FUNC(upd7220_device::read), FUNC(upd7220_device::write));
70 map(0x10, 0x10).w("brg1", FUNC(com8116_device::stt_str_w));
71 map(0x20, 0x23).rw("ppi", FUNC(i8255_device::read), FUNC(i8255_device::write));
72 map(0x30, 0x31).rw(m_usart, FUNC(i8251_device::read), FUNC(i8251_device::write));
73 map(0x40, 0x40).rw("mpsc", FUNC(upd7201_device::da_r), FUNC(upd7201_device::da_w));
74 map(0x41, 0x41).rw("mpsc", FUNC(upd7201_device::ca_r), FUNC(upd7201_device::ca_w));
75 map(0x48, 0x48).rw("mpsc", FUNC(upd7201_device::db_r), FUNC(upd7201_device::db_w));
76 map(0x49, 0x49).rw("mpsc", FUNC(upd7201_device::cb_r), FUNC(upd7201_device::cb_w));
77 map(0x50, 0x50).w("brg2", FUNC(com8116_device::stt_str_w));
78 map(0x60, 0x67).rw("pvtc", FUNC(scn2672_device::read), FUNC(scn2672_device::write));
79 map(0x70, 0x70).rw("pvtc", FUNC(scn2672_device::buffer_r), FUNC(scn2672_device::buffer_w));
80 map(0x71, 0x71).rw("pvtc", FUNC(scn2672_device::attr_buffer_r), FUNC(scn2672_device::attr_buffer_w));
81 }
82
pvtc_char_map(address_map & map)83 void v550_state::pvtc_char_map(address_map &map)
84 {
85 map(0x0000, 0x0fff).ram();
86 }
87
pvtc_attr_map(address_map & map)88 void v550_state::pvtc_attr_map(address_map &map)
89 {
90 map(0x0000, 0x0fff).ram();
91 }
92
93
INPUT_PORTS_START(v550)94 INPUT_PORTS_START(v550)
95 INPUT_PORTS_END
96
97
98 void v550_state::machine_start()
99 {
100 m_usart->write_cts(0);
101 }
102
v550(machine_config & config)103 void v550_state::v550(machine_config &config)
104 {
105 Z80(config, m_maincpu, 34.846_MHz_XTAL / 16); // NEC D780C (2.177875 MHz verified)
106 m_maincpu->set_addrmap(AS_PROGRAM, &v550_state::mem_map);
107 m_maincpu->set_addrmap(AS_IO, &v550_state::io_map);
108
109 NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // NEC D444C-2 + battery
110
111 upd7220_device &gdc(UPD7220(config, "gdc", 34.846_MHz_XTAL / 16)); // NEC D7220D (2.177875 MHz verified)
112 gdc.set_screen("screen");
113
114 I8255(config, "ppi"); // NEC D8255AC-5
115
116 I8251(config, m_usart, 34.846_MHz_XTAL / 16); // NEC D8251AC
117 m_usart->txd_handler().set("keyboard", FUNC(v550_keyboard_device::write_rxd));
118 m_usart->rxrdy_handler().set("mainint", FUNC(input_merger_device::in_w<1>));
119
120 upd7201_device& mpsc(UPD7201(config, "mpsc", 34.846_MHz_XTAL / 16)); // NEC D7201C
121 mpsc.out_int_callback().set("mainint", FUNC(input_merger_device::in_w<0>));
122
123 INPUT_MERGER_ANY_HIGH(config, "mainint").output_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
124
125 com8116_device &brg1(COM8116_020(config, "brg1", 1.8432_MHz_XTAL)); // SMC COM8116T-020
126 brg1.ft_handler().set("mpsc", FUNC(upd7201_device::txcb_w));
127 brg1.ft_handler().append("mpsc", FUNC(upd7201_device::rxcb_w));
128 brg1.fr_handler().set("usart", FUNC(i8251_device::write_txc));
129 brg1.fr_handler().append("usart", FUNC(i8251_device::write_rxc));
130
131 com8116_device &brg2(COM8116_020(config, "brg2", 1.8432_MHz_XTAL)); // SMC COM8116T-020
132 brg2.ft_handler().set("mpsc", FUNC(upd7201_device::txca_w));
133 brg2.fr_handler().set("mpsc", FUNC(upd7201_device::rxca_w));
134
135 v550_keyboard_device &keyboard(V550_KEYBOARD(config, "keyboard"));
136 keyboard.txd_callback().set(m_usart, FUNC(i8251_device::write_rxd));
137
138 SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
139 m_screen->set_raw(34.846_MHz_XTAL, 19 * 102, 0, 19 * 80, 295, 0, 272);
140 m_screen->set_screen_update(FUNC(v550_state::screen_update));
141
142 scn2672_device &pvtc(SCN2672(config, "pvtc", 34.846_MHz_XTAL / 19));
143 pvtc.set_addrmap(0, &v550_state::pvtc_char_map);
144 pvtc.set_addrmap(1, &v550_state::pvtc_attr_map);
145 pvtc.set_character_width(19);
146 pvtc.intr_callback().set_inputline(m_maincpu, INPUT_LINE_NMI);
147 pvtc.set_screen("screen");
148 // SCB2673 clock verified at 17.423 MHz
149 }
150
151
152 ROM_START( v550 )
153 // Silkscreened on bottom left of PCB: "PA016-A REV B"
154
155 ROM_REGION(0x8000, "maincpu", 0)
156 ROM_LOAD("e244-001_r07_u42.bin", 0x0000, 0x2000, CRC(d18a8b62) SHA1(7faf8a9f1ae3148adacbff960a2663793710cef2))
157 ROM_LOAD("e244-002_r07_u43.bin", 0x2000, 0x2000, CRC(1b62db47) SHA1(7ad69aea6088545d843c2e95737895f81c269ccc))
158 ROM_LOAD("e244-003_r07_u44.bin", 0x4000, 0x2000, CRC(f6d6f734) SHA1(a9efa8ebe86addb77872dbe9863ea7f75b33a2b9))
159 ROM_LOAD("e244-017_r07_u45.bin", 0x6000, 0x2000, CRC(b0dcd535) SHA1(9237723d01a720217f50f756bb55c7e5ed05a594))
160
161 ROM_REGION(0x1000, "chargen", 0)
162 ROM_LOAD("e242-085_r03_u97.bin", 0x0000, 0x1000, CRC(8a491cee) SHA1(d8a9546a7dd2ffc0a5e54524ee16068dde56975c))
163 ROM_END
164
165 COMP( 1982, v550, 0, 0, v550, v550, v550_state, empty_init, "Visual Technology", "Visual 550", MACHINE_IS_SKELETON )
166