diff options
Diffstat (limited to 'src/mess/machine/zx8302.c')
-rw-r--r-- | src/mess/machine/zx8302.c | 606 |
1 files changed, 0 insertions, 606 deletions
diff --git a/src/mess/machine/zx8302.c b/src/mess/machine/zx8302.c deleted file mode 100644 index 6866b61f290..00000000000 --- a/src/mess/machine/zx8302.c +++ /dev/null @@ -1,606 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Curt Coder -/********************************************************************** - - Sinclair ZX8302 emulation - -**********************************************************************/ - -/* - - TODO: - - - set time - - read from microdrive - - write to microdrive - - DTR/CTS handling - - network - -*/ - -#include "emu.h" -#include <time.h> -#include "machine/microdrv.h" -#include "zx8302.h" - - - -//************************************************************************** -// MACROS / CONSTANTS -//************************************************************************** - -#define LOG 0 - - -// Monday 1st January 1979 00:00:00 UTC -static const int RTC_BASE_ADJUST = 283996800; - - - -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -const device_type ZX8302 = &device_creator<zx8302_device>; - -//************************************************************************** -// INLINE HELPERS -//************************************************************************** - -//------------------------------------------------- -// trigger_interrupt - -//------------------------------------------------- - -inline void zx8302_device::trigger_interrupt(UINT8 line) -{ - m_irq |= line; - - m_out_ipl1l_cb(ASSERT_LINE); -} - - -//------------------------------------------------- -// transmit_ipc_data - transmit IPC data -//------------------------------------------------- - -inline void zx8302_device::transmit_ipc_data() -{ - /* - - IPC <-> ZX8302 serial link protocol - *********************************** - - Send bit to IPC - --------------- - - 1. ZX start bit (COMDATA = 0) - 2. IPC clock (COMCTL = 0, COMTL = 1) - 3. ZX data bit (COMDATA = 0/1) - 4. IPC clock (COMCTL = 0, COMTL = 1) - 5. ZX stop bit (COMDATA = 1) - - Receive bit from IPC - -------------------- - - 1. ZX start bit (COMDATA = 0) - 2. IPC clock (COMCTL = 0, COMTL = 1) - 3. IPC data bit (COMDATA = 0/1) - 4. IPC clock (COMCTL = 0, COMTL = 1) - 5. IPC stop bit (COMDATA = 1) - - */ - - switch (m_ipc_state) - { - case IPC_START: - if (LOG) logerror("ZX8302 '%s' COMDATA Start Bit\n", tag()); - - m_out_comdata_cb(BIT(m_idr, 0)); - m_ipc_busy = 1; - m_ipc_state = IPC_DATA; - break; - - case IPC_DATA: - if (LOG) logerror("ZX8302 '%s' COMDATA Data Bit: %x\n", tag(), BIT(m_idr, 1)); - - m_comdata_to_ipc = BIT(m_idr, 1); - m_out_comdata_cb(m_comdata_to_ipc); - m_ipc_state = IPC_STOP; - break; - - case IPC_STOP: - if (LOG) logerror("ZX8302 '%s' COMDATA Stop Bit\n", tag()); - - m_out_comdata_cb(BIT(m_idr, 2)); - m_ipc_busy = 0; - break; - } -} - - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// zx8302_device - constructor -//------------------------------------------------- - -zx8302_device::zx8302_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, ZX8302, "Sinclair ZX8302", tag, owner, clock, "zx8302", __FILE__), - device_serial_interface(mconfig, *this), - m_rtc_clock(0), - m_out_ipl1l_cb(*this), - m_out_baudx4_cb(*this), - m_out_comdata_cb(*this), - m_out_txd1_cb(*this), - m_out_txd2_cb(*this), - m_out_netout_cb(*this), - m_out_mdselck_cb(*this), - m_out_mdseld_cb(*this), - m_out_mdrdw_cb(*this), - m_out_erase_cb(*this), - m_out_raw1_cb(*this), - m_in_raw1_cb(*this), - m_out_raw2_cb(*this), - m_in_raw2_cb(*this), - m_dtr1(0), - m_cts2(0), - m_idr(1), - m_irq(0), - m_ctr(time(NULL) + RTC_BASE_ADJUST), - m_status(0), - m_comdata_from_ipc(1), - m_comdata_to_cpu(1), - m_comdata_to_ipc(1), - m_comctl(1), - m_ipc_state(0), - m_ipc_busy(0), - m_baudx4(0), - m_track(0) -{ -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void zx8302_device::device_start() -{ - // resolve callbacks - m_out_ipl1l_cb.resolve_safe(); - m_out_baudx4_cb.resolve_safe(); - m_out_comdata_cb.resolve_safe(); - m_out_txd1_cb.resolve_safe(); - m_out_txd2_cb.resolve_safe(); - m_out_netout_cb.resolve_safe(); - m_out_mdselck_cb.resolve_safe(); - m_out_mdseld_cb.resolve_safe(); - m_out_mdrdw_cb.resolve_safe(); - m_out_erase_cb.resolve_safe(); - m_out_raw1_cb.resolve_safe(); - m_in_raw1_cb.resolve_safe(0); - m_out_raw2_cb.resolve_safe(); - m_in_raw2_cb.resolve_safe(0); - - // allocate timers - m_baudx4_timer = timer_alloc(TIMER_BAUDX4); - m_rtc_timer = timer_alloc(TIMER_RTC); - m_gap_timer = timer_alloc(TIMER_GAP); - - m_rtc_timer->adjust(attotime::zero, 0, attotime::from_hz(m_rtc_clock / 32768)); - m_gap_timer->adjust(attotime::zero, 0, attotime::from_msec(31)); - - // register for state saving - save_item(NAME(m_dtr1)); - save_item(NAME(m_cts2)); - save_item(NAME(m_idr)); - save_item(NAME(m_tcr)); - save_item(NAME(m_tdr)); - save_item(NAME(m_irq)); - save_item(NAME(m_ctr)); - save_item(NAME(m_status)); - save_item(NAME(m_comdata_from_ipc)); - save_item(NAME(m_comdata_to_cpu)); - save_item(NAME(m_comdata_to_ipc)); - save_item(NAME(m_comctl)); - save_item(NAME(m_ipc_state)); - save_item(NAME(m_ipc_busy)); - save_item(NAME(m_baudx4)); - save_item(NAME(m_mdv_data)); - save_item(NAME(m_track)); -} - - -//------------------------------------------------- -// device_timer - handler timer events -//------------------------------------------------- - -void zx8302_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch (id) - { - case TIMER_BAUDX4: - m_baudx4 = !m_baudx4; - m_out_baudx4_cb(m_baudx4); - break; - - case TIMER_RTC: - m_ctr++; - break; - - case TIMER_GAP: - trigger_interrupt(INT_GAP); - break; - - default: - device_serial_interface::device_timer(timer, id, param, ptr); - break; - } -} - - -//------------------------------------------------- -// tra_callback - -//------------------------------------------------- - -void zx8302_device::tra_callback() -{ - switch (m_tcr & MODE_MASK) - { - case MODE_SER1: - m_out_txd1_cb(transmit_register_get_data_bit()); - break; - - case MODE_SER2: - m_out_txd2_cb(transmit_register_get_data_bit()); - break; - - case MODE_MDV: - // TODO - break; - - case MODE_NET: - m_out_netout_cb(transmit_register_get_data_bit()); - break; - } -} - - -//------------------------------------------------- -// tra_complete - -//------------------------------------------------- - -void zx8302_device::tra_complete() -{ - m_status &= ~STATUS_TX_BUFFER_FULL; - - trigger_interrupt(INT_TRANSMIT); -} - - -//------------------------------------------------- -// rcv_callback - -//------------------------------------------------- - -void zx8302_device::rcv_callback() -{ - switch (m_tcr & MODE_MASK) - { - case MODE_NET: - receive_register_update_bit(m_rs232_rx); - break; - } -} - - -//------------------------------------------------- -// rcv_complete - -//------------------------------------------------- - -void zx8302_device::rcv_complete() -{ - // TODO -} - - -//------------------------------------------------- -// rtc_r - real time clock read -//------------------------------------------------- - -READ8_MEMBER( zx8302_device::rtc_r ) -{ - UINT8 data = 0; - - switch (offset) - { - case 0: - data = (m_ctr >> 24) & 0xff; - break; - case 1: - data = (m_ctr >> 16) & 0xff; - break; - case 2: - data = (m_ctr >> 8) & 0xff; - break; - case 3: - data = m_ctr & 0xff; - break; - } - - return data; -} - - -//------------------------------------------------- -// rtc_w - real time clock write -//------------------------------------------------- - -WRITE8_MEMBER( zx8302_device::rtc_w ) -{ - if (LOG) logerror("ZX8302 '%s' Set Real Time Clock: %02x\n", tag(), data); -} - - -//------------------------------------------------- -// control_w - serial transmit clock -//------------------------------------------------- - -WRITE8_MEMBER( zx8302_device::control_w ) -{ - if (LOG) logerror("ZX8302 '%s' Transmit Control: %02x\n", tag(), data); - - int baud = (19200 >> (data & BAUD_MASK)); - int baudx4 = baud * 4; - - m_tcr = data; - - m_baudx4_timer->adjust(attotime::zero, 0, attotime::from_hz(baudx4)); - - set_tra_rate(baud); - set_data_frame(1, 8, PARITY_NONE, STOP_BITS_2); -} - - -//------------------------------------------------- -// mdv_track_r - microdrive track data -//------------------------------------------------- - -READ8_MEMBER( zx8302_device::mdv_track_r ) -{ - if (LOG) logerror("ZX8302 '%s' Microdrive Track %u: %02x\n", tag(), m_track, m_mdv_data[m_track]); - - UINT8 data = m_mdv_data[m_track]; - - m_track = !m_track; - - return data; -} - - -//------------------------------------------------- -// status_r - status register -//------------------------------------------------- - -READ8_MEMBER( zx8302_device::status_r ) -{ - /* - - bit description - - 0 Network port - 1 Transmit buffer full - 2 Receive buffer full - 3 Microdrive GAP - 4 SER1 DTR - 5 SER2 CTS - 6 IPC busy - 7 COMDATA - - */ - - UINT8 data = 0; - - // TODO network port - - // serial status - data |= m_status; - - // TODO microdrive GAP - - // data terminal ready - data |= m_dtr1 << 4; - - // clear to send - data |= m_cts2 << 5; - - // IPC busy - data |= m_ipc_busy << 6; - - // COMDATA - data |= m_comdata_to_cpu << 7; - - if (LOG) logerror("ZX8302 '%s' Status: %02x\n", tag(), data); - - return data; -} - - -//------------------------------------------------- -// ipc_command_w - IPC command -//------------------------------------------------- -// When the main CPU writes to the IPC it writes the lsn of 18003 -// this is encoded as follows : -// -// b0 start bit -// b1 data bit -// b2 stop bit -// b3 extra stop bit. -// -// At startup the IPC sits in a loop waiting for the comdata bit to go -// high, the main CPU does this by writing 0x01 to output register. - -WRITE8_MEMBER( zx8302_device::ipc_command_w ) -{ - if (LOG) logerror("ZX8302 '%s' IPC Command: %02x\n", tag(), data); - - m_idr = data; - m_ipc_state = IPC_START; - - transmit_ipc_data(); -} - - -//------------------------------------------------- -// mdv_control_w - microdrive control -//------------------------------------------------- - -WRITE8_MEMBER( zx8302_device::mdv_control_w ) -{ - /* - - bit description - - 0 MDSELDH - 1 MDSELCKH - 2 MDRDWL - 3 ERASE - 4 - 5 - 6 - 7 - - */ - - if (LOG) logerror("ZX8302 '%s' Microdrive Control: %02x\n", tag(), data); - - m_out_mdseld_cb(BIT(data, 0)); - m_out_mdselck_cb(BIT(data, 1)); - m_out_mdrdw_cb(BIT(data, 2)); - m_out_erase_cb(BIT(data, 3)); - - if (BIT(data, 1)) - { - m_status &= ~STATUS_RX_BUFFER_FULL; - } -} - - -//------------------------------------------------- -// irq_status_r - interrupt status -//------------------------------------------------- - -READ8_MEMBER( zx8302_device::irq_status_r ) -{ - if (LOG) logerror("ZX8302 '%s' Interrupt Status: %02x\n", tag(), m_irq); - - return m_irq; -} - - -//------------------------------------------------- -// irq_acknowledge_w - interrupt acknowledge -//------------------------------------------------- - -WRITE8_MEMBER( zx8302_device::irq_acknowledge_w ) -{ - if (LOG) logerror("ZX8302 '%s' Interrupt Acknowledge: %02x\n", tag(), data); - - m_irq &= ~data; - - if (!m_irq) - { - m_out_ipl1l_cb(CLEAR_LINE); - } -} - - -//------------------------------------------------- -// data_w - transmit buffer -//------------------------------------------------- - -WRITE8_MEMBER( zx8302_device::data_w ) -{ - if (LOG) logerror("ZX8302 '%s' Data Register: %02x\n", tag(), data); - - m_tdr = data; - m_status |= STATUS_TX_BUFFER_FULL; -} - - -//------------------------------------------------- -// vsync_w - vertical sync -//------------------------------------------------- - -WRITE_LINE_MEMBER( zx8302_device::vsync_w ) -{ - if (state) - { - if (LOG) logerror("ZX8302 '%s' Frame Interrupt\n", tag()); - - trigger_interrupt(INT_FRAME); - } -} - - -//------------------------------------------------- -// comctl_w - IPC COMCTL -//------------------------------------------------- - -WRITE_LINE_MEMBER( zx8302_device::comctl_w ) -{ - if (LOG) logerror("ZX8302 '%s' COMCTL: %x\n", tag(), state); - - if (state) - { - transmit_ipc_data(); - m_comdata_to_cpu = m_comdata_from_ipc; - } -} - - -//------------------------------------------------- -// comdata_w - IPC COMDATA -//------------------------------------------------- -// IPC writing comdata to CPU -// - -WRITE_LINE_MEMBER( zx8302_device::comdata_w ) -{ - if (LOG) logerror("ZX8302 '%s' COMDATA->CPU(pending): %x\n", tag(), state); - - m_comdata_from_ipc = state; -} - - -//------------------------------------------------- -// extint_w - external interrupt -//------------------------------------------------- - -WRITE_LINE_MEMBER( zx8302_device::extint_w ) -{ - if (LOG) logerror("ZX8302 '%s' EXTINT: %x\n", tag(), state); - - if (state == ASSERT_LINE) - { - trigger_interrupt(INT_EXTERNAL); - } -} - -WRITE_LINE_MEMBER( zx8302_device::write_netin ) -{ - m_rs232_rx = state; - device_serial_interface::rx_w(state); -} - -WRITE_LINE_MEMBER( zx8302_device::write_dtr1 ) -{ - m_dtr1 = state; -} - -WRITE_LINE_MEMBER( zx8302_device::write_cts2 ) -{ - m_cts2 = state; -} |