mame/src/emu/machine/ctronics.c
2011-05-06 12:45:56 +00:00

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);