MAME: Connect a serial port to a board driver

This ariticle shows how to add a serial port to a board driver in MAME.

When I say serial port in this article I mean a asyncronous serial port running at speeds suitable for a human text interface, normally up to 115200 baud. Synchrounous serial connections and split speed setups are for later explorations.

In any MAME driver for a board containing a serial port there is a section where the emulated serial device is connected to the MAME UI. I have choosen to use the default generic terminal emulation in MAME rather than one of the emulated terminals mainly because I don't have ROM:s for any of those. The section for one of the drivers I have written, to be found under src/mame/drivers, looks like this:

 /* Terminal Port config */
 MCFG_SCC8530_ADD("scc", SCC_CLOCK, 0, 0, 0, 0 )
 MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_txd))
 MCFG_Z80SCC_OUT_DTRA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_dtr))
 MCFG_Z80SCC_OUT_RTSA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_rts))

 MCFG_RS232_PORT_ADD ("rs232trm", default_rs232_devices, "terminal")

 MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("scc", scc8530_device, rxa_w))
 MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("scc", scc8530_device, ctsa_w))

Lets go through each of the statements above. The first one adds the serial device to the board and calls it "scc".

 MCFG_SCC8530_ADD("scc", SCC_CLOCK, 0, 0, 0, 0 )

If there were more than one SCC chip on the board it would be natural to call the second device "scc2" and so forth. Note however that "scc" is the chip itself not the port so the "scc" device in this case has also a port A and a port B.

Note also that the macro is called MCFG_SCC8530_ADD rather than MCFG_Z80SCC_ADD, to configure the emulation to mimic the subtle differences of the 8530 compared to the other SCC variants in the family which must match what is on the board of course to work with the ROM:s from that particular board. There is no way to "enhance" the emulation of a particular board by configure a more potent chip variant, it will probably not work at all and in best case have a similar capacity.

The SCC_CLOCK is defined in the board driver and must match the clock that the scc device uses on this particular board, in this case it is defined as XTAL_5MHz. The last four zeroes in the macro indicates that this board to not use separate clock for Rx and Tx on Port A and B respectivelly. This must match the board hardware and has nothing to do with configuring the bahviour of the ROM software.

The second line connects the transmit lines of port A, eg TXDA, of the "scc" device to a RS232 device called "rs232trm".

  MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_txd))

Now this has some magic behind the scenes that is not obvious. Firstly there is no reference to the "scc" device. After unvinding the *_ADD macros one can find that a reference to the added device is maintained between the lines which means that the order is very important!

There is also a reference to the "rs232trm" device which is undefined at this point. This is looked up at runtime and the reference to "rs232trm" is resolved to refer to the device created a few lines below.

The _CB refers to that this define sets up the callback in the port device which is called when the serial device wants to send data which is triggered by the original ROM code. The callback resides in the rs232_port_device class and is called write_txd.

The third and fourth lines connects in the same manner callbacks for the DTR and RTS handshake signals which are both supported by the SCC device. Some boards may have the handshake signals implemented through a parallell port which would be easy to emulate using the same macros.

 MCFG_Z80SCC_OUT_DTRA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_dtr))
 MCFG_Z80SCC_OUT_RTSA_CB(DEVWRITELINE("rs232trm", rs232_port_device, write_rts))

The macros in the last three lines are included from the bus/rs232/rs232.h header file. The first one adds the missing "rs232trm" device.

 MCFG_RS232_PORT_ADD ("rs232trm", default_rs232_devices, "terminal")

The RS232 device is implemented as a MAME slot device which means that it can connect between a number of different client devices who's names are listed in the default_rs232_devices array in devices/bus/rs232/rs232.cpp:

SLOT_INTERFACE_START( default_rs232_devices )
SLOT_INTERFACE("keyboard", SERIAL_KEYBOARD)
SLOT_INTERFACE("loopback", RS232_LOOPBACK)
SLOT_INTERFACE("null_modem", NULL_MODEM)
SLOT_INTERFACE("printer", SERIAL_PRINTER)
SLOT_INTERFACE("terminal", SERIAL_TERMINAL)
SLOT_INTERFACE("pty", PSEUDO_TERMINAL)
SLOT_INTERFACE_END

These are all there to interact with the end user though the UI so not real emulated devices in the sence that there was a physical original. We choose to use the "terminal" as default and this can be overriden with command line switches but that is a subject for another article.

The  next two lines for the RS232 configuration adds callbacks needed to handle RXA and CTS.

 MCFG_RS232_RXD_HANDLER (DEVWRITELINE ("scc", scc8530_device, rxa_w))
 MCFG_RS232_CTS_HANDLER (DEVWRITELINE ("scc", scc8530_device, ctsa_w))

So when the user presses a key in the terminal emulation it send the keystroke to port A of the "scc" device using the rxa_w callback of the SCC device driver. If the terminal gets more data than it can handle it will signal this by using the CTS callback. Note that the RS232 device macros uses the term HANDLER which is equivalent of CB (callback) of the SCC device

Inga kommentarer:

Skicka en kommentar