diff --git a/src/emu/bus/econet/e01.c b/src/emu/bus/econet/e01.c index b48cdfbbe9b..66b51a905a0 100644 --- a/src/emu/bus/econet/e01.c +++ b/src/emu/bus/econet/e01.c @@ -276,7 +276,7 @@ static ADDRESS_MAP_START( e01_mem, AS_PROGRAM, 8, e01_device ) AM_RANGE(0xfc08, 0xfc08) AM_MIRROR(0x00c0) AM_READ(ram_select_r) AM_WRITE(floppy_w) AM_RANGE(0xfc0c, 0xfc0f) AM_MIRROR(0x00c0) AM_DEVREADWRITE(WD2793_TAG, wd2793_t, read, write) AM_RANGE(0xfc10, 0xfc1f) AM_MIRROR(0x00c0) AM_DEVREADWRITE(R6522_TAG, via6522_device, read, write) - AM_RANGE(0xfc20, 0xfc23) AM_MIRROR(0x00c0) AM_DEVREADWRITE_LEGACY(MC6854_TAG, mc6854_r, mc6854_w) + AM_RANGE(0xfc20, 0xfc23) AM_MIRROR(0x00c0) AM_DEVREADWRITE(MC6854_TAG, mc6854_device, read, write) AM_RANGE(0xfc24, 0xfc24) AM_MIRROR(0x00c3) AM_READWRITE(network_irq_disable_r, network_irq_disable_w) AM_RANGE(0xfc28, 0xfc28) AM_MIRROR(0x00c3) AM_READWRITE(network_irq_enable_r, network_irq_enable_w) AM_RANGE(0xfc2c, 0xfc2c) AM_MIRROR(0x00c3) AM_READ_PORT("FLAP") @@ -769,6 +769,6 @@ WRITE8_MEMBER( e01_device::rtc_data_w ) void e01_device::econet_clk(int state) { - mc6854_rxc_w(m_adlc, state); - mc6854_txc_w(m_adlc, state); + m_adlc->rxc_w(state); + m_adlc->txc_w(state); } diff --git a/src/emu/machine/mc6854.c b/src/emu/machine/mc6854.c index 74b7e4245ca..b2009ef6500 100644 --- a/src/emu/machine/mc6854.c +++ b/src/emu/machine/mc6854.c @@ -31,8 +31,6 @@ #include "emu.h" #include "mc6854.h" -#include "devlegcy.h" - /******************* parameters ******************/ @@ -42,69 +40,12 @@ #define VERBOSE 0 -#define MAX_FRAME_LENGTH 65536 -/* arbitrary value, you may need to enlarge it if you get truncated frames */ - -#define FIFO_SIZE 3 -/* hardcoded size of the 6854 FIFO (this is a hardware limit) */ - #define FLAG 0x7e /* flag value, as defined by HDLC protocol: 01111110 */ #define BIT_LENGTH attotime::from_hz( 500000 ) - -/******************* internal chip data structure ******************/ - - -struct mc6854_t -{ - devcb_resolved_write_line out_irq_func; - devcb_resolved_read_line in_rxd_func; - devcb_resolved_write_line out_txd_func; - devcb_resolved_write_line out_rts_func; - devcb_resolved_write_line out_dtr_func; - - /* interface */ - const mc6854_interface* iface; - - /* registers */ - UINT8 cr1, cr2, cr3, cr4; /* control registers */ - UINT8 sr1, sr2; /* status registers */ - - UINT8 cts, dcd; - - /* transmit state */ - UINT8 tstate; - UINT16 tfifo[FIFO_SIZE]; /* X x 8-bit FIFO + full & last marker bits */ - UINT8 tones; /* counter for zero-insertion */ - emu_timer *ttimer; /* when to ask for more data */ - - /* receive state */ - UINT8 rstate; - UINT32 rreg; /* shift register */ - UINT8 rones; /* count '1 bits */ - UINT8 rsize; /* bits in the shift register */ - UINT16 rfifo[FIFO_SIZE]; /* X x 8-bit FIFO + full & addr marker bits */ - - /* frame-based interface*/ - UINT8 frame[MAX_FRAME_LENGTH]; - UINT32 flen, fpos; - -}; - -/* meaning of tstate / rtate: - 0 = idle / waiting for frame flag - 1 = flag sync - 2 = 8-bit address field(s) - 3-4 = 8-bit control field(s) - 5 = 8-bit logical control field(s) - 6 = variable-length data field(s) -*/ - - - /******************* utility function and macros ********************/ @@ -115,87 +56,87 @@ struct mc6854_t /* control register 1 */ -#define AC ( mc6854->cr1 & 1 ) -#define FCTDRA ( mc6854->cr2 & 8 ) +#define AC ( m_cr1 & 1 ) +#define FCTDRA ( m_cr2 & 8 ) /* extra register select bits */ -#define RRESET ( mc6854->cr1 & 0x40 ) -#define TRESET ( mc6854->cr1 & 0x80 ) +#define RRESET ( m_cr1 & 0x40 ) +#define TRESET ( m_cr1 & 0x80 ) /* transmit / reset condition */ -#define RIE ( mc6854->cr1 & 2 ) -#define TIE ( mc6854->cr1 & 4 ) +#define RIE ( m_cr1 & 2 ) +#define TIE ( m_cr1 & 4 ) /* interrupt enable */ -#define DISCONTINUE ( mc6854->cr1 & 0x20 ) +#define DISCONTINUE ( m_cr1 & 0x20 ) /* discontinue received frame */ /* control register 2 */ -#define PSE ( mc6854->cr2 & 1 ) +#define PSE ( m_cr2 & 1 ) /* prioritize status bits (TODO) */ -#define TWOBYTES ( mc6854->cr2 & 2 ) +#define TWOBYTES ( m_cr2 & 2 ) /* two-bytes mode */ -#define FMIDLE ( mc6854->cr2 & 4 ) +#define FMIDLE ( m_cr2 & 4 ) /* flag time fill (vs. mark idle) */ -#define TLAST ( mc6854->cr2 & 0x10 ) +#define TLAST ( m_cr2 & 0x10 ) /* transmit last byte of frame */ -#define RTS ( mc6854->cr2 & 0x80 ) +#define RTS ( m_cr2 & 0x80 ) /* request-to-send */ /* control register 3 */ -#define LCF ( mc6854->cr3 & 1 ) +#define LCF ( m_cr3 & 1 ) /* logical control field select */ -#define CEX ( mc6854->cr3 & 2 ) +#define CEX ( m_cr3 & 2 ) /* control field is 16 bits instead of 8 */ -#define AEX ( mc6854->cr3 & 4 ) +#define AEX ( m_cr3 & 4 ) /* extended address mode (vs normal 8-bit address mode) */ -#define IDL0 ( mc6854->cr3 & 8 ) +#define IDL0 ( m_cr3 & 8 ) /* idle condition begins with a '0' instead of a '1" */ -#define FDSE ( mc6854->cr3 & 0x10 ) +#define FDSE ( m_cr3 & 0x10 ) /* enable the flag detect status in SR1 */ -#define LOOP ( mc6854->cr3 & 0x20 ) +#define LOOP ( m_cr3 & 0x20 ) /* loop mode */ -#define TST ( mc6854->cr3 & 0x40 ) +#define TST ( m_cr3 & 0x40 ) /* test mode (or go active on poll) */ -#define DTR ( mc6854->cr3 & 0x80 ) +#define DTR ( m_cr3 & 0x80 ) /* data-transmit-ready (or loop on-line control) */ /* control register 4 */ -#define TWOINTER ( mc6854->cr4 & 1 ) +#define TWOINTER ( m_cr4 & 1 ) /* both an openning and a closing inter-frame are sent */ static const int word_length[4] = { 5, 6, 7, 8 }; -#define TWL word_length[ ( mc6854->cr4 >> 1 ) & 3 ] -#define RWL word_length[ ( mc6854->cr4 >> 3 ) & 3 ] +#define TWL word_length[ ( m_cr4 >> 1 ) & 3 ] +#define RWL word_length[ ( m_cr4 >> 3 ) & 3 ] /* transmit / receive word length */ -#define ABT ( mc6854->cr4 & 0x20 ) +#define ABT ( m_cr4 & 0x20 ) /* aborts */ -#define ABTEX ( mc6854->cr4 & 0x40 ) +#define ABTEX ( m_cr4 & 0x40 ) /* abort generates 16 '1' bits instead of 8 */ -#define NRZ ( mc6854->cr4 & 0x80 ) +#define NRZ ( m_cr4 & 0x80 ) /* zero complement / non-zero complement data format */ @@ -222,22 +163,125 @@ static const int word_length[4] = { 5, 6, 7, 8 }; -INLINE mc6854_t* get_safe_token( device_t *device ) +const device_type MC6854 = &device_creator; + +mc6854_device::mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, MC6854, "Motorola MC6854 ADLC", tag, owner, clock, "mc6854", __FILE__), + m_cr1(0), + m_cr2(0), + m_cr3(0), + m_cr4(0), + m_sr1(0), + m_sr2(0), + m_cts(0), + m_dcd(0), + m_tstate(0), + m_tones(0), + m_ttimer(NULL), + m_rstate(0), + m_rreg(0), + m_rones(0), + m_rsize(0), + m_flen(0), + m_fpos(0) { - assert( device != NULL ); - assert( device->type() == MC6854 ); - return (mc6854_t*) downcast(device)->token(); + for (int i = 0; i < MC6854_FIFO_SIZE; i++) + { + m_tfifo[i] = 0; + m_rfifo[i] = 0; + } + + for (int i = 0; i < MAX_FRAME_LENGTH; i++) + { + m_frame[i] = 0; + } } +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void mc6854_device::device_config_complete() +{ + // inherit a copy of the static data + const mc6854_interface *intf = reinterpret_cast(static_config()); + if (intf != NULL) + *static_cast(this) = *intf; + + // or initialize to defaults if none provided + else + { + memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb)); + memset(&m_in_rxd_cb, 0, sizeof(m_in_rxd_cb)); + memset(&m_out_txd_cb, 0, sizeof(m_out_txd_cb)); + memset(&m_out_rts_cb, 0, sizeof(m_out_rts_cb)); + memset(&m_out_dtr_cb, 0, sizeof(m_out_dtr_cb)); + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void mc6854_device::device_start() +{ + m_out_irq_func.resolve(m_out_irq_cb, *this); + m_in_rxd_func.resolve(m_in_rxd_cb, *this); + m_out_txd_func.resolve(m_out_txd_cb, *this); + m_out_rts_func.resolve(m_out_rts_cb, *this); + m_out_dtr_func.resolve(m_out_dtr_cb, *this); + + m_ttimer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mc6854_device::tfifo_cb), this)); + + save_item(NAME(m_cr1)); + save_item(NAME(m_cr2)); + save_item(NAME(m_cr3)); + save_item(NAME(m_cr4)); + save_item(NAME(m_sr1)); + save_item(NAME(m_sr2)); + save_item(NAME(m_cts)); + save_item(NAME(m_dcd)); + save_item(NAME(m_tstate)); + save_item(NAME(m_tfifo)); + save_item(NAME(m_tones)); + save_item(NAME(m_rstate)); + save_item(NAME(m_rreg)); + save_item(NAME(m_rones)); + save_item(NAME(m_rsize)); + save_item(NAME(m_rfifo)); + save_item(NAME(m_frame)); + save_item(NAME(m_flen)); + save_item(NAME(m_fpos)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void mc6854_device::device_reset() +{ + LOG (( "mc6854 reset\n" )); + m_cr1 = 0xc0; /* reset condition */ + m_cr2 = 0; + m_cr3 = 0; + m_cr4 = 0; + m_sr1 = 0; + m_sr2 = 0; + m_cts = 0; + m_dcd = 0; + tfifo_clear( ); + rfifo_clear( ); +} /*********************** transmit ***********************/ /* MC6854 fills bit queue */ -static void mc6854_send_bits( device_t *device, UINT32 data, int len, int zi ) +void mc6854_device::send_bits( UINT32 data, int len, int zi ) { - mc6854_t* mc6854 = get_safe_token( device ); attotime expire; int i; if ( zi ) @@ -250,83 +294,80 @@ static void mc6854_send_bits( device_t *device, UINT32 data, int len, int zi ) if ( data & 1 ) { d |= 1 << l; - mc6854->tones++; - if ( mc6854->tones == 5 ) + m_tones++; + if ( m_tones == 5 ) { /* insert a '0' after 5 consecutive '1" */ - mc6854->tones = 0; + m_tones = 0; l++; } } else - mc6854->tones = 0; + m_tones = 0; } data = d; len = l; } else - mc6854->tones = 0; + m_tones = 0; /* send bits */ - if ( !mc6854->out_txd_func.isnull() ) + if ( !m_out_txd_func.isnull() ) { for ( i = 0; i < len; i++, data >>= 1 ) - mc6854->out_txd_func( data & 1 ); + m_out_txd_func( data & 1 ); } /* schedule when to ask the MC6854 for more bits */ - expire = mc6854->ttimer ->remaining( ); + expire = m_ttimer ->remaining( ); if ( expire== attotime::never ) expire = attotime::zero; - mc6854->ttimer->reset( expire + (BIT_LENGTH * len)); + m_ttimer->reset( expire + (BIT_LENGTH * len)); } -/* CPU push -> tfifo[0] -> ... -> tfifo[FIFO_SIZE-1] -> pop */ -static void mc6854_tfifo_push( device_t *device, UINT8 data ) +/* CPU push -> tfifo[0] -> ... -> tfifo[MC6854_FIFO_SIZE-1] -> pop */ +void mc6854_device::tfifo_push( UINT8 data ) { - mc6854_t* mc6854 = get_safe_token( device ); int i; if ( TRESET ) return; /* push towards the rightmost free entry */ - for ( i = FIFO_SIZE - 1; i >= 0; i-- ) + for ( i = MC6854_FIFO_SIZE - 1; i >= 0; i-- ) { - if ( ! ( mc6854->tfifo[ i ] & 0x100 ) ) + if ( ! ( m_tfifo[ i ] & 0x100 ) ) break; } if ( i >= 0 ) - mc6854->tfifo[ i ] = data | 0x100; + m_tfifo[ i ] = data | 0x100; else - logerror( "%f mc6854_tfifo_push: FIFO overrun\n", device->machine().time().as_double() ); + logerror( "%f mc6854_tfifo_push: FIFO overrun\n", machine().time().as_double() ); /* start frame, if needed */ - if ( ! mc6854->tstate ) + if ( ! m_tstate ) { - LOG(( "%f mc6854_tfifo_push: start frame\n", device->machine().time().as_double() )); - mc6854->tstate = 2; - mc6854_send_bits( device, FLAG, 8, 0 ); + LOG(( "%f mc6854_tfifo_push: start frame\n", machine().time().as_double() )); + m_tstate = 2; + send_bits( FLAG, 8, 0 ); } } /* CPU asks for normal frame termination */ -static void mc6854_tfifo_terminate( device_t *device ) +void mc6854_device::tfifo_terminate( ) { - mc6854_t* mc6854 = get_safe_token( device ); - /* mark most recently pushed byte as the last one of the frame */ int i; - for ( i = 0; i < FIFO_SIZE; i++ ) + for ( i = 0; i < MC6854_FIFO_SIZE; i++ ) { - if ( mc6854->tfifo[ i ] & 0x100 ) + if ( m_tfifo[ i ] & 0x100 ) { - mc6854->tfifo[ i ] |= 0x200; + m_tfifo[ i ] |= 0x200; break; } } @@ -335,19 +376,19 @@ static void mc6854_tfifo_terminate( device_t *device ) /* call-back to refill the bit-stream from the FIFO */ -static TIMER_CALLBACK(mc6854_tfifo_cb) +TIMER_CALLBACK_MEMBER(mc6854_device::tfifo_cb) { device_t* device = (device_t*) ptr; - mc6854_t* mc6854 = get_safe_token( device ); - int i, data = mc6854->tfifo[ FIFO_SIZE - 1 ]; + + int i, data = m_tfifo[ MC6854_FIFO_SIZE - 1 ]; - if ( ! mc6854->tstate ) + if ( ! m_tstate ) return; /* shift FIFO to the right */ - for ( i = FIFO_SIZE - 1; i > 0; i-- ) - mc6854->tfifo[ i ] = mc6854->tfifo[ i - 1 ]; - mc6854->tfifo[ 0 ] = 0; + for ( i = MC6854_FIFO_SIZE - 1; i > 0; i-- ) + m_tfifo[ i ] = m_tfifo[ i - 1 ]; + m_tfifo[ 0 ] = 0; if ( data & 0x100 ) { @@ -355,98 +396,97 @@ static TIMER_CALLBACK(mc6854_tfifo_cb) int blen = 8; - switch ( mc6854->tstate ) + switch ( m_tstate ) { case 2: /* 8-bit address field */ if ( ( data & 1 ) || ( ! AEX ) ) - mc6854->tstate = 3; - LOG(( "%f mc6854_tfifo_cb: address field $%02X\n", machine.time().as_double(), data & 0xff )); + m_tstate = 3; + LOG(( "%f mc6854_tfifo_cb: address field $%02X\n", machine().time().as_double(), data & 0xff )); break; case 3: /* 8-bit control field */ if ( CEX ) - mc6854->tstate = 4; + m_tstate = 4; else if ( LCF ) - mc6854->tstate = 5; + m_tstate = 5; else - mc6854->tstate = 6; - LOG(( "%f mc6854_tfifo_cb: control field $%02X\n", machine.time().as_double(), data & 0xff )); + m_tstate = 6; + LOG(( "%f mc6854_tfifo_cb: control field $%02X\n", machine().time().as_double(), data & 0xff )); break; case 4: /* 8-bit extended control field (optional) */ if ( LCF ) - mc6854->tstate = 5; + m_tstate = 5; else - mc6854->tstate = 6; - LOG(( "%f mc6854_tfifo_cb: control field $%02X\n", machine.time().as_double(), data & 0xff )); + m_tstate = 6; + LOG(( "%f mc6854_tfifo_cb: control field $%02X\n", machine().time().as_double(), data & 0xff )); break; case 5: /* 8-bit logical control (optional) */ if ( ! ( data & 0x80 ) ) - mc6854->tstate = 6; - LOG(( "%f mc6854_tfifo_cb: logical control field $%02X\n", machine.time().as_double(), data & 0xff )); + m_tstate = 6; + LOG(( "%f mc6854_tfifo_cb: logical control field $%02X\n", machine().time().as_double(), data & 0xff )); break; case 6: /* variable-length data */ blen = TWL; - LOG(( "%f mc6854_tfifo_cb: data field $%02X, %i bits\n", machine.time().as_double(), data & 0xff, blen )); + LOG(( "%f mc6854_tfifo_cb: data field $%02X, %i bits\n", machine().time().as_double(), data & 0xff, blen )); break; default: - LOG(( "%f mc6854_tfifo_cb: state=%i\n", machine.time().as_double(), mc6854->tstate)); + LOG(( "%f mc6854_tfifo_cb: state=%i\n", machine().time().as_double(), m_tstate)); } - if ( mc6854->flen < MAX_FRAME_LENGTH ) - mc6854->frame[ mc6854->flen++ ] = data; + if ( m_flen < MAX_FRAME_LENGTH ) + m_frame[ m_flen++ ] = data; else logerror( "mc6854_tfifo_cb: truncated frame, max=%i\n", MAX_FRAME_LENGTH ); - mc6854_send_bits( device, data, blen, 1 ); + send_bits( data, blen, 1 ); } else { /* data underrun => abort */ - logerror( "%f mc6854_tfifo_cb: FIFO underrun\n", machine.time().as_double() ); - mc6854->sr1 |= TU; - mc6854->tstate = 0; - mc6854_send_bits( device, 0xffff, ABTEX ? 16 : 8, 0 ); - mc6854->flen = 0; + logerror( "%f mc6854_tfifo_cb: FIFO underrun\n", machine().time().as_double() ); + m_sr1 |= TU; + m_tstate = 0; + send_bits( 0xffff, ABTEX ? 16 : 8, 0 ); + m_flen = 0; } /* close frame, if needed */ if ( data & 0x200 ) { - int len = mc6854->flen; + int len = m_flen; - LOG(( "%f mc6854_tfifo_cb: end frame\n", machine.time().as_double() )); - mc6854_send_bits( device, 0xdeadbeef, 16, 1 ); /* send check-sum: TODO */ - mc6854_send_bits( device, FLAG, 8, 0 ); /* send closing flag */ + LOG(( "%f mc6854_tfifo_cb: end frame\n", machine().time().as_double() )); + send_bits( 0xdeadbeef, 16, 1 ); /* send check-sum: TODO */ + send_bits( FLAG, 8, 0 ); /* send closing flag */ - if ( mc6854->tfifo[ FIFO_SIZE - 1 ] & 0x100 ) + if ( m_tfifo[ MC6854_FIFO_SIZE - 1 ] & 0x100 ) { /* re-open frame asap */ - LOG(( "%f mc6854_tfifo_cb: start frame\n", machine.time().as_double() )); + LOG(( "%f mc6854_tfifo_cb: start frame\n", machine().time().as_double() )); if ( TWOINTER ) - mc6854_send_bits( device, FLAG, 8, 0 ); + send_bits( FLAG, 8, 0 ); } else - mc6854->tstate = 0; + m_tstate = 0; - mc6854->flen = 0; - if ( mc6854->iface->out_frame ) - mc6854->iface->out_frame( device, mc6854->frame, len ); + m_flen = 0; + if ( m_out_frame ) + m_out_frame( device, m_frame, len ); } } -static void mc6854_tfifo_clear( device_t *device ) +void mc6854_device::tfifo_clear( ) { - mc6854_t* mc6854 = get_safe_token( device ); - memset( mc6854->tfifo, 0, sizeof( mc6854->tfifo ) ); - mc6854->tstate = 0; - mc6854->flen = 0; - mc6854->ttimer->reset( ); + memset( m_tfifo, 0, sizeof( m_tfifo ) ); + m_tstate = 0; + m_flen = 0; + m_ttimer->reset( ); } @@ -456,131 +496,128 @@ static void mc6854_tfifo_clear( device_t *device ) /* MC6854 pushes a field in the FIFO */ -static void mc6854_rfifo_push( device_t *device, UINT8 d ) +void mc6854_device::rfifo_push( UINT8 d ) { - mc6854_t* mc6854 = get_safe_token( device ); int i, blen = 8; unsigned data = d; - switch ( mc6854->rstate ) + switch ( m_rstate ) { case 0: case 1: case 2: /* 8-bit address field */ if ( ( data & 1 ) || ( ! AEX ) ) - mc6854->rstate = 3; + m_rstate = 3; else - mc6854->rstate = 2; - LOG(( "%f mc6854_rfifo_push: address field $%02X\n", device->machine().time().as_double(), data )); + m_rstate = 2; + LOG(( "%f mc6854_rfifo_push: address field $%02X\n", machine().time().as_double(), data )); data |= 0x400; /* address marker */ break; case 3: /* 8-bit control field */ if ( CEX ) - mc6854->rstate = 4; + m_rstate = 4; else if ( LCF ) - mc6854->rstate = 5; + m_rstate = 5; else - mc6854->rstate = 6; - LOG(( "%f mc6854_rfifo_push: control field $%02X\n", device->machine().time().as_double(), data )); + m_rstate = 6; + LOG(( "%f mc6854_rfifo_push: control field $%02X\n", machine().time().as_double(), data )); break; case 4: /* 8-bit extended control field (optional) */ if ( LCF ) - mc6854->rstate = 5; + m_rstate = 5; else - mc6854->rstate = 6; - LOG(( "%f mc6854_rfifo_push: control field $%02X\n", device->machine().time().as_double(), data )); + m_rstate = 6; + LOG(( "%f mc6854_rfifo_push: control field $%02X\n", machine().time().as_double(), data )); break; case 5: /* 8-bit logical control (optional) */ if ( ! ( data & 0x80 ) ) - mc6854->rstate = 6; - LOG(( "%f mc6854_rfifo_push: logical control field $%02X\n", device->machine().time().as_double(), data )); + m_rstate = 6; + LOG(( "%f mc6854_rfifo_push: logical control field $%02X\n", machine().time().as_double(), data )); break; case 6: /* variable-length data */ blen = RWL; data >>= 8 - blen; - LOG(( "%f mc6854_rfifo_push: data field $%02X, %i bits\n", device->machine().time().as_double(), data, blen )); + LOG(( "%f mc6854_rfifo_push: data field $%02X, %i bits\n", machine().time().as_double(), data, blen )); break; } /* no further FIFO fill until FV is cleared! */ - if ( mc6854->sr2 & FV ) + if ( m_sr2 & FV ) { - LOG(( "%f mc6854_rfifo_push: field not pushed\n", device->machine().time().as_double() )); + LOG(( "%f mc6854_rfifo_push: field not pushed\n", machine().time().as_double() )); return; } data |= 0x100; /* entry full marker */ /* push towards the rightmost free entry */ - for ( i = FIFO_SIZE - 1; i >= 0; i-- ) + for ( i = MC6854_FIFO_SIZE - 1; i >= 0; i-- ) { - if ( ! ( mc6854->rfifo[ i ] & 0x100 ) ) + if ( ! ( m_rfifo[ i ] & 0x100 ) ) break; } if ( i >= 0 ) - mc6854->rfifo[ i ] = data | 0x100; + m_rfifo[ i ] = data | 0x100; else { /* FIFO full */ - mc6854->sr2 |= OVRN; - mc6854->rfifo[ 0 ] = data; - logerror( "%f mc6854_rfifo_push: FIFO overrun\n", device->machine().time().as_double() ); + m_sr2 |= OVRN; + m_rfifo[ 0 ] = data; + logerror( "%f mc6854_rfifo_push: FIFO overrun\n", machine().time().as_double() ); } - mc6854->rsize -= blen; + m_rsize -= blen; } -static void mc6854_rfifo_terminate( device_t *device ) +void mc6854_device::rfifo_terminate( ) { - mc6854_t* mc6854 = get_safe_token( device ); /* mark most recently pushed byte as the last one of the frame */ int i; - for ( i = 0; i < FIFO_SIZE; i++ ) + for ( i = 0; i < MC6854_FIFO_SIZE; i++ ) { - if ( mc6854->rfifo[ i ] & 0x100 ) + if ( m_rfifo[ i ] & 0x100 ) { - mc6854->tfifo[ i ] |= 0x200; + m_tfifo[ i ] |= 0x200; break; } } - mc6854->flen = 0; - mc6854->rstate = 1; + m_flen = 0; + m_rstate = 1; } /* CPU pops the FIFO */ -static UINT8 mc6854_rfifo_pop( device_t *device ) +UINT8 mc6854_device::rfifo_pop( ) { - mc6854_t* mc6854 = get_safe_token( device ); - int i, data = mc6854->rfifo[ FIFO_SIZE - 1 ]; + int i, data = m_rfifo[ MC6854_FIFO_SIZE - 1 ]; /* shift FIFO to the right */ - for ( i = FIFO_SIZE - 1; i > 0; i -- ) - mc6854->rfifo[ i ] = mc6854->rfifo[ i - 1 ]; - mc6854->rfifo[ 0 ] = 0; + for ( i = MC6854_FIFO_SIZE - 1; i > 0; i -- ) + m_rfifo[ i ] = m_rfifo[ i - 1 ]; + m_rfifo[ 0 ] = 0; - if ( mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x200 ) + if ( m_rfifo[ MC6854_FIFO_SIZE - 1 ] & 0x200 ) { /* last byte in frame */ - mc6854->sr2 |= FV; /* TODO: check CRC & set ERR instead of FV if error*/ + m_sr2 |= FV; /* TODO: check CRC & set ERR instead of FV if error*/ } /* auto-refill in frame mode */ - if ( mc6854->flen > 0 ) + if ( m_flen > 0 ) { - mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] ); - if ( mc6854->fpos == mc6854->flen ) - mc6854_rfifo_terminate( device ); + rfifo_push( m_frame[ m_fpos++ ] ); + if ( m_fpos == m_flen ) + rfifo_terminate( ); } return data; @@ -588,91 +625,88 @@ static UINT8 mc6854_rfifo_pop( device_t *device ) /* MC6854 makes fields from bits */ -WRITE_LINE_DEVICE_HANDLER( mc6854_set_rx ) +WRITE_LINE_MEMBER( mc6854_device::set_rx ) { - mc6854_t* mc6854 = get_safe_token( device ); - int fieldlen = ( mc6854->rstate < 6 ) ? 8 : RWL; + int fieldlen = ( m_rstate < 6 ) ? 8 : RWL; - if ( RRESET || (mc6854->sr2 & DCD) ) + if ( RRESET || (m_sr2 & DCD) ) return; if ( state ) { - mc6854->rones++; - mc6854->rreg = (mc6854->rreg >> 1) | 0x80000000; - if ( mc6854->rones >= 8 ) + m_rones++; + m_rreg = (m_rreg >> 1) | 0x80000000; + if ( m_rones >= 8 ) { /* abort */ - mc6854->rstate = 0; - mc6854->rsize = 0; - if ( mc6854->rstate > 1 ) + m_rstate = 0; + m_rsize = 0; + if ( m_rstate > 1 ) { /* only in-frame abort */ - mc6854->sr2 |= RABT; - LOG(( "%f mc6854_receive_bit: abort\n", device->machine().time().as_double() )); + m_sr2 |= RABT; + LOG(( "%f mc6854_receive_bit: abort\n", machine().time().as_double() )); } } else { - mc6854->rsize++; - if ( mc6854->rstate && mc6854->rsize >= fieldlen + 24 ) - mc6854_rfifo_push( device, mc6854->rreg ); + m_rsize++; + if ( m_rstate && m_rsize >= fieldlen + 24 ) + rfifo_push( m_rreg ); } } - else if ( mc6854->rones == 5 ) + else if ( m_rones == 5 ) { /* discards '0' inserted after 5 '1' */ - mc6854->rones = 0; + m_rones = 0; return; } - else if ( mc6854->rones == 6 ) + else if ( m_rones == 6 ) { /* flag */ if ( FDSE ) - mc6854->sr1 |= FD; + m_sr1 |= FD; - if ( mc6854->rstate > 1 ) + if ( m_rstate > 1 ) { /* end of frame */ - mc6854->rreg >>= 1; - mc6854->rsize++; - if ( mc6854->rsize >= fieldlen + 24 ) /* last field */ - mc6854_rfifo_push( device, mc6854->rreg ); - mc6854_rfifo_terminate( device ); - LOG(( "%f mc6854_receive_bit: end of frame\n", device->machine().time().as_double() )); + m_rreg >>= 1; + m_rsize++; + if ( m_rsize >= fieldlen + 24 ) /* last field */ + rfifo_push( m_rreg ); + rfifo_terminate( ); + LOG(( "%f mc6854_receive_bit: end of frame\n", machine().time().as_double() )); } - mc6854->rones = 0; - mc6854->rstate = 1; - mc6854->rsize = 0; + m_rones = 0; + m_rstate = 1; + m_rsize = 0; } else { - mc6854->rones = 0; - mc6854->rreg >>= 1; - mc6854->rsize++; - if ( mc6854->rstate && mc6854->rsize >= fieldlen + 24 ) - mc6854_rfifo_push( device, mc6854->rreg ); + m_rones = 0; + m_rreg >>= 1; + m_rsize++; + if ( m_rstate && m_rsize >= fieldlen + 24 ) + rfifo_push( m_rreg ); } } -static void mc6854_rfifo_clear( device_t *device ) +void mc6854_device::rfifo_clear( ) { - mc6854_t* mc6854 = get_safe_token( device ); - memset( mc6854->rfifo, 0, sizeof( mc6854->rfifo ) ); - mc6854->rstate = 0; - mc6854->rreg = 0; - mc6854->rsize = 0; - mc6854->rones = 0; - mc6854->flen = 0; + memset( m_rfifo, 0, sizeof( m_rfifo ) ); + m_rstate = 0; + m_rreg = 0; + m_rsize = 0; + m_rones = 0; + m_flen = 0; } -int mc6854_send_frame( device_t *device, UINT8* data, int len ) +int mc6854_device::send_frame( UINT8* data, int len ) { - mc6854_t* mc6854 = get_safe_token( device ); - if ( mc6854->rstate > 1 || mc6854->tstate > 1 || RTS ) + if ( m_rstate > 1 || m_tstate > 1 || RTS ) return -1; /* busy */ if ( len > MAX_FRAME_LENGTH ) @@ -685,15 +719,15 @@ int mc6854_send_frame( device_t *device, UINT8* data, int len ) logerror( "mc6854_send_frame: frame too short, size=%i, min=2\n", len ); len = 2; } - memcpy( mc6854->frame, data, len ); + memcpy( m_frame, data, len ); if ( FDSE ) - mc6854->sr1 |= FD; - mc6854->flen = len; - mc6854->fpos = 0; - mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] ); - mc6854_rfifo_push( device, mc6854->frame[ mc6854->fpos++ ] ); - if ( mc6854->fpos == mc6854->flen ) - mc6854_rfifo_terminate( device ); + m_sr1 |= FD; + m_flen = len; + m_fpos = 0; + rfifo_push( m_frame[ m_fpos++ ] ); + rfifo_push( m_frame[ m_fpos++ ] ); + if ( m_fpos == m_flen ) + rfifo_terminate( ); return 0; } @@ -703,130 +737,127 @@ int mc6854_send_frame( device_t *device, UINT8* data, int len ) -WRITE_LINE_DEVICE_HANDLER( mc6854_set_cts ) +WRITE_LINE_MEMBER( mc6854_device::set_cts ) { - mc6854_t* mc6854 = get_safe_token( device ); - if ( ! mc6854->cts && state ) - mc6854->sr1 |= CTS; - mc6854->cts = state; + if ( ! m_cts && state ) + m_sr1 |= CTS; + m_cts = state; - if ( mc6854->cts ) - mc6854->sr1 |= CTS; + if ( m_cts ) + m_sr1 |= CTS; else - mc6854->sr1 &= ~CTS; + m_sr1 &= ~CTS; } -WRITE_LINE_DEVICE_HANDLER( mc6854_set_dcd ) +WRITE_LINE_MEMBER( mc6854_device::set_dcd ) { - mc6854_t* mc6854 = get_safe_token( device ); - if ( ! mc6854->dcd && state ) + if ( ! m_dcd && state ) { - mc6854->sr2 |= DCD; + m_sr2 |= DCD; /* partial reset */ - mc6854->rstate = 0; - mc6854->rreg = 0; - mc6854->rsize = 0; - mc6854->rones = 0; + m_rstate = 0; + m_rreg = 0; + m_rsize = 0; + m_rones = 0; } - mc6854->dcd = state; + m_dcd = state; } -static void mc6854_update_sr2( mc6854_t* mc6854 ) +void mc6854_device::update_sr2( ) { /* update RDA */ - mc6854->sr2 |= RDA2; - if ( ! (mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x100) ) - mc6854->sr2 &= ~RDA2; - else if ( TWOBYTES && ! (mc6854->tfifo[ FIFO_SIZE - 2 ] & 0x100) ) - mc6854->sr2 &= ~RDA2; + m_sr2 |= RDA2; + if ( ! (m_rfifo[ MC6854_FIFO_SIZE - 1 ] & 0x100) ) + m_sr2 &= ~RDA2; + else if ( TWOBYTES && ! (m_tfifo[ MC6854_FIFO_SIZE - 2 ] & 0x100) ) + m_sr2 &= ~RDA2; /* update AP */ - if ( mc6854->rfifo[ FIFO_SIZE - 1 ] & 0x400 ) - mc6854->sr2 |= AP; + if ( m_rfifo[ MC6854_FIFO_SIZE - 1 ] & 0x400 ) + m_sr2 |= AP; else - mc6854->sr2 &= ~AP; + m_sr2 &= ~AP; } -static void mc6854_update_sr1( mc6854_t* mc6854 ) +void mc6854_device::update_sr1( ) { - mc6854_update_sr2( mc6854 ); + update_sr2( ); /* update S2RQ */ - if ( mc6854->sr2 & 0x7f ) - mc6854->sr1 |= S2RQ; + if ( m_sr2 & 0x7f ) + m_sr1 |= S2RQ; else - mc6854->sr1 &= ~S2RQ; + m_sr1 &= ~S2RQ; /* update TRDA (always prioritized by CTS) */ - if ( TRESET || ( mc6854->sr1 & CTS ) ) - mc6854->sr1 &= ~TDRA; + if ( TRESET || ( m_sr1 & CTS ) ) + m_sr1 &= ~TDRA; else { - mc6854->sr1 |= TDRA; - if ( mc6854->tfifo[ 0 ] & 0x100 ) - mc6854->sr1 &= ~TDRA; - else if ( TWOBYTES && (mc6854->tfifo[ 1 ] & 0x100) ) - mc6854->sr1 &= ~TDRA; + m_sr1 |= TDRA; + if ( m_tfifo[ 0 ] & 0x100 ) + m_sr1 &= ~TDRA; + else if ( TWOBYTES && (m_tfifo[ 1 ] & 0x100) ) + m_sr1 &= ~TDRA; } /* update RDA */ - if ( mc6854->sr2 & RDA2 ) - mc6854->sr1 |= RDA; + if ( m_sr2 & RDA2 ) + m_sr1 |= RDA; else - mc6854->sr1 &= ~RDA; + m_sr1 &= ~RDA; /* update IRQ */ - mc6854->sr1 &= ~IRQ; - if ( RIE && (mc6854->sr1 & (TU | TDRA) ) ) - mc6854->sr1 |= IRQ; + m_sr1 &= ~IRQ; + if ( RIE && (m_sr1 & (TU | TDRA) ) ) + m_sr1 |= IRQ; if ( TIE ) { - if ( mc6854->sr1 & (S2RQ | RDA | CTS) ) - mc6854->sr1 |= IRQ; - if ( mc6854->sr2 & (ERR | FV | DCD | OVRN | RABT | RIDLE | AP) ) - mc6854->sr1 |= IRQ; + if ( m_sr1 & (S2RQ | RDA | CTS) ) + m_sr1 |= IRQ; + if ( m_sr2 & (ERR | FV | DCD | OVRN | RABT | RIDLE | AP) ) + m_sr1 |= IRQ; } - mc6854->out_irq_func((mc6854->sr1 & IRQ) ? ASSERT_LINE : CLEAR_LINE); + m_out_irq_func((m_sr1 & IRQ) ? ASSERT_LINE : CLEAR_LINE); } -READ8_DEVICE_HANDLER ( mc6854_r ) +READ8_MEMBER( mc6854_device::read ) { - mc6854_t* mc6854 = get_safe_token( device ); switch ( offset ) { case 0: /* status register 1 */ - mc6854_update_sr1( mc6854 ); + update_sr1( ); LOG(( "%f $%04x mc6854_r: get SR1=$%02X (rda=%i,s2rq=%i,fd=%i,cts=%i,tu=%i,tdra=%i,irq=%i)\n", - space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->sr1, - ( mc6854->sr1 & RDA) ? 1 : 0, ( mc6854->sr1 & S2RQ) ? 1 : 0, - ( mc6854->sr1 & FD ) ? 1 : 0, ( mc6854->sr1 & CTS ) ? 1 : 0, - ( mc6854->sr1 & TU ) ? 1 : 0, ( mc6854->sr1 & TDRA) ? 1 : 0, - ( mc6854->sr1 & IRQ) ? 1 : 0 )); - return mc6854->sr1; + space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), m_sr1, + ( m_sr1 & RDA) ? 1 : 0, ( m_sr1 & S2RQ) ? 1 : 0, + ( m_sr1 & FD ) ? 1 : 0, ( m_sr1 & CTS ) ? 1 : 0, + ( m_sr1 & TU ) ? 1 : 0, ( m_sr1 & TDRA) ? 1 : 0, + ( m_sr1 & IRQ) ? 1 : 0 )); + return m_sr1; case 1: /* status register 2 */ - mc6854_update_sr2( mc6854 ); + update_sr2( ); LOG(( "%f $%04x mc6854_r: get SR2=$%02X (ap=%i,fv=%i,ridle=%i,rabt=%i,err=%i,dcd=%i,ovrn=%i,rda2=%i)\n", - space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->sr2, - ( mc6854->sr2 & AP ) ? 1 : 0, ( mc6854->sr2 & FV ) ? 1 : 0, - ( mc6854->sr2 & RIDLE) ? 1 : 0, ( mc6854->sr2 & RABT) ? 1 : 0, - ( mc6854->sr2 & ERR ) ? 1 : 0, ( mc6854->sr2 & DCD ) ? 1 : 0, - ( mc6854->sr2 & OVRN ) ? 1 : 0, ( mc6854->sr2 & RDA2) ? 1 : 0 )); - return mc6854->sr2; + space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), m_sr2, + ( m_sr2 & AP ) ? 1 : 0, ( m_sr2 & FV ) ? 1 : 0, + ( m_sr2 & RIDLE) ? 1 : 0, ( m_sr2 & RABT) ? 1 : 0, + ( m_sr2 & ERR ) ? 1 : 0, ( m_sr2 & DCD ) ? 1 : 0, + ( m_sr2 & OVRN ) ? 1 : 0, ( m_sr2 & RDA2) ? 1 : 0 )); + return m_sr2; case 2: /* receiver data register */ case 3: { - UINT8 data = mc6854_rfifo_pop( device ); + UINT8 data = rfifo_pop( ); LOG(( "%f $%04x mc6854_r: get data $%02X\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data )); return data; @@ -840,42 +871,41 @@ READ8_DEVICE_HANDLER ( mc6854_r ) -WRITE8_DEVICE_HANDLER ( mc6854_w ) +WRITE8_MEMBER( mc6854_device::write ) { - mc6854_t* mc6854 = get_safe_token( device ); switch ( offset ) { case 0: /* control register 1 */ - mc6854->cr1 = data; + m_cr1 = data; LOG(( "%f $%04x mc6854_w: set CR1=$%02X (ac=%i,irq=%c%c,%sreset=%c%c)\n", - space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr1, + space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), m_cr1, AC ? 1 : 0, RIE ? 'r' : '-', TIE ? 't' : '-', DISCONTINUE ? "discontinue," : "", RRESET ? 'r' : '-', TRESET ? 't' : '-' )); - if ( mc6854->cr1 & 0xc ) + if ( m_cr1 & 0xc ) logerror( "$%04x mc6854 DMA not handled (CR1=$%02X)\n", - space.machine().firstcpu->pcbase( ), mc6854->cr1 ); + space.machine().firstcpu->pcbase( ), m_cr1 ); if ( DISCONTINUE ) { /* abort receive FIFO but keeps shift register & synchro */ - mc6854->rstate = 0; - memset( mc6854->rfifo, 0, sizeof( mc6854->rfifo ) ); + m_rstate = 0; + memset( m_rfifo, 0, sizeof( m_rfifo ) ); } if ( RRESET ) { /* abort FIFO & synchro */ - mc6854_rfifo_clear( device ); - mc6854->sr1 &= ~FD; - mc6854->sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD); - if ( mc6854->dcd ) mc6854->sr2 |= DCD; + rfifo_clear( ); + m_sr1 &= ~FD; + m_sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD); + if ( m_dcd ) m_sr2 |= DCD; } if ( TRESET ) { - mc6854_tfifo_clear( device ); - mc6854->sr1 &= ~(TU | TDRA | CTS); - if ( mc6854->cts ) mc6854->sr1 |= CTS; + tfifo_clear( ); + m_sr1 &= ~(TU | TDRA | CTS); + if ( m_cts ) m_sr1 |= CTS; } break; @@ -883,83 +913,83 @@ WRITE8_DEVICE_HANDLER ( mc6854_w ) if ( AC ) { /* control register 3 */ - mc6854->cr3 = data; + m_cr3 = data; LOG(( "%f $%04x mc6854_w: set CR3=$%02X (lcf=%i,aex=%i,idl=%i,fdse=%i,loop=%i,tst=%i,dtr=%i)\n", - space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr3, + space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), m_cr3, LCF ? (CEX ? 16 : 8) : 0, AEX ? 1 : 0, IDL0 ? 0 : 1, FDSE ? 1 : 0, LOOP ? 1 : 0, TST ? 1 : 0, DTR ? 1 : 0 )); if ( LOOP ) - logerror( "$%04x mc6854 loop mode not handled (CR3=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr3 ); + logerror( "$%04x mc6854 loop mode not handled (CR3=$%02X)\n", space.machine().firstcpu->pcbase( ), m_cr3 ); if ( TST ) - logerror( "$%04x mc6854 test mode not handled (CR3=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr3 ); + logerror( "$%04x mc6854 test mode not handled (CR3=$%02X)\n", space.machine().firstcpu->pcbase( ), m_cr3 ); - mc6854->out_dtr_func( DTR ? 1 : 0 ); + m_out_dtr_func( DTR ? 1 : 0 ); } else { /* control register 2 */ - mc6854->cr2 = data; + m_cr2 = data; LOG(( "%f $%04x mc6854_w: set CR2=$%02X (pse=%i,bytes=%i,fmidle=%i,%s,tlast=%i,clr=%c%c,rts=%i)\n", - space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr2, + space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), m_cr2, PSE ? 1 : 0, TWOBYTES ? 2 : 1, FMIDLE ? 1 : 0, FCTDRA ? "fc" : "tdra", TLAST ? 1 : 0, data & 0x20 ? 'r' : '-', data & 0x40 ? 't' : '-', RTS ? 1 : 0 )); if ( PSE ) - logerror( "$%04x mc6854 status prioritization not handled (CR2=$%02X)\n", space.machine().firstcpu->pcbase( ), mc6854->cr2 ); + logerror( "$%04x mc6854 status prioritization not handled (CR2=$%02X)\n", space.machine().firstcpu->pcbase( ), m_cr2 ); if ( TLAST ) - mc6854_tfifo_terminate( device ); + tfifo_terminate( ); if ( data & 0x20 ) { /* clear receiver status */ - mc6854->sr1 &= ~FD; - mc6854->sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD); - if ( mc6854->dcd ) - mc6854->sr2 |= DCD; + m_sr1 &= ~FD; + m_sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD); + if ( m_dcd ) + m_sr2 |= DCD; } if ( data & 0x40 ) { /* clear transmitter status */ - mc6854->sr1 &= ~(TU | TDRA | CTS); - if ( mc6854->cts ) - mc6854->sr1 |= CTS; + m_sr1 &= ~(TU | TDRA | CTS); + if ( m_cts ) + m_sr1 |= CTS; } - mc6854->out_rts_func( RTS ? 1 : 0 ); + m_out_rts_func( RTS ? 1 : 0 ); } break; case 2: /* transmitter data: continue data */ LOG(( "%f $%04xmc6854_w: push data=$%02X\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data )); - mc6854_tfifo_push( device, data ); + tfifo_push( data ); break; case 3: if ( AC ) { /* control register 4 */ - mc6854->cr4 = data; - LOG(( "%f $%04x mc6854_w: set CR4=$%02X (interframe=%i,tlen=%i,rlen=%i,%s%s)\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), mc6854->cr4, + m_cr4 = data; + LOG(( "%f $%04x mc6854_w: set CR4=$%02X (interframe=%i,tlen=%i,rlen=%i,%s%s)\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), m_cr4, TWOINTER ? 2 : 1, TWL, RWL, ABT ? ( ABTEX ? "abort-ext," : "abort,") : "", NRZ ? "nrz" : "nrzi" )); if ( ABT ) { - mc6854->tstate = 0; - mc6854_send_bits( device, 0xffff, ABTEX ? 16 : 8, 0 ); - mc6854->flen = 0; + m_tstate = 0; + send_bits( 0xffff, ABTEX ? 16 : 8, 0 ); + m_flen = 0; } } else { /* transmitter data: last data */ LOG(( "%f $%04x mc6854_w: push last-data=$%02X\n", space.machine().time().as_double(), space.machine().firstcpu->pcbase( ), data )); - mc6854_tfifo_push( device, data ); - mc6854_tfifo_terminate( device ); + tfifo_push( data ); + tfifo_terminate( ); } break; @@ -968,106 +998,12 @@ WRITE8_DEVICE_HANDLER ( mc6854_w ) } } -WRITE_LINE_DEVICE_HANDLER( mc6854_rxc_w ) +WRITE_LINE_MEMBER( mc6854_device::rxc_w ) { // TODO } -WRITE_LINE_DEVICE_HANDLER( mc6854_txc_w ) +WRITE_LINE_MEMBER( mc6854_device::txc_w ) { // TODO } - -/************************ reset *****************************/ - -static DEVICE_RESET( mc6854 ) -{ - mc6854_t* mc6854 = get_safe_token( device ); - LOG (( "mc6854 reset\n" )); - mc6854->cr1 = 0xc0; /* reset condition */ - mc6854->cr2 = 0; - mc6854->cr3 = 0; - mc6854->cr4 = 0; - mc6854->sr1 = 0; - mc6854->sr2 = 0; - mc6854->cts = 0; - mc6854->dcd = 0; - mc6854_tfifo_clear( device ); - mc6854_rfifo_clear( device ); -} - - - -/************************ start *****************************/ - -static DEVICE_START( mc6854 ) -{ - mc6854_t* mc6854 = get_safe_token( device ); - - mc6854->iface = (const mc6854_interface*)device->static_config(); - mc6854->out_irq_func.resolve(mc6854->iface->out_irq_func, *device); - mc6854->in_rxd_func.resolve(mc6854->iface->in_rxd_func, *device); - mc6854->out_txd_func.resolve(mc6854->iface->out_txd_func, *device); - mc6854->out_rts_func.resolve(mc6854->iface->out_rts_func, *device); - mc6854->out_dtr_func.resolve(mc6854->iface->out_dtr_func, *device); - - mc6854->ttimer = device->machine().scheduler().timer_alloc(FUNC(mc6854_tfifo_cb), (void*) device ); - - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr1 ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr2 ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr3 ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cr4 ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->sr1 ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->sr2 ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->cts ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->dcd ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->tstate ); - state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->tfifo ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->tones ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rstate ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rreg ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rones ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->rsize ); - state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->rfifo ); - state_save_register_item_array( device->machine(), "mc6854", device->tag(), 0, mc6854->frame ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->flen ); - state_save_register_item( device->machine(), "mc6854", device->tag(), 0, mc6854->fpos ); -} - - - -const device_type MC6854 = &device_creator; - -mc6854_device::mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, MC6854, "Motorola MC6854 ADLC", tag, owner, clock, "mc6854", __FILE__) -{ - m_token = global_alloc_clear(mc6854_t); -} - -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void mc6854_device::device_config_complete() -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void mc6854_device::device_start() -{ - DEVICE_START_NAME( mc6854 )(this); -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void mc6854_device::device_reset() -{ - DEVICE_RESET_NAME( mc6854 )(this); -} diff --git a/src/emu/machine/mc6854.h b/src/emu/machine/mc6854.h index e2c5ee3909c..4f52c9a736b 100644 --- a/src/emu/machine/mc6854.h +++ b/src/emu/machine/mc6854.h @@ -9,22 +9,118 @@ #ifndef MC6854_H #define MC6854_H -class mc6854_device : public device_t + +#define MAX_FRAME_LENGTH 65536 +/* arbitrary value, you may need to enlarge it if you get truncated frames */ + +#define MC6854_FIFO_SIZE 3 +/* hardcoded size of the 6854 FIFO (this is a hardware limit) */ + + +/* ---------- configuration ------------ */ + +struct mc6854_interface +{ + devcb_write_line m_out_irq_cb; /* interrupt request */ + + /* low-level, bit-based interface */ + devcb_read_line m_in_rxd_cb; /* receive bit */ + devcb_write_line m_out_txd_cb; /* transmit bit */ + + /* high-level, frame-based interface */ + void ( * m_out_frame ) ( device_t *device, UINT8* data, int length ); + + /* control lines */ + devcb_write_line m_out_rts_cb; /* 1 = transmitting, 0 = idle */ + devcb_write_line m_out_dtr_cb; /* 1 = data transmit ready, 0 = busy */ +}; + + +class mc6854_device : public device_t, + public mc6854_interface { public: mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - ~mc6854_device() { global_free(m_token); } + ~mc6854_device() {} + + /* interface to CPU via address/data bus*/ + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); + + /* low-level, bit-based interface */ + DECLARE_WRITE_LINE_MEMBER( set_rx ); + + /* high-level, frame-based interface */ + int send_frame( UINT8* data, int length ); /* ret -1 if busy */ + + /* control lines */ + DECLARE_WRITE_LINE_MEMBER( set_cts ); /* 1 = clear-to-send, 0 = busy */ + DECLARE_WRITE_LINE_MEMBER( set_dcd ); /* 1 = carrier, 0 = no carrier */ + + /* clock */ + DECLARE_WRITE_LINE_MEMBER( rxc_w ); + DECLARE_WRITE_LINE_MEMBER( txc_w ); - // access to legacy token - void *token() const { assert(m_token != NULL); return m_token; } protected: // device-level overrides virtual void device_config_complete(); virtual void device_start(); virtual void device_reset(); + private: // internal state - void *m_token; + devcb_resolved_write_line m_out_irq_func; + devcb_resolved_read_line m_in_rxd_func; + devcb_resolved_write_line m_out_txd_func; + devcb_resolved_write_line m_out_rts_func; + devcb_resolved_write_line m_out_dtr_func; + + /* registers */ + UINT8 m_cr1, m_cr2, m_cr3, m_cr4; /* control registers */ + UINT8 m_sr1, m_sr2; /* status registers */ + + UINT8 m_cts, m_dcd; + + /* transmit state */ + UINT8 m_tstate; + UINT16 m_tfifo[MC6854_FIFO_SIZE]; /* X x 8-bit FIFO + full & last marker bits */ + UINT8 m_tones; /* counter for zero-insertion */ + emu_timer *m_ttimer; /* when to ask for more data */ + + /* receive state */ + UINT8 m_rstate; + UINT32 m_rreg; /* shift register */ + UINT8 m_rones; /* count '1 bits */ + UINT8 m_rsize; /* bits in the shift register */ + UINT16 m_rfifo[MC6854_FIFO_SIZE]; /* X x 8-bit FIFO + full & addr marker bits */ + + /* frame-based interface*/ + UINT8 m_frame[MAX_FRAME_LENGTH]; + UINT32 m_flen, m_fpos; + + + /* meaning of tstate / rtate: + 0 = idle / waiting for frame flag + 1 = flag sync + 2 = 8-bit address field(s) + 3-4 = 8-bit control field(s) + 5 = 8-bit logical control field(s) + 6 = variable-length data field(s) + */ + + void send_bits( UINT32 data, int len, int zi ); + void tfifo_push( UINT8 data ); + void tfifo_terminate( ); + TIMER_CALLBACK_MEMBER(tfifo_cb); + void tfifo_clear( ); + + void rfifo_push( UINT8 d ); + void rfifo_terminate( ); + UINT8 rfifo_pop( ); + void rfifo_clear( ); + + void update_sr2( ); + void update_sr1( ); }; extern const device_type MC6854; @@ -51,25 +147,6 @@ extern const device_type MC6854; */ -/* ---------- configuration ------------ */ - -struct mc6854_interface -{ - devcb_write_line out_irq_func; /* interrupt request */ - - /* low-level, bit-based interface */ - devcb_read_line in_rxd_func; /* receive bit */ - devcb_write_line out_txd_func; /* transmit bit */ - - /* high-level, frame-based interface */ - void ( * out_frame ) ( device_t *device, UINT8* data, int length ); - - /* control lines */ - devcb_write_line out_rts_func; /* 1 = transmitting, 0 = idle */ - devcb_write_line out_dtr_func; /* 1 = data transmit ready, 0 = busy */ -}; - - #define MCFG_MC6854_ADD(_tag, _intrf) \ MCFG_DEVICE_ADD(_tag, MC6854, 0) \ MCFG_DEVICE_CONFIG(_intrf) @@ -78,23 +155,4 @@ struct mc6854_interface MCFG_DEVICE_REMOVE(_tag) -/* ---------- functions ------------ */ -/* interface to CPU via address/data bus*/ -extern DECLARE_READ8_DEVICE_HANDLER ( mc6854_r ); -extern DECLARE_WRITE8_DEVICE_HANDLER ( mc6854_w ); - -/* low-level, bit-based interface */ -WRITE_LINE_DEVICE_HANDLER( mc6854_set_rx ); - -/* high-level, frame-based interface */ -extern int mc6854_send_frame( device_t *device, UINT8* data, int length ); /* ret -1 if busy */ - -/* control lines */ -WRITE_LINE_DEVICE_HANDLER( mc6854_set_cts ); /* 1 = clear-to-send, 0 = busy */ -WRITE_LINE_DEVICE_HANDLER( mc6854_set_dcd ); /* 1 = carrier, 0 = no carrier */ - -/* clock */ -WRITE_LINE_DEVICE_HANDLER( mc6854_rxc_w ); -WRITE_LINE_DEVICE_HANDLER( mc6854_txc_w ); - #endif diff --git a/src/mess/drivers/bbc.c b/src/mess/drivers/bbc.c index 1bcd663077c..09a930b06e3 100644 --- a/src/mess/drivers/bbc.c +++ b/src/mess/drivers/bbc.c @@ -46,11 +46,9 @@ #include "cpu/m6502/m65sc02.h" #include "machine/6522via.h" #include "machine/mc146818.h" /* RTC & CMOS RAM */ -#include "machine/mc6854.h" #include "machine/upd7002.h" #include "bus/centronics/ctronics.h" #include "bus/econet/econet.h" -#include "sound/sn76496.h" /* Sound */ #include "sound/tms5220.h" /* Speech */ #include "video/saa5050.h" /* Teletext */ @@ -621,9 +619,8 @@ static const sn76496_config psg_intf = WRITE_LINE_MEMBER(bbc_state::econet_clk_w) { - device_t *device = machine().device("mc6854"); - mc6854_rxc_w(device, state); - mc6854_txc_w(device, state); + m_adlc->rxc_w(state); + m_adlc->txc_w(state); } static ECONET_INTERFACE( econet_intf ) diff --git a/src/mess/drivers/poly.c b/src/mess/drivers/poly.c index a3af9fb2e8b..93538913a9f 100644 --- a/src/mess/drivers/poly.c +++ b/src/mess/drivers/poly.c @@ -78,7 +78,7 @@ static ADDRESS_MAP_START(poly_mem, AS_PROGRAM, 8, poly_state) //AM_RANGE(0xe006, 0xe006) // baud rate controller (0=9600,2=4800,4=2400,6=1200,8=600,A=300) AM_RANGE(0xe00c,0xe00f) AM_DEVREADWRITE("pia1", pia6821_device, read, write) //keyboard PIA 6821 AM_RANGE(0xe020,0xe027) AM_DEVREADWRITE("ptm", ptm6840_device, read, write) //timer 6840 - AM_RANGE(0xe030,0xe037) AM_DEVREADWRITE_LEGACY("adlc", mc6854_r, mc6854_w) //Data Link Controller 6854 + AM_RANGE(0xe030,0xe037) AM_DEVREADWRITE("adlc", mc6854_device, read, write) //Data Link Controller 6854 AM_RANGE(0xe040,0xe040) AM_NOP //Set protect flip-flop after 1 E-cycle AM_RANGE(0xe050,0xe05f) AM_RAM //Dynamic Address Translater (arranges memory banks) // AM_RANGE(0xe060,0xe060) Select Map 1 diff --git a/src/mess/includes/bbc.h b/src/mess/includes/bbc.h index 3f4c455ed85..e0c05a560f1 100644 --- a/src/mess/includes/bbc.h +++ b/src/mess/includes/bbc.h @@ -13,6 +13,7 @@ #include "machine/6522via.h" #include "machine/6850acia.h" +#include "machine/mc6854.h" #include "machine/ram.h" #include "machine/i8271.h" #include "machine/wd17xx.h" @@ -34,6 +35,7 @@ public: m_maincpu(*this, "maincpu"), m_ram(*this, RAM_TAG), m_mc6845(*this, "mc6845"), + m_adlc(*this, "mc6854"), m_sn(*this, "sn76489"), m_trom(*this, "saa5050"), m_tms(*this, "tms5220"), @@ -59,6 +61,7 @@ public: required_device m_maincpu; required_device m_ram; required_device m_mc6845; + optional_device m_adlc; optional_device m_sn; required_device m_trom; optional_device m_tms; diff --git a/src/mess/includes/thomson.h b/src/mess/includes/thomson.h index da1a6bd2858..52b1b10694c 100644 --- a/src/mess/includes/thomson.h +++ b/src/mess/includes/thomson.h @@ -98,6 +98,7 @@ class thomson_state : public driver_device public: thomson_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), + m_mc6854(*this, "mc6854"), m_maincpu(*this, "maincpu"), m_cassette(*this, "cassette"), m_buzzer(*this, "buzzer"), @@ -114,7 +115,9 @@ public: DECLARE_DEVICE_IMAGE_LOAD_MEMBER( to7_cartridge ); DECLARE_DEVICE_IMAGE_LOAD_MEMBER( mo5_cartridge ); - + + optional_device m_mc6854; + DECLARE_WRITE8_MEMBER( to7_set_cassette_motor ); DECLARE_WRITE8_MEMBER( mo5_set_cassette_motor ); DECLARE_WRITE_LINE_MEMBER( thom_dev_irq_0 ); @@ -319,7 +322,7 @@ protected: required_device m_mea8000; required_device m_ram; optional_device m_mc6846; - + /* bank logging and optimisations */ int m_old_cart_bank; int m_old_cart_bank_was_read_only; diff --git a/src/mess/machine/bbc.c b/src/mess/machine/bbc.c index e5a9c0a254b..a6585efa898 100644 --- a/src/mess/machine/bbc.c +++ b/src/mess/machine/bbc.c @@ -13,7 +13,6 @@ #include #include "emu.h" #include "cpu/m6502/m6502.h" -#include "sound/sn76496.h" #include "sound/tms5220.h" #include "machine/6522via.h" #include "machine/wd17xx.h" @@ -22,7 +21,6 @@ #include "machine/upd7002.h" #include "machine/i8271.h" #include "machine/mc146818.h" -#include "machine/mc6854.h" #include "bus/centronics/ctronics.h" #include "imagedev/cassette.h" @@ -576,8 +574,7 @@ READ8_MEMBER(bbc_state::bbcm_r) { via6522_device *via_0 = machine().device("via6522_0"); via6522_device *via_1 = machine().device("via6522_1"); - device_t *adlc = machine().device("mc6854"); - + myo = offset-0x200; if ((myo>=0x00) && (myo<=0x07)) return bbc_6845_r(space, myo-0x00); /* Video Controller */ if ((myo>=0x08) && (myo<=0x0f)) @@ -598,7 +595,7 @@ READ8_MEMBER(bbc_state::bbcm_r) if ((myo>=0x40) && (myo<=0x5f)) return via_0->read(space, myo-0x40); if ((myo>=0x60) && (myo<=0x7f)) return via_1->read(space, myo-0x60); if ((myo>=0x80) && (myo<=0x9f)) return 0xfe; - if ((myo>=0xa0) && (myo<=0xbf)) return mc6854_r(adlc, space, myo & 0x03); + if ((myo>=0xa0) && (myo<=0xbf)) return m_adlc->read(space, myo & 0x03); if ((myo>=0xc0) && (myo<=0xdf)) return 0xfe; if ((myo>=0xe0) && (myo<=0xff)) return 0xfe; } @@ -614,8 +611,7 @@ WRITE8_MEMBER(bbc_state::bbcm_w) { via6522_device *via_0 = machine().device("via6522_0"); via6522_device *via_1 = machine().device("via6522_1"); - device_t *adlc = machine().device("mc6854"); - + myo=offset-0x200; if ((myo>=0x00) && (myo<=0x07)) bbc_6845_w(space, myo-0x00, data); /* Video Controller */ if ((myo>=0x08) && (myo<=0x0f)) @@ -636,7 +632,7 @@ WRITE8_MEMBER(bbc_state::bbcm_w) if ((myo>=0x40) && (myo<=0x5f)) via_0->write(space, myo-0x40, data); if ((myo>=0x60) && (myo<=0x7f)) via_1->write(space, myo-0x60, data); //if ((myo>=0x80) && (myo<=0x9f)) - if ((myo>=0xa0) && (myo<=0xbf)) mc6854_w(adlc, space, myo & 0x03, data); + if ((myo>=0xa0) && (myo<=0xbf)) m_adlc->write(space, myo & 0x03, data); //if ((myo>=0xc0) && (myo<=0xdf)) //if ((myo>=0xe0) && (myo<=0xff)) } diff --git a/src/mess/machine/thomflop.c b/src/mess/machine/thomflop.c index 83e995e3ad5..543ba44f27a 100644 --- a/src/mess/machine/thomflop.c +++ b/src/mess/machine/thomflop.c @@ -1592,27 +1592,27 @@ void thomson_state::thmfc_floppy_init() TIMER_CALLBACK_MEMBER( thomson_state::ans4 ) { LOG(( "%f ans4\n", machine().time().as_double() )); - mc6854_set_cts( machine().device("mc6854"), 0 ); + m_mc6854->set_cts( 0 ); } TIMER_CALLBACK_MEMBER( thomson_state::ans3 ) { LOG(( "%f ans3\n", machine().time().as_double() )); - mc6854_set_cts( machine().device("mc6854"), 1 ); + m_mc6854->set_cts( 1 ); machine().scheduler().timer_set( attotime::from_usec( 100 ), timer_expired_delegate(FUNC(thomson_state::ans4),this)); } TIMER_CALLBACK_MEMBER( thomson_state::ans2 ) { LOG(( "%f ans2\n", machine().time().as_double() )); - mc6854_set_cts( machine().device("mc6854"), 0 ); + m_mc6854->set_cts( 0 ); machine().scheduler().timer_set( attotime::from_usec( 100 ), timer_expired_delegate(FUNC(thomson_state::ans3),this)); } TIMER_CALLBACK_MEMBER( thomson_state::ans ) { LOG(( "%f ans\n", machine().time().as_double() )); - mc6854_set_cts( machine().device("mc6854"), 1 ); + m_mc6854->set_cts( 1 ); machine().scheduler().timer_set( attotime::from_usec( 100 ), timer_expired_delegate(FUNC(thomson_state::ans2),this)); } /* consigne DKBOOT @@ -1657,7 +1657,7 @@ static void to7_network_got_frame( device_t *device, UINT8* data, int length ) thomson_state *state = device->machine().driver_data(); LOG(( "to7_network_got_frame: %i phones %i\n", data[2], data[0] )); device->machine().scheduler().timer_set( attotime::from_usec( 100 ), timer_expired_delegate(FUNC(thomson_state::ans),state)); - mc6854_set_cts( device, 0 ); + state->m_mc6854->set_cts( 0 ); } else if ( ! data[1] ) { @@ -1673,13 +1673,18 @@ static void to7_network_got_frame( device_t *device, UINT8* data, int length ) (data[10] == 0) ? "TO7" : (data[10] == 1) ? "MO5" : (data[10] == 2) ? "TO7/70" : "?", name )); } - } - -const mc6854_interface to7_network_iface = { DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, to7_network_got_frame, DEVCB_NULL, DEVCB_NULL }; - +const mc6854_interface to7_network_iface = +{ + DEVCB_NULL, + DEVCB_NULL, + DEVCB_NULL, + to7_network_got_frame, + DEVCB_NULL, + DEVCB_NULL +}; void thomson_state::to7_network_init() @@ -1693,8 +1698,8 @@ void thomson_state::to7_network_init() void thomson_state::to7_network_reset() { LOG(( "to7_network_reset: NR 07-005 network extension\n" )); - mc6854_set_cts( machine().device("mc6854"), 0 ); - mc6854_set_cts( machine().device("mc6854"), 1 ); + m_mc6854->set_cts( 0 ); + m_mc6854->set_cts( 1 ); } @@ -1702,7 +1707,7 @@ void thomson_state::to7_network_reset() READ8_MEMBER( thomson_state::to7_network_r ) { if ( offset < 4 ) - return mc6854_r( machine().device("mc6854"), space, offset ); + return m_mc6854->read( space, offset ); if ( offset == 8 ) { @@ -1721,7 +1726,7 @@ READ8_MEMBER( thomson_state::to7_network_r ) WRITE8_MEMBER( thomson_state::to7_network_w ) { if ( offset < 4 ) - mc6854_w( machine().device("mc6854"), space, offset, data ); + m_mc6854->write( space, offset, data ); else { logerror( "%f $%04x to7_network_w: invalid write offset %i (data=$%02X)\n",