diff --git a/src/devices/machine/iwm.cpp b/src/devices/machine/iwm.cpp index d1dcf79046a..460977f7c3f 100644 --- a/src/devices/machine/iwm.cpp +++ b/src/devices/machine/iwm.cpp @@ -56,6 +56,7 @@ void iwm_device::device_start() save_item(NAME(m_rsh)); save_item(NAME(m_wsh)); save_item(NAME(m_rw_bit_count)); + save_item(NAME(m_devsel)); } void iwm_device::device_reset() @@ -77,6 +78,7 @@ void iwm_device::device_reset() m_flux_write_start = 0; m_flux_write_count = 0; m_rw_bit_count = 0; + m_devsel = 0; m_devsel_cb(0); } @@ -85,9 +87,12 @@ void iwm_device::device_timer(emu_timer &, device_timer_id, int, void *) if(m_active == MODE_DELAY) { flush_write(); m_active = MODE_IDLE; + m_rw = MODE_IDLE; + m_rw_state = S_IDLE; if(m_floppy) m_floppy->mon_w(true); m_devsel_cb(0); + m_devsel = 0; m_status &= ~0x20; m_whd &= ~0x40; } @@ -99,6 +104,7 @@ void iwm_device::set_floppy(floppy_image_device *floppy) return; sync(); + flush_write(); logerror("floppy %s\n", floppy ? floppy->tag() : "-"); @@ -128,7 +134,8 @@ void iwm_device::write(offs_t offset, u8 data) void iwm_device::flush_write() { if(m_floppy && m_flux_write_start && m_last_sync > m_flux_write_start) { - if(m_flux_write_count && m_flux_write[m_flux_write_count-1] == m_last_sync) + bool last_on_edge = m_flux_write_count && m_flux_write[m_flux_write_count-1] == m_last_sync; + if(last_on_edge) m_flux_write_count--; attotime start = cycles_to_time(m_flux_write_start); attotime end = cycles_to_time(m_last_sync); @@ -137,16 +144,18 @@ void iwm_device::flush_write() fluxes[i] = cycles_to_time(m_flux_write[i]); m_floppy->write_flux(start, end, m_flux_write_count, m_flux_write_count ? &fluxes[0] : nullptr); m_flux_write_start = m_last_sync; - } - m_flux_write_count = 0; + m_flux_write_count = 0; + if(last_on_edge) + m_flux_write[m_flux_write_count++] = m_last_sync; + } else + m_flux_write_count = 0; + } u8 iwm_device::control(int offset, u8 data) { sync(); - // logerror("control trigger %x, %02x\n", offset, data); - u8 changed = m_control | (m_phases & 0xf); if(offset < 8) { if(offset & 1) m_phases |= 1 << (offset >> 1); @@ -160,22 +169,48 @@ u8 iwm_device::control(int offset, u8 data) m_control &= ~(1 << (offset >> 1)); } - changed ^= m_control | (m_phases & 0xf); - - if(changed & 0x30) - m_devsel_cb(m_control & 0x10 ? m_control & 0x20 ? 2 : 1 : 0); - - if(changed & 0x10) { - if(m_control & 0x10) { + if(m_control & 0x10) { + if(m_active != MODE_ACTIVE) { m_active = MODE_ACTIVE; m_status |= 0x20; if(m_floppy) m_floppy->mon_w(false); + } + + if((m_control & 0x80) == 0x00) { + if(m_rw != MODE_READ) { + if(m_rw == MODE_WRITE) { + flush_write(); + m_flux_write_start = 0; + } + m_rw = MODE_READ; + m_rw_state = S_IDLE; + m_next_state_change = 0; + m_sync_update = 0; + m_async_update = 0; + m_data = 0x00; + } + } else { + if(m_rw != MODE_WRITE) { + m_rw = MODE_WRITE; + m_rw_state = S_IDLE; + m_whd |= 0x40; + m_next_state_change = 0; + m_flux_write_start = m_last_sync; + m_flux_write_count = 0; + if(m_floppy) + m_floppy->set_write_splice(cycles_to_time(m_flux_write_start)); + } + } + } else { + if(m_active == MODE_ACTIVE) { + flush_write(); if(m_mode & 0x04) { - flush_write(); m_flux_write_start = 0; m_active = MODE_IDLE; + m_rw = MODE_IDLE; + m_rw_state = S_IDLE; m_status &= ~0x20; m_whd &= ~0x40; if(m_floppy) @@ -188,37 +223,10 @@ u8 iwm_device::control(int offset, u8 data) } } - if(changed & 0xd0) { - if((m_control & 0xc0) == 0x00 && m_active) { - if(m_rw == MODE_WRITE) { - flush_write(); - m_flux_write_start = 0; - } - m_rw = MODE_READ; - m_rw_state = S_IDLE; - m_next_state_change = 0; - m_sync_update = 0; - m_async_update = 0; - m_data = 0x00; - - } else if((m_control & 0xc0) == 0xc0 && m_active && m_rw != MODE_WRITE) { - m_rw = MODE_WRITE; - m_rw_state = S_IDLE; - m_whd |= 0x40; - m_next_state_change = 0; - m_flux_write_start = m_last_sync; - m_flux_write_count = 0; - if(m_floppy) - m_floppy->set_write_splice(cycles_to_time(m_flux_write_start)); - - } else if(m_rw == MODE_WRITE) { - if(!(m_control & 0x80)) { - flush_write(); - m_flux_write_start = 0; - m_rw = MODE_IDLE; - } - } else - m_rw = MODE_IDLE; + u8 devsel = m_active != MODE_IDLE ? m_control & 0x20 ? 2 : 1 : 0; + if(devsel != m_devsel) { + m_devsel = devsel; + m_devsel_cb(devsel); } if(0) { @@ -253,7 +261,7 @@ u8 iwm_device::control(int offset, u8 data) m_whd, m_data); } - if(m_active && !(m_control & 0xc0) && !is_sync() && (m_data & 0x80)) + if(m_active && !(m_control & 0x80) && !is_sync() && (m_data & 0x80)) m_async_update = m_last_sync + 14; switch(m_control & 0xc0) { @@ -337,8 +345,6 @@ u64 iwm_device::write_sync_half_window_size() const return m_mode & 0x08 ? 2 : 4; } -static u64 ssx1 = 0, ssx2 = 0; - void iwm_device::sync() { if(!m_active) @@ -358,12 +364,6 @@ void iwm_device::sync() next_flux_change = flux.is_never() ? u64(-1) : time_to_cycles(flux); if(next_flux_change <= m_last_sync) next_flux_change = m_last_sync+1; - if(!ssx1) - ssx1 = ssx2 = next_flux_change; - if(ssx2 != next_flux_change) { - ssx1 = ssx2; - ssx2 = next_flux_change; - } } if(next_sync < m_next_state_change) { m_last_sync = next_sync; @@ -429,7 +429,7 @@ void iwm_device::sync() case MODE_WRITE: { while(next_sync > m_last_sync) { - if(next_sync < m_next_state_change) { + if(next_sync < m_next_state_change || !(m_whd & 0x40)) { m_last_sync = next_sync; break; } @@ -454,8 +454,10 @@ void iwm_device::sync() case SW_WINDOW_LOAD: if(m_whd & 0x80) { + logerror("underrun\n"); + flush_write(); + m_flux_write_start = 0; m_whd &= ~0x40; - m_rw_state = S_IDLE; m_last_sync = next_sync; } else { m_wsh = m_data; diff --git a/src/devices/machine/iwm.h b/src/devices/machine/iwm.h index d3c2350d446..e8cb2189fa7 100644 --- a/src/devices/machine/iwm.h +++ b/src/devices/machine/iwm.h @@ -67,6 +67,7 @@ private: int m_active, m_rw, m_rw_state; u8 m_data, m_whd, m_mode, m_status, m_control, m_rw_bit_count; u8 m_rsh, m_wsh; + u8 m_devsel; u8 control(int offset, u8 data); u64 time_to_cycles(const attotime &tm) const;