diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/diserial.c | 76 | ||||
-rw-r--r-- | src/emu/diserial.h | 4 | ||||
-rw-r--r-- | src/emu/imagedev/bitbngr.c | 27 | ||||
-rw-r--r-- | src/emu/imagedev/bitbngr.h | 5 | ||||
-rw-r--r-- | src/emu/machine/ins8250.c | 683 | ||||
-rw-r--r-- | src/emu/machine/ins8250.h | 151 | ||||
-rw-r--r-- | src/emu/machine/microtch.c | 349 | ||||
-rw-r--r-- | src/emu/machine/microtch.h | 102 | ||||
-rw-r--r-- | src/emu/machine/pc16552d.c | 6 | ||||
-rw-r--r-- | src/emu/machine/pc16552d.h | 2 | ||||
-rw-r--r-- | src/mame/drivers/adp.c | 31 | ||||
-rw-r--r-- | src/mame/drivers/cd32.c | 21 | ||||
-rw-r--r-- | src/mame/drivers/magtouch.c | 45 | ||||
-rw-r--r-- | src/mame/drivers/meritm.c | 33 | ||||
-rw-r--r-- | src/mame/drivers/pcat_nit.c | 45 | ||||
-rw-r--r-- | src/mame/drivers/tmaster.c | 30 | ||||
-rw-r--r-- | src/mame/includes/cd32.h | 8 |
17 files changed, 813 insertions, 805 deletions
diff --git a/src/emu/diserial.c b/src/emu/diserial.c index 5e4cdfa37da..bcdd5b3ca10 100644 --- a/src/emu/diserial.c +++ b/src/emu/diserial.c @@ -76,12 +76,12 @@ void device_serial_interface::receive_register_update_bit(int bit) int previous_bit; //LOG(("receive register receive bit: %1x\n",bit)); - previous_bit = m_rcv_register_data & 1; + previous_bit = (m_rcv_register_data & 0x8000) && 1; /* shift previous bit 7 out */ - m_rcv_register_data = m_rcv_register_data<<1; + m_rcv_register_data = m_rcv_register_data>>1; /* shift new bit in */ - m_rcv_register_data = (m_rcv_register_data & 0xfffe) | bit; + m_rcv_register_data = (m_rcv_register_data & 0x7fff) | (bit<<15); /* update bit count received */ m_rcv_bit_count_received++; @@ -123,47 +123,34 @@ void device_serial_interface::receive_register_update_bit(int bit) void device_serial_interface::receive_register_extract() { - unsigned long data_shift; UINT8 data; receive_register_reset(); - data_shift = 0; - - /* if parity is even or odd, there should be a parity bit in the stream! */ - if (m_df_parity!=SERIAL_PARITY_NONE) - { - data_shift++; - } - - data_shift+=m_df_stop_bit_count; - /* strip off stop bits and parity */ - data = m_rcv_register_data>>data_shift; + data = m_rcv_register_data>>(16-m_rcv_bit_count); /* mask off other bits so data byte has 0's in unused bits */ - data = data & (0x0ff - >> - (8-(m_df_word_length))); + data &= ~(0xff<<m_df_word_length); m_rcv_byte_received = data; + if(m_df_parity == SERIAL_PARITY_NONE) + return; + + //unsigned char computed_parity; + //unsigned char parity_received; + + /* get state of parity bit received */ + //parity_received = (m_rcv_register_data>>m_df_word length) & 0x01; + /* parity enable? */ switch (m_df_parity) { - case SERIAL_PARITY_NONE: - break; - /* check parity */ case SERIAL_PARITY_ODD: case SERIAL_PARITY_EVEN: { - //unsigned char computed_parity; - //unsigned char parity_received; - - /* get state of parity bit received */ - //parity_received = (m_rcv_register_data>>m_df_stop_bit_count) & 0x01; - /* compute parity for received bits */ //computed_parity = serial_helper_get_parity(data); @@ -182,6 +169,10 @@ void device_serial_interface::receive_register_extract() } break; + case SERIAL_PARITY_MARK: + case SERIAL_PARITY_SPACE: + //computed_parity = parity_received; + break; } } @@ -225,23 +216,34 @@ void device_serial_interface::transmit_register_setup(UINT8 data_byte) int databit; /* get bit from data */ - databit = (transmit_data>>(m_df_word_length-1)) & 0x01; + databit = transmit_data & 0x01; /* add bit to formatted byte */ transmit_register_add_bit(databit); - transmit_data = transmit_data<<1; + transmit_data = transmit_data>>1; } /* parity */ if (m_df_parity!=SERIAL_PARITY_NONE) { /* odd or even parity */ - unsigned char parity; - - /* get parity */ - /* if parity = 0, data has even parity - i.e. there is an even number of one bits in the data */ - /* if parity = 1, data has odd parity - i.e. there is an odd number of one bits in the data */ - parity = serial_helper_get_parity(data_byte); + unsigned char parity = 0; + switch(m_df_parity) + { + case SERIAL_PARITY_EVEN: + case SERIAL_PARITY_ODD: + /* get parity */ + /* if parity = 0, data has even parity - i.e. there is an even number of one bits in the data */ + /* if parity = 1, data has odd parity - i.e. there is an odd number of one bits in the data */ + parity = serial_helper_get_parity(data_byte); + break; + case SERIAL_PARITY_MARK: + parity = 1; + break; + case SERIAL_PARITY_SPACE: + parity = 0; + break; + } transmit_register_add_bit(parity); } @@ -258,9 +260,7 @@ UINT8 device_serial_interface::transmit_register_get_data_bit() { int bit; - bit = (m_tra_register_data>> - (m_tra_bit_count - 1 - - m_tra_bit_count_transmitted)) & 0x01; + bit = (m_tra_register_data>>(m_tra_bit_count-1-m_tra_bit_count_transmitted))&1; m_tra_bit_count_transmitted++; diff --git a/src/emu/diserial.h b/src/emu/diserial.h index 4b2482b6c22..cfb4cdb5e07 100644 --- a/src/emu/diserial.h +++ b/src/emu/diserial.h @@ -19,7 +19,9 @@ enum { SERIAL_PARITY_NONE, /* no parity. a parity bit will not be in the transmitted/received data */ SERIAL_PARITY_ODD, /* odd parity */ - SERIAL_PARITY_EVEN /* even parity */ + SERIAL_PARITY_EVEN, /* even parity */ + SERIAL_PARITY_MARK, /* one parity */ + SERIAL_PARITY_SPACE /* zero parity */ }; /* diff --git a/src/emu/imagedev/bitbngr.c b/src/emu/imagedev/bitbngr.c index 19702a12d76..c57a2dda0ab 100644 --- a/src/emu/imagedev/bitbngr.c +++ b/src/emu/imagedev/bitbngr.c @@ -303,8 +303,6 @@ void bitbanger_device::bytes_to_bits_81N(void) void bitbanger_device::device_start(void) { - const bitbanger_config *config = (const bitbanger_config *) static_config(); - /* output config */ m_build_count = 0; m_output_timer = timer_alloc(TIMER_OUTPUT); @@ -316,13 +314,13 @@ void bitbanger_device::device_start(void) m_input_buffer_cursor = 0; /* defaults */ - m_mode = config->m_default_mode; - m_baud = config->m_default_baud; - m_tune = config->m_default_tune; + m_mode = m_default_mode; + m_baud = m_default_baud; + m_tune = m_default_tune; m_current_baud = attotime::from_hz(baud_value()); /* callback */ - m_input_callback.resolve(config->m_input_callback, *this); + m_input_func.resolve(m_input_callback, *this); } @@ -333,6 +331,18 @@ void bitbanger_device::device_start(void) void bitbanger_device::device_config_complete(void) { + const _bitbanger_config *intf = reinterpret_cast<const _bitbanger_config *>(static_config()); + if(intf != NULL) + { + *static_cast<_bitbanger_config *>(this) = *intf; + } + else + { + memset(&m_input_callback, 0, sizeof(m_input_callback)); + m_default_mode = 0; + m_default_baud = 0; + m_default_tune = 0; + } update_names(); } @@ -433,10 +443,7 @@ void bitbanger_device::set_input_line(UINT8 line) if (m_current_input != line) { m_current_input = line; - if (!m_input_callback.isnull()) - { - m_input_callback(line ? ASSERT_LINE : CLEAR_LINE); - } + m_input_func(line ? ASSERT_LINE : CLEAR_LINE); } } diff --git a/src/emu/imagedev/bitbngr.h b/src/emu/imagedev/bitbngr.h index a6f887201ae..24c662d3cae 100644 --- a/src/emu/imagedev/bitbngr.h +++ b/src/emu/imagedev/bitbngr.h @@ -84,7 +84,8 @@ struct _bitbanger_config class bitbanger_device : public device_t, - public device_image_interface + public device_image_interface, + public _bitbanger_config { public: // construction/destruction @@ -145,7 +146,7 @@ private: // variables emu_timer * m_output_timer; emu_timer * m_input_timer; - devcb_resolved_write_line m_input_callback; + devcb_resolved_write_line m_input_func; int m_output_value; int m_build_count; int m_build_byte; diff --git a/src/emu/machine/ins8250.c b/src/emu/machine/ins8250.c index 8fa8aea7aec..c1135ae2d4a 100644 --- a/src/emu/machine/ins8250.c +++ b/src/emu/machine/ins8250.c @@ -73,136 +73,66 @@ History: **********************************************************************/ -#include "emu.h" #include "machine/ins8250.h" +const device_type INS8250 = &device_creator<ins8250_device>; +const device_type NS16450 = &device_creator<ns16450_device>; +const device_type NS16550 = &device_creator<ns16550_device>; -#define LOG(LEVEL,N,M,A) \ - do { \ - if(LEVEL>=N) \ - { \ - if( M ) \ - logerror("%-24s",(char*)M ); \ - logerror A; \ - } \ - } while (0) - - -/* device types */ -enum { - TYPE_INS8250 = 0, - TYPE_INS8250A, - TYPE_NS16450, - TYPE_NS16550, - TYPE_NS16550A, - TYPE_PC16550D, - - NUM_TYPES -}; - - -/* device tags */ -static const char * const device_tags[NUM_TYPES] = { "ins8250", "ins8250a", "ns16450", "ns16550", "ns16550a", "pc16550d" }; - - -#define VERBOSE_COM 0 -#define COM_LOG(n,m,a) LOG(VERBOSE_COM,n,m,a) - -typedef struct { - devcb_resolved_write_line out_intr_func; - const ins8250_interface *interface; - int device_type; - - UINT8 thr; /* 0 -W transmitter holding register */ - UINT8 rbr; /* 0 R- receiver buffer register */ - UINT8 ier; /* 1 RW interrupt enable register */ - UINT8 dll; /* 0 RW divisor latch lsb (if DLAB = 1) */ - UINT8 dlm; /* 1 RW divisor latch msb (if DLAB = 1) */ - UINT8 iir; /* 2 R- interrupt identification register */ - UINT8 lcr; /* 3 RW line control register (bit 7: DLAB) */ - UINT8 mcr; /* 4 RW modem control register */ - UINT8 lsr; /* 5 R- line status register */ - UINT8 msr; /* 6 R- modem status register */ - UINT8 scr; /* 7 RW scratch register */ - -/* holds int pending state for com */ - UINT8 int_pending; - - // sending circuit - struct { - int active; - UINT8 data; - double time; - } send; -} ins8250_t; - -/* int's pending */ -#define COM_INT_PENDING_RECEIVED_DATA_AVAILABLE 0x0001 -#define COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY 0x0002 -#define COM_INT_PENDING_RECEIVER_LINE_STATUS 0x0004 -#define COM_INT_PENDING_MODEM_STATUS_REGISTER 0x0008 - - -INLINE ins8250_t *get_safe_token(device_t *device) +ins8250_uart_device::ins8250_uart_device(const machine_config &mconfig, device_type type, const char* name, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, type, name, tag, owner, clock), + device_serial_interface(mconfig, *this) { - assert( device != NULL ); - assert( ( device->type() == INS8250 ) || - ( device->type() == INS8250A ) || - ( device->type() == NS16450 ) || - ( device->type() == NS16550 ) || - ( device->type() == NS16550A ) || - ( device->type() == PC16550D ) ); - return (ins8250_t *)downcast<legacy_device_base *>(device)->token(); } - -/* setup iir with the priority id */ -static void ins8250_setup_iir(device_t *device) +ins8250_device::ins8250_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : ins8250_uart_device(mconfig, INS8250, "ins8250", tag, owner, clock) { - ins8250_t *ins8250 = get_safe_token(device); - - ins8250->iir &= ~(0x04|0x02); - - /* highest to lowest */ - if (ins8250->ier & ins8250->int_pending & COM_INT_PENDING_RECEIVER_LINE_STATUS) - { - ins8250->iir |=0x04|0x02; - return; - } - - if (ins8250->ier & ins8250->int_pending & COM_INT_PENDING_RECEIVED_DATA_AVAILABLE) - { - ins8250->iir |=0x04; - return; - } + m_device_type = TYPE_INS8250; +} - if (ins8250->ier & ins8250->int_pending & COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY) - { - ins8250->iir |=0x02; - return; - } +ns16450_device::ns16450_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : ins8250_uart_device(mconfig, NS16450, "ns16450", tag, owner, clock) +{ + m_device_type = TYPE_NS16450; +} - /* modem status has both bits clear */ +ns16550_device::ns16550_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : ins8250_uart_device(mconfig, NS16550, "ns16550", tag, owner, clock) +{ + m_device_type = TYPE_NS16550; } +/* int's pending */ +#define COM_INT_PENDING_RECEIVED_DATA_AVAILABLE 0x0001 +#define COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY 0x0002 +#define COM_INT_PENDING_RECEIVER_LINE_STATUS 0x0004 +#define COM_INT_PENDING_MODEM_STATUS_REGISTER 0x0008 /* ints will continue to be set for as long as there are ints pending */ -static void ins8250_update_interrupt(device_t *device) +void ins8250_uart_device::update_interrupt() { - ins8250_t *ins8250 = get_safe_token(device); int state; /* if any bits are set and are enabled */ - if (((ins8250->int_pending&ins8250->ier) & 0x0f) != 0) + if (((m_int_pending & m_regs.ier) & 0x0f) != 0) { /* trigger next highest priority int */ /* set int */ state = 1; - ins8250_setup_iir(device); + m_regs.iir &= ~(0x04|0x02); + + /* highest to lowest */ + if (m_regs.ier & m_int_pending & COM_INT_PENDING_RECEIVER_LINE_STATUS) + m_regs.iir |=0x04|0x02; + else if (m_regs.ier & m_int_pending & COM_INT_PENDING_RECEIVED_DATA_AVAILABLE) + m_regs.iir |=0x04; + else if (m_regs.ier & m_int_pending & COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY) + m_regs.iir |=0x02; /* int pending */ - ins8250->iir &= ~0x01; + m_regs.iir &= ~0x01; } else { @@ -210,128 +140,127 @@ static void ins8250_update_interrupt(device_t *device) state = 0; /* no ints pending */ - ins8250->iir |= 0x01; + m_regs.iir |= 0x01; /* priority level */ - ins8250->iir &= ~(0x04|0x02); + m_regs.iir &= ~(0x04|0x02); } /* set or clear the int */ - ins8250->out_intr_func(state); + m_out_int_func(state); } - - /* set pending bit and trigger int */ -static void ins8250_trigger_int(device_t *device, int flag) +void ins8250_uart_device::trigger_int(int flag) { - ins8250_t *ins8250 = get_safe_token(device); - - ins8250->int_pending |= flag; - ins8250_update_interrupt(device); + m_int_pending |= flag; + update_interrupt(); } - - /* clear pending bit, if any ints are pending, then int will be triggered, otherwise it will be cleared */ -static void ins8250_clear_int(device_t *device, int flag) +void ins8250_uart_device::clear_int(int flag) { - ins8250_t *ins8250 = get_safe_token(device); - - ins8250->int_pending &= ~flag; - ins8250_update_interrupt(device); + m_int_pending &= ~flag; + update_interrupt(); } +void ins8250_uart_device::update_clock() +{ + int baud; + if(m_regs.dl == 0) + { + m_timer->adjust(attotime::never); + return; + } + baud = clock()/(m_regs.dl*16); + m_timer->adjust(attotime::zero, 0, attotime::from_hz(baud)); +} -WRITE8_DEVICE_HANDLER( ins8250_w ) +WRITE8_MEMBER( ins8250_uart_device::ins8250_w ) { - static const char P[] = "NONENHNL"; /* names for parity select */ - ins8250_t *ins8250 = get_safe_token(device); - int tmp; + int tmp; switch (offset) { case 0: - if (ins8250->lcr & 0x80) + if (m_regs.lcr & 0x80) { - ins8250->dll = data; - tmp = ins8250->dlm * 256 + ins8250->dll; - COM_LOG(1,"COM_dll_w",("COM \"%s\" $%02x: [$%04x = %d baud]\n", device->tag(), - data, tmp, (tmp)?(int)(ins8250->interface->clockin/16/tmp):0)); + m_regs.dl = (m_regs.dl & 0xff00) | data; + update_clock(); } else { - ins8250->thr = data; - COM_LOG(2,"COM_thr_w",("COM $%02x\n", data)); - - if ( ins8250->mcr & 0x10 ) + m_regs.thr = data; + m_regs.lsr &= ~0x60; + if ( m_regs.mcr & 0x10 ) { - ins8250->lsr |= 1; - ins8250->rbr = data; - ins8250_trigger_int( device, COM_INT_PENDING_RECEIVED_DATA_AVAILABLE ); + m_regs.lsr |= 1; + m_regs.rbr = data; + trigger_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE); } - - if ( ins8250->interface->transmit ) - ins8250->interface->transmit(device, ins8250->thr); - - /* writing to thr will clear the int */ - ins8250_clear_int(device, COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY); } break; case 1: - if (ins8250->lcr & 0x80) + if (m_regs.lcr & 0x80) { - ins8250->dlm = data; - tmp = ins8250->dlm * 256 + ins8250->dll; - COM_LOG(1,"COM_dlm_w",("COM \"%s\" $%02x: [$%04x = %d baud]\n", device->tag(), - data, tmp, (tmp)?(int)(ins8250->interface->clockin/16/tmp):0)); + m_regs.dl = (m_regs.dl & 0xff) | (data << 8); + update_clock(); } else { - ins8250->ier = data; - COM_LOG(2,"COM_ier_w",("COM \"%s\" $%02x: enable int on RX %d, THRE %d, RLS %d, MS %d\n", device->tag(), - data, data&1, (data>>1)&1, (data>>2)&1, (data>>3)&1)); - COM_LOG(2,"COM_ier_w",("COM \"%s\" lsr = $%02x, int_pending = $%02x\n", device->tag(), ins8250->lsr, ins8250->int_pending )); - ins8250_update_interrupt(device); + m_regs.ier = data; + update_interrupt(); } break; case 2: - COM_LOG(1,"COM_fcr_w",("COM \"%s\" $%02x (16550 only)\n", device->tag(), data)); break; case 3: - ins8250->lcr = data; - COM_LOG(1,"COM_lcr_w",("COM \"%s\" $%02x word length %d, stop bits %d, parity %c, break %d, DLAB %d\n", device->tag(), - data, 5+(data&3), 1+((data>>2)&1), P[(data>>3)&7], (data>>6)&1, (data>>7)&1)); - break; + m_regs.lcr = data; + switch ((m_regs.lcr>>3) & 7) + { + case 1: + tmp = SERIAL_PARITY_ODD; + break; + case 3: + tmp = SERIAL_PARITY_EVEN; + break; + case 5: + tmp = SERIAL_PARITY_MARK; + break; + case 7: + tmp = SERIAL_PARITY_SPACE; + break; + default: + tmp = SERIAL_PARITY_NONE; + break; + } + // if 5 data bits and stb = 1, stop bits is supposed to be 1.5 + set_data_frame((m_regs.lcr & 3) + 5, (m_regs.lcr & 4)?2:1, tmp); + break; case 4: - if ( ( ins8250->mcr & 0x1f ) != ( data & 0x1f ) ) + if ( ( m_regs.mcr & 0x1f ) != ( data & 0x1f ) ) { - ins8250->mcr = data & 0x1f; - COM_LOG(1,"COM_mcr_w",("COM \"%s\" $%02x DTR %d, RTS %d, OUT1 %d, OUT2 %d, loopback %d\n", device->tag(), - data, data&1, (data>>1)&1, (data>>2)&1, (data>>3)&1, (data>>4)&1)); - if (ins8250->interface->handshake_out) - ins8250->interface->handshake_out(device,data); + m_regs.mcr = data & 0x1f; - if ( ins8250->mcr & 0x10 ) /* loopback test */ + if ( m_regs.mcr & 0x10 ) /* loopback test */ { - data = ( ( ins8250->mcr & 0x0c ) << 4 ) | ( ( ins8250->mcr & 0x01 ) << 5 ) | ( ( ins8250->mcr & 0x02 ) << 3 ); - if ( ( ins8250->msr & 0x20 ) != ( data & 0x20 ) ) - { + data = ( ( m_regs.mcr & 0x0c ) << 4 ) | ( ( m_regs.mcr & 0x01 ) << 5 ) | ( ( m_regs.mcr & 0x02 ) << 3 ); + if ( ( m_regs.msr & 0x20 ) != ( data & 0x20 ) ) data |= 0x02; - } - if ( ( ins8250->msr & 0x10 ) != ( data & 0x10 ) ) - { + if ( ( m_regs.msr & 0x10 ) != ( data & 0x10 ) ) data |= 0x01; - } - if ( ( ins8250->msr & 0x40 ) && ! ( data & 0x40 ) ) - { + if ( ( m_regs.msr & 0x40 ) && ! ( data & 0x40 ) ) data |= 0x04; - } - if ( ( ins8250->msr & 0x80 ) != ( data & 0x80 ) ) - { + if ( ( m_regs.msr & 0x80 ) != ( data & 0x80 ) ) data |= 0x08; - } - ins8250->msr = data; + m_regs.msr = data; + } + else + { + m_out_dtr_func(m_regs.mcr & 1); + m_out_rts_func((m_regs.mcr & 2) && 1); + m_out_out1_func((m_regs.mcr & 4) && 1); + m_out_out2_func((m_regs.mcr & 8) && 1); } } break; @@ -341,15 +270,13 @@ WRITE8_DEVICE_HANDLER( ins8250_w ) bits 5 - 0, you could cause an interrupt if the appropriate IER bit is set. */ - COM_LOG(1,"COM_lsr_w",("COM \"%s\" $%02x\n", device->tag(), data )); - - ins8250->lsr = data; + m_regs.lsr = data; tmp = 0; - tmp |= ( ins8250->lsr & 0x01 ) ? COM_INT_PENDING_RECEIVED_DATA_AVAILABLE : 0; - tmp |= ( ins8250->lsr & 0x1e ) ? COM_INT_PENDING_RECEIVER_LINE_STATUS : 0; - tmp |= ( ins8250->lsr & 0x20 ) ? COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY : 0; - ins8250_trigger_int( device, tmp ); + tmp |= ( m_regs.lsr & 0x01 ) ? COM_INT_PENDING_RECEIVED_DATA_AVAILABLE : 0; + tmp |= ( m_regs.lsr & 0x1e ) ? COM_INT_PENDING_RECEIVER_LINE_STATUS : 0; + tmp |= ( m_regs.lsr & 0x20 ) ? COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY : 0; + trigger_int(tmp); break; case 6: @@ -358,358 +285,188 @@ WRITE8_DEVICE_HANDLER( ins8250_w ) bits 3 - 0, you could cause an interrupt if the appropriate IER bit is set. */ - COM_LOG(1,"COM_msr_w",("COM \"%s\" $%02x\n", device->tag(), data )); + m_regs.msr = data; - ins8250->msr = data; - - if ( ins8250->msr & 0x0f ) - { - ins8250_trigger_int( device, COM_INT_PENDING_MODEM_STATUS_REGISTER ); - } + if ( m_regs.msr & 0x0f ) + trigger_int(COM_INT_PENDING_MODEM_STATUS_REGISTER); break; case 7: - ins8250->scr = data; - COM_LOG(2,"COM_scr_w",("COM \"%s\" $%02x\n", device->tag(), data)); + m_regs.scr = data; break; } - - if (ins8250->interface->refresh_connected) - ins8250->interface->refresh_connected(device); } - - -READ8_DEVICE_HANDLER( ins8250_r ) +READ8_MEMBER( ins8250_uart_device::ins8250_r ) { - ins8250_t *ins8250 = get_safe_token(device); int data = 0x0ff; switch (offset) { case 0: - if (ins8250->lcr & 0x80) - { - data = ins8250->dll; - COM_LOG(1,"COM_dll_r",("COM \"%s\" $%02x\n", device->tag(), data)); - } + if (m_regs.lcr & 0x80) + data = (m_regs.dl & 0xff); else { - data = ins8250->rbr; - if( ins8250->lsr & 0x01 ) - { - ins8250->lsr &= ~0x01; /* clear data ready status */ - COM_LOG(2,"COM_rbr_r",("COM \"%s\" $%02x\n", device->tag(), data)); - } + data = m_regs.rbr; + if( m_regs.lsr & 0x01 ) + m_regs.lsr &= ~0x01; /* clear data ready status */ - ins8250_clear_int(device, COM_INT_PENDING_RECEIVED_DATA_AVAILABLE); + clear_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE); } break; case 1: - if (ins8250->lcr & 0x80) - { - data = ins8250->dlm; - COM_LOG(1,"COM_dlm_r",("COM \"%s\" $%02x\n", device->tag(), data)); - } + if (m_regs.lcr & 0x80) + data = (m_regs.dl >> 8); else - { - data = ins8250->ier & 0x0f; - COM_LOG(2,"COM_ier_r",("COM \"%s\" $%02x\n", device->tag(), data)); - } + data = m_regs.ier & 0x0f; break; case 2: - data = ins8250->iir; - COM_LOG(2,"COM_iir_r",("COM \"%s\" $%02x\n", device->tag(), data)); + data = m_regs.iir; /* The documentation says that reading this register will clear the int if this is the source of the int */ - if ( ins8250->ier & COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY ) - { - ins8250_clear_int(device, COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY); - } + if ( m_regs.ier & COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY ) + clear_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY); break; case 3: - data = ins8250->lcr; - COM_LOG(2,"COM_lcr_r",("COM \"%s\" $%02x\n", device->tag(), data)); + data = m_regs.lcr; break; case 4: - data = ins8250->mcr; - COM_LOG(2,"COM_mcr_r",("COM \"%s\" $%02x\n", device->tag(), data)); + data = m_regs.mcr; break; case 5: - -#if 0 - if (ins8250->send.active && (machine.time()-ins8250->send.time>uart_byte_time(n))) - { - // currently polling is enough for pc1512 - ins8250->lsr |= 0x40; /* set TSRE */ - ins8250->send.active = 0; - if ( ins8250->mcr & 0x10 ) - { - ins8250->lsr |= 1; - ins8250->rbr = ins8250->send.data; - } - } -#endif - ins8250->lsr |= 0x60; /* set THRE */ - data = ins8250->lsr; - if( ins8250->lsr & 0x1f ) - { - ins8250->lsr &= 0xe1; /* clear FE, PE and OE and BREAK bits */ - COM_LOG(2,"COM_lsr_r",("COM \"%s\" $%02x, DR %d, OE %d, PE %d, FE %d, BREAK %d, THRE %d, TSRE %d\n", device->tag(), - data, data&1, (data>>1)&1, (data>>2)&1, (data>>3)&1, (data>>4)&1, (data>>5)&1, (data>>6)&1)); - } + data = m_regs.lsr; + if( m_regs.lsr & 0x1f ) + m_regs.lsr &= 0xe1; /* clear FE, PE and OE and BREAK bits */ /* reading line status register clears int */ - ins8250_clear_int(device, COM_INT_PENDING_RECEIVER_LINE_STATUS); + clear_int(COM_INT_PENDING_RECEIVER_LINE_STATUS); break; case 6: - data = ins8250->msr; - ins8250->msr &= 0xf0; /* reset delta values */ - COM_LOG(2,"COM_msr_r",("COM \"%s\" $%02x\n", device->tag(), data)); + data = m_regs.msr; + m_regs.msr &= 0xf0; /* reset delta values */ /* reading msr clears int */ - ins8250_clear_int(device, COM_INT_PENDING_MODEM_STATUS_REGISTER); + clear_int(COM_INT_PENDING_MODEM_STATUS_REGISTER); break; case 7: - data = ins8250->scr; - COM_LOG(2,"COM_scr_r",("COM \"%s\" $%02x\n", device->tag(), data)); + data = m_regs.scr; break; } - - if (ins8250->interface->refresh_connected) - ins8250->interface->refresh_connected(device); - return data; } - - -void ins8250_receive(device_t *device, int data) +void ins8250_uart_device::update_msr(int bit, UINT8 state) { - ins8250_t *ins8250 = get_safe_token(device); - - /* check if data rate 1200 baud is set */ - if( ins8250->dlm != 0x00 || ins8250->dll != 0x60 ) - ins8250->lsr |= 0x08; /* set framing error */ - - /* if data not yet serviced */ - if( ins8250->lsr & 0x01 ) - ins8250->lsr |= 0x02; /* set overrun error */ - - /* put data into receiver buffer register */ - ins8250->rbr = data; - - /* set data ready status */ - ins8250->lsr |= 0x01; - - /* set pending state for this interrupt. */ - ins8250_trigger_int(device, COM_INT_PENDING_RECEIVED_DATA_AVAILABLE); - - -// /* OUT2 + received line data avail interrupt enabled? */ -// if( (COM_mcr[n] & 0x08) && (COM_ier[n] & 0x01) ) -// { -// if (com_interface.interrupt) -// com_interface.interrupt(4-(n&1), 1); -// -// } -} - -/************************************************************************** - * change the modem status register - **************************************************************************/ -void ins8250_handshake_in(device_t *device, int new_msr) -{ - ins8250_t *ins8250 = get_safe_token(device); - - /* no change in modem status bits? */ - if( ((ins8250->msr ^ new_msr) & 0xf0) == 0 ) + UINT8 mask = (1<<bit); + if((m_regs.msr & mask) == (state<<bit)) return; - - /* set delta status bits 0..3 and new modem status bits 4..7 */ - ins8250->msr = (((ins8250->msr ^ new_msr) >> 4) & 0x0f) | (new_msr & 0xf0); - - ins8250_trigger_int(device, COM_INT_PENDING_MODEM_STATUS_REGISTER); - -// /* set up interrupt information register */ - // COM_iir[n] &= ~(0x06 | 0x01); - -// /* OUT2 + modem status interrupt enabled? */ -// if( (COM_mcr[n] & 0x08) && (COM_ier[n] & 0x08) ) -// { -// if (com_interface.interrupt) -// com_interface.interrupt(4-(n&1), 1); -// } -} - - -static void common_start( device_t *device, int device_type ) -{ - ins8250_t *ins8250 = get_safe_token(device); - - ins8250->interface = (const ins8250_interface*)device->static_config(); - ins8250->device_type = device_type; - - ins8250->out_intr_func.resolve(ins8250->interface->out_intr_cb, *device); -} - - -static DEVICE_START( ins8250 ) -{ - common_start( device, TYPE_INS8250 ); -} - - -static DEVICE_START( ins8250a ) -{ - common_start( device, TYPE_INS8250A ); -} - - -static DEVICE_START( ns16450 ) -{ - common_start( device, TYPE_NS16450 ); + m_regs.msr = (m_regs.msr & ~mask) | (mask & (state<<bit)); + m_regs.msr = (m_regs.msr & ~(mask << 4)) | (1<<(bit+4)); + trigger_int(COM_INT_PENDING_MODEM_STATUS_REGISTER); } - -static DEVICE_START( ns16550 ) +WRITE_LINE_MEMBER(ins8250_uart_device::dcd_w) { - common_start( device, TYPE_NS16550 ); + update_msr(3, (state&&1)); } - -static DEVICE_START( ns16550a ) +WRITE_LINE_MEMBER(ins8250_uart_device::dsr_w) { - common_start( device, TYPE_NS16550A ); + update_msr(1, (state&&1)); } - -static DEVICE_START( pc16550d ) +WRITE_LINE_MEMBER(ins8250_uart_device::ri_w) { - common_start( device, TYPE_PC16550D ); + update_msr(2, (state&&1)); } - -static DEVICE_RESET( ins8250 ) +WRITE_LINE_MEMBER(ins8250_uart_device::cts_w) { - ins8250_t *ins8250 = get_safe_token(device); - - ins8250->ier = 0; - ins8250->iir = 1; - ins8250->lcr = 0; - ins8250->mcr = 0; - ins8250->lsr = (1<<5) | (1<<6); - - ins8250->send.active=0; - - /* refresh with reset state of register */ - if (ins8250->interface->refresh_connected) - ins8250->interface->refresh_connected(device); + update_msr(0, (state&&1)); } - -DEVICE_GET_INFO( ins8250 ) +void ins8250_uart_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - switch ( state ) + receive_register_update_bit(m_rx_line); + if(is_receive_register_full()) { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ins8250_t); break; - case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ins8250); break; - case DEVINFO_FCT_STOP: /* nothing */ break; - case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(ins8250); break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor INS8250/INS8250B"); break; - case DEVINFO_STR_FAMILY: strcpy(info->s, "INS8250"); break; - case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break; - case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; - case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MESS Team"); break; + if(m_regs.lsr & 0x01) + { + m_regs.lsr |= 0x02; //overrun + trigger_int(COM_INT_PENDING_RECEIVER_LINE_STATUS); + } + else + { + m_regs.lsr |= 0x01; + receive_register_extract(); + m_regs.rbr = get_received_char(); + trigger_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE); + } + receive_register_reset(); } -} - -DEVICE_GET_INFO( ins8250a ) -{ - switch ( state ) + if(is_transmit_register_empty()) { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor INS8250A/INS82C50A"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ins8250a); break; - - default: DEVICE_GET_INFO_CALL(ins8250); break; + if(!(m_regs.lsr & 0x20)) + { + transmit_register_setup(m_regs.thr); + m_regs.lsr &= ~0x40; + m_regs.lsr |= 0x20; + trigger_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY); + } + else + m_regs.lsr |= 0x40; } + else + m_out_tx_func(transmit_register_get_data_bit()); } - -DEVICE_GET_INFO( ns16450 ) +void ins8250_uart_device::device_start() { - switch ( state ) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor NS16450/PC16450"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ns16450); break; - - default: DEVICE_GET_INFO_CALL(ins8250); break; - } + m_out_tx_func.resolve(m_out_tx_cb, *this); + m_out_dtr_func.resolve(m_out_dtr_cb, *this); + m_out_rts_func.resolve(m_out_rts_cb, *this); + m_out_int_func.resolve(m_out_int_cb, *this); + m_out_out1_func.resolve(m_out_out1_cb, *this); + m_out_out2_func.resolve(m_out_out2_cb, *this); + + m_timer = timer_alloc(); } - -DEVICE_GET_INFO( ns16550 ) +void ins8250_uart_device::device_reset() { - switch ( state ) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor NS16550/PC16550"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ns16550); break; - - default: DEVICE_GET_INFO_CALL(ins8250); break; - } + memset(&m_regs, '\0', sizeof(m_regs)); + m_regs.ier = 0; + m_regs.iir = 1; + m_regs.lcr = 0; + m_regs.mcr = 0; + m_regs.lsr = (1<<5) | (1<<6); + m_int_pending = 0; + m_rx_line = 0; + m_timer->adjust(attotime::never); + receive_register_reset(); + transmit_register_reset(); + m_out_rts_func(0); + m_out_dtr_func(0); + m_out_out1_func(0); + m_out_out2_func(0); } - -DEVICE_GET_INFO( ns16550a ) +void ins8250_uart_device::device_config_complete() { - switch ( state ) + const ins8250_interface *intf = reinterpret_cast<const ins8250_interface *>(static_config()); + if(intf != NULL) { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor NS16550A/PC16550A"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ns16550a); break; - - default: DEVICE_GET_INFO_CALL(ins8250); break; + *static_cast<ins8250_interface *>(this) = *intf; } -} - - -DEVICE_GET_INFO( pc16550d ) -{ - switch ( state ) + else { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor PC16550D"); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(pc16550d); break; - - default: DEVICE_GET_INFO_CALL(ins8250); break; + memset(&m_out_tx_cb, 0, sizeof(m_out_tx_cb)); + memset(&m_out_dtr_cb, 0, sizeof(m_out_dtr_cb)); + memset(&m_out_rts_cb, 0, sizeof(m_out_rts_cb)); + memset(&m_out_int_cb, 0, sizeof(m_out_int_cb)); + memset(&m_out_out1_cb, 0, sizeof(m_out_out1_cb)); + memset(&m_out_out2_cb, 0, sizeof(m_out_out2_cb)); } } - - - -DEFINE_LEGACY_DEVICE(INS8250, ins8250); -DEFINE_LEGACY_DEVICE(INS8250A, ins8250a); -DEFINE_LEGACY_DEVICE(NS16450, ns16450); -DEFINE_LEGACY_DEVICE(NS16550, ns16550); -DEFINE_LEGACY_DEVICE(NS16550A, ns16550a); -DEFINE_LEGACY_DEVICE(PC16550D, pc16550d); diff --git a/src/emu/machine/ins8250.h b/src/emu/machine/ins8250.h index ef00e544573..f89dee43937 100644 --- a/src/emu/machine/ins8250.h +++ b/src/emu/machine/ins8250.h @@ -7,77 +7,120 @@ #ifndef __INS8250_H_ #define __INS8250_H_ -#include "devlegcy.h" - -DECLARE_LEGACY_DEVICE(INS8250, ins8250); -DECLARE_LEGACY_DEVICE(INS8250A, ins8250a); -DECLARE_LEGACY_DEVICE(NS16450, ns16450); -DECLARE_LEGACY_DEVICE(NS16550, ns16550); -DECLARE_LEGACY_DEVICE(NS16550A, ns16550a); -DECLARE_LEGACY_DEVICE(PC16550D, pc16550d); - -#define UART8250_HANDSHAKE_OUT_DTR 0x01 -#define UART8250_HANDSHAKE_OUT_RTS 0x02 - -#define UART8250_HANDSHAKE_IN_DSR 0x020 -#define UART8250_HANDSHAKE_IN_CTS 0x010 -#define UART8250_INPUTS_RING_INDICATOR 0x0040 -#define UART8250_INPUTS_DATA_CARRIER_DETECT 0x0080 - +#include "emu.h" /*************************************************************************** - TYPE DEFINITIONS + CLASS DEFINITIONS ***************************************************************************/ - -typedef void (*ins8250_transmit_func)(device_t *device, int data); -typedef void (*ins8250_handshake_out_func)(device_t *device, int data); -typedef void (*ins8250_refresh_connect_func)(device_t *device); - -#define INS8250_TRANSMIT(name) void name(device_t *device, int data) -#define INS8250_HANDSHAKE_OUT(name) void name(device_t *device, int data) -#define INS8250_REFRESH_CONNECT(name) void name(device_t *device) - -typedef struct +struct ins8250_interface +{ + devcb_write_line m_out_tx_cb; + devcb_write_line m_out_dtr_cb; + devcb_write_line m_out_rts_cb; + devcb_write_line m_out_int_cb; + devcb_write_line m_out_out1_cb; + devcb_write_line m_out_out2_cb; +}; + +class ins8250_uart_device : public device_t, + public device_serial_interface, + public ins8250_interface +{ +public: + ins8250_uart_device(const machine_config &mconfig, device_type type, const char* name, const char *tag, device_t *owner, UINT32 clock); + DECLARE_WRITE8_MEMBER( ins8250_w ); + DECLARE_READ8_MEMBER( ins8250_r ); + DECLARE_WRITE_LINE_MEMBER( dcd_w ); + DECLARE_WRITE_LINE_MEMBER( dsr_w ); + DECLARE_WRITE_LINE_MEMBER( ri_w ); + DECLARE_WRITE_LINE_MEMBER( cts_w ); + DECLARE_WRITE_LINE_MEMBER( rx_w ) { m_rx_line = state; } + void input_callback(UINT8 state) { m_input_state = state; } + +protected: + virtual void device_start(); + virtual void device_config_complete(); + virtual void device_reset(); + enum { + TYPE_INS8250 = 0, + TYPE_INS8250A, + TYPE_NS16450, + TYPE_NS16550, + TYPE_NS16550A, + TYPE_PC16550D, + }; + int m_device_type; +private: + struct { + UINT8 thr; /* 0 -W transmitter holding register */ + UINT8 rbr; /* 0 R- receiver buffer register */ + UINT8 ier; /* 1 RW interrupt enable register */ + UINT16 dl; /* 0/1 RW divisor latch (if DLAB = 1) */ + UINT8 iir; /* 2 R- interrupt identification register */ + UINT8 lcr; /* 3 RW line control register (bit 7: DLAB) */ + UINT8 mcr; /* 4 RW modem control register */ + UINT8 lsr; /* 5 R- line status register */ + UINT8 msr; /* 6 R- modem status register */ + UINT8 scr; /* 7 RW scratch register */ + } m_regs; + UINT8 m_int_pending; + UINT8 m_rx_line; + + devcb_resolved_write_line m_out_tx_func; + devcb_resolved_write_line m_out_dtr_func; + devcb_resolved_write_line m_out_rts_func; + devcb_resolved_write_line m_out_int_func; + devcb_resolved_write_line m_out_out1_func; + devcb_resolved_write_line m_out_out2_func; + + void update_interrupt(); + void update_clock(); + void trigger_int(int flag); + void clear_int(int flag); + void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + void update_msr(int bit, UINT8 state); + + emu_timer *m_timer; +}; + +class ins8250_device : public ins8250_uart_device { - long clockin; - devcb_write_line out_intr_cb; +public: + ins8250_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; - ins8250_transmit_func transmit; - ins8250_handshake_out_func handshake_out; +class ns16450_device : public ins8250_uart_device +{ +public: + ns16450_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; - // refresh object connected to this port - ins8250_refresh_connect_func refresh_connected; -} ins8250_interface; +class ns16550_device : public ins8250_uart_device +{ +public: + ns16550_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; +extern const device_type INS8250; +extern const device_type NS16450; +extern const device_type NS16550; /*************************************************************************** DEVICE CONFIGURATION MACROS ***************************************************************************/ -#define MCFG_INS8250_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, INS8250, 0) \ +#define MCFG_INS8250_ADD(_tag, _intrf, _clock) \ + MCFG_DEVICE_ADD(_tag, INS8250, _clock) \ MCFG_DEVICE_CONFIG(_intrf) -#define MCFG_NS16450_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, NS16450, 0) \ +#define MCFG_NS16450_ADD(_tag, _intrf, _clock) \ + MCFG_DEVICE_ADD(_tag, NS16450, _clock) \ MCFG_DEVICE_CONFIG(_intrf) -#define MCFG_NS16550_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, NS16550, 0) \ +#define MCFG_NS16550_ADD(_tag, _intrf, _clock) \ + MCFG_DEVICE_ADD(_tag, NS16550, _clock) \ MCFG_DEVICE_CONFIG(_intrf) - -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - -void ins8250_receive(device_t *device, int data); -void ins8250_handshake_in(device_t *device, int new_msr); - -READ8_DEVICE_HANDLER( ins8250_r ); -WRITE8_DEVICE_HANDLER( ins8250_w ); - - -#endif /* __INS8250_H_ */ +#endif diff --git a/src/emu/machine/microtch.c b/src/emu/machine/microtch.c index c551bc89c0c..5aa7e1477bd 100644 --- a/src/emu/machine/microtch.c +++ b/src/emu/machine/microtch.c @@ -9,49 +9,23 @@ */ -#include "emu.h" #include "microtch.h" #define LOG 0 -enum MICROTOUCH_FORMAT -{ - FORMAT_UNKNOWN, - FORMAT_TABLET, - FORMAT_DECIMAL -}; +const device_type MICROTOUCH = &device_creator<microtouch_device>; -ALLOW_SAVE_TYPE(MICROTOUCH_FORMAT); - -enum MICROTOUCH_MODE +microtouch_device::microtouch_device(const machine_config &mconfig, device_type type, const char* name, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, type, name, tag, owner, clock) { - MODE_INACTIVE, - MODE_STREAM, - MODE_POINT -}; - -ALLOW_SAVE_TYPE(MICROTOUCH_MODE); +} -static struct +microtouch_device::microtouch_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, MICROTOUCH, "Microtouch Touchscreen", tag, owner, clock) { - UINT8 rx_buffer[16]; - int rx_buffer_ptr; - emu_timer* timer; - UINT8 tx_buffer[16]; - UINT8 tx_buffer_num; - UINT8 tx_buffer_ptr; - int reset_done; - MICROTOUCH_FORMAT format; - MICROTOUCH_MODE mode; - int last_touch_state; - int last_x; - int last_y; - microtouch_tx_func tx_callback; - microtouch_touch_func touch_callback; -} microtouch; - - -static int microtouch_check_command( const char* commandtocheck, int command_len, UINT8* command_data ) +} + +int microtouch_device::check_command( const char* commandtocheck, int command_len, UINT8* command_data ) { if ( (command_len == (strlen(commandtocheck) + 2)) && (command_data[0] == 0x01) && @@ -66,20 +40,20 @@ static int microtouch_check_command( const char* commandtocheck, int command_len } } -static void microtouch_send_format_table_packet(UINT8 flag, int x, int y) +void microtouch_device::send_format_table_packet(UINT8 flag, int x, int y) { - microtouch.tx_buffer[microtouch.tx_buffer_num++] = flag; + m_tx_buffer[m_tx_buffer_num++] = flag; // lower byte (7bits) of x coordinate - microtouch.tx_buffer[microtouch.tx_buffer_num++] = x & 0x7f; + m_tx_buffer[m_tx_buffer_num++] = x & 0x7f; // higher byte (7bits) of x coordinate - microtouch.tx_buffer[microtouch.tx_buffer_num++] = (x >> 7) & 0x7f; + m_tx_buffer[m_tx_buffer_num++] = (x >> 7) & 0x7f; // lower byte (7bits) of y coordinate - microtouch.tx_buffer[microtouch.tx_buffer_num++] = y & 0x7f; + m_tx_buffer[m_tx_buffer_num++] = y & 0x7f; // higher byte (7bits) of y coordinate - microtouch.tx_buffer[microtouch.tx_buffer_num++] = (y >> 7) & 0x7f; -}; + m_tx_buffer[m_tx_buffer_num++] = (y >> 7) & 0x7f; +} -static void microtouch_send_format_decimal_packet(int x, int y) +void microtouch_device::send_format_decimal_packet(int x, int y) { int decx, decy; @@ -91,201 +65,284 @@ static void microtouch_send_format_decimal_packet(int x, int y) decy = 999; // header byte - microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x01; + m_tx_buffer[m_tx_buffer_num++] = 0x01; // x coordinate in decimal mode - microtouch.tx_buffer[microtouch.tx_buffer_num++] = (decx / 100) + '0'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = ((decx / 10) % 10) + '0'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = (decx % 10) + '0'; + m_tx_buffer[m_tx_buffer_num++] = (decx / 100) + '0'; + m_tx_buffer[m_tx_buffer_num++] = ((decx / 10) % 10) + '0'; + m_tx_buffer[m_tx_buffer_num++] = (decx % 10) + '0'; // comma (separator) - microtouch.tx_buffer[microtouch.tx_buffer_num++] = ','; + m_tx_buffer[m_tx_buffer_num++] = ','; // y coordinate in decimal mode - microtouch.tx_buffer[microtouch.tx_buffer_num++] = (decy / 100) + '0'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = ((decy / 10) % 10) + '0'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = (decy % 10) + '0'; + m_tx_buffer[m_tx_buffer_num++] = (decy / 100) + '0'; + m_tx_buffer[m_tx_buffer_num++] = ((decy / 10) % 10) + '0'; + m_tx_buffer[m_tx_buffer_num++] = (decy % 10) + '0'; // terminator - microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x0d; + m_tx_buffer[m_tx_buffer_num++] = 0x0d; } -static void microtouch_send_touch_packet(running_machine &machine) +void microtouch_device::send_touch_packet() { - int tx = input_port_read(machine, "TOUCH_X"); - int ty = input_port_read(machine, "TOUCH_Y"); + int tx = input_port_read(*this, "TOUCH_X"); + int ty = input_port_read(*this, "TOUCH_Y"); - if ( microtouch.touch_callback == NULL || - microtouch.touch_callback( machine, &tx, &ty ) != 0 ) + if ( m_out_touch_cb == NULL || + m_out_touch_cb( &tx, &ty ) != 0 ) { ty = 0x4000 - ty; - switch( microtouch.format ) + switch( m_format ) { case FORMAT_TABLET: - microtouch_send_format_table_packet(0xc8, tx, ty); + send_format_table_packet(0xc8, tx, ty); break; case FORMAT_DECIMAL: - microtouch_send_format_decimal_packet(tx, ty); + send_format_decimal_packet(tx, ty); break; case FORMAT_UNKNOWN: break; } - microtouch.last_touch_state = 1; - microtouch.last_x = tx; - microtouch.last_y = ty; + m_last_touch_state = 1; + m_last_x = tx; + m_last_y = ty; } } -static TIMER_CALLBACK(microtouch_timer_callback) +void microtouch_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - if ( microtouch.tx_buffer_ptr < microtouch.tx_buffer_num ) + if ( m_tx_buffer_ptr < m_tx_buffer_num ) { - microtouch.tx_callback( machine, microtouch.tx_buffer[microtouch.tx_buffer_ptr++] ); - if ( microtouch.tx_buffer_ptr == microtouch.tx_buffer_num ) + tx( m_tx_buffer[m_tx_buffer_ptr++] ); + if ( m_tx_buffer_ptr == m_tx_buffer_num ) { - microtouch.tx_buffer_ptr = microtouch.tx_buffer_num = 0; + m_tx_buffer_ptr = m_tx_buffer_num = 0; } return; } - if ( (microtouch.reset_done == 0) || - (microtouch.format == FORMAT_UNKNOWN) || - (microtouch.mode != MODE_STREAM)) + if ( (m_reset_done == 0) || + (m_format == FORMAT_UNKNOWN) || + (m_mode != MODE_STREAM)) { return; } // send format tablet packet - if ( input_port_read(machine, "TOUCH") & 0x01 ) + if ( input_port_read(*this, "TOUCH") & 0x01 ) { - microtouch_send_touch_packet(machine); + send_touch_packet(); } else { - if ( microtouch.last_touch_state == 1 ) + if ( m_last_touch_state == 1 ) { - microtouch.last_touch_state = 0; - switch( microtouch.format ) + m_last_touch_state = 0; + switch( m_format ) { case FORMAT_TABLET: - microtouch_send_format_table_packet(0x88, microtouch.last_x, microtouch.last_y); + send_format_table_packet(0x88, m_last_x, m_last_y); break; case FORMAT_DECIMAL: - microtouch_send_format_decimal_packet(microtouch.last_x, microtouch.last_y); + send_format_decimal_packet(m_last_x, m_last_y); break; case FORMAT_UNKNOWN: break; } } } -}; +} -void microtouch_init(running_machine &machine, microtouch_tx_func tx_cb, microtouch_touch_func touch_cb) +void microtouch_device::device_config_complete() { - memset(µtouch, 0, sizeof(microtouch)); - - microtouch.last_touch_state = -1; - microtouch.tx_callback = tx_cb; - microtouch.touch_callback = touch_cb; - - microtouch.timer = machine.scheduler().timer_alloc(FUNC(microtouch_timer_callback)); - microtouch.timer->adjust(attotime::from_hz(167*5), 0, attotime::from_hz(167*5)); - - microtouch.format = FORMAT_UNKNOWN; - microtouch.mode = MODE_INACTIVE; - - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.reset_done); - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.last_touch_state); - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.last_x); - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.last_y); - state_save_register_item_array(machine, "microtouch", NULL, 0, microtouch.rx_buffer); - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.rx_buffer_ptr); - state_save_register_item_array(machine, "microtouch", NULL, 0, microtouch.tx_buffer); - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.tx_buffer_num); - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.tx_buffer_ptr); - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.format); - state_save_register_item(machine, "microtouch", NULL, 0, microtouch.mode); -}; - + const microtouch_interface *intf = reinterpret_cast<const microtouch_interface *>(static_config()); + if(intf != NULL) + *static_cast<microtouch_interface *>(this) = *intf; + else + { + memset(&m_out_tx_cb, 0, sizeof(m_out_tx_cb)); + memset(&m_out_touch_cb, 0, sizeof(m_out_touch_cb)); + } +} -void microtouch_rx(int count, UINT8* data) +void microtouch_device::device_start() { - int i; + memset(m_rx_buffer, 0, sizeof(m_rx_buffer)); + memset(m_tx_buffer, 0, sizeof(m_tx_buffer)); + m_rx_buffer_ptr = 0; + m_tx_buffer_ptr = 0; + m_tx_buffer_num = 0; + m_reset_done = 0; + m_format = 0; + m_mode = 0; + m_last_x = 0; + m_last_y = 0; + m_last_touch_state = -1; + + m_timer = timer_alloc(); + m_timer->adjust(attotime::from_hz(167*5), 0, attotime::from_hz(167*5)); + + m_format = FORMAT_UNKNOWN; + m_mode = MODE_INACTIVE; + + save_item(NAME(m_reset_done)); + save_item(NAME(m_last_touch_state)); + save_item(NAME(m_last_x)); + save_item(NAME(m_last_y)); + save_item(NAME(m_rx_buffer)); + save_item(NAME(m_rx_buffer_ptr)); + save_item(NAME(m_tx_buffer)); + save_item(NAME(m_tx_buffer_num)); + save_item(NAME(m_tx_buffer_ptr)); + save_item(NAME(m_format)); + save_item(NAME(m_mode)); + m_out_tx_func.resolve(m_out_tx_cb, *this); +} - for ( i = 0; (i < count) && ((microtouch.rx_buffer_ptr + i) < 16); i++ ) - { - microtouch.rx_buffer[i+microtouch.rx_buffer_ptr] = data[i]; - microtouch.rx_buffer_ptr++; - } - if (microtouch.rx_buffer_ptr > 0 && (microtouch.rx_buffer[microtouch.rx_buffer_ptr-1] == 0x0d)) +WRITE8_MEMBER(microtouch_device::rx) +{ + m_rx_buffer[m_rx_buffer_ptr] = data; + m_rx_buffer_ptr++; + if(m_rx_buffer_ptr == 16) + return; + + if (m_rx_buffer_ptr > 0 && (m_rx_buffer[m_rx_buffer_ptr-1] == 0x0d)) { if (LOG) { char command[16]; memset(command, 0, sizeof(command)); - strncpy( command, (const char*)microtouch.rx_buffer + 1, microtouch.rx_buffer_ptr - 2 ); + strncpy( command, (const char*)m_rx_buffer + 1, m_rx_buffer_ptr - 2 ); logerror("Microtouch: received command %s\n", command); } // check command - if ( microtouch_check_command( "MS", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) ) + if ( check_command( "MS", m_rx_buffer_ptr, m_rx_buffer ) ) { - microtouch.mode = MODE_STREAM; + m_mode = MODE_STREAM; } - else if ( microtouch_check_command( "MI", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) ) + else if ( check_command( "MI", m_rx_buffer_ptr, m_rx_buffer ) ) { - microtouch.mode = MODE_INACTIVE; + m_mode = MODE_INACTIVE; } - else if ( microtouch_check_command( "MP", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) ) + else if ( check_command( "MP", m_rx_buffer_ptr, m_rx_buffer ) ) { - microtouch.mode = MODE_POINT; + m_mode = MODE_POINT; } - else if ( microtouch_check_command( "R", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) ) + else if ( check_command( "R", m_rx_buffer_ptr, m_rx_buffer ) ) { - microtouch.tx_buffer_num = 0; - microtouch.reset_done = 1; + m_tx_buffer_num = 0; + m_reset_done = 1; } - else if ( microtouch_check_command( "FT", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) ) + else if ( check_command( "FT", m_rx_buffer_ptr, m_rx_buffer ) ) { - microtouch.format = FORMAT_TABLET; + m_format = FORMAT_TABLET; } - else if ( microtouch_check_command( "FD", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) ) + else if ( check_command( "FD", m_rx_buffer_ptr, m_rx_buffer ) ) { - microtouch.format = FORMAT_DECIMAL; + m_format = FORMAT_DECIMAL; } - else if ( microtouch_check_command("OI", microtouch.rx_buffer_ptr, microtouch.rx_buffer ) ) + else if ( check_command("OI", m_rx_buffer_ptr, m_rx_buffer ) ) { // output identity - SMT3, ver 01.00 - microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x01; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = 'Q'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = '1'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = '0'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = '1'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = '0'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = '0'; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x0d; - microtouch.rx_buffer_ptr = 0; + m_tx_buffer[m_tx_buffer_num++] = 0x01; + m_tx_buffer[m_tx_buffer_num++] = 'Q'; + m_tx_buffer[m_tx_buffer_num++] = '1'; + m_tx_buffer[m_tx_buffer_num++] = '0'; + m_tx_buffer[m_tx_buffer_num++] = '1'; + m_tx_buffer[m_tx_buffer_num++] = '0'; + m_tx_buffer[m_tx_buffer_num++] = '0'; + m_tx_buffer[m_tx_buffer_num++] = 0x0d; + m_rx_buffer_ptr = 0; return; } // send response - microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x01; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x30; - microtouch.tx_buffer[microtouch.tx_buffer_num++] = 0x0d; - microtouch.rx_buffer_ptr = 0; + m_tx_buffer[m_tx_buffer_num++] = 0x01; + m_tx_buffer[m_tx_buffer_num++] = 0x30; + m_tx_buffer[m_tx_buffer_num++] = 0x0d; + m_rx_buffer_ptr = 0; } }; -static INPUT_CHANGED( microtouch_touch ) +INPUT_CHANGED_MEMBER( microtouch_device::touch ) { - if ( newval && ( microtouch.mode == MODE_POINT ) ) + if ( newval && ( m_mode == MODE_POINT ) ) { - microtouch_send_touch_packet( field.machine() ); + send_touch_packet(); } } -INPUT_PORTS_START(microtouch) +static INPUT_PORTS_START(microtouch) PORT_START("TOUCH") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME( "Touch screen" ) PORT_CHANGED( microtouch_touch, 0 ) + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME( "Touch screen" ) PORT_CHANGED_MEMBER( DEVICE_SELF,microtouch_device, touch, 0 ) PORT_START("TOUCH_X") PORT_BIT( 0x3fff, 0x2000, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15) PORT_START("TOUCH_Y") PORT_BIT( 0x3fff, 0x2000, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(45) PORT_KEYDELTA(15) INPUT_PORTS_END +ioport_constructor microtouch_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(microtouch); +} + +const device_type MICROTOUCH_SERIAL = &device_creator<microtouch_serial_device>; + +microtouch_serial_device::microtouch_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : microtouch_device(mconfig, MICROTOUCH_SERIAL, "Microtouch Serial Touchscreen", tag, owner, clock), + device_serial_interface(mconfig, *this) +{ +} + +void microtouch_serial_device::device_config_complete() +{ + const microtouch_serial_interface *intf = reinterpret_cast<const microtouch_serial_interface *>(static_config()); + if(intf != NULL) + *static_cast<microtouch_serial_interface *>(this) = *intf; + else + { + memset(&m_out_stx_cb, 0, sizeof(m_out_stx_cb)); + } + memset(&(microtouch_interface::m_out_tx_cb), 0, sizeof(microtouch_interface::m_out_tx_cb)); + memset(&m_out_touch_cb, 0, sizeof(m_out_touch_cb)); +} + +void microtouch_serial_device::device_start() +{ + microtouch_device::device_start(); + m_timer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock())); + set_data_frame(8, 1, SERIAL_PARITY_NONE); //8N1? + m_out_stx_func.resolve(m_out_stx_cb, *this); + m_count = 0; + m_output_valid = false; + + save_item(NAME(m_count)); + save_item(NAME(m_output_valid)); + save_item(NAME(m_output)); + save_item(NAME(m_rx_line)); +} + +void microtouch_serial_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if(is_transmit_register_empty()) + { + if(m_output_valid) + { + transmit_register_setup(m_output); + m_output_valid = false; + } + } + else + m_out_stx_func(transmit_register_get_data_bit()); + + receive_register_update_bit(m_rx_line); + if(is_receive_register_full()) + { + receive_register_extract(); + microtouch_device::rx(*memory_nonspecific_space(machine()), 0, get_received_char()); + receive_register_reset(); + } + + if((m_count == 0) && (m_output_valid == false)) + microtouch_device::device_timer(timer, id, param, ptr); + + ++m_count %= 8; +} diff --git a/src/emu/machine/microtch.h b/src/emu/machine/microtch.h index d378c49eb91..81f4275ce51 100644 --- a/src/emu/machine/microtch.h +++ b/src/emu/machine/microtch.h @@ -1,12 +1,104 @@ #ifndef _MICROTOUCH_H #define _MICROTOUCH_H -INPUT_PORTS_EXTERN(microtouch); +#include "emu.h" -typedef void (*microtouch_tx_func)(running_machine &machine, UINT8 data); -typedef int (*microtouch_touch_func)(running_machine &machine, int *touch_x, int *touch_y); +typedef int (*microtouch_touch_func)(int *touch_x, int *touch_y); +#define MICROTOUCH_TOUCH(name) int name(int *touch_x, int *touch_y) -void microtouch_init(running_machine &machine, microtouch_tx_func tx_cb, microtouch_touch_func touch_cb); -void microtouch_rx(int count, UINT8* data); +struct microtouch_interface +{ + devcb_write8 m_out_tx_cb; + microtouch_touch_func m_out_touch_cb; +}; + +class microtouch_device : + public device_t, + public microtouch_interface +{ +public: + microtouch_device(const machine_config &mconfig, device_type type, const char* name, const char *tag, device_t *owner, UINT32 clock); + microtouch_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual ioport_constructor device_input_ports() const; + DECLARE_WRITE8_MEMBER(rx); + DECLARE_INPUT_CHANGED_MEMBER(touch); +protected: + virtual void device_start(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + virtual void device_config_complete(); + virtual void tx(UINT8 data) { m_out_tx_func(0, data); } + emu_timer* m_timer; +private: + int check_command( const char* commandtocheck, int command_len, UINT8* command_data ); + void send_format_table_packet(UINT8 flag, int x, int y); + void send_format_decimal_packet(int x, int y); + void send_touch_packet(); + + enum + { + FORMAT_UNKNOWN, + FORMAT_TABLET, + FORMAT_DECIMAL + }; + enum + { + MODE_INACTIVE, + MODE_STREAM, + MODE_POINT + }; + UINT8 m_rx_buffer[16]; + int m_rx_buffer_ptr; + UINT8 m_tx_buffer[16]; + UINT8 m_tx_buffer_num; + UINT8 m_tx_buffer_ptr; + int m_reset_done; + int m_format; + int m_mode; + int m_last_touch_state; + int m_last_x; + int m_last_y; + devcb_resolved_write8 m_out_tx_func; +}; + +extern const device_type MICROTOUCH; + +#define MCFG_MICROTOUCH_ADD(_tag, _intrf) \ + MCFG_DEVICE_ADD(_tag, MICROTOUCH, 0) \ + MCFG_DEVICE_CONFIG(_intrf) + +struct microtouch_serial_interface +{ + devcb_write_line m_out_stx_cb; +}; + +class microtouch_serial_device + : public microtouch_device, + public device_serial_interface, + public microtouch_serial_interface +{ +public: + microtouch_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + DECLARE_WRITE_LINE_MEMBER(rx) {m_rx_line = state;} +protected: + virtual void device_start(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + virtual void device_config_complete(); + virtual void tx(UINT8 data) {m_output = data; m_output_valid = true;} + virtual void input_callback(UINT8 state) { m_input_state = state; } +private: + int m_count; + bool m_output_valid; + UINT8 m_output; + UINT8 m_rx_line; + devcb_resolved_write_line m_out_stx_func; +}; + +extern const device_type MICROTOUCH_SERIAL; + +#define MCFG_MICROTOUCH_SERIAL_ADD(_tag, _intrf, _clock) \ + MCFG_DEVICE_ADD(_tag, MICROTOUCH_SERIAL, _clock) \ + MCFG_DEVICE_CONFIG(_intrf) #endif //_MICROTOUCH_H diff --git a/src/emu/machine/pc16552d.c b/src/emu/machine/pc16552d.c index 4595d48a85f..00f7e4b68f5 100644 --- a/src/emu/machine/pc16552d.c +++ b/src/emu/machine/pc16552d.c @@ -55,7 +55,7 @@ typedef struct PC16552D_CHANNEL ch[2]; int frequency; void (* irq_handler)(running_machine &machine, int channel, int value); - void (* tx_callback)(int channel, int count, UINT8* data); + void (* tx_callback)(running_machine &machine, int channel, int count, UINT8* data); } PC16552D_REGS; #define MAX_PC16552D_CHIPS 4 @@ -151,7 +151,7 @@ static TIMER_CALLBACK( tx_fifo_timer_callback ) ch = &duart[chip].ch[channel]; if (duart[chip].tx_callback) - duart[chip].tx_callback(channel, ch->tx_fifo_num, ch->tx_fifo); + duart[chip].tx_callback(machine, channel, ch->tx_fifo_num, ch->tx_fifo); ch->tx_fifo_num = 0; @@ -387,7 +387,7 @@ static void duart_w(running_machine &machine, int chip, int reg, UINT8 data) /*****************************************************************************/ -void pc16552d_init(running_machine &machine, int chip, int frequency, void (* irq_handler)(running_machine &machine, int channel, int value), void (* tx_callback)(int channel, int count, UINT8* data)) +void pc16552d_init(running_machine &machine, int chip, int frequency, void (* irq_handler)(running_machine &machine, int channel, int value), void (* tx_callback)(running_machine &machine, int channel, int count, UINT8* data)) { memset(&duart[chip], 0, sizeof(PC16552D_REGS)); diff --git a/src/emu/machine/pc16552d.h b/src/emu/machine/pc16552d.h index 93f2181e37a..98d117040cf 100644 --- a/src/emu/machine/pc16552d.h +++ b/src/emu/machine/pc16552d.h @@ -1,7 +1,7 @@ #ifndef PC16552D_H #define PC16552D_H -void pc16552d_init(running_machine &machine, int chip, int frequency, void (* irq_handler)(running_machine &machine, int channel, int value), void (* tx_callback)(int channel, int count, UINT8* data)); +void pc16552d_init(running_machine &machine, int chip, int frequency, void (* irq_handler)(running_machine &machine, int channel, int value), void (* tx_callback)(running_machine &machine, int channel, int count, UINT8* data)); void pc16552d_rx_data(running_machine &machine, int chip, int channel, UINT8 data); READ8_HANDLER(pc16552d_0_r); diff --git a/src/mame/drivers/adp.c b/src/mame/drivers/adp.c index 904fcd1e5f1..a33088ad857 100644 --- a/src/mame/drivers/adp.c +++ b/src/mame/drivers/adp.c @@ -157,11 +157,14 @@ class adp_state : public driver_device public: adp_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), - m_h63484(*this, "h63484") + m_h63484(*this, "h63484"), + m_microtouch(*this, "microtouch") { } required_device<h63484_device> m_h63484; - + required_device<microtouch_device> m_microtouch; + + DECLARE_WRITE8_MEMBER(microtouch_tx); UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); /* misc */ @@ -262,20 +265,20 @@ static void duart_irq_handler( device_t *device, UINT8 vector ) { adp_state *state = device->machine().driver_data<adp_state>(); device_set_input_line_and_vector(state->m_maincpu, 4, HOLD_LINE, vector); -}; +} static void duart_tx( device_t *device, int channel, UINT8 data ) { + adp_state *state = device->machine().driver_data<adp_state>(); if (channel == 0) { - microtouch_rx(1, &data); + state->m_microtouch->rx(*memory_nonspecific_space(device->machine()), 0, data); } -}; +} -static void microtouch_tx( running_machine &machine, UINT8 data ) +WRITE8_MEMBER( adp_state::microtouch_tx ) { - adp_state *state = machine.driver_data<adp_state>(); - duart68681_rx_data(state->m_duart, 0, data); + duart68681_rx_data(m_duart, 0, data); } static UINT8 duart_input( device_t *device ) @@ -283,10 +286,15 @@ static UINT8 duart_input( device_t *device ) return input_port_read(device->machine(), "DSW1"); } +static const microtouch_interface adb_microtouch_config = +{ + DEVCB_DRIVER_MEMBER(adp_state, microtouch_tx), + NULL +}; + static MACHINE_START( skattv ) { adp_state *state = machine.driver_data<adp_state>(); - microtouch_init(machine, microtouch_tx, 0); state->m_maincpu = machine.device("maincpu"); state->m_duart = machine.device("duart68681"); @@ -530,8 +538,6 @@ INPUT_PORTS_END #endif static INPUT_PORTS_START( skattv ) - PORT_INCLUDE(microtouch) - PORT_START("DSW1") PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_COIN5 ) PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN6 ) @@ -661,6 +667,7 @@ static MACHINE_CONFIG_START( quickjac, adp_state ) MCFG_MACHINE_RESET(skattv) MCFG_DUART68681_ADD( "duart68681", XTAL_8_664MHz / 2, skattv_duart68681_config ) + MCFG_MICROTOUCH_ADD( "microtouch", adb_microtouch_config ) MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(60) @@ -692,6 +699,7 @@ static MACHINE_CONFIG_START( skattv, adp_state ) MCFG_MACHINE_RESET(skattv) MCFG_DUART68681_ADD( "duart68681", XTAL_8_664MHz / 2, skattv_duart68681_config ) + MCFG_MICROTOUCH_ADD( "microtouch", adb_microtouch_config ) MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(60) @@ -719,6 +727,7 @@ static MACHINE_CONFIG_START( backgamn, adp_state ) MCFG_CPU_PROGRAM_MAP(backgamn_mem) MCFG_DUART68681_ADD( "duart68681", XTAL_8_664MHz / 2, skattv_duart68681_config ) + MCFG_MICROTOUCH_ADD( "microtouch", adb_microtouch_config ) MCFG_MACHINE_START(skattv) MCFG_MACHINE_RESET(skattv) diff --git a/src/mame/drivers/cd32.c b/src/mame/drivers/cd32.c index e85890ebc2b..bdf36ae1f9a 100644 --- a/src/mame/drivers/cd32.c +++ b/src/mame/drivers/cd32.c @@ -35,7 +35,6 @@ #include "includes/cd32.h" #include "sound/cdda.h" #include "imagedev/chd_cd.h" -#include "machine/microtch.h" #include "machine/amigafdc.h" #define CD32PAL_XTAL_X1 XTAL_28_37516MHz @@ -760,6 +759,12 @@ static const i2cmem_interface i2cmem_interface = I2CMEM_SLAVE_ADDRESS, NVRAM_PAGE_SIZE, NVRAM_SIZE }; +static const microtouch_interface cd32_microtouch_config = +{ + DEVCB_DRIVER_MEMBER(cd32_state, microtouch_tx), + NULL +}; + static MACHINE_CONFIG_START( cd32base, cd32_state ) /* basic machine hardware */ @@ -800,6 +805,8 @@ static MACHINE_CONFIG_START( cd32base, cd32_state ) MCFG_MOS8520_ADD("cia_0", AMIGA_68EC020_PAL_CLOCK / 10, cia_0_intf) MCFG_MOS8520_ADD("cia_1", AMIGA_68EC020_PAL_CLOCK / 10, cia_1_intf) + MCFG_MICROTOUCH_ADD( "microtouch", cd32_microtouch_config ) + /* fdc */ MCFG_AMIGA_FDC_ADD("fdc", AMIGA_68000_NTSC_CLOCK) MACHINE_CONFIG_END @@ -1375,8 +1382,6 @@ static DRIVER_INIT(mgprem11) static INPUT_PORTS_START( odeontw2 ) // PORT_INCLUDE( cd32 ) - PORT_INCLUDE( microtouch ) - PORT_START("CIA0PORTA") PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) @@ -1440,14 +1445,15 @@ INPUT_PORTS_END static void serial_w(running_machine &machine, UINT16 data) { + cd32_state *state = machine.driver_data<cd32_state>(); UINT8 data8 = data & 0xff; if ( data8 != 0x00 ) - microtouch_rx(1, &data8); + state->m_microtouch->rx(*memory_nonspecific_space(machine), 0, data8); } -static void microtouch_tx(running_machine &machine, UINT8 data) +WRITE8_MEMBER (cd32_state::microtouch_tx) { - amiga_serial_in_w(machine, data); + amiga_serial_in_w(machine(), data); } static DRIVER_INIT( odeontw2 ) @@ -1472,9 +1478,6 @@ static DRIVER_INIT( odeontw2 ) /* input hack */ state->m_input_hack = NULL; - - /* touch screen */ - microtouch_init(machine, microtouch_tx, NULL); } /***************************************************************************************************/ diff --git a/src/mame/drivers/magtouch.c b/src/mame/drivers/magtouch.c index 3db07ddb63a..957438793b3 100644 --- a/src/mame/drivers/magtouch.c +++ b/src/mame/drivers/magtouch.c @@ -85,8 +85,16 @@ class magtouch_state : public driver_device { public: magtouch_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) { } + : driver_device(mconfig, type, tag), + m_uart(*this, "ns16450_0"), + m_microtouch(*this, "microtouch") + { } + required_device<ns16450_device> m_uart; + required_device<microtouch_serial_device> m_microtouch; + + DECLARE_WRITE_LINE_MEMBER(microtouch_out); + DECLARE_WRITE_LINE_MEMBER(microtouch_in); }; @@ -96,15 +104,14 @@ public: * *************************************/ -static void magtouch_microtouch_tx_callback(running_machine &machine, UINT8 data) +WRITE_LINE_MEMBER(magtouch_state::microtouch_out) { - ins8250_receive(machine.device("ns16450_0"), data); -}; + m_microtouch->rx(state); +} -static INS8250_TRANSMIT( magtouch_com_transmit ) +WRITE_LINE_MEMBER(magtouch_state::microtouch_in) { - UINT8 data8 = data; - microtouch_rx(1, &data8); + m_uart->rx_w(state); } static WRITE_LINE_DEVICE_HANDLER( at_com_interrupt_1 ) @@ -114,11 +121,17 @@ static WRITE_LINE_DEVICE_HANDLER( at_com_interrupt_1 ) static const ins8250_interface magtouch_com0_interface = { - 1843200, + DEVCB_DRIVER_LINE_MEMBER(magtouch_state, microtouch_out), + DEVCB_NULL, + DEVCB_NULL, DEVCB_LINE(at_com_interrupt_1), - magtouch_com_transmit, - NULL, - NULL + DEVCB_NULL, + DEVCB_NULL +}; + +static const microtouch_serial_interface magtouch_microtouch_interface = +{ + DEVCB_DRIVER_LINE_MEMBER(magtouch_state, microtouch_in) }; /************************************* @@ -161,12 +174,10 @@ ADDRESS_MAP_END static ADDRESS_MAP_START( magtouch_io, AS_IO, 32 ) AM_IMPORT_FROM(pcat32_io_common) AM_RANGE(0x02e0, 0x02e7) AM_READWRITE8(magtouch_io_r, magtouch_io_w, 0xffffffff) - AM_RANGE(0x03f8, 0x03ff) AM_DEVREADWRITE8("ns16450_0", ins8250_r, ins8250_w, 0xffffffff) + AM_RANGE(0x03f8, 0x03ff) AM_DEVREADWRITE8_MODERN("ns16450_0", ns16450_device, ins8250_r, ins8250_w, 0xffffffff) ADDRESS_MAP_END static INPUT_PORTS_START( magtouch ) - PORT_INCLUDE(microtouch) - PORT_START("IN0") PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Clear") PORT_CODE(KEYCODE_C) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_SERVICE) @@ -191,7 +202,7 @@ static MACHINE_START( magtouch ) memory_configure_bank(machine, "rombank", 0, 0x80, machine.region("game_prg")->base(), 0x8000 ); memory_set_bank(machine, "rombank", 0); - microtouch_init(machine, magtouch_microtouch_tx_callback, NULL); +// microtouch_init(machine, magtouch_microtouch_tx_callback, NULL); } static MACHINE_CONFIG_START( magtouch, magtouch_state ) @@ -212,8 +223,8 @@ static MACHINE_CONFIG_START( magtouch, magtouch_state ) // MCFG_FRAGMENT_ADD( at_kbdc8042 ) MCFG_FRAGMENT_ADD( pcat_common ) - MCFG_NS16450_ADD( "ns16450_0", magtouch_com0_interface ) - + MCFG_NS16450_ADD( "ns16450_0", magtouch_com0_interface, XTAL_1_8432MHz ) + MCFG_MICROTOUCH_SERIAL_ADD( "microtouch", magtouch_microtouch_interface, 9600 ) // rate? MACHINE_CONFIG_END diff --git a/src/mame/drivers/meritm.c b/src/mame/drivers/meritm.c index 61fe10c53aa..e2cb53210c1 100644 --- a/src/mame/drivers/meritm.c +++ b/src/mame/drivers/meritm.c @@ -129,8 +129,10 @@ public: meritm_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_v9938_0(*this, "v9938_0"), - m_v9938_1(*this, "v9938_1") { } + m_v9938_1(*this, "v9938_1"), + m_microtouch(*this, "microtouch") { } + DECLARE_WRITE8_MEMBER(microtouch_tx); UINT8* m_ram; device_t *m_z80pio[2]; int m_vint; @@ -144,6 +146,7 @@ public: ds1204_t m_ds1204; required_device<v9938_device> m_v9938_0; required_device<v9938_device> m_v9938_1; + required_device<microtouch_device> m_microtouch; }; @@ -271,22 +274,24 @@ static void ds1204_init(running_machine &machine, const UINT8* key, const UINT8* * *************************************/ -static void pc16650d_tx_callback(int channel, int count, UINT8* data) +static void pc16650d_tx_callback(running_machine &machine, int channel, int count, UINT8* data) { - microtouch_rx(count, data); -}; + meritm_state *state = machine.driver_data<meritm_state>(); + for(int i = 0; i < count; i++) + state->m_microtouch->rx(*memory_nonspecific_space(machine), 0, data[i]); +} -static void meritm_microtouch_tx_callback(running_machine &machine, UINT8 data) +WRITE8_MEMBER(meritm_state::microtouch_tx) { - pc16552d_rx_data(machine, 0, 0, data); -}; + pc16552d_rx_data(space.machine(), 0, 0, data); +} /************************************* * * Microtouch touch coordinate transformation * *************************************/ -static int meritm_touch_coord_transform(running_machine &machine, int *touch_x, int *touch_y) +MICROTOUCH_TOUCH(meritm_touch_coord_transform) { int xscr = (int)((double)(*touch_x)/0x4000*544); int yscr = (int)((double)(*touch_y)/0x4000*480); @@ -311,6 +316,12 @@ static int meritm_touch_coord_transform(running_machine &machine, int *touch_x, return 1; } +static const microtouch_interface meritm_microtouch_config = +{ + DEVCB_DRIVER_MEMBER(meritm_state, microtouch_tx), + meritm_touch_coord_transform +}; + /************************************* * * Video @@ -627,8 +638,6 @@ ADDRESS_MAP_END *************************************/ static INPUT_PORTS_START(meritm_crt260) - PORT_INCLUDE(microtouch) - PORT_START("PIO1_PORTA") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) @@ -997,7 +1006,6 @@ static MACHINE_START(meritm_crt250_crt252_crt258) { MACHINE_START_CALL(meritm_crt250_questions); pc16552d_init(machine, 0, UART_CLK, NULL, pc16650d_tx_callback); - microtouch_init(machine, meritm_microtouch_tx_callback, meritm_touch_coord_transform); } static MACHINE_START(meritm_crt260) @@ -1014,7 +1022,6 @@ static MACHINE_START(meritm_crt260) meritm_switch_banks(machine); MACHINE_START_CALL(merit_common); pc16552d_init(machine, 0, UART_CLK, NULL, pc16650d_tx_callback); - microtouch_init(machine, meritm_microtouch_tx_callback, meritm_touch_coord_transform); state_save_register_global(machine, state->m_bank); state_save_register_global(machine, state->m_psd_a15); state_save_register_global_pointer(machine, state->m_ram, 0x8000); @@ -1089,6 +1096,8 @@ static MACHINE_CONFIG_START( meritm_crt250, meritm_state ) MCFG_SOUND_ADD("aysnd", AY8910, SYSTEM_CLK/12) MCFG_SOUND_CONFIG(ay8910_config) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) + + MCFG_MICROTOUCH_ADD("microtouch", meritm_microtouch_config) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED( meritm_crt250_questions, meritm_crt250 ) diff --git a/src/mame/drivers/pcat_nit.c b/src/mame/drivers/pcat_nit.c index 641e11ad69e..e6a2cf0c02d 100644 --- a/src/mame/drivers/pcat_nit.c +++ b/src/mame/drivers/pcat_nit.c @@ -96,21 +96,27 @@ class pcat_nit_state : public driver_device { public: pcat_nit_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) { } + : driver_device(mconfig, type, tag), + m_uart(*this, "ns16450_0"), + m_microtouch(*this, "microtouch") + { } UINT8 *m_banked_nvram; -}; + required_device<ns16450_device> m_uart; + required_device<microtouch_serial_device> m_microtouch; + DECLARE_WRITE_LINE_MEMBER(microtouch_out); + DECLARE_WRITE_LINE_MEMBER(microtouch_in); +}; -static void pcat_nit_microtouch_tx_callback(running_machine &machine, UINT8 data) +WRITE_LINE_MEMBER(pcat_nit_state::microtouch_out) { - ins8250_receive(machine.device("ns16450_0"), data); -}; + m_microtouch->rx(state); +} -static INS8250_TRANSMIT( pcat_nit_com_transmit ) +WRITE_LINE_MEMBER(pcat_nit_state::microtouch_in) { - UINT8 data8 = data; - microtouch_rx(1, &data8); + m_uart->rx_w(state); } static WRITE_LINE_DEVICE_HANDLER( at_com_interrupt_1 ) @@ -120,11 +126,17 @@ static WRITE_LINE_DEVICE_HANDLER( at_com_interrupt_1 ) static const ins8250_interface pcat_nit_com0_interface = { - 1843200, + DEVCB_DRIVER_LINE_MEMBER(pcat_nit_state, microtouch_out), + DEVCB_NULL, + DEVCB_NULL, DEVCB_LINE(at_com_interrupt_1), - pcat_nit_com_transmit, - NULL, - NULL + DEVCB_NULL, + DEVCB_NULL +}; + +static const microtouch_serial_interface pcat_nit_microtouch_interface = +{ + DEVCB_DRIVER_LINE_MEMBER(pcat_nit_state, microtouch_in) }; /************************************* @@ -194,12 +206,10 @@ static ADDRESS_MAP_START( pcat_nit_io, AS_IO, 32 ) AM_IMPORT_FROM(pcat32_io_common) AM_RANGE(0x0278, 0x027f) AM_READ8(pcat_nit_io_r, 0xffffffff) AM_WRITENOP AM_RANGE(0x0280, 0x0283) AM_READNOP - AM_RANGE(0x03f8, 0x03ff) AM_DEVREADWRITE8("ns16450_0", ins8250_r, ins8250_w, 0xffffffff) + AM_RANGE(0x03f8, 0x03ff) AM_DEVREADWRITE8_MODERN("ns16450_0", ns16450_device, ins8250_r, ins8250_w, 0xffffffff) ADDRESS_MAP_END static INPUT_PORTS_START( pcat_nit ) - PORT_INCLUDE(microtouch) - PORT_START("IN0") PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Clear") PORT_CODE(KEYCODE_C) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_SERVICE) @@ -224,7 +234,7 @@ static MACHINE_START( streetg2 ) memory_configure_bank(machine, "rombank", 0, 0x80, machine.region("game_prg")->base(), 0x8000 ); memory_set_bank(machine, "rombank", 0); - microtouch_init(machine, pcat_nit_microtouch_tx_callback, NULL); + //microtouch_init(machine, pcat_nit_microtouch_tx_callback, NULL); } static MACHINE_CONFIG_START( pcat_nit, pcat_nit_state ) @@ -245,7 +255,8 @@ static MACHINE_CONFIG_START( pcat_nit, pcat_nit_state ) // MCFG_FRAGMENT_ADD( at_kbdc8042 ) MCFG_FRAGMENT_ADD( pcat_common ) - MCFG_NS16450_ADD( "ns16450_0", pcat_nit_com0_interface ) + MCFG_NS16450_ADD( "ns16450_0", pcat_nit_com0_interface, XTAL_1_8432MHz ) + MCFG_MICROTOUCH_SERIAL_ADD( "microtouch", pcat_nit_microtouch_interface, 9600 ) // rate? MCFG_NVRAM_ADD_0FILL("nvram") diff --git a/src/mame/drivers/tmaster.c b/src/mame/drivers/tmaster.c index 05a88612a75..30ccc788662 100644 --- a/src/mame/drivers/tmaster.c +++ b/src/mame/drivers/tmaster.c @@ -121,9 +121,12 @@ class tmaster_state : public driver_device public: tmaster_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), - m_maincpu(*this,"maincpu") + m_maincpu(*this,"maincpu"), + m_microtouch(*this,"microtouch") { } + DECLARE_WRITE8_MEMBER(microtouch_tx); + int m_okibank; UINT8 m_rtc_ram[8]; bitmap_ind16 m_bitmap[2][2]; @@ -141,6 +144,7 @@ public: device_t *m_duart68681; required_device<cpu_device> m_maincpu; + optional_device<microtouch_device> m_microtouch; }; @@ -179,18 +183,23 @@ static void duart_irq_handler(device_t *device, UINT8 vector) static void duart_tx(device_t *device, int channel, UINT8 data) { + tmaster_state *state = device->machine().driver_data<tmaster_state>(); if ( channel == 0 ) { - microtouch_rx(1, &data); + state->m_microtouch->rx(*memory_nonspecific_space(device->machine()), 0, data); } }; -static void microtouch_tx(running_machine &machine, UINT8 data) +WRITE8_MEMBER( tmaster_state::microtouch_tx ) { - tmaster_state *state = machine.driver_data<tmaster_state>(); - duart68681_rx_data(state->m_duart68681, 0, data); + duart68681_rx_data(m_duart68681, 0, data); } +static const microtouch_interface tmaster_microtouch_config = +{ + DEVCB_DRIVER_MEMBER(tmaster_state, microtouch_tx), + NULL +}; /*************************************************************************** @@ -766,8 +775,6 @@ ADDRESS_MAP_END ***************************************************************************/ static INPUT_PORTS_START( tm ) - PORT_INCLUDE( microtouch ) - PORT_START("COIN") PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN5 ) // "M. Coin 1 Input" PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN6 ) // "M. Coin 2 Input" @@ -788,8 +795,6 @@ static INPUT_PORTS_START( tm ) INPUT_PORTS_END static INPUT_PORTS_START( tmaster ) - PORT_INCLUDE( microtouch ) - PORT_START("COIN") PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_COIN1 ) // "M. Coin 1 Input" PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN2 ) // "M. Coin 2 Input" @@ -863,11 +868,6 @@ INPUT_PORTS_END ***************************************************************************/ -static MACHINE_START( tmaster ) -{ - microtouch_init(machine, microtouch_tx, 0); -} - static MACHINE_RESET( tmaster ) { tmaster_state *state = machine.driver_data<tmaster_state>(); @@ -904,10 +904,10 @@ static MACHINE_CONFIG_START( tm3k, tmaster_state ) MCFG_CPU_PROGRAM_MAP(tmaster_map) MCFG_TIMER_ADD_SCANLINE("scantimer", tm3k_interrupt, "screen", 0, 1) - MCFG_MACHINE_START(tmaster) MCFG_MACHINE_RESET(tmaster) MCFG_DUART68681_ADD( "duart68681", XTAL_8_664MHz / 2 /*??*/, tmaster_duart68681_config ) + MCFG_MICROTOUCH_ADD( "microtouch", tmaster_microtouch_config ) MCFG_NVRAM_ADD_0FILL("nvram") diff --git a/src/mame/includes/cd32.h b/src/mame/includes/cd32.h index 615a935e4cd..39b6ff6de71 100644 --- a/src/mame/includes/cd32.h +++ b/src/mame/includes/cd32.h @@ -8,13 +8,19 @@ CuboCD32 definitions #define __CUBOCD32_H__ #include "includes/amiga.h" +#include "machine/microtch.h" class cd32_state : public amiga_state { public: cd32_state(const machine_config &mconfig, device_type type, const char *tag) - : amiga_state(mconfig, type, tag) { } + : amiga_state(mconfig, type, tag), + m_microtouch(*this, "microtouch") + { } + required_device<microtouch_device> m_microtouch; + + DECLARE_WRITE8_MEMBER(microtouch_tx); UINT16 m_potgo_value; int m_cd32_shifter[2]; void (*m_input_hack)(running_machine &machine); |