Expanded the Z80-DART interface to allow future implementation of Z80-SIO features: [Curt Coder]

- added separate clock inputs for channel B
- added SYNC inputs/outputs for both channels
This commit is contained in:
Curt Coder 2010-08-21 00:03:37 +00:00
parent e5e8a7b4d9
commit 6791eb9adb
2 changed files with 121 additions and 17 deletions

View File

@ -5,12 +5,19 @@
Copyright (c) 2008, The MESS Team. Copyright (c) 2008, The MESS Team.
Visit http://mamedev.org for licensing and usage restrictions. Visit http://mamedev.org for licensing and usage restrictions.
The z80dart/z80sio itself is based on an older intel serial chip, the i8274 MPSC
(see http://doc.chipfind.ru/pdf/intel/8274.pdf), which also has almost identical
behavior, except lacks the interrupt daisy chaining and has its own interrupt/dma
scheme which uses write register 2 on channel A, that register which is unused on
the z80dart and z80sio.
***************************************************************************/ ***************************************************************************/
/* /*
TODO: TODO:
- synchronous mode (Z80-SIO/1,2)
- break detection - break detection
- wr0 reset tx interrupt pending - wr0 reset tx interrupt pending
- wait/ready - wait/ready
@ -193,17 +200,19 @@ void z80dart_device_config::device_config_complete()
// or initialize to defaults if none provided // or initialize to defaults if none provided
else else
{ {
m_rx_clock_a = m_tx_clock_a = m_rx_tx_clock_b = 0; m_rx_clock_a = m_tx_clock_a = m_rx_clock_b = m_tx_clock_b = 0;
memset(&m_in_rxda_func, 0, sizeof(m_in_rxda_func)); memset(&m_in_rxda_func, 0, sizeof(m_in_rxda_func));
memset(&m_out_txda_func, 0, sizeof(m_out_txda_func)); memset(&m_out_txda_func, 0, sizeof(m_out_txda_func));
memset(&m_out_dtra_func, 0, sizeof(m_out_dtra_func)); memset(&m_out_dtra_func, 0, sizeof(m_out_dtra_func));
memset(&m_out_rtsa_func, 0, sizeof(m_out_rtsa_func)); memset(&m_out_rtsa_func, 0, sizeof(m_out_rtsa_func));
memset(&m_out_wrdya_func, 0, sizeof(m_out_wrdya_func)); memset(&m_out_wrdya_func, 0, sizeof(m_out_wrdya_func));
memset(&m_out_synca_func, 0, sizeof(m_out_synca_func));
memset(&m_in_rxdb_func, 0, sizeof(m_in_rxdb_func)); memset(&m_in_rxdb_func, 0, sizeof(m_in_rxdb_func));
memset(&m_out_txdb_func, 0, sizeof(m_out_txdb_func)); memset(&m_out_txdb_func, 0, sizeof(m_out_txdb_func));
memset(&m_out_dtrb_func, 0, sizeof(m_out_dtrb_func)); memset(&m_out_dtrb_func, 0, sizeof(m_out_dtrb_func));
memset(&m_out_rtsb_func, 0, sizeof(m_out_rtsb_func)); memset(&m_out_rtsb_func, 0, sizeof(m_out_rtsb_func));
memset(&m_out_wrdyb_func, 0, sizeof(m_out_wrdyb_func)); memset(&m_out_wrdyb_func, 0, sizeof(m_out_wrdyb_func));
memset(&m_out_syncb_func, 0, sizeof(m_out_syncb_func));
memset(&m_out_int_func, 0, sizeof(m_out_int_func)); memset(&m_out_int_func, 0, sizeof(m_out_int_func));
} }
} }
@ -237,28 +246,35 @@ void z80dart_device::device_start()
// resolve callbacks // resolve callbacks
devcb_resolve_write_line(&m_out_int_func, &m_config.m_out_int_func, this); devcb_resolve_write_line(&m_out_int_func, &m_config.m_out_int_func, this);
m_channel[Z80DART_CH_A].start(this, Z80DART_CH_A, m_config.m_in_rxda_func, m_config.m_out_txda_func, m_config.m_out_dtra_func, m_config.m_out_rtsa_func, m_config.m_out_wrdya_func); m_channel[Z80DART_CH_A].start(this, Z80DART_CH_A, m_config.m_in_rxda_func, m_config.m_out_txda_func, m_config.m_out_dtra_func, m_config.m_out_rtsa_func, m_config.m_out_wrdya_func, m_config.m_out_synca_func);
m_channel[Z80DART_CH_B].start(this, Z80DART_CH_B, m_config.m_in_rxdb_func, m_config.m_out_txdb_func, m_config.m_out_dtrb_func, m_config.m_out_rtsb_func, m_config.m_out_wrdyb_func); m_channel[Z80DART_CH_B].start(this, Z80DART_CH_B, m_config.m_in_rxdb_func, m_config.m_out_txdb_func, m_config.m_out_dtrb_func, m_config.m_out_rtsb_func, m_config.m_out_wrdyb_func, m_config.m_out_syncb_func);
if (m_config.m_rx_clock_a != 0) if (m_config.m_rx_clock_a != 0)
{ {
// allocate channel A receive timer // allocate channel A receive timer
m_rxca_timer = timer_alloc(&m_machine, dart_channel::static_rxca_tick, (void *)&m_channel[Z80DART_CH_A]); m_rxca_timer = timer_alloc(&m_machine, dart_channel::static_rxc_tick, (void *)&m_channel[Z80DART_CH_A]);
timer_adjust_periodic(m_rxca_timer, attotime_zero, 0, ATTOTIME_IN_HZ(m_config.m_rx_clock_a)); timer_adjust_periodic(m_rxca_timer, attotime_zero, 0, ATTOTIME_IN_HZ(m_config.m_rx_clock_a));
} }
if (m_config.m_tx_clock_a != 0) if (m_config.m_tx_clock_a != 0)
{ {
// allocate channel A transmit timer // allocate channel A transmit timer
m_txca_timer = timer_alloc(&m_machine, dart_channel::static_txca_tick, (void *)&m_channel[Z80DART_CH_A]); m_txca_timer = timer_alloc(&m_machine, dart_channel::static_txc_tick, (void *)&m_channel[Z80DART_CH_A]);
timer_adjust_periodic(m_txca_timer, attotime_zero, 0, ATTOTIME_IN_HZ(m_config.m_tx_clock_a)); timer_adjust_periodic(m_txca_timer, attotime_zero, 0, ATTOTIME_IN_HZ(m_config.m_tx_clock_a));
} }
if (m_config.m_rx_tx_clock_b != 0) if (m_config.m_rx_clock_b != 0)
{ {
// allocate channel B receive/transmit timer // allocate channel B receive timer
m_rxtxcb_timer = timer_alloc(&m_machine, dart_channel::static_rxtxcb_tick, (void *)&m_channel[Z80DART_CH_B]); m_rxcb_timer = timer_alloc(&m_machine, dart_channel::static_rxc_tick, (void *)&m_channel[Z80DART_CH_B]);
timer_adjust_periodic(m_rxtxcb_timer, attotime_zero, 0, ATTOTIME_IN_HZ(m_config.m_rx_tx_clock_b)); timer_adjust_periodic(m_rxcb_timer, attotime_zero, 0, ATTOTIME_IN_HZ(m_config.m_rx_clock_b));
}
if (m_config.m_tx_clock_b != 0)
{
// allocate channel B transmit timer
m_txcb_timer = timer_alloc(&m_machine, dart_channel::static_txc_tick, (void *)&m_channel[Z80DART_CH_B]);
timer_adjust_periodic(m_txcb_timer, attotime_zero, 0, ATTOTIME_IN_HZ(m_config.m_tx_clock_b));
} }
state_save_register_device_item_array(this, 0, m_int_state); state_save_register_device_item_array(this, 0, m_int_state);
@ -456,7 +472,7 @@ z80dart_device::dart_channel::dart_channel()
// start - channel startup // start - channel startup
//------------------------------------------------- //-------------------------------------------------
void z80dart_device::dart_channel::start(z80dart_device *device, int index, const devcb_read_line &in_rxd, const devcb_write_line &out_txd, const devcb_write_line &out_dtr, const devcb_write_line &out_rts, const devcb_write_line &out_wrdy) void z80dart_device::dart_channel::start(z80dart_device *device, int index, const devcb_read_line &in_rxd, const devcb_write_line &out_txd, const devcb_write_line &out_dtr, const devcb_write_line &out_rts, const devcb_write_line &out_wrdy, const devcb_write_line &out_sync)
{ {
m_index = index; m_index = index;
m_device = device; m_device = device;
@ -466,6 +482,7 @@ void z80dart_device::dart_channel::start(z80dart_device *device, int index, cons
devcb_resolve_write_line(&m_out_dtr_func, &out_dtr, m_device); devcb_resolve_write_line(&m_out_dtr_func, &out_dtr, m_device);
devcb_resolve_write_line(&m_out_rts_func, &out_rts, m_device); devcb_resolve_write_line(&m_out_rts_func, &out_rts, m_device);
devcb_resolve_write_line(&m_out_wrdy_func, &out_wrdy, m_device); devcb_resolve_write_line(&m_out_wrdy_func, &out_wrdy, m_device);
devcb_resolve_write_line(&m_out_sync_func, &out_sync, m_device);
state_save_register_device_item_array(m_device, m_index, m_rr); state_save_register_device_item_array(m_device, m_index, m_rr);
state_save_register_device_item_array(m_device, m_index, m_wr); state_save_register_device_item_array(m_device, m_index, m_wr);
@ -1314,6 +1331,16 @@ void z80dart_device::dart_channel::ri_w(int state)
} }
//-------------------------------------------------
// sync_w - sync handler
//-------------------------------------------------
void z80dart_device::dart_channel::sync_w(int state)
{
LOG(("Z80DART \"%s\" Channel %c : SYNC %u\n", m_device->tag(), 'A' + m_index, state));
}
//------------------------------------------------- //-------------------------------------------------
// rx_w - receive clock // rx_w - receive clock
//------------------------------------------------- //-------------------------------------------------
@ -1373,9 +1400,13 @@ WRITE_LINE_DEVICE_HANDLER( z80dart_dcda_w ) { downcast<z80dart_device *>(device)
WRITE_LINE_DEVICE_HANDLER( z80dart_dcdb_w ) { downcast<z80dart_device *>(device)->dcd_w(Z80DART_CH_B, state); } WRITE_LINE_DEVICE_HANDLER( z80dart_dcdb_w ) { downcast<z80dart_device *>(device)->dcd_w(Z80DART_CH_B, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_ria_w ) { downcast<z80dart_device *>(device)->ri_w(Z80DART_CH_A, state); } WRITE_LINE_DEVICE_HANDLER( z80dart_ria_w ) { downcast<z80dart_device *>(device)->ri_w(Z80DART_CH_A, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_rib_w ) { downcast<z80dart_device *>(device)->ri_w(Z80DART_CH_B, state); } WRITE_LINE_DEVICE_HANDLER( z80dart_rib_w ) { downcast<z80dart_device *>(device)->ri_w(Z80DART_CH_B, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_synca_w ) { downcast<z80dart_device *>(device)->sync_w(Z80DART_CH_A, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_syncb_w ) { downcast<z80dart_device *>(device)->sync_w(Z80DART_CH_B, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_rxca_w ) { downcast<z80dart_device *>(device)->rx_w(Z80DART_CH_A, state); } WRITE_LINE_DEVICE_HANDLER( z80dart_rxca_w ) { downcast<z80dart_device *>(device)->rx_w(Z80DART_CH_A, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_txca_w ) { downcast<z80dart_device *>(device)->tx_w(Z80DART_CH_A, state); } WRITE_LINE_DEVICE_HANDLER( z80dart_txca_w ) { downcast<z80dart_device *>(device)->tx_w(Z80DART_CH_A, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_rxcb_w ) { downcast<z80dart_device *>(device)->rx_w(Z80DART_CH_B, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_txcb_w ) { downcast<z80dart_device *>(device)->tx_w(Z80DART_CH_B, state); }
WRITE_LINE_DEVICE_HANDLER( z80dart_rxtxcb_w ) { downcast<z80dart_device *>(device)->rx_w(Z80DART_CH_B, state); downcast<z80dart_device *>(device)->tx_w(Z80DART_CH_B, state); } WRITE_LINE_DEVICE_HANDLER( z80dart_rxtxcb_w ) { downcast<z80dart_device *>(device)->rx_w(Z80DART_CH_B, state); downcast<z80dart_device *>(device)->tx_w(Z80DART_CH_B, state); }
READ8_DEVICE_HANDLER( z80dart_cd_ba_r ) READ8_DEVICE_HANDLER( z80dart_cd_ba_r )
@ -1409,3 +1440,6 @@ WRITE8_DEVICE_HANDLER( z80dart_ba_cd_w )
} }
const device_type Z80DART = z80dart_device_config::static_alloc_device_config; const device_type Z80DART = z80dart_device_config::static_alloc_device_config;
const device_type Z80SIO0 = z80dart_device_config::static_alloc_device_config; // FIXME
const device_type Z80SIO1 = z80dart_device_config::static_alloc_device_config; // FIXME
const device_type Z80SIO2 = z80dart_device_config::static_alloc_device_config; // FIXME

View File

@ -17,7 +17,7 @@
_M1 8 | | 33 C/_D _M1 8 | | 33 C/_D
Vdd 9 | | 32 _RD Vdd 9 | | 32 _RD
_W/RDYA 10 | Z80-DART | 31 GND _W/RDYA 10 | Z80-DART | 31 GND
_RIA 11 | | 30 _W/RDYB _RIA 11 | Z80-SIO/0 | 30 _W/RDYB
RxDA 12 | | 29 _RIB RxDA 12 | | 29 _RIB
_RxCA 13 | | 28 RxDB _RxCA 13 | | 28 RxDB
_TxCA 14 | | 27 _RxTxCB _TxCA 14 | | 27 _RxTxCB
@ -28,6 +28,50 @@
_DCDA 19 | | 22 _DCDB _DCDA 19 | | 22 _DCDB
CLK 20 |_____________| 21 _RESET CLK 20 |_____________| 21 _RESET
_____ _____
D1 1 |* \_/ | 40 D0
D3 2 | | 39 D2
D5 3 | | 38 D4
D7 4 | | 37 D6
_INT 5 | | 36 _IORQ
IEI 6 | | 35 _CE
IEO 7 | | 34 B/_A
_M1 8 | | 33 C/_D
Vdd 9 | | 32 _RD
_W/RDYA 10 | Z80-SIO/1 | 31 GND
_SYNCA 11 | | 30 _W/RDYB
RxDA 12 | | 29 _SYNCB
_RxCA 13 | | 28 RxDB
_TxCA 14 | | 27 _RxCB
TxDA 15 | | 26 _TxCB
_DTRA 16 | | 25 TxDB
_RTSA 17 | | 24 _RTSB
_CTSA 18 | | 23 _CTSB
_DCDA 19 | | 22 _DCDB
CLK 20 |_____________| 21 _RESET
_____ _____
D1 1 |* \_/ | 40 D0
D3 2 | | 39 D2
D5 3 | | 38 D4
D7 4 | | 37 D6
_INT 5 | | 36 _IORQ
IEI 6 | | 35 _CE
IEO 7 | | 34 B/_A
_M1 8 | | 33 C/_D
Vdd 9 | | 32 _RD
_W/RDYA 10 | Z80-SIO/2 | 31 GND
_SYNCA 11 | | 30 _W/RDYB
RxDA 12 | | 29 _RxDB
_RxCA 13 | | 28 _RxCB
_TxCA 14 | | 27 _TxCB
TxDA 15 | | 26 TxDB
_DTRA 16 | | 25 _DTRB
_RTSA 17 | | 24 _RTSB
_CTSA 18 | | 23 _CTSB
_DCDA 19 | | 22 _DCDB
CLK 20 |_____________| 21 _RESET
***************************************************************************/ ***************************************************************************/
#ifndef __Z80DART_H__ #ifndef __Z80DART_H__
@ -57,6 +101,18 @@ enum
MDRV_DEVICE_ADD(_tag, Z80DART, _clock) \ MDRV_DEVICE_ADD(_tag, Z80DART, _clock) \
MDRV_DEVICE_CONFIG(_config) MDRV_DEVICE_CONFIG(_config)
#define MDRV_Z80SIO0_ADD(_tag, _clock, _config) \
MDRV_DEVICE_ADD(_tag, Z80SIO0, _clock) \
MDRV_DEVICE_CONFIG(_config)
#define MDRV_Z80SIO1_ADD(_tag, _clock, _config) \
MDRV_DEVICE_ADD(_tag, Z80SIO1, _clock) \
MDRV_DEVICE_CONFIG(_config)
#define MDRV_Z80SIO2_ADD(_tag, _clock, _config) \
MDRV_DEVICE_ADD(_tag, Z80SIO2, _clock) \
MDRV_DEVICE_CONFIG(_config)
#define MDRV_Z80DART_REMOVE(_tag) \ #define MDRV_Z80DART_REMOVE(_tag) \
MDRV_DEVICE_REMOVE(_tag) MDRV_DEVICE_REMOVE(_tag)
@ -76,19 +132,22 @@ struct z80dart_interface
{ {
int m_rx_clock_a; // channel A receive clock int m_rx_clock_a; // channel A receive clock
int m_tx_clock_a; // channel A transmit clock int m_tx_clock_a; // channel A transmit clock
int m_rx_tx_clock_b; // channel B receive/transmit clock int m_rx_clock_b; // channel B receive clock
int m_tx_clock_b; // channel B transmit clock
devcb_read_line m_in_rxda_func; devcb_read_line m_in_rxda_func;
devcb_write_line m_out_txda_func; devcb_write_line m_out_txda_func;
devcb_write_line m_out_dtra_func; devcb_write_line m_out_dtra_func;
devcb_write_line m_out_rtsa_func; devcb_write_line m_out_rtsa_func;
devcb_write_line m_out_wrdya_func; devcb_write_line m_out_wrdya_func;
devcb_write_line m_out_synca_func;
devcb_read_line m_in_rxdb_func; devcb_read_line m_in_rxdb_func;
devcb_write_line m_out_txdb_func; devcb_write_line m_out_txdb_func;
devcb_write_line m_out_dtrb_func; devcb_write_line m_out_dtrb_func;
devcb_write_line m_out_rtsb_func; devcb_write_line m_out_rtsb_func;
devcb_write_line m_out_wrdyb_func; devcb_write_line m_out_wrdyb_func;
devcb_write_line m_out_syncb_func;
devcb_write_line m_out_int_func; devcb_write_line m_out_int_func;
}; };
@ -147,6 +206,7 @@ public:
void ri_w(int which, int state) { m_channel[which].ri_w(state); } void ri_w(int which, int state) { m_channel[which].ri_w(state); }
void rx_w(int which, int state) { m_channel[which].rx_w(state); } void rx_w(int which, int state) { m_channel[which].rx_w(state); }
void tx_w(int which, int state) { m_channel[which].tx_w(state); } void tx_w(int which, int state) { m_channel[which].tx_w(state); }
void sync_w(int which, int state) { m_channel[which].sync_w(state); }
private: private:
// device-level overrides // device-level overrides
@ -170,7 +230,7 @@ private:
public: public:
dart_channel(); dart_channel();
void start(z80dart_device *device, int index, const devcb_read_line &in_rxd, const devcb_write_line &out_txd, const devcb_write_line &out_dtr, const devcb_write_line &out_rts, const devcb_write_line &out_wrdy); void start(z80dart_device *device, int index, const devcb_read_line &in_rxd, const devcb_write_line &out_txd, const devcb_write_line &out_dtr, const devcb_write_line &out_rts, const devcb_write_line &out_wrdy, const devcb_write_line &out_sync);
void reset(); void reset();
UINT8 control_read(); UINT8 control_read();
@ -186,6 +246,7 @@ private:
void ri_w(int state); void ri_w(int state);
void rx_w(int state); void rx_w(int state);
void tx_w(int state); void tx_w(int state);
void sync_w(int state);
private: private:
void take_interrupt(int level); void take_interrupt(int level);
@ -201,9 +262,8 @@ private:
void receive(); void receive();
void transmit(); void transmit();
static TIMER_CALLBACK( static_rxca_tick ) { reinterpret_cast<dart_channel *>(ptr)->rx_w(1); } static TIMER_CALLBACK( static_rxc_tick ) { reinterpret_cast<dart_channel *>(ptr)->rx_w(1); }
static TIMER_CALLBACK( static_txca_tick ) { reinterpret_cast<dart_channel *>(ptr)->tx_w(1); } static TIMER_CALLBACK( static_txc_tick ) { reinterpret_cast<dart_channel *>(ptr)->tx_w(1); }
static TIMER_CALLBACK( static_rxtxcb_tick ) { reinterpret_cast<dart_channel *>(ptr)->rx_w(1); reinterpret_cast<dart_channel *>(ptr)->tx_w(1); }
z80dart_device *m_device; z80dart_device *m_device;
int m_index; int m_index;
@ -213,6 +273,7 @@ private:
devcb_resolved_write_line m_out_dtr_func; devcb_resolved_write_line m_out_dtr_func;
devcb_resolved_write_line m_out_rts_func; devcb_resolved_write_line m_out_rts_func;
devcb_resolved_write_line m_out_wrdy_func; devcb_resolved_write_line m_out_wrdy_func;
devcb_resolved_write_line m_out_sync_func;
// register state // register state
UINT8 m_rr[3]; // read register UINT8 m_rr[3]; // read register
@ -259,12 +320,16 @@ private:
// timers // timers
emu_timer * m_rxca_timer; emu_timer * m_rxca_timer;
emu_timer * m_txca_timer; emu_timer * m_txca_timer;
emu_timer * m_rxtxcb_timer; emu_timer * m_rxcb_timer;
emu_timer * m_txcb_timer;
}; };
// device type definition // device type definition
extern const device_type Z80DART; extern const device_type Z80DART;
extern const device_type Z80SIO0;
extern const device_type Z80SIO1;
extern const device_type Z80SIO2;
/* /*
#define Z8470 DEVICE_GET_INFO_NAME(z8470) #define Z8470 DEVICE_GET_INFO_NAME(z8470)
#define LH0081 DEVICE_GET_INFO_NAME(lh0088) #define LH0081 DEVICE_GET_INFO_NAME(lh0088)
@ -295,6 +360,8 @@ READ8_DEVICE_HANDLER( z80dart_d_r );
// serial clocks // serial clocks
WRITE_LINE_DEVICE_HANDLER( z80dart_rxca_w ); WRITE_LINE_DEVICE_HANDLER( z80dart_rxca_w );
WRITE_LINE_DEVICE_HANDLER( z80dart_txca_w ); WRITE_LINE_DEVICE_HANDLER( z80dart_txca_w );
WRITE_LINE_DEVICE_HANDLER( z80dart_rxcb_w );
WRITE_LINE_DEVICE_HANDLER( z80dart_txcb_w );
WRITE_LINE_DEVICE_HANDLER( z80dart_rxtxcb_w ); WRITE_LINE_DEVICE_HANDLER( z80dart_rxtxcb_w );
// ring indicator // ring indicator
@ -309,5 +376,8 @@ WRITE_LINE_DEVICE_HANDLER( z80dart_dcdb_w );
WRITE_LINE_DEVICE_HANDLER( z80dart_ctsa_w ); WRITE_LINE_DEVICE_HANDLER( z80dart_ctsa_w );
WRITE_LINE_DEVICE_HANDLER( z80dart_ctsb_w ); WRITE_LINE_DEVICE_HANDLER( z80dart_ctsb_w );
// sync
WRITE_LINE_DEVICE_HANDLER( z80dart_synca_w );
WRITE_LINE_DEVICE_HANDLER( z80dart_syncb_w );
#endif #endif