diff options
Diffstat (limited to 'src/emu/machine/pc_lpt.c')
-rw-r--r-- | src/emu/machine/pc_lpt.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/src/emu/machine/pc_lpt.c b/src/emu/machine/pc_lpt.c new file mode 100644 index 00000000000..e5558835e21 --- /dev/null +++ b/src/emu/machine/pc_lpt.c @@ -0,0 +1,170 @@ +/*************************************************************************** + + IBM-PC printer interface + +***************************************************************************/ + +#include "emu.h" +#include "pc_lpt.h" +#include "bus/centronics/covox.h" +#include "bus/centronics/image.h" + + +const device_type PC_LPT = &device_creator<pc_lpt_device>; + +pc_lpt_device::pc_lpt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, PC_LPT, "PC-LPT", tag, owner, clock, "pc_lpt", __FILE__), + m_irq(1), + m_data(0xff), + m_irq_enabled(1), + m_centronics_ack(1), + m_irq_handler(*this), + m_cent_data_in(*this, "cent_data_in"), + m_cent_data_out(*this, "cent_data_out"), + m_cent_status_in(*this, "cent_status_in"), + m_cent_ctrl_in(*this, "cent_ctrl_in"), + m_cent_ctrl_out(*this, "cent_ctrl_out") +{ +} + +void pc_lpt_device::device_start() +{ + m_irq_handler.resolve_safe(); + + save_item(NAME(m_irq)); + save_item(NAME(m_data)); + save_item(NAME(m_control)); + save_item(NAME(m_centronics_ack)); + save_item(NAME(m_irq_enabled)); + + m_cent_data_out->write(m_data); +} + +void pc_lpt_device::device_reset() +{ + m_control = ~(0 ^ CONTROL_INIT); + m_cent_ctrl_out->write(m_control); +} + +static SLOT_INTERFACE_START(pc_centronics) + SLOT_INTERFACE("image", CENTRONICS_PRINTER_IMAGE) + SLOT_INTERFACE("covox", CENTRONICS_COVOX) + SLOT_INTERFACE("covox_stereo", CENTRONICS_COVOX_STEREO) +SLOT_INTERFACE_END + +static MACHINE_CONFIG_FRAGMENT( pc_lpt ) + MCFG_CENTRONICS_ADD("centronics", pc_centronics, "image") + MCFG_CENTRONICS_DATA_INPUT_BUFFER("cent_data_in") + MCFG_CENTRONICS_FAULT_HANDLER(DEVWRITELINE("cent_status_in", input_buffer_device, write_bit3)) + MCFG_CENTRONICS_SELECT_HANDLER(DEVWRITELINE("cent_status_in", input_buffer_device, write_bit4)) + MCFG_CENTRONICS_PERROR_HANDLER(DEVWRITELINE("cent_status_in", input_buffer_device, write_bit5)) + MCFG_CENTRONICS_ACK_HANDLER(WRITELINE(pc_lpt_device, write_centronics_ack)) + MCFG_CENTRONICS_BUSY_HANDLER(DEVWRITELINE("cent_status_in", input_buffer_device, write_bit7)) + + MCFG_CENTRONICS_STROBE_HANDLER(DEVWRITELINE("cent_ctrl_in", input_buffer_device, write_bit0)) + MCFG_CENTRONICS_AUTOFD_HANDLER(DEVWRITELINE("cent_ctrl_in", input_buffer_device, write_bit1)) + MCFG_CENTRONICS_INIT_HANDLER(DEVWRITELINE("cent_ctrl_in", input_buffer_device, write_bit2)) + MCFG_CENTRONICS_SELECT_IN_HANDLER(DEVWRITELINE("cent_ctrl_in", input_buffer_device, write_bit3)) + + MCFG_DEVICE_ADD("cent_data_in", INPUT_BUFFER, 0) + MCFG_DEVICE_ADD("cent_ctrl_in", INPUT_BUFFER, 0) + MCFG_DEVICE_ADD("cent_status_in", INPUT_BUFFER, 0) + + MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", "centronics") + + MCFG_DEVICE_ADD("cent_ctrl_out", OUTPUT_LATCH, 0) + MCFG_OUTPUT_LATCH_BIT0_HANDLER(DEVWRITELINE("centronics", centronics_device, write_strobe)) + MCFG_OUTPUT_LATCH_BIT1_HANDLER(DEVWRITELINE("centronics", centronics_device, write_autofd)) + MCFG_OUTPUT_LATCH_BIT2_HANDLER(DEVWRITELINE("centronics", centronics_device, write_init)) + MCFG_OUTPUT_LATCH_BIT3_HANDLER(DEVWRITELINE("centronics", centronics_device, write_select_in)) + MCFG_OUTPUT_LATCH_BIT4_HANDLER(WRITELINE(pc_lpt_device, write_irq_enabled)) +MACHINE_CONFIG_END + +machine_config_constructor pc_lpt_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( pc_lpt ); +} + +READ8_MEMBER( pc_lpt_device::data_r ) +{ + // pull up mechanism for input lines, zeros are provided by peripheral + return m_data & m_cent_data_in->read(); +} + +WRITE8_MEMBER( pc_lpt_device::data_w ) +{ + m_data = data; + m_cent_data_out->write(m_data); +} + +READ8_MEMBER( pc_lpt_device::status_r ) +{ + return m_cent_status_in->read() ^ STATUS_BUSY; +} + +READ8_MEMBER( pc_lpt_device::control_r ) +{ + return ~((m_control & m_cent_ctrl_in->read() & 0x3f) ^ CONTROL_INIT); +} + +WRITE8_MEMBER( pc_lpt_device::control_w ) +{ + // logerror("pc_lpt_control_w: 0x%02x\n", data); + + m_control = ~(data ^ CONTROL_INIT); + m_cent_ctrl_out->write(m_control); +} + +READ8_MEMBER( pc_lpt_device::read ) +{ + switch (offset) + { + case 0: return data_r(space, 0); + case 1: return status_r(space, 0); + case 2: return control_r(space, 0); + } + + /* if we reach this its an error */ + logerror("PC-LPT %s: Read from invalid offset %x\n", tag(), offset); + + return 0xff; +} + +WRITE8_MEMBER( pc_lpt_device::write ) +{ + switch (offset) + { + case 0: data_w(space, 0, data); break; + case 1: break; + case 2: control_w(space, 0, data); break; + } +} + +void pc_lpt_device::update_irq() +{ + int irq = 1; // high impedance + if (!m_irq_enabled) + { + irq = m_centronics_ack; + } + + if (m_irq != irq) + { + m_irq = irq; + m_irq_handler(!irq); + } +} + +WRITE_LINE_MEMBER( pc_lpt_device::write_irq_enabled ) +{ + m_irq_enabled = state; + update_irq(); +} + +WRITE_LINE_MEMBER( pc_lpt_device::write_centronics_ack ) +{ + m_centronics_ack = state; + m_cent_status_in->write_bit6(state); + update_irq(); +} + |