tisdag 21 februari 2017

The prodigy #9 - the BCD display part 3


Netlist is a CPU device in MAME that slices the time at a higher rate than the clocks on the other devices and is because of this able to calculate levels in analog as well as in digital circuits between the clock cycles. This is important as it can also span multiple clock domains and synchronize independently running sub circuits including CPU:s.

The drawback is of course that it takes more host CPU power to emulate things this way so the trick is to find a good mid ground. In the prodigy project we need a 74164 device that is implemented as part of the Netlist framework in order to contribute to this better emulation.

In the previous blog we checked out how to emulate the 74164 the usual way. To do the same thing using MAME Netlists we need to write a netlist device and it is also quite small however the way of connecting it the Prodigy driver is more complex.

If we start with the device configuration it looks like this:

MCFG_DEVICE_ADD(NETLIST_TAG, NETLIST_CPU, XTAL_2MHz * 30)
MCFG_NETLIST_SETUP(prodigy)

MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cb1", "cb1.IN", 0)
MCFG_NETLIST_LOGIC_INPUT(NETLIST_TAG, "cb2", "cb2.IN", 0)
MCFG_NETLIST_LOGIC_OUTPUT(NETLIST_TAG, "bcd_bit0",  "bcd_bit0",  prodigy_state, bcd_bit0_cb, "")
MCFG_NETLIST_LOGIC_OUTPUT(NETLIST_TAG, "bcd_bit1",  "bcd_bit1",  prodigy_state, bcd_bit1_cb, "")
MCFG_NETLIST_LOGIC_OUTPUT(NETLIST_TAG, "bcd_bit2",  "bcd_bit2",  prodigy_state, bcd_bit2_cb, "")
MCFG_NETLIST_LOGIC_OUTPUT(NETLIST_TAG, "bcd_bit3",  "bcd_bit3",  prodigy_state, bcd_bit3_cb, "")
MCFG_NETLIST_LOGIC_OUTPUT(NETLIST_TAG, "bcd_bit4",  "bcd_bit4",  prodigy_state, bcd_bit4_cb, "")
MCFG_NETLIST_LOGIC_OUTPUT(NETLIST_TAG, "bcd_bit5",  "bcd_bit5",  prodigy_state, bcd_bit5_cb, "")
MCFG_NETLIST_LOGIC_OUTPUT(NETLIST_TAG, "bcd_bit6",  "bcd_bit6",  prodigy_state, bcd_bit6_cb, "")
MCFG_NETLIST_LOGIC_OUTPUT(NETLIST_TAG, "bcd_bit7",  "bcd_bit7",  prodigy_state, bcd_bit7_cb, "")

As can be seen the NETLIST_CPU runs at 30 times the 2MHz of the CPU and VIA devices. This is not a tuned value at this point as we may need to add more things ot the Netlist later. The second thing that strikes the eye is that there is no sign of the 74164 itself but instead a netlist called 'prodigy'. This is because the circuit itself is a sub device put in separate file, the setup of the 74164 looks like this:

 TTL_INPUT(cb1, 0)
 TTL_INPUT(cb2, 0)

 TTL_74164(SHIFT, cb2, cb2, high, cb1)
 ALIAS(bcd_bit0, SHIFT.QA)
 ALIAS(bcd_bit1, SHIFT.QB)
 ALIAS(bcd_bit2, SHIFT.QC)
 ALIAS(bcd_bit3, SHIFT.QD)
 ALIAS(bcd_bit4, SHIFT.QE)
 ALIAS(bcd_bit5, SHIFT.QF)
 ALIAS(bcd_bit6, SHIFT.QG)
 ALIAS(bcd_bit7, SHIFT.QH)


To actually hook up all this to the VIA requires some more glue, first we need to tell MAME that we need the netlist circuit and the inputs to it.


 required_device<netlist_mame_device_t> m_bcd;
 required_device<netlist_mame_logic_input_t> m_cb1;
 required_device<netlist_mame_logic_input_t> m_cb2;


We also the callbacks where the Netlist communicates back the changes in signal states:


NETDEV_LOGIC_CALLBACK_MEMBER(prodigy_state::bcd_bit0_cb) 
{ 
 if (data != 0) 
  m_digit |= 0x01;
 else 
  m_digit &= ~(0x01);
}

Lastly we use some trampoline methods to route the VIA output into our Netlist:


MCFG_VIA6522_CB1_HANDLER(WRITELINE(prodigy_state, via_cb1_w))
MCFG_VIA6522_CB2_HANDLER(WRITELINE(prodigy_state, via_cb2_w))

WRITE_LINE_MEMBER(prodigy_state::via_cb1_w)
{
 LOGCLK("%s: %d\n", FUNCNAME, state);
 m_cb1->write(state);
}

WRITE_LINE_MEMBER(prodigy_state::via_cb2_w)
{
 LOGCLK("%s: %d\n", FUNCNAME, state);
 m_cb2->write(state);
}

To summarize the chain of events that takes place:

  • The CB1 and CB2 trampoline handlers, via_cb1_w and via_cb2_w respectivelly, are called when the VIA device generates changes on these outputs. 
  • The  handlers calls the write method on the netlist input devices m_cb1 and m_cb2. 
  • The netlist is crunched at 30 times the CPU clock, at an emulated 60MHz, and are able to calculate the logical signals at this rate. 
  • When the 74164 output signals enters a TTL low or high levels the bcd_bitx_cb() callback routine corresponding to the bit that has changed is called with the logical state. 
  • The callbacks finally compiles all the changes into a 8 bit pattern which are the segment values to be lit!
Next thing is to lit the correct BCD display! 

Inga kommentarer:

Skicka en kommentar