mirror of
https://github.com/holub/mame
synced 2025-04-26 02:07:14 +03:00
392 lines
11 KiB
C
392 lines
11 KiB
C
/***************************************************************************
|
|
|
|
Centronics printer interface
|
|
|
|
***************************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "ctronics.h"
|
|
#include "imagedev/printer.h"
|
|
|
|
|
|
/***************************************************************************
|
|
FUNCTION PROTOTYPES
|
|
***************************************************************************/
|
|
|
|
static WRITE_LINE_DEVICE_HANDLER( centronics_printer_online );
|
|
static TIMER_CALLBACK( ack_callback );
|
|
static TIMER_CALLBACK( busy_callback );
|
|
|
|
|
|
/***************************************************************************
|
|
TYPE DEFINITIONS
|
|
***************************************************************************/
|
|
|
|
typedef struct _centronics_state centronics_state;
|
|
struct _centronics_state
|
|
{
|
|
device_t *printer;
|
|
|
|
devcb_resolved_write_line out_ack_func;
|
|
devcb_resolved_write_line out_busy_func;
|
|
devcb_resolved_write_line out_not_busy_func;
|
|
|
|
int strobe;
|
|
int busy;
|
|
int ack;
|
|
int auto_fd;
|
|
int pe;
|
|
int fault;
|
|
|
|
UINT8 data;
|
|
};
|
|
|
|
|
|
/*****************************************************************************
|
|
INLINE FUNCTIONS
|
|
*****************************************************************************/
|
|
|
|
INLINE centronics_state *get_safe_token(device_t *device)
|
|
{
|
|
assert(device != NULL);
|
|
assert(device->type() == CENTRONICS);
|
|
|
|
return (centronics_state *)downcast<legacy_device_base *>(device)->token();
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
GLOBAL VARIABLES
|
|
*****************************************************************************/
|
|
|
|
const centronics_interface standard_centronics =
|
|
{
|
|
FALSE,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL,
|
|
DEVCB_NULL
|
|
};
|
|
|
|
|
|
/*****************************************************************************
|
|
PRINTER INTERFACE
|
|
*****************************************************************************/
|
|
|
|
static MACHINE_CONFIG_FRAGMENT( centronics )
|
|
MCFG_PRINTER_ADD("printer")
|
|
MCFG_PRINTER_ONLINE(centronics_printer_online)
|
|
MACHINE_CONFIG_END
|
|
|
|
|
|
/*****************************************************************************
|
|
DEVICE INTERFACE
|
|
*****************************************************************************/
|
|
|
|
static DEVICE_START( centronics )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
const centronics_interface *intf = (const centronics_interface *)device->static_config();
|
|
|
|
/* validate some basic stuff */
|
|
assert(device->static_config() != NULL);
|
|
|
|
/* set some initial values */
|
|
centronics->pe = FALSE;
|
|
centronics->fault = FALSE;
|
|
centronics->busy = TRUE;
|
|
centronics->strobe = TRUE;
|
|
|
|
/* get printer device */
|
|
centronics->printer = device->subdevice("printer");
|
|
|
|
/* resolve callbacks */
|
|
centronics->out_ack_func.resolve(intf->out_ack_func, *device);
|
|
centronics->out_busy_func.resolve(intf->out_busy_func, *device);
|
|
centronics->out_not_busy_func.resolve(intf->out_not_busy_func, *device);
|
|
|
|
/* register for state saving */
|
|
device->save_item(NAME(centronics->auto_fd));
|
|
device->save_item(NAME(centronics->strobe));
|
|
device->save_item(NAME(centronics->busy));
|
|
device->save_item(NAME(centronics->ack));
|
|
device->save_item(NAME(centronics->data));
|
|
}
|
|
|
|
static DEVICE_RESET( centronics )
|
|
{
|
|
}
|
|
|
|
DEVICE_GET_INFO( centronics )
|
|
{
|
|
switch (state)
|
|
{
|
|
/* --- the following bits of info are returned as 64-bit signed integers --- */
|
|
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(centronics_state); break;
|
|
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
|
|
|
|
/* --- the following bits of info are returned as pointers --- */
|
|
case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = MACHINE_CONFIG_NAME(centronics); break;
|
|
|
|
/* --- the following bits of info are returned as pointers to data or functions --- */
|
|
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(centronics); break;
|
|
case DEVINFO_FCT_STOP: /* Nothing */ break;
|
|
case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(centronics); break;
|
|
|
|
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
|
case DEVINFO_STR_NAME: strcpy(info->s, "Centronics"); break;
|
|
case DEVINFO_STR_FAMILY: strcpy(info->s, "Centronics"); break;
|
|
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
|
|
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
|
|
case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break;
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
IMPLEMENTATION
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
centronics_printer_online - callback that
|
|
sets us busy when the printer goes offline
|
|
-------------------------------------------------*/
|
|
|
|
void centronics_printer_online(device_t *device, int state)
|
|
{
|
|
centronics_state *centronics = get_safe_token(device->owner());
|
|
|
|
/* when going online, set PE and FAULT high and BUSY low */
|
|
centronics->pe = state;
|
|
centronics->fault = state;
|
|
centronics->busy = !state;
|
|
}
|
|
|
|
|
|
static TIMER_CALLBACK( ack_callback )
|
|
{
|
|
centronics_state *centronics = (centronics_state *)ptr;
|
|
|
|
/* signal change */
|
|
centronics->out_ack_func(param);
|
|
centronics->ack = param;
|
|
|
|
if (param == FALSE)
|
|
{
|
|
/* data is now ready, output it */
|
|
printer_output(centronics->printer, centronics->data);
|
|
|
|
/* ready to receive more data, return BUSY to low */
|
|
machine.scheduler().timer_set(attotime::from_usec(7), FUNC(busy_callback), FALSE, ptr);
|
|
}
|
|
}
|
|
|
|
|
|
static TIMER_CALLBACK( busy_callback )
|
|
{
|
|
centronics_state *centronics = (centronics_state *)ptr;
|
|
|
|
/* signal change */
|
|
centronics->out_busy_func(param);
|
|
centronics->out_not_busy_func(!param);
|
|
centronics->busy = param;
|
|
|
|
if (param == TRUE)
|
|
{
|
|
/* timer to turn ACK low to receive data */
|
|
machine.scheduler().timer_set(attotime::from_usec(10), FUNC(ack_callback), FALSE, ptr);
|
|
}
|
|
else
|
|
{
|
|
/* timer to return ACK to high state */
|
|
machine.scheduler().timer_set(attotime::from_usec(5), FUNC(ack_callback), TRUE, ptr);
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_data_w - write print data
|
|
-------------------------------------------------*/
|
|
|
|
WRITE8_DEVICE_HANDLER( centronics_data_w )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
centronics->data = data;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_data_r - return current data
|
|
-------------------------------------------------*/
|
|
|
|
READ8_DEVICE_HANDLER( centronics_data_r )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
return centronics->data;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
set_line - helper to set individual bits
|
|
-------------------------------------------------*/
|
|
|
|
static void set_line(device_t *device, int line, int state)
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
|
|
if (state)
|
|
centronics->data |= 1 << line;
|
|
else
|
|
centronics->data &= ~(1 << line);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_dx_w - write line dx print data
|
|
-------------------------------------------------*/
|
|
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_d0_w ) { set_line(device, 0, state); }
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_d1_w ) { set_line(device, 1, state); }
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_d2_w ) { set_line(device, 2, state); }
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_d3_w ) { set_line(device, 3, state); }
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_d4_w ) { set_line(device, 4, state); }
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_d5_w ) { set_line(device, 5, state); }
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_d6_w ) { set_line(device, 6, state); }
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_d7_w ) { set_line(device, 7, state); }
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_strobe_w - signal that data is
|
|
ready
|
|
-------------------------------------------------*/
|
|
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_strobe_w )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
|
|
/* look for a high -> low transition */
|
|
if (centronics->strobe == TRUE && state == FALSE && centronics->busy == FALSE)
|
|
{
|
|
/* STROBE has gone low, data is ready */
|
|
device->machine().scheduler().timer_set(attotime::zero, FUNC(busy_callback), TRUE, centronics);
|
|
}
|
|
|
|
centronics->strobe = state;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_prime_w - initialize and reset
|
|
printer (centronics mode)
|
|
-------------------------------------------------*/
|
|
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_prime_w )
|
|
{
|
|
assert(((const centronics_interface *)device->static_config())->is_ibmpc == FALSE);
|
|
|
|
/* reset printer if line is low */
|
|
if (state == FALSE)
|
|
DEVICE_RESET_CALL( centronics );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_init_w - initialize and reset
|
|
printer (ibm mode)
|
|
-------------------------------------------------*/
|
|
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_init_w )
|
|
{
|
|
assert(((const centronics_interface *)device->static_config())->is_ibmpc == TRUE);
|
|
|
|
/* reset printer if line is low */
|
|
if (state == FALSE)
|
|
DEVICE_RESET_CALL( centronics );
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_autofeed_w - auto line feed
|
|
-------------------------------------------------*/
|
|
|
|
WRITE_LINE_DEVICE_HANDLER( centronics_autofeed_w )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
assert(((const centronics_interface *)device->static_config())->is_ibmpc == TRUE);
|
|
|
|
centronics->auto_fd = state;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_ack_r - return the state of the
|
|
ack line
|
|
-------------------------------------------------*/
|
|
|
|
READ_LINE_DEVICE_HANDLER( centronics_ack_r )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
return centronics->ack;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_busy_r - return the state of the
|
|
busy line
|
|
-------------------------------------------------*/
|
|
|
|
READ_LINE_DEVICE_HANDLER( centronics_busy_r )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
return centronics->busy;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_pe_r - return the state of the
|
|
pe line
|
|
-------------------------------------------------*/
|
|
|
|
READ_LINE_DEVICE_HANDLER( centronics_pe_r )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
return centronics->pe;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_not_busy_r - return the state of the
|
|
not busy line
|
|
-------------------------------------------------*/
|
|
|
|
READ_LINE_DEVICE_HANDLER( centronics_not_busy_r )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
return !centronics->busy;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_vcc_r - return the state of the
|
|
vcc line
|
|
-------------------------------------------------*/
|
|
|
|
READ_LINE_DEVICE_HANDLER( centronics_vcc_r )
|
|
{
|
|
/* always return high */
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
centronics_fault_r - return the state of the
|
|
fault line
|
|
-------------------------------------------------*/
|
|
|
|
READ_LINE_DEVICE_HANDLER( centronics_fault_r )
|
|
{
|
|
centronics_state *centronics = get_safe_token(device);
|
|
return centronics->fault;
|
|
}
|
|
|
|
DEFINE_LEGACY_DEVICE(CENTRONICS, centronics);
|