Previous 199869 Revisions Next

r17684 Thursday 6th September, 2012 at 20:08:05 UTC by Jonathan Gevaryahu
(MESS) VK100: Correctly hooked up vsync interrupt to crtc instead of video subsystem; Figured out the low two bits of SYSTAT_A from tracing and hooked both up, and updated the SYSTAT_A documentation comments. Additional documentation comments for the SMC COM5016T baud rate divider. Made the DU/DVM/DIR/WOPS 8*4bit register file an actual 4-entry array, to simplify address decoding later. [Lord Nightmare]
[src/mess/drivers]vk100.c

trunk/src/mess/drivers/vk100.c
r17683r17684
44
55        12/05/2009 Skeleton driver.
66        28/07/2009 added Guru-readme(TM)
7        08/01/2012 Fleshed out driver.
78
89        Todo:
910              * fix vector generator hardware enough to pass the startup self test
1011                the tests are described on page 6-5 thru 6-8 of the tech reference
1112              * hook up the direction and sync prom to the sync counter
1213              * figure out the correct meaning of systat b register - needed for communications selftest
13              * hook up smc_5016t baud generator to i8251 rx and tx clocks - begun
14              * hook up smc com5016t baud generator to i8251 rx and tx clocks - begun
1415
1516 Tony DiCenzo, now the director of standards and architecture at Oracle, was on the team that developed the VK100
1617 see http://startup.nmnaturalhistory.org/visitorstories/view.php?ii=79
r17683r17684
154155   UINT8* m_trans;
155156   UINT8* m_pattern;
156157   UINT8* m_dir;
158   UINT8 m_vsync; // vsync pin of crtc
157159   UINT16 m_vgX;
158160   UINT16 m_vgY;
159161   UINT16 m_vgERR; // error register can cause carries which need to be caught
r17683r17684
163165   UINT8 m_vgPMUL; // reload value for PMUL_Count
164166   UINT8 m_vgPMUL_Count;
165167   UINT8 m_vgDownCount; // down counter = number of pixels, loaded from vgDU on execute
166   UINT8 m_vgDU;
167   UINT8 m_vgDVM;
168   UINT8 m_vgDIR;
169   UINT8 m_vgWOPS;
168#define VG_DU m_regfile[0]
169#define VG_DVM m_regfile[1]
170#define VG_DIR m_regfile[2]
171#define VG_WOPS m_regfile[3]
172   UINT8 m_regfile[4];
170173   UINT8 m_VG_MODE; // 2 bits, latched on EXEC
171174   UINT8 m_vgGO; // activated on next SYNC pulse after EXEC
172175   UINT8 m_ACTS;
r17683r17684
243246   block |= data<<(nybbleNum*4); // write the new part
244247   // NOTE: this next part may have to be made conditional on VG_MODE
245248   // check if the attribute nybble is supposed to be modified, and if so do so
246   if (state->m_vgWOPS&0x08) block = (block&0x0FFF)|(((UINT16)state->m_vgWOPS&0xF0)<<8);
249   if (state->VG_WOPS&0x08) block = (block&0x0FFF)|(((UINT16)state->VG_WOPS&0xF0)<<8);
247250   state->m_vram[(EA<<1)+1] = block&0xFF; // write block back to vram
248251   state->m_vram[(EA<<1)] = (block&0xFF00)>>8; // ''
249252}
r17683r17684
253256   vk100_state *state = machine.driver_data<vk100_state>();
254257   UINT8 thisNyb = vram_read(machine); // read in the nybble
255258   // pattern rom addressing is a complex mess. see the pattern rom def later in this file.
256   UINT8 newNyb = state->m_pattern[((state->m_vgPAT&state->m_vgPAT_Mask)?0x200:0)|((state->m_vgWOPS&7)<<6)|((state->m_vgX&3)<<4)|thisNyb]; // calculate new nybble based on pattern rom
259   UINT8 newNyb = state->m_pattern[((state->m_vgPAT&state->m_vgPAT_Mask)?0x200:0)|((state->VG_WOPS&7)<<6)|((state->m_vgX&3)<<4)|thisNyb]; // calculate new nybble based on pattern rom
257260   // finally write the block back to ram depending on the VG_MODE (sort of a hack until we get the vector and synd and dir roms all hooked up)
258261   switch (state->m_VG_MODE)
259262   {
r17683r17684
305308     */
306309   //UINT8 direction_rom = state->m_dir[];
307310   // HACK: we need the proper direction rom dump for this!
308   switch(state->m_vgDIR&0x7)
311   switch(state->VG_DIR&0x7)
309312   {
310313      case 0:
311314         state->m_vgX++;
r17683r17684
423426/* port 0x60: "DU" load vg vector major register */
424427WRITE8_MEMBER(vk100_state::vgDU)
425428{
426   m_vgDU = data;
429   VG_DU = data;
427430#ifdef VG60_VERBOSE
428   logerror("VG: 0x60: DU Reg loaded with %02X\n", m_vgDU);
431   logerror("VG: 0x60: DU Reg loaded with %02X\n", VG_DU);
429432#endif
430433}
431434
432435/* port 0x61: "DVM" load vg vector minor register */
433436WRITE8_MEMBER(vk100_state::vgDVM)
434437{
435   m_vgDVM = data;
438   VG_DVM = data;
436439#ifdef VG60_VERBOSE
437   logerror("VG: 0x61: DVM Reg loaded with %02X\n", m_vgDVM);
440   logerror("VG: 0x61: DVM Reg loaded with %02X\n", VG_DVM);
438441#endif
439442}
440443
441444/* port 0x62: "DIR" load vg Direction register */
442445WRITE8_MEMBER(vk100_state::vgDIR)
443446{
444   m_vgDIR = data;
447   VG_DIR = data;
445448#ifdef VG60_VERBOSE
446   logerror("VG: 0x62: DIR Reg loaded with %02X\n", m_vgDIR);
449   logerror("VG: 0x62: DIR Reg loaded with %02X\n", VG_DIR);
447450#endif
448451}
449452
r17683r17684
455458 */
456459WRITE8_MEMBER(vk100_state::vgWOPS)
457460{
458   m_vgWOPS = data;
461   VG_WOPS = data;
459462#ifdef VG60_VERBOSE
460463   static const char *const functions[] = { "Overlay", "Replace", "Complement", "Erase" };
461   logerror("VG: 0x64: WOPS Reg loaded with %02X: KGRB %d%d%d%d, AttrChange %d, Function %s, Negate %d\n", data, (m_vgWOPS>>7)&1, (m_vgWOPS>>6)&1, (m_vgWOPS>>5)&1, (m_vgWOPS>>4)&1, (m_vgWOPS>>3)&1, functions[(m_vgWOPS>>1)&3], m_vgWOPS&1);
464   logerror("VG: 0x64: 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, functions[(VG_WOPS>>1)&3], VG_WOPS&1);
462465#endif
463466}
464467
r17683r17684
475478#endif
476479   m_vgPMUL_Count = m_vgPMUL; // load PMUL_Count
477480   m_vgPAT_Mask = 0x80;
478   m_vgDownCount = m_vgDU; // set down counter to length of major vector
481   m_vgDownCount = VG_DU; // set down counter to length of major vector
479482   m_VG_MODE = offset&3;
480483   m_vgGO = 1;
481484   machine().scheduler().timer_set(attotime::zero, FUNC(execute_vg));
r17683r17684
501504#endif
502505}
503506
504/* port 0x6C: "BAUD" controls the smc5016t dual baud generator which
507/* port 0x6C: "BAUD" controls the smc com5016t dual baud generator which
505508 * controls the divisors for the rx and tx clocks on the 8251 from the
506 * 5.0688Mhz cpu xtal :
509    5.0688Mhz cpu xtal.
510   It has 5v,12v on pins 2 and 9, pin 10 is NC.
511 * A later part that replaced this on the market is SMC COM8116(T)/8136(T), which
512    was a 5v-only part (pin 9 and 10 are NC, 10 is a clock out on the 8136.
513 *  Note that even on the SMC COM5016T version, SMC would allow the user
514     to mask their own dividers on custom ordered chips if desired.
515 *  The COM8116(T)/8136(T) came it at least 4 mask rom types meant for different
516     input clocks:
517     -000 or no mark for 5.0688Mhz (which exactly matches the table below)
518     -003 is for 6.01835MHz
519     -005 is for 4.915200Mhz
520     -006 is for 5.0688Mhz but omits the 2000 baud entry, instead has 200,
521      and output frequencies are 2x as fast (meant for a 32X clock uart)
522     -013 is for 2.76480MHz
523     -013A is for 5.52960MHz
524     (several other unknown refclock masks appear on partscalper sites)
525    GI also made a clone of the 8116 5v chip called the AY-5-8116(T)/8136(T)
526     which had at least two masks: -000/no mark and -005, matching speeds above
527    WD made the WD1943 which is similarly 5v compatible, with -00, -05, -06 masks
528    The COM8046(T) has 5 bits for selection instead of 4, but still expects
529     a 5.0688MHz reference clock, and the second half of the table matches the
530     values below; the first half of the table is the values below /2, rounded
531     down (for uarts which need a clock rate of 32x baud instead of 16x).
532    WD's BR1941 is also functionally compatible but uses 5v,12v,-5v on pins 2,9,10
507533 * 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
508534 * The others are based on page 13 of http://www.hartetechnologies.com/manuals/Tarbell/Tarbell%20Z80%20CPU%20Board%20Model%203033.pdf
509535 * D C B A   Divisor                                Expected Baud
r17683r17684
537563}
538564
539565/* port 0x40-0x47: "SYSTAT A"; various status bits, poorly documented in the tech manual
540 * /GO    BIT3   BIT2   BIT1   BIT0   Dip       ?      ?
541 *                                    Switch
542 * d7     d6     d5     d4     d3     d2        d1     d0
543 * bit3, 2, 1, 0 are the last 4 bits read by the vector generator from VRAM
544 * note: if the vector generator is not running, reading SYSTAT A will
545 * supposedly FORCE the vector generator to read one nybble from the
546 * current x,y! (how does this work schematicwise??? it may just read
547 * the last nybble read by the constantly running sync counter, in
548 * which case the hack here sort of works as well)
549 * this appears to be the only way the vram can be READ by the cpu
550 d2 is where the dipswitch values are read from, based on the offset
551 d1 is unknown
552 d0 is unknown
566 * /GO    BIT3   BIT2   BIT1   BIT0   Dip     RST7.5 GND
567 *                                    Switch  VSYNC
568 * d7     d6     d5     d4     d3     d2      d1     d0
569  bit3, 2, 1, 0 are the 4 bits output from the VRAM 12->4 multiplexer
570   which are also inputs to the pattern rom; they are constantly updated
571   by the sync rom and related circuitry.
572  This is the only way the vram can be read by the cpu.
573  d7 is from the /Q output of the GO latch
574  d6,5,4,3 are from the 74ls298 at ic4 (right edge of pcb)
575  d2 is where the dipswitch values are read from, based on the offset
576  d1 is connected to 8085 rst7.5 (pin 7) and crtc pin 40 (VSYNC) [verified via tracing]
577  d0 is tied to GND [verified via tracing]
553578
554579 31D reads and checks d7 in a loop
555580 205 reads, xors with 0x55 (from reg D), ANDS result with 0x78 and branches if it is not zero (checking for bit pattern 1010?)
r17683r17684
562587#ifdef SYSTAT_A_VERBOSE
563588   if (cpu_get_pc(m_maincpu) != 0x31D) logerror("0x%04X: SYSTAT_A Read!\n", cpu_get_pc(m_maincpu));
564589#endif
565   return ((m_vgGO?0:1)<<7)|(vram_read(machine())<<3)|(((ioport("SWITCHES")->read()>>dipswitchLUT[offset])&1)?0x4:0)|0x3;
590   return ((m_vgGO?0:1)<<7)|(vram_read(machine())<<3)|(((ioport("SWITCHES")->read()>>dipswitchLUT[offset])&1)?0x4:0)|(m_vsync?0x2:0);
566591}
567592
568593/* port 0x48: "SYSTAT B"; NOT documented in the tech manual at all.
r17683r17684
853878   output_set_value("hardcopy_led", 1);
854879   output_set_value("l1_led", 1);
855880   output_set_value("l2_led", 1);
881   state->m_vsync = 0;
856882   state->m_vgX = 0;
857883   state->m_vgY = 0;
858884   state->m_vgERR = 0;
r17683r17684
862888   state->m_vgPMUL = 0;
863889   state->m_vgPMUL_Count = 0;
864890   state->m_vgDownCount = 0;
865   state->m_vgDU = 0;
866   state->m_vgDVM = 0;
867   state->m_vgDIR = 0;
868   state->m_vgWOPS = 0;
891   state->VG_DU = 0;
892   state->VG_DVM = 0;
893   state->VG_DIR = 0;
894   state->VG_WOPS = 0;
869895   state->m_VG_MODE = 0;
870896   state->m_vgGO = 0;
871897   state->m_ACTS = 1;
r17683r17684
873899   state->m_TXDivisor = 6336;
874900}
875901
876static INTERRUPT_GEN( vk100_vertical_interrupt )
902static WRITE_LINE_DEVICE_HANDLER(crtc_vsync)
877903{
878   vk100_state *state = device->machine().driver_data<vk100_state>();
879   device_set_input_line(state->m_maincpu, I8085_RST75_LINE, ASSERT_LINE);
880   device_set_input_line(state->m_maincpu, I8085_RST75_LINE, CLEAR_LINE);
904   vk100_state *m_state = device->machine().driver_data<vk100_state>();
905   device_set_input_line(m_state->m_maincpu, I8085_RST75_LINE, state? ASSERT_LINE : CLEAR_LINE);
906   m_state->m_vsync = state;
881907}
882908
883909static WRITE_LINE_DEVICE_HANDLER(i8251_rxrdy_int)
r17683r17684
958984   DEVCB_NULL,
959985   DEVCB_NULL,
960986   DEVCB_NULL,
961   DEVCB_NULL,
987   DEVCB_LINE(crtc_vsync),
962988   NULL
963989};
964990
r17683r17684
9821008   MCFG_CPU_ADD("maincpu", I8085A, XTAL_5_0688MHz)
9831009   MCFG_CPU_PROGRAM_MAP(vk100_mem)
9841010   MCFG_CPU_IO_MAP(vk100_io)
985   MCFG_CPU_VBLANK_INT("screen", vk100_vertical_interrupt)
9861011
9871012   MCFG_MACHINE_RESET(vk100)
9881013

Previous 199869 Revisions Next


© 1997-2024 The MAME Team