1 // license:BSD-3-Clause
2 // copyright-holders:Jonathan Gevaryahu
3 /***************************************************************************
4
5 DEC VK100 'GIGI'
6
7 12/05/2009 Skeleton driver.
8 28/07/2009 added Guru-readme(TM)
9 08/01/2012 Fleshed out driver.
10
11 Todo:
12 * fix vector generator hardware enough to pass the startup self test
13 the tests are described on page 6-5 thru 6-8 of the tech reference
14 * hook up the bresenham DU/DVM/ERR stuff, currently only simple directional vectors work
15 * hook up the vector and sync proms to the sync counter
16 * figure out how the erase prom actually works at a hardware level
17 * redump the vector prom, the first two bytes look bad
18 * figure out the correct meaning of systat b register - needed for communications selftest
19 * hook up smc com5016t baud generator to i8251 rx and tx clocks - begun
20
21 Notes:
22 The directions for the DIR value are arranged, starting from the *
23 as the vector origin:
24 3 2 1
25 \ | /
26 \|/
27 4--*--0
28 /|\
29 / | \
30 5 6 7
31
32 The X and Y counters are techincally 12 bits long each, though
33 only the low 9 and 10 bits respectively are used for ram addressing.
34 The MSB bit of each counter does have a special purpose with
35 regards to the RAS/ERASE prom though, perhaps to detect an
36 underflow 000->FFF
37
38 Tony DiCenzo, now the director of standards and architecture at Oracle, was on the team that developed the VK100
39 see http://startup.nmnaturalhistory.org/visitorstories/view.php?ii=79
40 Robert "Bob" C. Quinn was definitely lead engineer on the VT125
41 Robert "Bob" T. Collins was the lead engineer on the VK100
42 Pedro Ortiz (https://www.linkedin.com/pub/pedro-ortiz/16/68b/196) did the drafting for the enclosure and case
43
44 The prototype name for the VK100 was 'SMAKY' (Smart Keyboard)
45
46 ****************************************************************************/
47 /*
48 DEC VK100
49 DEC, 1982
50
51 This is a VK100 terminal, otherwise known as a DEC Gigi graphics terminal.
52 There's a technical manual dated 1982 here:
53 http://web.archive.org/web/20091015205827/http://www.computer.museum.uq.edu.au/pdf/EK-VK100-TM-001%20VK100%20Technical%20Manual.pdf
54 Installation and owner's manual is at:
55 http://www.bitsavers.org/pdf/dec/terminal/gigi/EK-VK100-IN-002_GIGI_Terminal_Installation_and_Owners_Manual_Apr81.pdf
56 An enormous amount of useful info can be derived from the VT125 technical manual:
57 http://www.bitsavers.org/pdf/dec/terminal/vt100/EK-VT100-TM-003_VT100_Technical_Manual_Jul82.pdf starting on page 6-70, pdf page 316
58 And its schematics:
59 http://bitsavers.org/pdf/dec/terminal/vt125/MP01053_VT125_Mar82.pdf
60
61 PCB Layout
62 ----------
63
64 VK100 LOGICBOARD
65 |-------| |---------| |---------| |-| |-| |-| |-|
66 |---|-20 mA-|----|---EIA---|--|HARD-COPY|----|B|-|G|-|R|--|-|--DSW(8)--|
67 | BW |
68 | POWER |
69 | PR2 |
70 | HD46505SP 4116 4116 4116 4116 |
71 | |
72 | 4116 4116 4116 4116 |
73 | PR5 INTEL ROM1 |
74 | PR1 PR6 P8251A 4116 4116 4116 4116 |
75 | 45.6192MHz ROM2 PR3 |
76 | 4116 4116 4116 4116 |
77 | 4116 4116 4116 INTEL ROM3 |
78 | D8202A |
79 | 4116 4116 4116 5.0688MHz ROM4 PR4 |
80 | |
81 | 4116 4116 INTEL SMC_5016T PIEZO |
82 | D8085A IDC40 LM556 75452 |
83 |----------------------------------------------------------------------|
84 Notes:
85 ROM1 - TP-01 (C) DEC 23-031E4-00 (M) SCM91276L 8114
86 ROM2 - TP-01 (C) DEC 1980 23-017E4-00 MOSTEK MK36444N 8116
87 ROM3 - TP-01 (C) MICROSOFT 1979 23-018E4-00 MOSTEK MK36445N 8113
88 ROM4 - TP-01 (C) DEC 1980 23-190E2-00 P8316E AMD 35517 8117DPP
89
90 LED meanings:
91 The LEDS on the vk100 (there are 7) are set up above the keyboard as:
92 Label: ON LINE LOCAL NO SCROLL BASIC HARD-COPY L1 L2
93 Bit: !d5 d5 !d4 !d3 !d2 !d1 !d0 (of port 0x68)
94 according to manual from http://www.bitsavers.org/pdf/dec/terminal/gigi/EK-VK100-IN-002_GIGI_Terminal_Installation_and_Owners_Manual_Apr81.pdf
95 where X = on, 0 = off, ? = variable (- = off)
96 - X 0 0 0 0 0 (0x1F) = Microprocessor error
97 X - 0 X X X X (0x30) "
98
99 - X 0 0 0 0 X (0x1E) = ROM error
100 X - 0 0 ? ? ? (0x3x) "
101 1E 3F = rom error, rom 1 (0000-0fff)
102 1E 3E = rom error, rom 1 (1000-1fff)
103 1E 3D = rom error, rom 2 (2000-2fff)
104 1E 3C = rom error, rom 2 (3000-3fff)
105 1E 3B = rom error, rom 3 (4000-4fff)
106 1E 3A = rom error, rom 3 (5000-5fff)
107 1E 39 = rom error, rom 4 (6000-6fff)
108
109 - X 0 0 0 X 0 (0x1D) = RAM error
110 X - 0 ? ? ? ? (0x3x) "
111
112 - X 0 0 0 X X (0x1C) = CRT Controller error
113 X - 0 X X X X (0x30) "
114 This test writes 0xF to port 00 (crtc address reg) and writes a pattern to it
115 via port 01 (crtc data reg) then reads it back and checks to be sure the data
116 matches.
117
118 - X 0 0 X 0 0 (0x1B) = CRT Controller time-out
119 X - 0 X X X X (0x30) "
120 This test writes 00 to all the crtc registers and checks to be sure an rst7.5
121 (vblank) interrupt fires on the 8085 within a certain time period.
122
123 - X 0 0 X 0 X (0x1A) = Vector time-out error
124 X - 0 X X X X (0x30) "
125 Not sure exactly what this tests, likely tries firing the vector generator
126 state machine and sees if the GO bit ever finishes and goes back to 0
127 */
128 #include "emu.h"
129
130 #include "bus/rs232/rs232.h"
131 #include "cpu/i8085/i8085.h"
132 #include "sound/beep.h"
133 #include "video/mc6845.h"
134 #include "machine/com8116.h"
135 #include "machine/i8251.h"
136
137 #include "screen.h"
138 #include "speaker.h"
139
140 #include "vk100.lh"
141
142
143 // named timer IDs
144 #define TID_I8251_RX 1
145 #define TID_I8251_TX 2
146 #define TID_SYNC 3
147
148 // show messages related to writes to the 0x4x VG registers
149 #undef VG40_VERBOSE
150 // show messages related to writes to the 0x6x VG registers
151 #undef VG60_VERBOSE
152 // show messages related to LED/beeper writes
153 #undef LED_VERBOSE
154 // show messages related to KYBD writes
155 #undef KBD_VERBOSE
156 // debug the pattern reg
157 #undef PAT_DEBUG
158 // show reads from the two systat registers
159 #undef SYSTAT_A_VERBOSE
160 #undef SYSTAT_B_VERBOSE
161
162 // debug state dump for the vector generator
163 #undef DEBUG_VG_STATE
164
165 #define RS232_TAG "rs232"
166 #define COM5016T_TAG "com5016t"
167
168 class vk100_state : public driver_device
169 {
170 public:
vk100_state(const machine_config & mconfig,device_type type,const char * tag)171 vk100_state(const machine_config &mconfig, device_type type, const char *tag) :
172 driver_device(mconfig, type, tag),
173 m_maincpu(*this, "maincpu"),
174 m_crtc(*this, "crtc"),
175 m_speaker(*this, "beeper"),
176 m_uart(*this, "i8251"),
177 //m_i8251_rx_timer(nullptr),
178 //m_i8251_tx_timer(nullptr),
179 //m_sync_timer(nullptr),
180
181 m_capsshift(*this, "CAPSSHIFT"),
182 m_dipsw(*this, "SWITCHES"),
183 m_online_led(*this, "online_led"),
184 m_local_led(*this, "local_led"),
185 m_noscroll_led(*this, "noscroll_led"),
186 m_basic_led(*this, "basic_led"),
187 m_hardcopy_led(*this, "hardcopy_led"),
188 m_l1_led(*this, "l1_led"),
189 m_l2_led(*this, "l2_led")
190 {
191 }
192
193 void vk100(machine_config &config);
194
195 void init_vk100();
196
197 private:
198 enum
199 {
200 TIMER_EXECUTE_VG
201 };
202
203 required_device<cpu_device> m_maincpu;
204 required_device<mc6845_device> m_crtc;
205 required_device<beep_device> m_speaker;
206 required_device<i8251_device> m_uart;
207 //required_device<> m_i8251_rx_timer;
208 //required_device<> m_i8251_tx_timer;
209 //required_device<> m_sync_timer;
210
211 required_ioport m_capsshift;
212 required_ioport m_dipsw;
213
214 output_finder<> m_online_led;
215 output_finder<> m_local_led;
216 output_finder<> m_noscroll_led;
217 output_finder<> m_basic_led;
218 output_finder<> m_hardcopy_led;
219 output_finder<> m_l1_led;
220 output_finder<> m_l2_led;
221
222 uint8_t* m_vram;
223 uint8_t* m_trans;
224 uint8_t* m_pattern;
225 uint8_t* m_dir;
226 uint8_t* m_sync;
227 uint8_t* m_vector;
228 uint8_t* m_ras_erase;
229 uint8_t m_dir_a6; // latched a6 of dir rom
230 uint8_t m_cout; // carry out from vgERR adder
231 uint8_t m_vsync; // vsync pin of crtc
232 uint16_t m_vgX; // 12 bit X value for vector draw position
233 uint16_t m_vgY; // 12 bit Y value for vector draw position
234 uint16_t m_vgERR; // error register can cause carries which need to be caught
235 uint8_t m_vgSOPS;
236 uint8_t m_vgPAT;
237 uint16_t m_vgPAT_Mask; // current mask for PAT
238 uint8_t m_vgPMUL; // reload value for PMUL_Count
239 uint8_t m_vgPMUL_Count;
240 uint8_t m_vgDownCount; // down counter = number of pixels, loaded from vgDU on execute
241 #define VG_DU m_vgRegFile[0]
242 #define VG_DVM m_vgRegFile[1]
243 #define VG_DIR m_vgRegFile[2]
244 #define VG_WOPS m_vgRegFile[3]
245 uint8_t m_vgRegFile[4];
246 uint8_t m_VG_MODE; // 2 bits, latched on EXEC
247 uint8_t m_vgGO; // activated on next SYNC pulse after EXEC
248 uint8_t m_ACTS;
249 uint8_t m_ADSR;
250 ioport_port* m_col_array[16];
251
252 void vgLD_X(offs_t offset, uint8_t data);
253 void vgLD_Y(offs_t offset, uint8_t data);
254 void vgERR(uint8_t data);
255 void vgSOPS(uint8_t data);
256 void vgPAT(uint8_t data);
257 void vgPMUL(uint8_t data);
258 void vgREG(offs_t offset, uint8_t data);
259 void vgEX(offs_t offset, uint8_t data);
260 void KBDW(uint8_t data);
261 uint8_t vk100_keyboard_column_r(offs_t offset);
262 uint8_t SYSTAT_A(offs_t offset);
263 uint8_t SYSTAT_B();
264
265 virtual void machine_start() override;
266 virtual void video_start() override;
267 TIMER_CALLBACK_MEMBER(execute_vg);
268 DECLARE_WRITE_LINE_MEMBER(crtc_vsync);
269 DECLARE_WRITE_LINE_MEMBER(i8251_rxrdy_int);
270 DECLARE_WRITE_LINE_MEMBER(i8251_txrdy_int);
271 DECLARE_WRITE_LINE_MEMBER(i8251_rts);
272 uint8_t vram_read();
273 uint8_t vram_attr_read();
274 MC6845_UPDATE_ROW(crtc_update_row);
275 void vram_write(uint8_t data);
276
277 void vk100_io(address_map &map);
278 void vk100_mem(address_map &map);
279
280 virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
281 };
282
283 // vram access functions:
284 /* figure out vram address based on tech manual page 5-24:
285 * real address to 16-bit chunk a13 a12 | a11 a10 a9 a8 | a7 a6 a5 a4 | a3 a2 a1 a0
286 * X+Y input Y8 Y7 | Y6 Y5 Y4 Y3 | Y2 Y1 X9' X8'| X7' X6' X5' X4'
287 * X3' and X2' choose a 4-bit block, X1 and X0 choose a bit within that.
288 * Figure out the ram address in address space "vram" based on this:
289 * vram is 0x8000 long (0x4000 16-bit blocks in sequence)
290 * so:
291 * vram: a14 a13 a12 | a11 a10 a9 a8 | a7 a6 a5 a4 | a3 a2 a1 a0
292 * vg: Y8 Y7 Y6 | Y5 Y4 Y3 Y2 | Y1 X9' X8' X7'| X6' X5' X4'(x3') x2' x1 x0
293 * X3' is handled by the nybbleNum statement, as is X2'
294 * X1 and X0 are handled by the pattern rom directly:
295 * x0 -> a0, x1 -> a1
296 * this handles bits like:
297 * x1 x0
298 * 0 0 -> bit 0
299 * 0 1 -> bit 1
300 * 1 0 -> bit 2
301 * 1 1 -> bit 3
302 */
303
304 // returns one nybble from vram array based on X and Y regs
vram_read()305 uint8_t vk100_state::vram_read()
306 {
307 // XFinal is (X'&0x3FC)|(X&0x3)
308 uint16_t XFinal = m_trans[(m_vgX&0x3FC)>>2]<<2|(m_vgX&0x3); // appears correct
309 // EA is the effective ram address for a 16-bit block
310 uint16_t EA = ((m_vgY&0x1FE)<<5)|(XFinal>>4); // appears correct
311 // block is the 16 bit block directly (note EA has to be <<1 to correctly index a byte)
312 uint16_t block = m_vram[(EA<<1)+1] | (m_vram[(EA<<1)]<<8);
313 // nybbleNum is which of the four nybbles within the block to address. should NEVER be 3!
314 uint8_t nybbleNum = (XFinal&0xC)>>2;
315 return (block>>(4*nybbleNum))&0xF;
316 }
317
318 // returns the attribute nybble for the current pixel based on X and Y regs
vram_attr_read()319 uint8_t vk100_state::vram_attr_read()
320 {
321 // XFinal is (X'&0x3FC)|(X&0x3)
322 uint16_t XFinal = m_trans[(m_vgX&0x3FC)>>2]<<2|(m_vgX&0x3); // appears correct
323 // EA is the effective ram address for a 16-bit block
324 uint16_t EA = ((m_vgY&0x1FE)<<5)|(XFinal>>4); // appears correct
325 // block is the 16 bit block directly (note EA has to be <<1 to correctly index a byte)
326 uint16_t block = m_vram[(EA<<1)+1] | (m_vram[(EA<<1)]<<8);
327 // nybbleNum is the attribute nybble, which in this case is always 3
328 uint8_t nybbleNum = 3;
329 return (block>>(4*nybbleNum))&0xF;
330 }
331
332 // writes one nybble to vram array based on X and Y regs, and updates the attrib ram if needed
vram_write(uint8_t data)333 void vk100_state::vram_write(uint8_t data)
334 {
335 // XFinal is (X'&0x3FC)|(X&0x3)
336 uint16_t XFinal = m_trans[(m_vgX&0x3FC)>>2]<<2|(m_vgX&0x3); // appears correct
337 // EA is the effective ram address for a 16-bit block
338 uint16_t EA = ((m_vgY&0x1FE)<<5)|(XFinal>>4); // appears correct
339 // block is the 16 bit block directly (note EA has to be <<1 to correctly index a byte)
340 uint16_t block = m_vram[(EA<<1)+1] | (m_vram[(EA<<1)]<<8);
341 // nybbleNum is which of the four nybbles within the block to address. should NEVER be 3!
342 uint8_t nybbleNum = (XFinal&0xC)>>2;
343 block &= ~((uint16_t)0xF<<(nybbleNum*4)); // mask out the part we want to replace
344 block |= data<<(nybbleNum*4); // write the new part
345 // NOTE: this next part may have to be made conditional on VG_MODE
346 // check if the attribute nybble is supposed to be modified, and if so do so
347 if (VG_WOPS&0x08) block = (block&0x0FFF)|(((uint16_t)VG_WOPS&0xF0)<<8);
348 m_vram[(EA<<1)+1] = block&0xFF; // write block back to vram
349 m_vram[(EA<<1)] = (block&0xFF00)>>8; // ''
350 }
351
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)352 void vk100_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
353 {
354 switch (id)
355 {
356 case TIMER_EXECUTE_VG:
357 execute_vg(ptr, param);
358 break;
359 default:
360 throw emu_fatalerror("Unknown id in vk100_state::device_timer");
361 }
362 }
363
364 /* this is the "DIRECTION ROM" == mb6309 (256x8, 82s135)
365 * see figure 5-24 on page 5-39
366 * It tells the direction and enable for counting on the X and Y counters
367 * and also handles the non-math related parts of the bresenham line algorithm
368 * control bits:
369 * /CE1 ----- DCOUNT 0 H [verified via tracing]
370 * /CE2 ----- ENA ERROR L [verified via tracing]
371 * addr bits: 76543210
372 * ||||\\\\-- DIR (vgDIR register low 4 bits)
373 * |||\------ C OUT aka ERROR CARRY (strobed in by STROBE L from the error counter's adder) [verified via tracing]
374 * ||\------- Y0 (the otherwise unused lsb of the Y register, used for bresenham) [verified via tracing]
375 * |\-------- feedback bit from d5 strobed by V CLK [verified via tracing]
376 * \--------- GND; the second half of the prom is blank (0x00)
377 * data bits: 76543210
378 * |||||||\-- ENA Y (enables change on Y counter)
379 * ||||||\--- ENA X (enables change on X counter)
380 * |||||\---- Y DIRECTION (high is count down, low is count up)
381 * ||||\----- X DIRECTION (high is count down, low is count up)
382 * |||\------ PIXEL WRT
383 * ||\------- feedback bit to a6, this bit is held in PRESET/1 condition by GO being inactive, and if the vector prom is disabled it is pulled to 1 [verified via tracing and schematics]
384 * |\-------- UNUSED, always 0
385 * \--------- UNUSED, always 0
386 * The VT125 prom @ E41 is literally identical to this, the same exact part: 23-059B1
387 */
TIMER_CALLBACK_MEMBER(vk100_state::execute_vg)388 TIMER_CALLBACK_MEMBER(vk100_state::execute_vg)
389 {
390 m_cout = 1; // hack for now
391 uint8_t dirbyte = m_dir[(m_dir_a6<<6)|((m_vgY&1)<<5)|(m_cout<<4)|VG_DIR];
392 #ifdef DEBUG_VG_STATE
393 static const char *const vg_functions[] = { "Move", "Dot", "Vector", "Erase" };
394 fprintf(stderr, "VGMODE: %s; DIR: A:%02x; D:%02x; X: %03X; Y: %03X; DownCount: %02X\n", vg_functions[m_VG_MODE], ((m_dir_a6<<6)|((m_vgY&1)<<5)|(m_cout<<4)|VG_DIR), dirbyte, m_vgX, m_vgY, m_vgDownCount);
395 #endif
396 m_dir_a6 = m_vgGO?((dirbyte&0x20)>>5):1;
397 if (dirbyte&2) // ena_x is active
398 {
399 if (dirbyte&0x80) m_vgX--;
400 else m_vgX++;
401 }
402 if (dirbyte&1) // ena_y is active
403 {
404 if (dirbyte&0x40) m_vgY--;
405 else m_vgY++;
406 }
407 if (dirbyte&0x10) m_vgDownCount--; // decrement the down counter
408 uint8_t thisNyb = vram_read(); // read in the nybble
409 // pattern rom addressing is a complex mess. see the pattern rom def later in this file.
410 uint8_t newNyb = m_pattern[((m_vgPAT&m_vgPAT_Mask)?0x200:0)|((VG_WOPS&7)<<6)|((m_vgX&3)<<4)|thisNyb]; // calculate new nybble based on pattern rom
411 // finally write the block back to ram depending on the VG_MODE (sort of a hack until we get the vector and sync and dir roms all hooked up)
412 // but only do it if the direction rom said so!
413 switch (m_VG_MODE)
414 {
415 case 0: // move; adjusts the x and y but doesn't write anything. do nothing
416 break;
417 case 1: // dot: only write the LAST pixel in the chain? TODO: some fallthrough magic here?
418 if ((m_vgDownCount) == 0x00)
419 {
420 if (dirbyte&0x10) vram_write(newNyb); // write out the modified nybble
421 }
422 break;
423 case 2: // vec: draw the vector
424 if (dirbyte&0x10) vram_write(newNyb); // write out the modified nybble
425 break;
426 case 3: // er: erase: special case here: wipe the entire screen (except for color/attrib?) and then set done.
427 for (int i = 0; i < 0x8000; i++)
428 {
429 if (!(i&1)) // avoid stomping attribute
430 m_vram[i] = m_vram[i]&0xF0;
431 else // (i&1)
432 m_vram[i] = 0;
433 }
434 m_vgGO = 0; // done
435 break;
436 }
437 if ((m_vgDownCount) == 0x00) m_vgGO = 0; // check if the down counter hit terminal count (0), if so we're done.
438 if (((++m_vgPMUL_Count)&0xF)==0) // if pattern multiplier counter overflowed
439 {
440 m_vgPMUL_Count = m_vgPMUL; // reload counter
441 m_vgPAT_Mask >>= 1; // shift the mask
442 if (m_vgPAT_Mask == 0) m_vgPAT_Mask = 0x80; // reset mask if it hits 0
443 }
444 if (m_vgGO) timer_set(attotime::from_hz(XTAL(45'619'200)/3/12/2), TIMER_EXECUTE_VG); // /3/12/2 is correct. the sync counter is clocked by the dot clock, despite the error on figure 5-21
445 }
446
447 /* ports 0x40 and 0x41: load low and high bytes of vector gen X register */
vgLD_X(offs_t offset,uint8_t data)448 void vk100_state::vgLD_X(offs_t offset, uint8_t data)
449 {
450 m_vgX &= 0xFF << ((1-offset)*8);
451 m_vgX |= ((uint16_t)data) << (offset*8);
452 #ifdef VG40_VERBOSE
453 logerror("VG: 0x%02X: X Reg loaded with %04X, new X value is %04X\n", 0x40+offset, ((uint16_t)data) << (offset*8), m_vgX);
454 #endif
455 }
456
457 /* ports 0x42 and 0x43: load low and high bytes of vector gen Y register */
vgLD_Y(offs_t offset,uint8_t data)458 void vk100_state::vgLD_Y(offs_t offset, uint8_t data)
459 {
460 m_vgY &= 0xFF << ((1-offset)*8);
461 m_vgY |= ((uint16_t)data) << (offset*8);
462 #ifdef VG40_VERBOSE
463 logerror("VG: 0x%02X: Y Reg loaded with %04X, new Y value is %04X\n", 0x42+offset, ((uint16_t)data) << (offset*8), m_vgY);
464 #endif
465 }
466
467 /* port 0x44: "ERR" load bresenham line algorithm 'error' count */
vgERR(uint8_t data)468 void vk100_state::vgERR(uint8_t data)
469 {
470 m_vgERR = data;
471 #ifdef VG40_VERBOSE
472 logerror("VG: 0x44: ERR Reg loaded with %02X\n", m_vgERR);
473 #endif
474 }
475
476 /* port 0x45: "SOPS" screen options
477 * (handled by 74LS273 @ E55, schematic sheet 10, all signals called 'VVG1 BDx' where x is 7 to 0)
478 * Blink --Background color-- Blink Serial Serial Reverse
479 * Enable Green Red Blue Control SL1 SL0 BG/FG
480 * d7 d6 d5 d4 d3 d2 d1 d0
481 * apparently, SLx: 00 = rs232/eia(J6), 01 = 20ma(J1), 10 = hardcopy(J7), 11 = test/loopback
482 * Serial Select (SLx) routing controls are rather complex, shown on schematic
483 * page 9:
484 * VDC2 | I8251 pins | SYSTAT_B bits
485 * SL1 SL0 | 8251RXD 8251RTS 8251TXD 8251/DTR 8251/DSR 8251CTS | SYSTATB_ACTS SYSTATB_ADSR
486 * 0 0 J6 /RXD J6 /RTS J6 TXD J6 /DTR J7 URTS GND J6 /CTS J6 /DSR
487 * 0 1 J1 +-R ACTS(loop) J1 +-T J6 /DTR J7 URTS GND 8251RTS(loop) J6 /DSR
488 * 1 0 J7 DRXD J7 DRTS* J7 DTXD J6 /DTR J7 URTS GND J7 /DCTS J6 /DSR
489 * 1 1 8251TXD ACTS(loop) 8251RXD J6 /DTR J7 URTS GND 8251RTS(loop) J6 /DSR
490 * * and UCTS, the pin drives both pins on J7
491 */
vgSOPS(uint8_t data)492 void vk100_state::vgSOPS(uint8_t data)
493 {
494 m_vgSOPS = data;
495 #ifdef VG40_VERBOSE
496 static const char *const serialDest[4] = { "EIA232", "20ma", "Hardcopy", "Loopback/test" };
497 logerror("VG: 0x45: SOPS Reg loaded with %02X: Background KGRB: %d%d%d%d, Blink: %d, Serial select: %s, Reverse BG/FG: %d\n", m_vgSOPS, (m_vgSOPS>>7)&1, (m_vgSOPS>>6)&1, (m_vgSOPS>>5)&1, (m_vgSOPS>>4)&1, (m_vgSOPS>>3)&1, serialDest[(m_vgSOPS>>1)&3], m_vgSOPS&1);
498 #endif
499 }
500
501 /* port 0x46: "PAT" load vg Pattern register */
vgPAT(uint8_t data)502 void vk100_state::vgPAT(uint8_t data)
503 {
504 m_vgPAT = data;
505 #ifdef PAT_DEBUG
506 for (int i = 7; i >= 0; i--)
507 {
508 printf("%s", (data&(1<<i))?"X":".");
509 }
510 printf("\n");
511 #endif
512 #ifdef VG40_VERBOSE
513 logerror("VG: 0x46: PAT Reg loaded with %02X\n", m_vgPAT);
514 #endif
515 }
516
517 /* port 0x47: "PMUL" load vg Pattern Multiply Register
518 The pattern multiply register loads a counter which counts reads from
519 the pattern register and increments on each one. if it overflows from
520 1111 to 0000 the pattern register is shifted right one bit and the
521 counter is reloaded from PMUL */
vgPMUL(uint8_t data)522 void vk100_state::vgPMUL(uint8_t data)
523 {
524 m_vgPMUL = data;
525 #ifdef VG40_VERBOSE
526 logerror("VG: 0x47: PMUL Reg loaded with %02X\n", m_vgPMUL);
527 #endif
528 }
529
530 /* port 0x60: "DU" load vg vector major register */
531 /* port 0x61: "DVM" load vg vector minor register */
532 /* port 0x62: "DIR" load vg Direction register */
533 /* port 0x63: "WOPS" vector 'pixel' write options
534 * --Attributes to change -- Enable -- Functions --
535 * Blink Green Red Blue Attrib F1 F0 FN
536 * Change
537 * d7 d6 d5 d4 d3 d2 d1 d0
538 */
vgREG(offs_t offset,uint8_t data)539 void vk100_state::vgREG(offs_t offset, uint8_t data)
540 {
541 m_vgRegFile[offset] = data;
542 #ifdef VG60_VERBOSE
543 static const char *const regDest[4] = { "DU", "DVM", "DIR", "WOPS" };
544 static const char *const wopsFunctions[] = { "Overlay", "Replace", "Complement", "Erase" };
545 if (offset < 3) logerror("VG: 0x%02x: %s Reg loaded with %02X\n", (0x60+offset), regDest[offset], m_vgRegFile[offset]);
546 else logerror("VG: 0x63: WOPS Reg loaded with %02X: KGRB %d%d%d%d, AttrChange %d, Function %s, Negate %d\n", data, (VG_WOPS>>7)&1, (VG_WOPS>>6)&1, (VG_WOPS>>5)&1, (VG_WOPS>>4)&1, (VG_WOPS>>3)&1, wopsFunctions[(VG_WOPS>>1)&3], VG_WOPS&1);
547 #endif
548 }
549
550
551 /* port 0x64: "EX MOV" execute a move (relative move of x and y using du/dvm/dir/err, no writing) */
552 /* port 0x65: "EX DOT" execute a dot (draw a dot at x,y?) */
553 /* port 0x66: "EX VEC" execute a vector (draw a vector from x,y to a destination using du/dvm/dir/err ) */
554 /* port 0x67: "EX ER" execute an erase (clear the screen to the bg color, i.e. fill vram with zeroes) */
vgEX(offs_t offset,uint8_t data)555 void vk100_state::vgEX(offs_t offset, uint8_t data)
556 {
557 #ifdef VG60_VERBOSE
558 static const char *const ex_functions[] = { "Move", "Dot", "Vector", "Erase" };
559 logerror("VG Execute %s 0x%02X written with %d\n", ex_functions[offset&3], 0x67+offset, data);
560 //fprintf(stderr, "VG Execute %s 0x%02X written with %d\n", ex_functions[offset&3], 0x67+offset, data);
561 #endif
562 m_vgPMUL_Count = m_vgPMUL; // load PMUL_Count
563 m_vgPAT_Mask = 0x80;
564 m_vgDownCount = VG_DU; // set down counter to length of major vector
565 m_VG_MODE = offset&3;
566 m_vgGO = 1;
567 timer_set(attotime::zero, TIMER_EXECUTE_VG);
568 }
569
570
571 /* port 0x68: "KBDW" d7 is beeper, d6 is keyclick, d5-d0 are keyboard LEDS */
KBDW(uint8_t data)572 void vk100_state::KBDW(uint8_t data)
573 {
574 m_online_led = BIT(data, 5) ? 1 : 0;
575 m_local_led = BIT(data, 5) ? 0 : 1;
576 m_noscroll_led = BIT(data, 4) ? 1 : 0;
577 m_basic_led = BIT(data, 3) ? 1 : 0;
578 m_hardcopy_led = BIT(data, 2) ? 1 : 0;
579 m_l1_led = BIT(data, 1) ? 1 : 0;
580 m_l2_led = BIT(data, 0) ? 1 : 0;
581 #ifdef LED_VERBOSE
582 if (BIT(data, 6)) logerror("kb keyclick bit 6 set: not emulated yet (multivibrator)!\n");
583 #endif
584 m_speaker->set_state(BIT(data, 7));
585 #ifdef LED_VERBOSE
586 logerror("LED state: %02X: %s %s %s %s %s %s\n", data&0xFF, (data&0x20)?"------- LOCAL ":"ON LINE ----- ", (data&0x10)?"--------- ":"NO SCROLL ", (data&0x8)?"----- ":"BASIC ", (data&0x4)?"--------- ":"HARD-COPY ", (data&0x2)?"-- ":"L1 ", (data&0x1)?"-- ":"L2 ");
587 #endif
588 }
589
590 /* port 0x6C: "BAUD" controls the smc com5016t dual baud generator which
591 * controls the divisors for the rx and tx clocks on the 8251 from the
592 5.0688Mhz cpu xtal.
593 It has 5v,12v on pins 2 and 9, pin 10 is NC.
594 * A later part that replaced this on the market is SMC COM8116(T)/8136(T), which
595 was a 5v-only part (pin 9 and 10 are NC, 10 is a clock out on the 8136.
596 * Note that even on the SMC COM5016T version, SMC would allow the user
597 to mask their own dividers on custom ordered chips if desired.
598 * The COM8116(T)/8136(T) came it at least 4 mask rom types meant for different
599 input clocks:
600 -000 or no mark for 5.0688Mhz (which exactly matches the table below) (synertek sy2661-3 also matches this exactly)
601 -003 is for 6.01835MHz
602 -005 is for 4.915200Mhz
603 -006 is for 5.0688Mhz but omits the 2000 baud entry, instead has 200,
604 and output frequencies are 2x as fast (meant for a 32X clock uart)
605 -013 is for 2.76480MHz
606 -013A is for 5.52960MHz
607 (several other unknown refclock masks appear on partscalper sites)
608 GI also made a clone of the 8116 5v chip called the AY-5-8116(T)/8136(T)
609 which had at least two masks: -000/no mark and -005, matching speeds above
610 WD made the WD1943 which is similarly 5v compatible, with -00, -05, -06 masks
611 The COM8046(T) has 5 bits for selection instead of 4, but still expects
612 a 5.0688MHz reference clock, and the second half of the table matches the
613 values below; the first half of the table is the values below /2, rounded
614 down (for uarts which need a clock rate of 32x baud instead of 16x).
615 WD's BR1941 is also functionally compatible but uses 5v,12v,-5v on pins 2,9,10
616 * The baud divisor lookup table has 16 entries, but only entries 2,5,6,7,A,C,E,F are documented/used in the vk100 tech manual
617 * The others are based on page 13 of http://www.hartetechnologies.com/manuals/Tarbell/Tarbell%20Z80%20CPU%20Board%20Model%203033.pdf
618 * D C B A Divisor Expected Baud
619 * 0 0 0 0 - 6336 (5068800 / 6336 = 16*50 = 50 baud
620 * 0 0 0 1 - 4224 (5068800 / 4224 = 16*75) = 75 baud
621 * 0 0 1 0 - 2880 (5068800 / 2880 = 16*110) = 110 baud
622 * 0 0 1 1 - 2355 (5068800 / 2355 = 16*134.5223) ~= 134.5 baud
623 * 0 1 0 0 - 2112 (5068800 / 2112 = 16*150) = 150 baud
624 * 0 1 0 1 - 1056 (5068800 / 1056 = 16*300) = 300 baud
625 * 0 1 1 0 - 528 (5068800 / 528 = 16*600) = 600 baud
626 * 0 1 1 1 - 264 (5068800 / 264 = 16*1200) = 1200 baud
627 * 1 0 0 0 - 176 (5068800 / 176 = 16*1800) = 1800 baud
628 * 1 0 0 1 - 158 (5068800 / 158 = 16*2005.0633) ~= 2000 baud
629 * 1 0 1 0 - 132 (5068800 / 132 = 16*2400) = 2400 baud
630 * 1 0 1 1 - 88 (5068800 / 88 = 16*3600) = 3600 baud
631 * 1 1 0 0 - 66 (5068800 / 66 = 16*4800) = 4800 baud
632 * 1 1 0 1 - 44 (5068800 / 44 = 16*7200) = 7200 baud
633 * 1 1 1 0 - 33 (5068800 / 33 = 16*9600) = 9600 baud
634 * 1 1 1 1 - 16 (5068800 / 16 = 16*19800) ~= 19200 baud
635 */
636
637 /* port 0x40-0x47: "SYSTAT A"; various status bits, poorly documented in the tech manual
638 * /GO VDM1 VDM1 VDM1 VDM1 Dip RST7.5 GND***
639 * BIT3 BIT2 BIT1 BIT0 Switch VSYNC
640 * d7 d6 d5 d4 d3 d2 d1 d0
641 bit3, 2, 1, 0 are the 4 bits output from the VRAM 12->4 multiplexer
642 which are also inputs to the pattern rom; they are constantly updated
643 by the sync rom and related circuitry.
644 This is the only way the vram can be read by the cpu.
645 d7 is from the /Q output of the GO latch
646 d6,5,4,3 are from the 74ls298 at ic4 (right edge of pcb)
647 d2 is where the dipswitch values are read from, based on the offset
648 d1 is connected to 8085 rst7.5 (pin 7) and crtc pin 40 (VSYNC) [verified via tracing]
649 d0 is tied to GND [verified via tracing] but the schematics both tie it to GND
650 and call it LP FLAG, may be a leftover from development.
651
652 31D reads and checks d7 in a loop
653 205 reads, xors with 0x55 (from reg D), ANDS result with 0x78 and branches if it is not zero (checking for bit pattern 1010?)
654 299 reads, rotates result right 3 times and ANDs the result with 0x0F
655 2A4 reads, rotates result left 1 time and ANDS the result with 0xF0
656 */
SYSTAT_A(offs_t offset)657 uint8_t vk100_state::SYSTAT_A(offs_t offset)
658 {
659 uint8_t dipswitchLUT[8] = { 1,3,5,7,6,4,2,0 }; // the dipswitches map in a weird order to offsets
660 #ifdef SYSTAT_A_VERBOSE
661 if (m_maincpu->pc() != 0x31D) logerror("0x%04X: SYSTAT_A Read!\n", m_maincpu->pc());
662 #endif
663 return ((m_vgGO?0:1)<<7)|(vram_read()<<3)|(((m_dipsw->read()>>dipswitchLUT[offset])&1)?0x4:0)|(m_vsync?0x2:0);
664 }
665
666 /* port 0x48: "SYSTAT B"; NOT documented in the tech manual at all.
667 * when in loopback/test mode, SYSTAT_B is read and expected the following, around 0x606:
668 * reset 8751, modewrite of 0x5E
669 * write command -> 0x20 (normal, normal, /RTS is 0, normal, normal, receive off, /DTR is 1, transmit off)
670 * read SYSTAT B (and xor with 0xe), expect d7 to be CLEAR or jump to error
671 * write command -> 0x05 (normal, normal, /RTS is 1, normal, normal, receive ON, /DTR is 0, transmit off)
672 * read SYSTAT B (and xor with 0xe), expect d7 to be SET or jump to error
673 * after this it does something and waits for an rxrdy interrupt
674
675 shows the results of:
676 * ACTS (/CTS) ADSR (/DSR) GND GND ATTR3 ATTR2 ATTR1 ATTR0
677 * d7 d6 d5 d4 d3 d2 d1 d0
678 * the ACTS (inverse of DCTS) signal lives in one of these bits (see 5-62)
679 * it XORs the read of systat_b with the E register (which holds 0x6)
680 * and checks the result
681 * The 4 attribute ram bits for the cell being pointed at by the X and Y regs are readable as the low nybble.
682 * The DSR pin is readable as bit 6.
683 */
SYSTAT_B()684 uint8_t vk100_state::SYSTAT_B()
685 {
686 #ifdef SYSTAT_B_VERBOSE
687 logerror("0x%04X: SYSTAT_B Read!\n", m_maincpu->pc());
688 #endif
689 return (m_ACTS<<7)|(m_ADSR<<6)|vram_attr_read();
690 }
691
vk100_keyboard_column_r(offs_t offset)692 uint8_t vk100_state::vk100_keyboard_column_r(offs_t offset)
693 {
694 uint8_t code = m_col_array[offset&0xF]->read() | m_capsshift->read();
695 #ifdef KBD_VERBOSE
696 logerror("Keyboard column %X read, returning %02X\n", offset&0xF, code);
697 #endif
698 return code;
699 }
700
vk100_mem(address_map & map)701 void vk100_state::vk100_mem(address_map &map)
702 {
703 map.unmap_value_high();
704 map(0x0000, 0x6fff).rom();
705 map(0x7000, 0x700f).mirror(0x0ff0).r(FUNC(vk100_state::vk100_keyboard_column_r));
706 map(0x8000, 0xbfff).ram();
707 }
708
709 /*
710 * 8085 IO address map (x = ignored; * = selects address within this range; ? = not sure; ** = subparts check this bit)
711 * (a15 to a8 are latched the same value as a7-a0 on the 8080 and 8085)
712 * [this map is derived from extensive tracing as well as some guesswork, noted for the crtc, systat_b and the uart]
713 a7 a6 a5 a4 a3 a2 a1 a0
714 x 0 x x x x x 0 W CRTC address
715 x 0 x x x x x 1 RW CRTC register r/w
716 x 1 * * * ** ** ** read area (rightmost 74ls138):
717 x 1 0 0 0 * * * R SYSTAT_A (a0-a3 chooses the bit of the dipswitches read via d3)
718 x 1 0 0 1 x x x R SYSTAT_B
719 x 1 0 1 0 x x 0 R i8251 UART data
720 x 1 0 1 0 x x 1 R i8251 UART status
721 x 1 0 1 1 x x x R unused
722 x 1 1 0 0 x x x R unused
723 x 1 1 0 1 x x x R unused
724 x 1 1 1 0 x x x R unused
725 x 1 1 1 1 x x x R unused
726 x 1 0 x x * * * write area (right 74ls138):
727 x 1 0 x x 0 0 0 W X (low 8 bits)
728 x 1 0 x x 0 0 1 W X (high 4 bits)
729 x 1 0 x x 0 1 0 W Y (low 8 bits)
730 x 1 0 x x 0 1 1 W Y (high 4 bits)
731 x 1 0 x x 1 0 0 W ERR
732 x 1 0 x x 1 0 1 W SOPS
733 x 1 0 x x 1 1 0 W PAT
734 x 1 0 x x 1 1 1 W PMUL
735 x 1 1 * * * ** ** write area (middle 74ls138):
736 x 1 1 0 0 0 ** ** write to register file 2x 74ls670:
737 x 1 1 0 0 0 0 0 W DU
738 x 1 1 0 0 0 0 1 W DVM
739 x 1 1 0 0 0 1 0 W DIR
740 x 1 1 0 0 0 1 1 W WOPS
741 x 1 1 0 0 1 * * W set VG_MODE to * * XOR 3 and Execute (if GO is not active)
742 x 1 1 0 1 0 x x W KYBDW
743 x 1 1 0 1 1 x x W BAUD
744 x 1 1 1 0 0 x 0 W i8251 UART data
745 x 1 1 1 0 0 x 1 W i8251 UART control
746 x 1 1 1 0 1 x x W unused
747 x 1 1 1 1 0 x x W unused
748 x 1 1 1 1 1 x x W unused
749 */
vk100_io(address_map & map)750 void vk100_state::vk100_io(address_map &map)
751 {
752 map.unmap_value_high();
753 map.global_mask(0xff); // guess, probably correct
754 map(0x00, 0x00).mirror(0xBE).w(m_crtc, FUNC(mc6845_device::address_w));
755 map(0x01, 0x01).mirror(0xBE).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
756 // Comments are from page 118 (5-14) of http://web.archive.org/web/20091015205827/http://www.computer.museum.uq.edu.au/pdf/EK-VK100-TM-001%20VK100%20Technical%20Manual.pdf
757 map(0x40, 0x41).mirror(0x98).w(FUNC(vk100_state::vgLD_X)); //LD X LO + HI 12 bits
758 map(0x42, 0x43).mirror(0x98).w(FUNC(vk100_state::vgLD_Y)); //LD Y LO + HI 12 bits
759 map(0x44, 0x44).mirror(0x98).w(FUNC(vk100_state::vgERR)); //LD ERR ('error' in bresenham algorithm)
760 map(0x45, 0x45).mirror(0x98).w(FUNC(vk100_state::vgSOPS)); //LD SOPS (screen options (plus uart dest))
761 map(0x46, 0x46).mirror(0x98).w(FUNC(vk100_state::vgPAT)); //LD PAT (pattern register)
762 map(0x47, 0x47).mirror(0x98).w(FUNC(vk100_state::vgPMUL)); //LD PMUL (pattern multiplier)
763 map(0x60, 0x63).mirror(0x80).w(FUNC(vk100_state::vgREG)); //LD DU, DVM, DIR, WOPS (register file)
764 map(0x64, 0x67).mirror(0x80).w(FUNC(vk100_state::vgEX)); //EX MOV, DOT, VEC, ER
765 map(0x68, 0x68).mirror(0x83).w(FUNC(vk100_state::KBDW)); //KBDW (probably mirror(0x03))
766 map(0x6C, 0x6C).mirror(0x83).w(COM5016T_TAG, FUNC(com8116_device::stt_str_w)); //LD BAUD (baud rate clock divider setting for i8251 tx and rx clocks) (probably mirror(0x03))
767 map(0x70, 0x71).mirror(0x82).w(m_uart, FUNC(i8251_device::write)); //LD COMD
768 //map(0x74, 0x74).mirror(0x83).w(FUNC(vk100_state::unknown_74));
769 //map(0x78, 0x78).mirror(0x83).w(FUNC(vk100_state::kbdw)); //KBDW ?(mirror?)
770 //map(0x7C, 0x7C).mirror(0x83).w(FUNC(vk100_state::unknown_7C));
771 map(0x40, 0x47).mirror(0x80).r(FUNC(vk100_state::SYSTAT_A)); // SYSTAT A (state machine done and last 4 bits of vram, as well as dipswitches)
772 map(0x48, 0x48).mirror(0x87/*0x80*/).r(FUNC(vk100_state::SYSTAT_B)); // SYSTAT B (uart stuff)
773 map(0x50, 0x51).mirror(0x86).r(m_uart, FUNC(i8251_device::read)); // UART O
774 //map(0x58, 0x58).mirror(0x87).r(FUNC(vk100_state::unknown_58));
775 //map(0x60, 0x60).mirror(0x87).r(FUNC(vk100_state::unknown_60));
776 //map(0x68, 0x68).mirror(0x87).r(FUNC(vk100_state::unknown_68)); // NOT USED
777 //map(0x70, 0x70).mirror(0x87).r(FUNC(vk100_state::unknown_70));
778 //map(0x78, 0x7f).mirror(0x87).r(FUNC(vk100_state::unknown_78));
779 }
780
781 /* Input ports */
782 static INPUT_PORTS_START( vk100 )
783 // the dipswitches are common ground: when open (upward) the lines are pulled to 5v, otherwise they read as 0
784 PORT_START("SWITCHES")
785 PORT_DIPNAME( 0x01, 0x00, "Power Frequency" ) PORT_DIPLOCATION("SW:!1")
786 PORT_DIPSETTING( 0x00, "60Hz" )
787 PORT_DIPSETTING( 0x01, "50Hz" )
788 PORT_DIPNAME( 0x02, 0x00, "Default Serial Port" ) PORT_DIPLOCATION("SW:!2")
789 PORT_DIPSETTING( 0x00, "EIA port" )
790 PORT_DIPSETTING( 0x02, "20ma port" )
791 PORT_DIPNAME( 0x04, 0x00, "Default US/UK" ) PORT_DIPLOCATION("SW:!3")
792 PORT_DIPSETTING( 0x00, "US" )
793 PORT_DIPSETTING( 0x04, "UK" )
794 PORT_DIPNAME( 0x18, 0x00, "Default Parity" ) PORT_DIPLOCATION("SW:!4,!5")
795 PORT_DIPSETTING( 0x00, "Off" )
796 PORT_DIPSETTING( 0x10, "Even" )
797 PORT_DIPSETTING( 0x08, "Odd" )
798 PORT_DIPSETTING( 0x18, "Do Not Use This Setting" )
799 PORT_DIPNAME( 0xe0, 0x00, "Default Baud Rate" ) PORT_DIPLOCATION("SW:!6,!7,!8")
800 PORT_DIPSETTING( 0x00, "110" )
801 PORT_DIPSETTING( 0x80, "300" )
802 PORT_DIPSETTING( 0x40, "600" )
803 PORT_DIPSETTING( 0xc0, "1200" )
804 PORT_DIPSETTING( 0x20, "2400" )
805 PORT_DIPSETTING( 0xa0, "4800" )
806 PORT_DIPSETTING( 0x60, "9600" )
807 PORT_DIPSETTING( 0xe0, "19200" )
808
809 PORT_START("CAPSSHIFT") // CAPS LOCK and SHIFT appear as the high 2 bits on all rows
810 PORT_BIT(0x3f, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_CODE(KEYCODE_LSHIFT)811 PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT)
812 PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_TOGGLE PORT_NAME("Caps lock") PORT_CODE(KEYCODE_CAPSLOCK)
813 PORT_START("COL0")
814 PORT_BIT(0x1f, IP_ACTIVE_LOW, IPT_UNUSED)
815 PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_UNUSED) // row 0 bit 6 is always low, checked by keyboard test
816 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED) // all rows have these bits left low to save a mask op later
817 PORT_START("COL1")
818 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Set Up") PORT_CODE(KEYCODE_F5)
819 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC)
820 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB)
821 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
822 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num Enter") PORT_CODE(KEYCODE_ENTER_PAD)
823 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF1/Hardcopy") PORT_CODE(KEYCODE_F1)
824 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
825 PORT_START("COL2")
826 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1)
827 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q)
828 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A)
829 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("No scroll") PORT_CODE(KEYCODE_LALT)
830 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 1") PORT_CODE(KEYCODE_1_PAD)
831 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF2/Locator") PORT_CODE(KEYCODE_F2)
832 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
833 PORT_START("COL3")
834 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2)
835 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W)
836 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S)
837 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z)
838 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 2") PORT_CODE(KEYCODE_2_PAD)
839 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF3/Text") PORT_CODE(KEYCODE_F3)
840 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
841 PORT_START("COL4")
842 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3)
843 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E)
844 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D)
845 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X)
846 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 3") PORT_CODE(KEYCODE_3_PAD)
847 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("PF4/Reset") PORT_CODE(KEYCODE_F4)
848 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
849 PORT_START("COL5")
850 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4)
851 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R)
852 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F)
853 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C)
854 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 4") PORT_CODE(KEYCODE_4_PAD)
855 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP)
856 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
857 PORT_START("COL6")
858 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5)
859 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T)
860 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G)
861 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V)
862 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 5") PORT_CODE(KEYCODE_5_PAD)
863 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN)
864 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
865 PORT_START("COL7")
866 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6)
867 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y)
868 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H)
869 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B)
870 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 6") PORT_CODE(KEYCODE_6_PAD)
871 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT)
872 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
873 PORT_START("COL8")
874 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7)
875 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U)
876 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J)
877 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE)
878 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 7") PORT_CODE(KEYCODE_7_PAD)
879 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT)
880 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
881 PORT_START("COL9")
882 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8)
883 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I)
884 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K)
885 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N)
886 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 8") PORT_CODE(KEYCODE_8_PAD)
887 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
888 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
889 PORT_START("COLA")
890 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9)
891 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O)
892 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L)
893 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M)
894 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 9") PORT_CODE(KEYCODE_9_PAD)
895 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
896 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
897 PORT_START("COLB")
898 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0)
899 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P)
900 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON)
901 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA)
902 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num 0") PORT_CODE(KEYCODE_0_PAD)
903 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
904 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
905 PORT_START("COLC")
906 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS)
907 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE)
908 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("'") PORT_CODE(KEYCODE_QUOTE)
909 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP)
910 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num -") PORT_CODE(KEYCODE_MINUS_PAD)
911 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
912 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
913 PORT_START("COLD")
914 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("=") PORT_CODE(KEYCODE_EQUALS)
915 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE)
916 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
917 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH)
918 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num ,") PORT_CODE(KEYCODE_PLUS_PAD)
919 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
920 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
921 PORT_START("COLE")
922 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("~") PORT_CODE(KEYCODE_TILDE)
923 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete") PORT_CODE(KEYCODE_DEL)
924 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\") PORT_CODE(KEYCODE_BACKSLASH)
925 PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line feed") PORT_CODE(KEYCODE_RALT)
926 PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num .") PORT_CODE(KEYCODE_DEL_PAD)
927 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
928 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
929 PORT_START("COLF")
930 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE)
931 PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_F6)
932 PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER)
933 PORT_BIT(0x18, IP_ACTIVE_LOW, IPT_UNUSED)
934 PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL)
935 PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED)
936 INPUT_PORTS_END
937
938
939 void vk100_state::machine_start()
940 {
941 m_online_led.resolve();
942 m_local_led.resolve();
943 m_noscroll_led.resolve();
944 m_basic_led.resolve();
945 m_hardcopy_led.resolve();
946 m_l1_led.resolve();
947 m_l2_led.resolve();
948
949 m_online_led = 1;
950 m_local_led = 0;
951 m_noscroll_led = 1;
952 m_basic_led = 1;
953 m_hardcopy_led = 1;
954 m_l1_led = 1;
955 m_l2_led = 1;
956 m_vsync = 0;
957 m_dir_a6 = 1;
958 m_cout = 0;
959 m_vgX = 0;
960 m_vgY = 0;
961 m_vgERR = 0;
962 m_vgSOPS = 0;
963 m_vgPAT = 0;
964 m_vgPAT_Mask = 0x80;
965 m_vgPMUL = 0;
966 m_vgPMUL_Count = 0;
967 m_vgDownCount = 0;
968 VG_DU = 0;
969 VG_DVM = 0;
970 VG_DIR = 0;
971 VG_WOPS = 0;
972 m_VG_MODE = 0;
973 m_vgGO = 0;
974 m_ACTS = 1;
975 m_ADSR = 1;
976 char kbdcol[8];
977 // look up all 16 tags 'the slow way' but only once on reset
978 for (int i = 0; i < 16; i++)
979 {
980 sprintf(kbdcol,"COL%X", i);
981 m_col_array[i] = ioport(kbdcol);
982 }
983 }
984
WRITE_LINE_MEMBER(vk100_state::crtc_vsync)985 WRITE_LINE_MEMBER(vk100_state::crtc_vsync)
986 {
987 m_maincpu->set_input_line(I8085_RST75_LINE, state? ASSERT_LINE : CLEAR_LINE);
988 m_vsync = state;
989 }
990
WRITE_LINE_MEMBER(vk100_state::i8251_rxrdy_int)991 WRITE_LINE_MEMBER(vk100_state::i8251_rxrdy_int)
992 {
993 m_maincpu->set_input_line(I8085_RST65_LINE, state?ASSERT_LINE:CLEAR_LINE);
994 }
995
WRITE_LINE_MEMBER(vk100_state::i8251_txrdy_int)996 WRITE_LINE_MEMBER(vk100_state::i8251_txrdy_int)
997 {
998 m_maincpu->set_input_line(I8085_RST55_LINE, state?ASSERT_LINE:CLEAR_LINE);
999 }
1000
WRITE_LINE_MEMBER(vk100_state::i8251_rts)1001 WRITE_LINE_MEMBER(vk100_state::i8251_rts)
1002 {
1003 logerror("callback: RTS state changed to %d\n", state);
1004 // TODO: only change this during loopback mode!
1005 m_ACTS = state;
1006 }
1007
init_vk100()1008 void vk100_state::init_vk100()
1009 {
1010 // figure out how the heck to initialize the timers here
1011 //m_i8251_rx_timer = timer_alloc(TID_I8251_RX);
1012 //m_i8251_tx_timer = timer_alloc(TID_I8251_TX);
1013 //m_i8251_sync_timer = timer_alloc(TID_SYNC);
1014 //machine().scheduler().timer_set(attotime::from_hz(10000), FUNC(i8251_rx_clk));
1015 }
1016
video_start()1017 void vk100_state::video_start()
1018 {
1019 m_vram = memregion("vram")->base();
1020 m_trans = memregion("trans")->base();
1021 m_pattern = memregion("pattern")->base();
1022 m_dir = memregion("dir")->base();
1023 m_sync = memregion("sync")->base();
1024 m_vector = memregion("vector")->base();
1025 m_ras_erase = memregion("ras_erase")->base();
1026 }
1027
MC6845_UPDATE_ROW(vk100_state::crtc_update_row)1028 MC6845_UPDATE_ROW( vk100_state::crtc_update_row )
1029 {
1030 static const uint32_t colorTable[16] = {
1031 0x000000, 0x0000FF, 0xFF0000, 0xFF00FF, 0x00FF00, 0x00FFFF, 0xFFFF00, 0xFFFFFF,
1032 0x000000, 0x0000FF, 0xFF0000, 0xFF00FF, 0x00FF00, 0x00FFFF, 0xFFFF00, 0xFFFFFF };
1033 static const uint32_t colorTable2[16] = {
1034 0x000000, 0x0000FF, 0xFF0000, 0xFF00FF, 0x00FF00, 0x00FFFF, 0xFFFF00, 0xFFFFFF,
1035 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 };
1036 //printf("y=%d, ma=%04x, ra=%02x, x_count=%02x ", y, ma, ra, x_count);
1037 /* figure out ram address based on tech manual page 5-23:
1038 * real address to 16-bit chunk a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0
1039 * crtc input MA11 MA10 MA9 MA8 MA7 MA6 RA1 RA0 MA5 MA4 MA3 MA2 MA1 MA0
1040 */
1041 uint16_t EA = ((ma&0xfc0)<<2)|((ra&0x3)<<6)|(ma&0x3F);
1042 // display the 64 different 12-bit-wide chunks
1043 for (int i = 0; i < 64; i++)
1044 {
1045 uint16_t block = m_vram[(EA<<1)+(2*i)+1] | (m_vram[(EA<<1)+(2*i)]<<8);
1046 uint32_t fgColor = (m_vgSOPS&0x08)?colorTable[(block&0xF000)>>12]:colorTable2[(block&0xF000)>>12];
1047 uint32_t bgColor = (m_vgSOPS&0x08)?colorTable[(m_vgSOPS&0xF0)>>4]:colorTable2[(m_vgSOPS&0xF0)>>4];
1048 // display a 12-bit wide chunk
1049 for (int j = 0; j < 12; j++)
1050 {
1051 bitmap.pix(y, (12*i)+j) = (((block&(0x0001<<j))?1:0)^(m_vgSOPS&1))?fgColor:bgColor;
1052 }
1053 }
1054 }
1055
1056
vk100(machine_config & config)1057 void vk100_state::vk100(machine_config &config)
1058 {
1059 /* basic machine hardware */
1060 I8085A(config, m_maincpu, XTAL(5'068'800));
1061 m_maincpu->set_addrmap(AS_PROGRAM, &vk100_state::vk100_mem);
1062 m_maincpu->set_addrmap(AS_IO, &vk100_state::vk100_io);
1063
1064 /* video hardware */
1065 screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
1066 screen.set_raw(XTAL(45'619'200)/3, 882, 0, 720, 370, 0, 350 ); // fake screen timings for startup until 6845 sets real ones
1067 screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update));
1068
1069 MC6845(config, m_crtc, 45.6192_MHz_XTAL/3/12); // unknown variant
1070 m_crtc->set_screen("screen");
1071 m_crtc->set_show_border_area(false);
1072 m_crtc->set_char_width(12);
1073 m_crtc->set_update_row_callback(FUNC(vk100_state::crtc_update_row));
1074 m_crtc->out_vsync_callback().set(FUNC(vk100_state::crtc_vsync));
1075
1076 /* i8251 uart */
1077 I8251(config, m_uart, 0);
1078 m_uart->txd_handler().set(RS232_TAG, FUNC(rs232_port_device::write_txd));
1079 m_uart->dtr_handler().set(RS232_TAG, FUNC(rs232_port_device::write_dtr));
1080 m_uart->rts_handler().set(RS232_TAG, FUNC(rs232_port_device::write_rts));
1081 m_uart->rxrdy_handler().set(FUNC(vk100_state::i8251_rxrdy_int));
1082 m_uart->txrdy_handler().set(FUNC(vk100_state::i8251_txrdy_int));
1083
1084 rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, nullptr));
1085 rs232.rxd_handler().set(m_uart, FUNC(i8251_device::write_rxd));
1086 rs232.dsr_handler().set(m_uart, FUNC(i8251_device::write_dsr));
1087
1088 com8116_device &dbrg(COM8116(config, COM5016T_TAG, 5.0688_MHz_XTAL));
1089 dbrg.fr_handler().set(m_uart, FUNC(i8251_device::write_rxc));
1090 dbrg.ft_handler().set(m_uart, FUNC(i8251_device::write_txc));
1091
1092 config.set_default_layout(layout_vk100);
1093
1094 SPEAKER(config, "mono").front_center();
1095 BEEP(config, m_speaker, 116).add_route(ALL_OUTPUTS, "mono", 0.25); // 116 hz (page 172 of TM), but duty cycle is wrong here!
1096 }
1097
1098 /* ROM definition */
1099 /* according to http://www.computer.museum.uq.edu.au/pdf/EK-VK100-TM-001%20VK100%20Technical%20Manual.pdf
1100 page 5-10 (pdf pg 114), The 4 firmware roms should go from 0x0000-0x1fff,
1101 0x2000-0x3fff, 0x4000-0x5fff and 0x6000-0x63ff; The last rom is actually a
1102 little bit longer and goes to 67ff.
1103 */
1104 ROM_START( vk100 )
1105 ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
1106 ROM_LOAD( "23-031e4-00.rom1.e53", 0x0000, 0x2000, CRC(c8596398) SHA1(a8dc833dcdfb7550c030ac3d4143e266b1eab03a))
1107 ROM_LOAD( "23-017e4-00.rom2.e52", 0x2000, 0x2000, CRC(e857a01e) SHA1(914b2c51c43d0d181ffb74e3ea59d74e70ab0813))
1108 ROM_LOAD( "23-018e4-00.rom3.e51", 0x4000, 0x2000, CRC(b3e7903b) SHA1(8ad6ed25cd9b04a9968aa09ab69ba526d35ca550))
1109 ROM_LOAD( "23-190e2-00.rom4.e50", 0x6000, 0x1000, CRC(ad596fa5) SHA1(b30a24155640d32c1b47a3a16ea33cd8df2624f6)) // probably an overdump, e2 implies the size is 0x800 not 0x1000, and the end is all blank
1110
1111 ROM_REGION( 0x8000, "vram", ROMREGION_ERASE00 ) // 32k of vram
1112
1113 ROM_REGION( 0x400, "pattern", ROMREGION_ERASEFF )
1114 /* This is the "PATTERN ROM", (1k*4, 82s137)
1115 * it contains a table of 4 output bits based on input of: (from figure 5-18):
1116 * 4 input bits bank-selected from RAM (a0, a1, a2, a3)
1117 * 2 select bits to choose one of the 4 bits, sourced from the X reg LSBs (a4, a5)
1118 * 3 pattern function bits from WOPS (F0 "N" is a6, F1 and F2 are a7 and a8
1119 * and one bit from the lsb of the pattern register shifter (a9)
1120 * control bits:
1121 * /CE1 ----- GND [verified via tracing]
1122 * /CE2 ----- GND [verified via tracing]
1123 * addr bits 9876543210
1124 * ||||||\\\\- input from ram (A)
1125 * ||||\\----- bit select (from x reg lsb)
1126 * |||\------- negate (N) \___ low 3 bits of WOPS
1127 * |\\-------- function /
1128 * \---------- pattern bit (P)
1129 * data bits: 3210
1130 * \\\\-- output to ram (M), but gated by an io line from vector rom
1131 * functions are:
1132 * Overlay: M=A|(P^N)
1133 * Replace: M=P^N
1134 * Complement: M=A^(P^N)
1135 * Erase: M=N
1136 */
1137 ROM_LOAD( "wb8201_656f1.m1-7643-5.pr4.ic14", 0x0000, 0x0400, CRC(e8ecf59f) SHA1(49e9d109dad3d203d45471a3f4ca4985d556161f)) // label verified from nigwil's board
1138
1139 ROM_REGION(0x100, "trans", ROMREGION_ERASEFF )
1140 /* this is the "TRANSLATOR ROM" described in figure 5-17 on page 5-27 (256*8, 82s135)
1141 * it contains a table of 256 values which skips every fourth value so 00 01 02 04 05 06 08.. etc, wraps at the end
1142 * control bits:
1143 * /CE1 ----- GND [verified via tracing]
1144 * /CE2 ----- GND [verified via tracing]
1145 * addr bits: 76543210
1146 * \\\\\\\\- X9 thru X2
1147 * data bits: 76543210
1148 * \\\\\\\\- X'9 thru X'2
1149 * The VT125 prom @ E60 is literally identical to this, the same exact part: 23-060B1
1150 */
1151 ROM_LOAD( "wb---0_060b1.mmi6309.pr2.ic82", 0x0000, 0x0100, CRC(198317fc) SHA1(00e97104952b3fbe03a4f18d800d608b837d10ae)) // label verified from nigwil's board
1152
1153 ROM_REGION(0x100, "dir", ROMREGION_ERASEFF )
1154 /* this is the "DIRECTION ROM" == mb6309 (256x8, 82s135)
1155 * see figure 5-24 on page 5-39
1156 * It tells the direction and enable for counting on the X and Y counters
1157 * and also handles the non-math related parts of the bresenham line algorithm
1158 * control bits:
1159 * /CE1 ----- DCOUNT 0 H [verified via tracing]
1160 * /CE2 ----- ENA ERROR L [verified via tracing]
1161 * addr bits: 76543210
1162 * ||||\\\\-- DIR (vgDIR register low 4 bits)
1163 * |||\------ C OUT aka ERROR CARRY (strobed in by STROBE L from the error counter's adder) [verified via tracing]
1164 * ||\------- Y0 (the otherwise unused lsb of the Y register, used for bresenham) [verified via tracing]
1165 * |\-------- feedback bit from d5 strobed by V CLK [verified via tracing]
1166 * \--------- GND; the second half of the prom is blank (0x00)
1167 * data bits: 76543210
1168 * |||||||\-- ENA Y (enables change on X counter) [works with code]
1169 * ||||||\--- ENA X (enables change on Y counter) [works with code]
1170 * |||||\---- Y DIRECTION (high is count down, low is count up)
1171 * ||||\----- X DIRECTION (high is count down, low is count up)
1172 * |||\------ PIXEL WRT
1173 * ||\------- feedback bit to a6, this bit is held in PRESET/1 condition by GO being inactive, and if the vector prom is disabled it is pulled to 1 [verified via tracing and schematics]
1174 * |\-------- UNUSED, always 0
1175 * \--------- UNUSED, always 0
1176 * The VT125 prom @ E41 is literally identical to this, the same exact part: 23-059B1
1177 */
1178 ROM_LOAD( "wb8141_059b1.tbp18s22.pr5.ic111", 0x0000, 0x0100, CRC(4b63857a) SHA1(3217247d983521f0b0499b5c4ef6b5de9844c465)) // label verified from andy's board
1179
1180 ROM_REGION( 0x100, "ras_erase", ROMREGION_ERASEFF )
1181 /* this is the "RAS/ERASE ROM" involved with driving the RAS lines and erasing VRAM dram (256*4, 82s129)
1182 * control bits:
1183 * /CE1 ----- /WRITE aka WRITE L (pin 6 of vector rom after being latched by its ls273) [verified via tracing and vt125 schematic]
1184 * /CE2 ----- /ENA WRITE aka ENA WRITE L [verified via tracing and vt125 schematic]
1185 * (INHIBIT WRITE L (pin 5 of ls74 to extreme left edge of translate prom) XOR STROBE D COUNT (pin 5 of ls74 near the 20ma port) (pin 3 of the ls86 above the crtc)
1186 * addr bits: 76543210
1187 * |||||||\-- X'2 [verified via tracing]
1188 * ||||||\--- X'3 [verified via tracing]
1189 * |||||\---- register file bit 3/upper file MSB (DIR prom pin 4, ls191 2nd from left edge left of the hd46505 pin 9, upper ls670n pin 6, ls283 at the left edge left of the hd46505 pin 15) [verified via tracing]
1190 * ||||\----- (Y8 NOR !(X10 NAND X9)) (pins 4,5,6 of ls32 left of 8085, and pins 1,2 of the ls04 in the lower left corner, pins 10,9,8 of the ls00 at the left edge drawn from the ls74 between the 8251 and 8202) [verified via tracing]
1191 * |||\------ (X10 NOR Y10) (pins 10,9,8 of ls32 left of 8085) [verified via tracing]
1192 * ||\------- X11 (D out of ls191 left of ls191 left of hd46505) [verified via tracing]
1193 * |\-------- Y11 (D out of ls191 left of hd46505) [verified via tracing]
1194 * \--------- ERASE L/d5 on the vector rom [verified via tracing]
1195 * data bits: 3210
1196 * |||\-- /WE for VRAM Attribute bits
1197 * ||\--- /WE for VRAM bits 0-3 (leftmost bits, first to be shifted out)
1198 * |\---- /WE for VRAM bits 4-7
1199 * \----- /WE for VRAM bits 8-11 (rightmost bits, last to be shifted out)
1200 * The VT125 prom E93 is mostly equivalent to the ras/erase prom; On the vt125 version, the inputs are:
1201 * (X'10 NOR X'11)
1202 * (Y9 NOR Y10)
1203 * Y11
1204 * X8 (aka PX8)
1205 * X9 (aka PX9)
1206 * ERASE L
1207 * X'3
1208 * X'2
1209 * and the outputs are:
1210 * MWR 2
1211 * MWR 1
1212 * MWR 0
1213 * since the vt125 has ram laid out differently than the vk100 and
1214 only has 3 banks (but 2 planes of 3 banks), I (LN) assume there
1215 are four wr banks on the v100, one per nybble, and the X'3 and
1216 X'2 inputs lend credence to this.
1217 *
1218 */
1219 ROM_LOAD( "wb8151_573a2.mmi6301.pr3.ic41", 0x0000, 0x0100, CRC(75885a9f) SHA1(c721dad6a69c291dd86dad102ed3a8ddd620ecc4)) // Stamp/silkscreen: "WB8151 // 573A2" (23-573A2), 82S129 equivalent @ E41
1220 // label verified from nigwil's and andy's board
1221
1222 ROM_REGION( 0x100, "vector", ROMREGION_ERASEFF )
1223 // WARNING: it is possible that the first two bytes of this prom are bad!
1224 // The PROM on andy's board appears to be damaged, this will need to be redumped from another board.
1225 /* this is the "VECTOR ROM" (256*8, 82s135) which runs the vector generator state machine
1226 * the vector rom bits are complex and are unfortunately poorly documented
1227 * in the tech manual. see figure 5-23.
1228 * control bits:
1229 * /CE1 ----- /GO aka GO L [verified via tracing]
1230 * /CE2 ----- GND [verified via tracing]
1231 * addr bits: 76543210
1232 * ||||\\\\-- To sync counter, which counts 0xC 0x3 0x2 0x1 0x0 0x5 0x4 0xB 0xA 0x9 0x8 0xD in that order
1233 * |||\------ (MODE 0 NAND GO) \_This effectively means when GO is low, these bits are both 1, when GO is high, these bits are the inverse of the MODE bits; this is DIFFERENT from the vt125, and was probably removed as unnecessary given that /GO is an enable for the vector rom anyway [verified via tracing]
1234 * ||\------- (MODE 1 NAND GO) /
1235 * |\-------- ? C OUT (when set, only one /LD ERROR pulse occurs instead of two)
1236 * \--------- ? FINISH (/LD ERROR only goes active (low) when this is unset)
1237 *
1238 * data bits: 76543210
1239 * |||||||\-- /WRITE aka WRITE L (fig 5-20, page 5-32, writes the post-pattern-converted value back to vram at X,Y)
1240 * ||||||\--- DONE L [verified via tracing]
1241 * |||||\---- VECTOR CLK aka V CLK [verified via tracing]
1242 * ||||\----- /LD ERROR aka STROBE ERROR L (strobes the adder result value into the vgERR register)
1243 * |||\------ D LOAD [by process of elimination and limited tracing]
1244 * ||\------- ERASE L (latched, forces a4 on the sync rom low and also forces a7 on the ras/erase rom; the counter rom may be involved in blanking all of vram) [verified via tracing]
1245 * |\-------- C0 aka C IN (high during DVM read, low otherwise, a carry in to the adder so DVM is converted from 1s to 2s complement)
1246 * \--------- SHIFT ENA [verified via tracing]
1247 * The data bits all have pull-ups to +5v if the /CE1 pin is not low
1248 * According to the VT125 tech manual (vt100 tech manual rev 3, page 6-85) the 8 signals here are:
1249 * ERASE L - d5
1250 * SHIFT ENA - d7
1251 * C IN - d6
1252 * D LOAD - d4
1253 * WRITE L - d0
1254 * DONE L - d1
1255 * VECTOR CLK - d2
1256 * STROBE ERROR L - d3
1257 *
1258 * The VT125 prom E71 and its latch E70 is mostly equivalent to the vector prom, but the address order is different
1259 */
1260 ROM_LOAD( "wb8146_058b1.mmi6309.pr1.ic99", 0x0000, 0x0100, BAD_DUMP CRC(71b01864) SHA1(e552f5b0bc3f443299282b1da7e9dbfec60e12bf)) // label verified from nigwil's and andy's board
1261
1262 ROM_REGION( 0x20, "sync", ROMREGION_ERASEFF )
1263 /* this is the "SYNC ROM" == mb6331 (32x8, 82s123)
1264 * It generates the ram RAS/CAS and a few other signals, see figure 5-20 on page 5-32
1265 * The exact pins for each signal are not documented.
1266 * control bits:
1267 * /CE1 -- GND(Unused)
1268 * addr bits: 43210
1269 * |\\\\-- To sync counter, which counts 0xC 0x3 0x2 0x1 0x0 0x5 0x4 0xB 0xA 0x9 0x8 0xD in that order
1270 * \------ comes from the gated ERASE L/d5 from the vector rom, only low during VG_MODE == ER (ERase Screen) [verified via tracing]
1271 * when high: the sync rom matches figure 5-20 (page 5-32) and 5-23 (page 5-38)
1272 * when low: RA/RB is fixed on WOPS in the register file
1273 * LD SHFR does NOT output pulses (effectively blanking the screen)
1274 * WRT/RD is held at /RD so vg to vram do nothing,
1275 * however while the crtc is refreshing the screen it instead is writing zeroes to every location
1276 * data bits: 76543210
1277 * |||||||\-- WRT/RD (write high when x,y (vg) drives vram, read low when ma (crtc) drives vram)
1278 * ||||||\--- /RAS (for vram)
1279 * |||||\---- STROBE aka STROBE L aka VG STROBE(latches the carry bit from the adder to the direction rom AND causes the data at the X,Y address of vram to be read into the holding register before pattern is applied)
1280 * ||||\----- LD SHFR (loads the 12-bit shift register of data to be shifted to screen)
1281 * |||\------ /CAS (for vram)
1282 * ||\------- RA\__selects which slot of the 8x4 register file (du, dvm, dir, or wops) is selected
1283 * |\-------- RB/
1284 * \--------- SYNC (latches the EXECUTE signal from an EXEC * write to activate the GO signal and enable the Vector rom) [verified via tracing]
1285 * The VT125 proms E64/E66 and their respective latches E65 and E83 are mostly equivalent to the sync rom
1286 */
1287 ROM_LOAD( "wb8014_297a1.74s288.pr6.ic89", 0x0000, 0x0020, CRC(e2f7c566) SHA1(a4c3dc5d07667141ad799168a862cb3c489b4934)) // label verified from nigwil's and andy's board
1288 ROM_END
1289
1290 /* Driver */
1291
1292 /* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */
1293 COMP( 1980, vk100, 0, 0, vk100, vk100, vk100_state, init_vk100, "Digital Equipment Corporation", "VK100 'GIGI'", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
1294