From bd00b9c11fb608a8b1731d302d22c84aa6c3a1f4 Mon Sep 17 00:00:00 2001 From: Curt Coder Date: Wed, 10 Dec 2014 12:15:19 +0200 Subject: (MESS) c8050: Floppy WIP. (nw) --- src/emu/bus/bus.mak | 1 + src/emu/bus/ieee488/c2040fdc.c | 187 ---------------- src/emu/bus/ieee488/c2040fdc.h | 46 +--- src/emu/bus/ieee488/c8050fdc.c | 490 +++++++++++++++++++++++++++++++++++++++++ src/emu/bus/ieee488/c8050fdc.h | 168 ++++++++++++++ 5 files changed, 665 insertions(+), 227 deletions(-) create mode 100644 src/emu/bus/ieee488/c8050fdc.c create mode 100644 src/emu/bus/ieee488/c8050fdc.h diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak index c9caa8d9de1..8f1e0e7798a 100644 --- a/src/emu/bus/bus.mak +++ b/src/emu/bus/bus.mak @@ -403,6 +403,7 @@ BUSOBJS += $(BUSOBJ)/ieee488/c2031.o BUSOBJS += $(BUSOBJ)/ieee488/c2040.o BUSOBJS += $(BUSOBJ)/ieee488/c2040fdc.o BUSOBJS += $(BUSOBJ)/ieee488/c8050.o +BUSOBJS += $(BUSOBJ)/ieee488/c8050fdc.o BUSOBJS += $(BUSOBJ)/ieee488/c8280.o BUSOBJS += $(BUSOBJ)/ieee488/d9060.o BUSOBJS += $(BUSOBJ)/ieee488/softbox.o diff --git a/src/emu/bus/ieee488/c2040fdc.c b/src/emu/bus/ieee488/c2040fdc.c index 48b888bd9f8..5440176cced 100644 --- a/src/emu/bus/ieee488/c2040fdc.c +++ b/src/emu/bus/ieee488/c2040fdc.c @@ -9,15 +9,6 @@ **********************************************************************/ -/* - - TODO: - - - writing starts in the middle of a byte - - 8050 PLL - -*/ - #include "c2040fdc.h" @@ -35,7 +26,6 @@ //************************************************************************** const device_type C2040_FDC = &device_creator; -const device_type C8050_FDC = &device_creator; //------------------------------------------------- @@ -67,31 +57,6 @@ const rom_entry *c2040_fdc_t::device_rom_region() const // c2040_fdc_t - constructor //------------------------------------------------- -c2040_fdc_t::c2040_fdc_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : - device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__), - m_write_sync(*this), - m_write_ready(*this), - m_write_error(*this), - m_gcr_rom(*this, "gcr"), - m_floppy0(NULL), - m_floppy1(NULL), - m_mtr0(1), - m_mtr1(1), - m_stp0(0), - m_stp1(0), - m_ds(0), - m_drv_sel(0), - m_mode_sel(0), - m_rw_sel(0), - m_period(attotime::from_hz(clock)) -{ - cur_live.tm = attotime::never; - cur_live.state = IDLE; - cur_live.next_state = -1; - cur_live.write_position = 0; - cur_live.write_start_time = attotime::never; -} - c2040_fdc_t::c2040_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, C2040_FDC, "C2040 FDC", tag, owner, clock, "c2040fdc", __FILE__), m_write_sync(*this), @@ -118,9 +83,6 @@ c2040_fdc_t::c2040_fdc_t(const machine_config &mconfig, const char *tag, device_ cur_live.drv_sel = m_drv_sel; } -c8050_fdc_t::c8050_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : - c2040_fdc_t(mconfig, C8050_FDC, "C8050 FDC", tag, owner, clock, "c8050fdc", __FILE__) { } - //------------------------------------------------- @@ -635,152 +597,3 @@ void c2040_fdc_t::set_floppy(floppy_image_device *floppy0, floppy_image_device * m_floppy0 = floppy0; m_floppy1 = floppy1; } - -void c8050_fdc_t::live_start() -{ - cur_live.tm = machine().time(); - cur_live.state = RUNNING; - cur_live.next_state = -1; - - cur_live.shift_reg = 0; - cur_live.shift_reg_write = 0; - cur_live.cycle_counter = 0; - cur_live.cell_counter = 0; - cur_live.bit_counter = 0; - cur_live.ds = m_ds; - cur_live.drv_sel = m_drv_sel; - cur_live.mode_sel = m_mode_sel; - cur_live.rw_sel = m_rw_sel; - cur_live.pi = m_pi; - - pll_reset(cur_live.tm, attotime::from_double(0)); - checkpoint_live = cur_live; - pll_save_checkpoint(); - - live_run(); -} - -void c8050_fdc_t::pll_reset(const attotime &when, const attotime clock) -{ - cur_pll.reset(when); - cur_pll.set_clock(clock); -} - -void c8050_fdc_t::pll_save_checkpoint() -{ - checkpoint_pll = cur_pll; -} - -void c8050_fdc_t::pll_retrieve_checkpoint() -{ - cur_pll = checkpoint_pll; -} - -void c8050_fdc_t::checkpoint() -{ - checkpoint_live = cur_live; - pll_save_checkpoint(); -} - -void c8050_fdc_t::rollback() -{ - cur_live = checkpoint_live; - pll_retrieve_checkpoint(); -} - -void c8050_fdc_t::live_run(const attotime &limit) -{ - if(cur_live.state == IDLE || cur_live.next_state != -1) - return; - - for(;;) { - switch(cur_live.state) { - case RUNNING: { - bool syncpoint = false; - - if (cur_live.tm > limit) - return; - - int bit = get_next_bit(cur_live.tm, limit); - if(bit < 0) - return; - - if (syncpoint) { - commit(cur_live.tm); - - cur_live.tm += m_period; - live_delay(RUNNING_SYNCPOINT); - return; - } - - cur_live.tm += m_period; - break; - } - - case RUNNING_SYNCPOINT: { - m_write_ready(cur_live.ready); - m_write_sync(cur_live.sync); - m_write_error(cur_live.error); - - cur_live.state = RUNNING; - checkpoint(); - break; - } - } - } -} - -int c8050_fdc_t::get_next_bit(attotime &tm, const attotime &limit) -{ - return cur_pll.get_next_bit(tm, get_floppy(), limit); -} - -void c8050_fdc_t::stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp) -{ - if (mtr) return; - - int tracks = 0; - - switch (old_stp) - { - case 0: if (stp == 1) tracks++; else if (stp == 2) tracks--; break; - case 1: if (stp == 3) tracks++; else if (stp == 0) tracks--; break; - case 2: if (stp == 0) tracks++; else if (stp == 3) tracks--; break; - case 3: if (stp == 2) tracks++; else if (stp == 1) tracks--; break; - } - - if (tracks == -1) - { - floppy->dir_w(1); - floppy->stp_w(1); - floppy->stp_w(0); - } - else if (tracks == 1) - { - floppy->dir_w(0); - floppy->stp_w(1); - floppy->stp_w(0); - } - - old_stp = stp; -} - -WRITE_LINE_MEMBER( c8050_fdc_t::odd_hd_w ) -{ - if (m_odd_hd != state) - { - live_sync(); - m_odd_hd = cur_live.odd_hd = state; - if (LOG) logerror("%s ODD HD %u\n", machine().time().as_string(), state); - m_floppy0->ss_w(!state); - if (m_floppy1) m_floppy1->ss_w(!state); - checkpoint(); - live_run(); - } -} - -WRITE_LINE_MEMBER( c8050_fdc_t::pull_sync_w ) -{ - // TODO - if (LOG) logerror("%s PULL SYNC %u\n", machine().time().as_string(), state); -} diff --git a/src/emu/bus/ieee488/c2040fdc.h b/src/emu/bus/ieee488/c2040fdc.h index e9d43bc1e1c..d64d2de7c01 100644 --- a/src/emu/bus/ieee488/c2040fdc.h +++ b/src/emu/bus/ieee488/c2040fdc.h @@ -18,10 +18,7 @@ #include "formats/d64_dsk.h" #include "formats/d67_dsk.h" #include "formats/g64_dsk.h" -#include "formats/d80_dsk.h" -#include "formats/d82_dsk.h" #include "imagedev/floppy.h" -#include "machine/fdc_pll.h" @@ -50,7 +47,6 @@ class c2040_fdc_t : public device_t { public: // construction/destruction - c2040_fdc_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); c2040_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); template static devcb_base &set_sync_wr_callback(device_t &device, _Object object) { return downcast(device).m_write_sync.set_callback(object); } @@ -68,8 +64,6 @@ public: DECLARE_READ_LINE_MEMBER( wps_r ) { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); } DECLARE_READ_LINE_MEMBER( sync_r ) { return checkpoint_live.sync; } - DECLARE_READ_LINE_MEMBER( ready_r ) { return checkpoint_live.ready; } - DECLARE_READ_LINE_MEMBER( error_r ) { return checkpoint_live.error; } void stp0_w(int stp); void stp1_w(int stp); @@ -147,9 +141,10 @@ protected: emu_timer *t_gen; floppy_image_device* get_floppy(); - virtual void live_start(); - virtual void checkpoint(); - virtual void rollback(); + + void live_start(); + void checkpoint(); + void rollback(); bool write_next_bit(bool bit, const attotime &limit); void start_writing(const attotime &tm); void commit(const attotime &tm); @@ -157,43 +152,14 @@ protected: void live_delay(int state); void live_sync(); void live_abort(); - virtual void live_run(const attotime &limit = attotime::never); + void live_run(const attotime &limit = attotime::never); void get_next_edge(const attotime &when); - virtual int get_next_bit(attotime &tm, const attotime &limit); + int get_next_bit(attotime &tm, const attotime &limit); }; -// ======================> c8050_fdc_t - -class c8050_fdc_t : public c2040_fdc_t -{ -public: - // construction/destruction - c8050_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - DECLARE_WRITE_LINE_MEMBER( odd_hd_w ); - DECLARE_WRITE_LINE_MEMBER( pull_sync_w ); - -protected: - fdc_pll_t cur_pll, checkpoint_pll; - - void stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp); - - virtual void live_start(); - virtual void checkpoint(); - virtual void rollback(); - void pll_reset(const attotime &when, const attotime clock); - void pll_save_checkpoint(); - void pll_retrieve_checkpoint(); - virtual void live_run(const attotime &limit = attotime::never); - virtual int get_next_bit(attotime &tm, const attotime &limit); -}; - - - // device type definition extern const device_type C2040_FDC; -extern const device_type C8050_FDC; diff --git a/src/emu/bus/ieee488/c8050fdc.c b/src/emu/bus/ieee488/c8050fdc.c new file mode 100644 index 00000000000..b49880d4693 --- /dev/null +++ b/src/emu/bus/ieee488/c8050fdc.c @@ -0,0 +1,490 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +/********************************************************************** + + Commodore 8050 floppy disk controller emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "c8050fdc.h" + + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define LOG 0 + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type C8050_FDC = &device_creator; + + +//------------------------------------------------- +// ROM( c8050_fdc ) +//------------------------------------------------- + +ROM_START( c8050_fdc ) + ROM_REGION( 0x800, "gcr", 0) + ROM_LOAD( "901467.uk6", 0x000, 0x800, CRC(a23337eb) SHA1(97df576397608455616331f8e837cb3404363fa2) ) +ROM_END + + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const rom_entry *c8050_fdc_t::device_rom_region() const +{ + return ROM_NAME( c8050_fdc ); +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// c8050_fdc_t - constructor +//------------------------------------------------- + +c8050_fdc_t::c8050_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, C8050_FDC, "C8050 FDC", tag, owner, clock, "c8050fdc", __FILE__), + m_write_sync(*this), + m_write_ready(*this), + m_write_error(*this), + m_gcr_rom(*this, "gcr"), + m_floppy0(NULL), + m_floppy1(NULL), + m_mtr0(1), + m_mtr1(1), + m_stp0(0), + m_stp1(0), + m_ds(0), + m_drv_sel(0), + m_mode_sel(0), + m_rw_sel(0), + m_period(attotime::from_hz(clock)) +{ + cur_live.tm = attotime::never; + cur_live.state = IDLE; + cur_live.next_state = -1; + cur_live.drv_sel = m_drv_sel; +} + + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void c8050_fdc_t::device_start() +{ + // resolve callbacks + m_write_sync.resolve_safe(); + m_write_ready.resolve_safe(); + m_write_error.resolve_safe(); + + // allocate timer + t_gen = timer_alloc(0); + + // register for state saving + save_item(NAME(m_mtr0)); + save_item(NAME(m_mtr1)); + save_item(NAME(m_stp0)); + save_item(NAME(m_stp1)); + save_item(NAME(m_ds)); + save_item(NAME(m_drv_sel)); + save_item(NAME(m_mode_sel)); + save_item(NAME(m_rw_sel)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void c8050_fdc_t::device_reset() +{ + live_abort(); +} + + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- + +void c8050_fdc_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + live_sync(); + live_run(); +} + +floppy_image_device* c8050_fdc_t::get_floppy() +{ + return cur_live.drv_sel ? m_floppy1 : m_floppy0; +} + +void c8050_fdc_t::stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp) +{ + if (mtr) return; + + int tracks = 0; + + switch (old_stp) + { + case 0: if (stp == 1) tracks++; else if (stp == 2) tracks--; break; + case 1: if (stp == 3) tracks++; else if (stp == 0) tracks--; break; + case 2: if (stp == 0) tracks++; else if (stp == 3) tracks--; break; + case 3: if (stp == 2) tracks++; else if (stp == 1) tracks--; break; + } + + if (tracks == -1) + { + floppy->dir_w(1); + floppy->stp_w(1); + floppy->stp_w(0); + } + else if (tracks == 1) + { + floppy->dir_w(0); + floppy->stp_w(1); + floppy->stp_w(0); + } + + old_stp = stp; +} + +void c8050_fdc_t::stp0_w(int stp) +{ + if (m_stp0 != stp) + { + live_sync(); + this->stp_w(m_floppy0, m_mtr0, m_stp0, stp); + checkpoint(); + live_run(); + } +} + +void c8050_fdc_t::stp1_w(int stp) +{ + if (m_stp1 != stp) + { + live_sync(); + if (m_floppy1) this->stp_w(m_floppy1, m_mtr1, m_stp1, stp); + checkpoint(); + live_run(); + } +} + +void c8050_fdc_t::ds_w(int ds) +{ + if (m_ds != ds) + { + live_sync(); + m_ds = cur_live.ds = ds; + checkpoint(); + live_run(); + } +} + +void c8050_fdc_t::set_floppy(floppy_image_device *floppy0, floppy_image_device *floppy1) +{ + m_floppy0 = floppy0; + m_floppy1 = floppy1; +} + +void c8050_fdc_t::live_start() +{ + cur_live.tm = machine().time(); + cur_live.state = RUNNING; + cur_live.next_state = -1; + + cur_live.shift_reg = 0; + cur_live.shift_reg_write = 0; + cur_live.cycle_counter = 0; + cur_live.cell_counter = 0; + cur_live.bit_counter = 0; + cur_live.ds = m_ds; + cur_live.drv_sel = m_drv_sel; + cur_live.mode_sel = m_mode_sel; + cur_live.rw_sel = m_rw_sel; + cur_live.pi = m_pi; + + pll_reset(cur_live.tm, attotime::from_double(0)); + checkpoint_live = cur_live; + pll_save_checkpoint(); + + live_run(); +} + +void c8050_fdc_t::pll_reset(const attotime &when, const attotime clock) +{ + cur_pll.reset(when); + cur_pll.set_clock(clock); +} + +void c8050_fdc_t::pll_start_writing(const attotime &tm) +{ + cur_pll.start_writing(tm); +} + +void c8050_fdc_t::pll_commit(floppy_image_device *floppy, const attotime &tm) +{ + cur_pll.commit(floppy, tm); +} + +void c8050_fdc_t::pll_stop_writing(floppy_image_device *floppy, const attotime &tm) +{ + cur_pll.stop_writing(floppy, tm); +} + +void c8050_fdc_t::pll_save_checkpoint() +{ + checkpoint_pll = cur_pll; +} + +void c8050_fdc_t::pll_retrieve_checkpoint() +{ + cur_pll = checkpoint_pll; +} + +int c8050_fdc_t::pll_get_next_bit(attotime &tm, floppy_image_device *floppy, const attotime &limit) +{ + return cur_pll.get_next_bit(tm, floppy, limit); +} + +bool c8050_fdc_t::pll_write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit) +{ + return cur_pll.write_next_bit_prev_cell(bit, tm, floppy, limit); +} + +void c8050_fdc_t::checkpoint() +{ + pll_commit(get_floppy(), cur_live.tm); + checkpoint_live = cur_live; + pll_save_checkpoint(); +} + +void c8050_fdc_t::rollback() +{ + cur_live = checkpoint_live; + pll_retrieve_checkpoint(); +} + +void c8050_fdc_t::live_sync() +{ + if(!cur_live.tm.is_never()) { + if(cur_live.tm > machine().time()) { + rollback(); + live_run(machine().time()); + pll_commit(get_floppy(), cur_live.tm); + } else { + pll_commit(get_floppy(), cur_live.tm); + if(cur_live.next_state != -1) { + cur_live.state = cur_live.next_state; + cur_live.next_state = -1; + } + if(cur_live.state == IDLE) { + pll_stop_writing(get_floppy(), cur_live.tm); + cur_live.tm = attotime::never; + } + } + cur_live.next_state = -1; + checkpoint(); + } +} + +void c8050_fdc_t::live_abort() +{ + if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) { + rollback(); + live_run(machine().time()); + } + + pll_stop_writing(get_floppy(), cur_live.tm); + + cur_live.tm = attotime::never; + cur_live.state = IDLE; + cur_live.next_state = -1; + + cur_live.ready = 1; + cur_live.sync = 1; + cur_live.error = 1; +} + + +void c8050_fdc_t::live_run(const attotime &limit) +{ + if(cur_live.state == IDLE || cur_live.next_state != -1) + return; + + for(;;) { + switch(cur_live.state) { + case RUNNING: { + bool syncpoint = false; + + if (cur_live.tm > limit) + return; + + int bit = pll_get_next_bit(cur_live.tm, get_floppy(), limit); + if(bit < 0) + return; + + if (syncpoint) { + live_delay(RUNNING_SYNCPOINT); + return; + } + break; + } + + case RUNNING_SYNCPOINT: { + m_write_ready(cur_live.ready); + m_write_sync(cur_live.sync); + m_write_error(cur_live.error); + + cur_live.state = RUNNING; + checkpoint(); + break; + } + } + } +} + +READ8_MEMBER( c8050_fdc_t::read ) +{ + UINT8 e = checkpoint_live.e; + offs_t i = checkpoint_live.i; + + UINT8 data = (BIT(e, 6) << 7) | (BIT(i, 7) << 6) | (e & 0x33) | (BIT(e, 2) << 3) | (i & 0x04); + + if (LOG) logerror("%s VIA reads data %02x (%03x)\n", machine().time().as_string(), data, checkpoint_live.shift_reg); + + return data; +} + +WRITE8_MEMBER( c8050_fdc_t::write ) +{ + if (m_pi != data) + { + live_sync(); + m_pi = cur_live.pi = data; + checkpoint(); + if (LOG) logerror("%s PI %02x\n", machine().time().as_string(), data); + live_run(); + } +} + +WRITE_LINE_MEMBER( c8050_fdc_t::drv_sel_w ) +{ + if (m_drv_sel != state) + { + live_sync(); + m_drv_sel = cur_live.drv_sel = state; + checkpoint(); + if (LOG) logerror("%s DRV SEL %u\n", machine().time().as_string(), state); + live_run(); + } +} + +WRITE_LINE_MEMBER( c8050_fdc_t::mode_sel_w ) +{ + if (m_mode_sel != state) + { + live_sync(); + m_mode_sel = cur_live.mode_sel = state; + checkpoint(); + if (LOG) logerror("%s MODE SEL %u\n", machine().time().as_string(), state); + live_run(); + } +} + +WRITE_LINE_MEMBER( c8050_fdc_t::rw_sel_w ) +{ + if (m_rw_sel != state) + { + live_sync(); + m_rw_sel = cur_live.rw_sel = state; + checkpoint(); + if (LOG) logerror("%s RW SEL %u\n", machine().time().as_string(), state); + if (m_rw_sel) { + pll_stop_writing(get_floppy(), machine().time()); + } else { + pll_start_writing(machine().time()); + } + live_run(); + } +} + +WRITE_LINE_MEMBER( c8050_fdc_t::mtr0_w ) +{ + if (m_mtr0 != state) + { + live_sync(); + m_mtr0 = state; + if (LOG) logerror("%s MTR0 %u\n", machine().time().as_string(), state); + m_floppy0->mon_w(state); + checkpoint(); + + if (!m_mtr0 || !m_mtr1) { + if(cur_live.state == IDLE) { + live_start(); + } + } else { + live_abort(); + } + + live_run(); + } +} + +WRITE_LINE_MEMBER( c8050_fdc_t::mtr1_w ) +{ + if (m_mtr1 != state) + { + live_sync(); + m_mtr1 = state; + if (LOG) logerror("%s MTR1 %u\n", machine().time().as_string(), state); + if (m_floppy1) m_floppy1->mon_w(state); + checkpoint(); + + if (!m_mtr0 || !m_mtr1) { + if(cur_live.state == IDLE) { + live_start(); + } + } else { + live_abort(); + } + + live_run(); + } +} + +WRITE_LINE_MEMBER( c8050_fdc_t::odd_hd_w ) +{ + if (m_odd_hd != state) + { + live_sync(); + m_odd_hd = cur_live.odd_hd = state; + if (LOG) logerror("%s ODD HD %u\n", machine().time().as_string(), state); + m_floppy0->ss_w(!state); + if (m_floppy1) m_floppy1->ss_w(!state); + checkpoint(); + live_run(); + } +} + +WRITE_LINE_MEMBER( c8050_fdc_t::pull_sync_w ) +{ + // TODO + if (LOG) logerror("%s PULL SYNC %u\n", machine().time().as_string(), state); +} diff --git a/src/emu/bus/ieee488/c8050fdc.h b/src/emu/bus/ieee488/c8050fdc.h new file mode 100644 index 00000000000..ed098d1db6a --- /dev/null +++ b/src/emu/bus/ieee488/c8050fdc.h @@ -0,0 +1,168 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +/********************************************************************** + + Commodore 8050 floppy disk controller emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#pragma once + +#ifndef __C8050_FLOPPY__ +#define __C8050_FLOPPY__ + +#include "emu.h" +#include "formats/d80_dsk.h" +#include "formats/d82_dsk.h" +#include "imagedev/floppy.h" +#include "machine/fdc_pll.h" + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_C8050_SYNC_CALLBACK(_write) \ + devcb = &c8050_fdc_t::set_sync_wr_callback(*device, DEVCB_##_write); + +#define MCFG_C8050_READY_CALLBACK(_write) \ + devcb = &c8050_fdc_t::set_ready_wr_callback(*device, DEVCB_##_write); + +#define MCFG_C8050_ERROR_CALLBACK(_write) \ + devcb = &c8050_fdc_t::set_error_wr_callback(*device, DEVCB_##_write); + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> c8050_fdc_t + +class c8050_fdc_t : public device_t +{ +public: + // construction/destruction + c8050_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + template static devcb_base &set_sync_wr_callback(device_t &device, _Object object) { return downcast(device).m_write_sync.set_callback(object); } + template static devcb_base &set_ready_wr_callback(device_t &device, _Object object) { return downcast(device).m_write_ready.set_callback(object); } + template static devcb_base &set_error_wr_callback(device_t &device, _Object object) { return downcast(device).m_write_error.set_callback(object); } + + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); + + DECLARE_WRITE_LINE_MEMBER( drv_sel_w ); + DECLARE_WRITE_LINE_MEMBER( mode_sel_w ); + DECLARE_WRITE_LINE_MEMBER( rw_sel_w ); + DECLARE_WRITE_LINE_MEMBER( mtr0_w ); + DECLARE_WRITE_LINE_MEMBER( mtr1_w ); + DECLARE_WRITE_LINE_MEMBER( odd_hd_w ); + DECLARE_WRITE_LINE_MEMBER( pull_sync_w ); + + DECLARE_READ_LINE_MEMBER( wps_r ) { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); } + DECLARE_READ_LINE_MEMBER( sync_r ) { return checkpoint_live.sync; } + + void stp0_w(int stp); + void stp1_w(int stp); + void ds_w(int ds); + + void set_floppy(floppy_image_device *floppy0, floppy_image_device *floppy1); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + + // optional information overrides + virtual const rom_entry *device_rom_region() const; + + void stp_w(floppy_image_device *floppy, int mtr, int &old_stp, int stp); + + enum { + IDLE, + RUNNING, + RUNNING_SYNCPOINT + }; + + struct live_info { + attotime tm; + int state, next_state; + int sync; + int ready; + int error; + int ds; + int drv_sel; + int mode_sel; + int rw_sel; + int odd_hd; + + attotime edge; + UINT16 shift_reg; + int cycle_counter; + int cell_counter; + int bit_counter; + UINT8 e; + offs_t i; + + UINT8 pi; + UINT16 shift_reg_write; + }; + + devcb_write_line m_write_sync; + devcb_write_line m_write_ready; + devcb_write_line m_write_error; + + required_memory_region m_gcr_rom; + + floppy_image_device *m_floppy0; + floppy_image_device *m_floppy1; + + int m_mtr0; + int m_mtr1; + int m_stp0; + int m_stp1; + int m_ds; + int m_drv_sel; + int m_mode_sel; + int m_rw_sel; + int m_odd_hd; + UINT8 m_pi; + + attotime m_period; + + live_info cur_live, checkpoint_live; + fdc_pll_t cur_pll, checkpoint_pll; + emu_timer *t_gen; + + floppy_image_device* get_floppy(); + + void live_start(); + void checkpoint(); + void rollback(); + void pll_reset(const attotime &when, const attotime clock); + void pll_start_writing(const attotime &tm); + void pll_commit(floppy_image_device *floppy, const attotime &tm); + void pll_stop_writing(floppy_image_device *floppy, const attotime &tm); + int pll_get_next_bit(attotime &tm, floppy_image_device *floppy, const attotime &limit); + bool pll_write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit); + void pll_save_checkpoint(); + void pll_retrieve_checkpoint(); + void live_delay(int state); + void live_sync(); + void live_abort(); + void live_run(const attotime &limit = attotime::never); +}; + + +// device type definition +extern const device_type C8050_FDC; + + + +#endif -- cgit v1.2.3