From f6cea0ce99b5424835d28c80f1d759a7c2a78e5d Mon Sep 17 00:00:00 2001 From: arbee Date: Sat, 23 May 2020 19:30:21 -0400 Subject: [PATCH] new files (nw) --- src/devices/bus/a2bus/a2iwm.cpp | 93 ++++++ src/devices/bus/a2bus/a2iwm.h | 54 ++++ src/devices/machine/applefdintf.cpp | 73 +++++ src/devices/machine/applefdintf.h | 103 +++++++ src/devices/machine/iwm.cpp | 439 ++++++++++++++++++++++++++++ src/devices/machine/iwm.h | 88 ++++++ src/devices/machine/swim1.cpp | 173 +++++++++++ src/devices/machine/swim1.h | 48 +++ src/devices/machine/swim2.cpp | 175 +++++++++++ src/devices/machine/swim2.h | 48 +++ src/devices/machine/swim3.cpp | 173 +++++++++++ src/devices/machine/swim3.h | 48 +++ 12 files changed, 1515 insertions(+) create mode 100644 src/devices/bus/a2bus/a2iwm.cpp create mode 100644 src/devices/bus/a2bus/a2iwm.h create mode 100755 src/devices/machine/applefdintf.cpp create mode 100755 src/devices/machine/applefdintf.h create mode 100644 src/devices/machine/iwm.cpp create mode 100644 src/devices/machine/iwm.h create mode 100644 src/devices/machine/swim1.cpp create mode 100644 src/devices/machine/swim1.h create mode 100644 src/devices/machine/swim2.cpp create mode 100644 src/devices/machine/swim2.h create mode 100644 src/devices/machine/swim3.cpp create mode 100644 src/devices/machine/swim3.h diff --git a/src/devices/bus/a2bus/a2iwm.cpp b/src/devices/bus/a2bus/a2iwm.cpp new file mode 100644 index 00000000000..29c85569bac --- /dev/null +++ b/src/devices/bus/a2bus/a2iwm.cpp @@ -0,0 +1,93 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont, O. Galibert +/********************************************************************* + + a2iwm.c + + Implementation of the Apple II IWM controller card + +*********************************************************************/ + +#include "emu.h" +#include "formats/ap2_dsk.h" +#include "machine/applefdintf.h" +#include "a2iwm.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +DEFINE_DEVICE_TYPE(A2BUS_IWM, a2bus_iwm_device, "a2iwm", "Apple IWM controller card") + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void a2bus_iwm_device::device_add_mconfig(machine_config &config) +{ + IWM(config, m_iwm, clock(), 1021800*2); + m_iwm->phases_cb().set(FUNC(a2bus_iwm_device::phases_w)); + m_iwm->devsel_cb().set(FUNC(a2bus_iwm_device::devsel_w)); + applefdintf_device::add_525(config, m_floppy[0]); + applefdintf_device::add_525(config, m_floppy[1]); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +a2bus_iwm_device::a2bus_iwm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, A2BUS_IWM, tag, owner, clock), + device_a2bus_card_interface(mconfig, *this), + m_iwm(*this, "iwm"), + m_floppy(*this, "%u", 0U) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void a2bus_iwm_device::device_start() +{ +} + +void a2bus_iwm_device::device_reset() +{ +} + +/*------------------------------------------------- + read_c0nx - called for reads from this card's c0nx space +-------------------------------------------------*/ + +uint8_t a2bus_iwm_device::read_c0nx(u8 offset) +{ + return m_iwm->read(offset); +} + + +/*------------------------------------------------- + write_c0nx - called for writes to this card's c0nx space +-------------------------------------------------*/ + +void a2bus_iwm_device::write_c0nx(u8 offset, u8 data) +{ + m_iwm->write(offset, data); +} + +void a2bus_iwm_device::devsel_w(u8 data) +{ + if(data & 1) + m_iwm->set_floppy(m_floppy[0]->get_device()); + else if(data & 2) + m_iwm->set_floppy(m_floppy[1]->get_device()); + else + m_iwm->set_floppy(nullptr); +} + +void a2bus_iwm_device::phases_w(u8 data) +{ + auto flp = m_iwm->get_floppy(); + if(flp) + flp->seek_phase_w(data); +} diff --git a/src/devices/bus/a2bus/a2iwm.h b/src/devices/bus/a2bus/a2iwm.h new file mode 100644 index 00000000000..07f76384c28 --- /dev/null +++ b/src/devices/bus/a2bus/a2iwm.h @@ -0,0 +1,54 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont, O. Galibert +/********************************************************************* + + a2iwm.h + + Apple II IWM Controller Card, new floppy + +*********************************************************************/ + +#ifndef MAME_BUS_A2BUS_A2IWM_H +#define MAME_BUS_A2BUS_A2IWM_H + +#pragma once + +#include "a2bus.h" +#include "imagedev/floppy.h" +#include "formats/flopimg.h" +#include "machine/iwm.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +class a2bus_iwm_device: + public device_t, + public device_a2bus_card_interface +{ +public: + // construction/destruction + a2bus_iwm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + // overrides of standard a2bus slot functions + virtual uint8_t read_c0nx(u8 offset) override; + virtual void write_c0nx(u8 offset, u8 data) override; + + required_device m_iwm; + required_device_array m_floppy; + +private: + void devsel_w(u8 data); + void phases_w(u8 data); +}; + +// device type definition +DECLARE_DEVICE_TYPE(A2BUS_IWM, a2bus_iwm_device) + +#endif // MAME_BUS_A2BUS_A2IWM_H diff --git a/src/devices/machine/applefdintf.cpp b/src/devices/machine/applefdintf.cpp new file mode 100755 index 00000000000..3b1590720c1 --- /dev/null +++ b/src/devices/machine/applefdintf.cpp @@ -0,0 +1,73 @@ +// license:BSD-3-Clause +// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont + +#include "emu.h" +#include "applefdintf.h" +#include "formats/ap2_dsk.h" +#include "formats/ap_dsk35.h" +#include "formats/pc_dsk.h" + +FLOPPY_FORMATS_MEMBER(applefdintf_device::formats_525_13) + FLOPPY_EDD_FORMAT, + FLOPPY_WOZ_FORMAT +FLOPPY_FORMATS_END + +FLOPPY_FORMATS_MEMBER(applefdintf_device::formats_525) + FLOPPY_A216S_FORMAT, + FLOPPY_RWTS18_FORMAT, + FLOPPY_EDD_FORMAT, + FLOPPY_WOZ_FORMAT +FLOPPY_FORMATS_END + +FLOPPY_FORMATS_MEMBER(applefdintf_device::formats_35) + FLOPPY_DC42_FORMAT, + FLOPPY_PC_FORMAT +FLOPPY_FORMATS_END + +void applefdintf_device::floppies_525(device_slot_interface &device) +{ + device.option_add("525", FLOPPY_525_SD); +} + +void applefdintf_device::floppies_35(device_slot_interface &device) +{ + device.option_add("35", FLOPPY_35_HD); +} + +applefdintf_device::applefdintf_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + m_phases_cb(*this), + m_devsel_cb(*this), + m_sel35_cb(*this), + m_hdsel_cb(*this) +{ +} + +void applefdintf_device::device_start() +{ + m_phases_cb.resolve_safe(); + m_devsel_cb.resolve_safe(); + m_sel35_cb.resolve_safe(); + m_hdsel_cb.resolve_safe(); + save_item(NAME(m_phases)); + save_item(NAME(m_phases_input)); +} + +void applefdintf_device::device_reset() +{ + m_phases = 0xf0; + m_phases_input = 0x00; + update_phases(); +} + +void applefdintf_device::phases_w(u8 phases) +{ + m_phases_input = phases; + update_phases(); +} + +void applefdintf_device::update_phases() +{ + u8 mask = m_phases >> 4; + m_phases_cb((m_phases & mask) | (m_phases_input & (mask ^ 0xf))); +} diff --git a/src/devices/machine/applefdintf.h b/src/devices/machine/applefdintf.h new file mode 100755 index 00000000000..c6cc7a2d451 --- /dev/null +++ b/src/devices/machine/applefdintf.h @@ -0,0 +1,103 @@ +// license:BSD-3-Clause +// copyright-holders:O. Galibert +/********************************************************************* + + applefdintf.h + + Common interface of various Apple Floppy Disk Controllers, implemented + in the classic Apple controller, the IWM and the SWIM variants + + +*********************************************************************/ + +#ifndef MAME_MACHINE_APPLEFDINTF_H +#define MAME_MACHINE_APPLEFDINTF_H + +#pragma once + +#include "imagedev/floppy.h" + +class applefdintf_device : public device_t +{ +public: + // read/write handlers for cpu access + virtual uint8_t read(offs_t offset) = 0; + virtual void write(offs_t offset, u8 data) = 0; + + // phases line management + // Input from the exterior for the devices where they are bidirectional + void phases_w(u8 phases); + // Push output for when driven by the chip + auto phases_cb() { return m_phases_cb.bind(); } + + // sel35 line when present (active high) + auto sel35_cb() { return m_sel35_cb.bind(); } + + // drive select lines (two of them in the low bits, active high) + auto devsel_cb() { return m_devsel_cb.bind(); } + + // hdsel line when present and in output mode (active high) + auto hdsel_cb() { return m_hdsel_cb.bind(); } + + // floppy selection input, to be updated according to the previous callbacks, + // nullptr if none selected + virtual void set_floppy(floppy_image_device *floppy) = 0; + + // get the currently selected floppy + virtual floppy_image_device *get_floppy() const = 0; + + // Floppy formats + // 13-sector 5.25 + DECLARE_FLOPPY_FORMATS(formats_525_13); + + // 5.25 + DECLARE_FLOPPY_FORMATS(formats_525); + + // 3.5 + DECLARE_FLOPPY_FORMATS(formats_35); + + // Floppy drives slot-level + // 5.25 + static void floppies_525(device_slot_interface &device); + template static void add_525_13(machine_config &config, T &floppy) { + FLOPPY_CONNECTOR(config, floppy, floppies_525, "525", formats_525_13); + } + template static void add_525_13_nc(machine_config &config, T &floppy) { + FLOPPY_CONNECTOR(config, floppy, floppies_525, "", formats_525_13); + } + + template static void add_525(machine_config &config, T &floppy) { + FLOPPY_CONNECTOR(config, floppy, floppies_525, "525", formats_525); + } + template static void add_525_nc(machine_config &config, T &floppy) { + FLOPPY_CONNECTOR(config, floppy, floppies_525, "", formats_525); + } + + // 3.5 + static void floppies_35(device_slot_interface &device); + template static void add_35(machine_config &config, T &floppy) { + FLOPPY_CONNECTOR(config, floppy, floppies_35, "35", formats_35); + } + template static void add_35_nc(machine_config &config, T &floppy) { + FLOPPY_CONNECTOR(config, floppy, floppies_35, "", formats_35); + } + +protected: + devcb_write8 m_phases_cb, m_devsel_cb; + devcb_write_line m_sel35_cb, m_hdsel_cb; + + // Current phase value in the bottom bits, input/output flags in the top bits + u8 m_phases; + + // Current value of the driven external phases input + u8 m_phases_input; + + applefdintf_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + void update_phases(); +}; + +#endif // MAME_MACHINE_APPLEFDINTF_H diff --git a/src/devices/machine/iwm.cpp b/src/devices/machine/iwm.cpp new file mode 100644 index 00000000000..e3524afbee4 --- /dev/null +++ b/src/devices/machine/iwm.cpp @@ -0,0 +1,439 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + iwm.c + + Implementation of the Apple IWM floppy disk controller + +*********************************************************************/ + +#include "emu.h" +#include "iwm.h" + +DEFINE_DEVICE_TYPE(IWM_FDC, iwm_device, "iwm", "Apple IWM floppy controller") + +iwm_device::iwm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t q3_clock) : + applefdintf_device(mconfig, IWM_FDC, tag, owner, clock), + m_q3_clock(q3_clock) +{ + m_q3_fclk_ratio = double(clock)/double(q3_clock); // ~0.25 + m_fclk_q3_ratio = double(q3_clock)/double(clock); // ~4 +} + +u64 iwm_device::q3_to_fclk(u64 cycles) const +{ + return u64(m_q3_fclk_ratio * double(cycles) + 0.5); +} + +u64 iwm_device::fclk_to_q3(u64 cycles) const +{ + return u64(m_fclk_q3_ratio * double(cycles) + 0.5); +} + +void iwm_device::device_start() +{ + applefdintf_device::device_start(); + + m_timer = timer_alloc(); + save_item(NAME(m_last_sync)); + save_item(NAME(m_next_state_change)); + save_item(NAME(m_sync_update)); + save_item(NAME(m_async_update)); + save_item(NAME(m_flux_write_start)); + save_item(NAME(m_flux_write)); + save_item(NAME(m_flux_write_count)); + save_item(NAME(m_q3_clock)); + save_item(NAME(m_active)); + save_item(NAME(m_rw)); + save_item(NAME(m_rw_state)); + save_item(NAME(m_data)); + save_item(NAME(m_whd)); + save_item(NAME(m_mode)); + save_item(NAME(m_status)); + save_item(NAME(m_control)); + save_item(NAME(m_rsh)); + save_item(NAME(m_wsh)); +} + +void iwm_device::device_reset() +{ + applefdintf_device::device_reset(); + + m_floppy = nullptr; + m_last_sync = machine().time().as_ticks(clock()); + m_next_state_change = 0; + m_active = MODE_IDLE; + m_rw = MODE_IDLE; + m_rw_state = S_IDLE; + m_data = 0x00; + m_whd = 0xff; + m_mode = 0x00; + m_status = 0x00; + m_control = 0x00; + m_wsh = 0x00; + m_rsh = 0x00; + m_flux_write_start = 0; + m_flux_write_count = 0; + m_devsel_cb(1); +} + +void iwm_device::device_timer(emu_timer &, device_timer_id, int, void *) +{ + if(m_active == MODE_DELAY) { + m_active = MODE_IDLE; + if(m_floppy) + m_floppy->mon_w(true); + m_status &= ~0x20; + } +} + +void iwm_device::set_floppy(floppy_image_device *floppy) +{ + if(m_floppy == floppy) + return; + + sync(); + + if(m_floppy) + m_floppy->mon_w(true); + m_floppy = floppy; + if(m_active) + m_floppy->mon_w(false); + update_phases(); +} + +floppy_image_device *iwm_device::get_floppy() const +{ + return m_floppy; +} + +uint8_t iwm_device::read(offs_t offset) +{ + return control(offset, 0x00); +} + +void iwm_device::write(offs_t offset, u8 data) +{ + control(offset, data); +} + +void iwm_device::flush_write() +{ + if(m_floppy && m_last_sync > m_flux_write_start) { + if(m_flux_write_count && m_flux_write[m_flux_write_count-1] == m_last_sync) + m_flux_write_count--; + attotime start = cycles_to_time(m_flux_write_start); + attotime end = cycles_to_time(m_last_sync); + std::vector fluxes(m_flux_write_count); + for(u32 i=0; i != m_flux_write_count; i++) + 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_count = 0; + m_flux_write_start = m_last_sync; +} + +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); + else + m_phases &= ~(1 << (offset >> 1)); + update_phases(); + } else { + if(offset & 1) + m_control |= 1 << (offset >> 1); + else + m_control &= ~(1 << (offset >> 1)); + } + + changed ^= m_control | (m_phases & 0xf); + + if(changed & 0x20) + m_devsel_cb(m_control & 0x20 ? 2 : 1); + + if(changed & 0x10) { + if(m_control & 0x10) { + m_active = MODE_ACTIVE; + if(m_floppy) + m_floppy->mon_w(false); + m_status |= 0x20; + } else { + if(m_mode & 0x04) { + m_active = MODE_IDLE; + if(m_floppy) { + m_floppy->mon_w(true); + m_floppy->seek_phase_w(0); + } + m_status &= ~0x20; + } else { + m_active = MODE_DELAY; + m_timer->adjust(cycles_to_time(8388608)); + } + } + } + + if(changed & 0xd0) { + if((m_control & 0xc0) == 0x00 && m_active) { + if(m_rw == MODE_WRITE) + flush_write(); + 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 && (changed & 0xc0) == 0x40 && m_active && m_rw != MODE_WRITE) { + m_rw = MODE_WRITE; + m_rw_state = S_IDLE; + 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_rw = MODE_IDLE; + } + } else + m_rw = MODE_IDLE; + } + + if(changed || 1) { + u8 s = m_control & 0xc0; + const char *slot = "?"; + if(s == 0x00 && !m_active) + slot = "idle / ff"; + if(s == 0x00 && m_active) + slot = "read / read data"; + if(s == 0x40) + slot = "wp sense / read status"; + if(s == 0x80) + slot = "write / read whd"; + if(s == 0xc0 && !m_active) + slot = "mode set / write mode"; + if(s == 0xc0 && m_active) + slot = "write load / write data"; + + logerror("control %c%c %c%c %c%c%c%c (%s) [%s, %s]\n", + m_control & 0x80 ? '1' : '0', + m_control & 0x40 ? '1' : '0', + m_control & 0x20 ? 'b' : 'a', + m_control & 0x10 ? '#' : '.', + m_phases & 0x08 ? '#' : '.', + m_phases & 0x04 ? '#' : '.', + m_phases & 0x02 ? '#' : '.', + m_phases & 0x01 ? '#' : '.', + slot, + m_active == MODE_IDLE ? "idle" : m_active == MODE_DELAY ? "delay" : "active", + m_rw == MODE_IDLE ? "idle" : m_rw == MODE_READ ? "read" : "write"); + } + + if(m_active && !(m_control & 0xc0) && !is_sync() && (m_data & 0x80)) + m_async_update = m_last_sync + 14; + + switch(m_control & 0xc0) { + case 0x00: return m_active ? m_data : 0xff; + case 0x40: return m_status; + case 0x80: return m_whd; + case 0xc0: if(offset & 1) { if(m_active) data_w(data); else mode_w(data); } return 0xff; + } + + abort(); +} + +void iwm_device::mode_w(u8 data) +{ + m_mode = data; + m_status = (m_status & 0xe0) | (data & 0x1f); + logerror("mode %02x%s%s%s%s%s%s%s\n", m_mode, + m_mode & 0x80 ? " b7" : "", + m_mode & 0x40 ? " mz-reset" : "", + m_mode & 0x20 ? " test" : " normal", + m_mode & 0x10 ? " 8MHz" : " 7MHz", + m_mode & 0x08 ? " fast" : " slow", + m_mode & 0x04 ? "" : " timer", + m_mode & 0x02 ? " async" : " sync", + m_mode & 0x01 ? " latched" : ""); +} + +void iwm_device::data_w(u8 data) +{ + m_data = data; + if(is_sync() && m_rw == MODE_WRITE) + m_wsh = data; +} + +u64 iwm_device::time_to_cycles(const attotime &tm) const +{ + return tm.as_ticks(clock()); +} + +attotime iwm_device::cycles_to_time(u64 cycles) const +{ + return attotime::from_ticks(cycles, clock()); +} + +bool iwm_device::is_sync() const +{ + return m_mode & 0x02 ? false : true; +} + +u64 iwm_device::half_window_size() const +{ + switch(m_mode & 0x18) { + case 0x00: return 14; + case 0x08: return 7; + case 0x10: return 16; + case 0x18: return 8; + } + abort(); +} + +u64 iwm_device::window_size() const +{ + switch(m_mode & 0x18) { + case 0x00: return 28; + case 0x08: return 14; + case 0x10: return 36; + case 0x18: return 16; + } + abort(); +} + +u64 iwm_device::read_register_update_delay() const +{ + return m_mode & 0x08 ? 4 : 8; +} + +u64 iwm_device::write_sync_half_window_size() const +{ + return m_mode & 0x08 ? 2 : 4; +} + +void iwm_device::sync() +{ + if(!m_active) + return; + + u64 next_sync = machine().time().as_ticks(clock()); + switch(m_rw) { + case MODE_IDLE: + m_last_sync = next_sync; + break; + + case MODE_READ: { + u64 next_flux_change = 0; + while(next_sync > m_last_sync) { + if(next_flux_change <= m_last_sync) { + attotime flux = m_floppy ? m_floppy->get_next_transition(cycles_to_time(m_last_sync+1)) : attotime::never; + 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(next_sync < m_next_state_change) { + m_last_sync = next_sync; + break; + } + if(m_last_sync < m_next_state_change) + m_last_sync = m_next_state_change; + switch(m_rw_state) { + case S_IDLE: + m_rsh = 0x00; + m_rw_state = SR_WINDOW_EDGE_0; + m_next_state_change = m_last_sync + window_size(); + m_sync_update = 0; + m_async_update = 0; + break; + + case SR_WINDOW_EDGE_0: + case SR_WINDOW_EDGE_1: { + u64 endw = m_next_state_change + (m_rw_state == SR_WINDOW_EDGE_0 ? window_size() : half_window_size()); + if(m_rw_state == SR_WINDOW_EDGE_0 && endw >= next_flux_change && next_sync >= next_flux_change) { + m_last_sync = m_next_state_change = next_flux_change; + m_rw_state = SR_WINDOW_EDGE_1; + break; + } + if(next_sync < endw) { + m_last_sync = next_sync; + break; + } + m_rsh = (m_rsh << 1) | (m_rw_state == SR_WINDOW_EDGE_1 ? 1 : 0); + m_next_state_change = m_last_sync = endw; + m_rw_state = SR_WINDOW_EDGE_0; + if(is_sync()) { + if(m_rsh >= 0x80) { + m_data = m_rsh; + m_rsh = 0; + } else if(m_rsh >= 0x04) { + m_data = m_rsh; + m_sync_update = 0; + } else if(m_rsh >= 0x02) + m_sync_update = m_last_sync + read_register_update_delay(); + + } else if(m_rsh >= 0x80) { + m_data = m_rsh; + m_rsh = 0; + } + break; + } + } + } + if(m_sync_update && m_sync_update <= m_last_sync) { + if(is_sync()) + m_data = m_rsh; + m_sync_update = 0; + } + if(m_async_update && m_async_update <= m_last_sync) { + if(!is_sync()) { + m_data = 0; + } + m_async_update = 0; + } + break; + } + + case MODE_WRITE: { + while(next_sync > m_last_sync) { + if(next_sync < m_next_state_change) { + m_last_sync = next_sync; + break; + } + if(m_last_sync < m_next_state_change) + m_last_sync = m_next_state_change; + switch(m_rw_state) { + case S_IDLE: + m_wsh = m_data; + m_rw_state = SW_WINDOW_MIDDLE; + m_next_state_change = q3_to_fclk(fclk_to_q3(m_last_sync) + write_sync_half_window_size()); + m_flux_write_count = 0; + break; + + case SW_WINDOW_MIDDLE: + if(m_wsh & 0x80) + m_flux_write[m_flux_write_count++] = m_last_sync; + m_wsh <<= 1; + m_next_state_change = q3_to_fclk(fclk_to_q3(m_last_sync) + write_sync_half_window_size()); + + m_rw_state = SW_WINDOW_END; + break; + case SW_WINDOW_END: + if(m_flux_write_count == m_flux_write.size()) + flush_write(); + m_next_state_change = q3_to_fclk(fclk_to_q3(m_last_sync) + write_sync_half_window_size()); + m_rw_state = SW_WINDOW_MIDDLE; + break; + } + } + break; + } +} +} diff --git a/src/devices/machine/iwm.h b/src/devices/machine/iwm.h new file mode 100644 index 00000000000..6bb48f5043b --- /dev/null +++ b/src/devices/machine/iwm.h @@ -0,0 +1,88 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + Apple IWM floppy disk controller + +*********************************************************************/ + +#pragma once + +#ifndef MAME_MACHINE_IWM_H +#define MAME_MACHINE_IWM_H + +#include "applefdintf.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +class iwm_device: public applefdintf_device +{ +public: + // construction/destruction + iwm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t q3_clock = 0); + iwm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, XTAL q3_clock) : + iwm_device(mconfig, tag, owner, clock, q3_clock.value()) {} + + virtual u8 read(offs_t offset) override; + virtual void write(offs_t offset, u8 data) override; + + virtual void set_floppy(floppy_image_device *floppy) override; + virtual floppy_image_device *get_floppy() const override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + +private: + enum { + MODE_IDLE, + MODE_ACTIVE, MODE_DELAY, // m_active modes + MODE_READ, MODE_WRITE // m_rw modes + }; + + // state machine states + enum { + S_IDLE, + SR_WINDOW_EDGE_0, + SR_WINDOW_EDGE_1, + SW_WINDOW_MIDDLE, + SW_WINDOW_END + }; + + floppy_image_device *m_floppy; + emu_timer *m_timer; + double m_q3_fclk_ratio, m_fclk_q3_ratio; + u64 m_last_sync, m_next_state_change, m_sync_update, m_async_update; + u64 m_flux_write_start; + std::array m_flux_write; + u32 m_flux_write_count; + u32 m_q3_clock; + int m_active, m_rw, m_rw_state; + u8 m_data, m_whd, m_mode, m_status, m_control; + u8 m_rsh, m_wsh; + + void sync(); + u8 control(int offset, u8 data); + u64 time_to_cycles(const attotime &tm) const; + attotime cycles_to_time(u64 cycles) const; + u64 fclk_to_q3(u64 cycles) const; + u64 q3_to_fclk(u64 cycles) const; + + void mode_w(u8 data); + void data_w(u8 data); + + u64 window_size() const; + u64 half_window_size() const; + u64 read_register_update_delay() const; + u64 write_sync_half_window_size() const; + inline bool is_sync() const; + void flush_write(); +}; + +DECLARE_DEVICE_TYPE(IWM, iwm_device) + +#endif /* MAME_MACHINE_IWM_H */ diff --git a/src/devices/machine/swim1.cpp b/src/devices/machine/swim1.cpp new file mode 100644 index 00000000000..1af6cb60301 --- /dev/null +++ b/src/devices/machine/swim1.cpp @@ -0,0 +1,173 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + Implementation of the Apple SWIM1 floppy disk controller + +*********************************************************************/ + +#include "emu.h" +#include "swim1.h" + +DEFINE_DEVICE_TYPE(SWIM1, swim1_device, "swim1", "Apple SWIM1 (Sander/Wozniak Integrated Machine) version 1 floppy controller") + +swim1_device::swim1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + applefdintf_device(mconfig, SWIM1, tag, owner, clock) +{ +} + +void swim1_device::device_start() +{ + applefdintf_device::device_start(); + save_item(NAME(m_mode)); + save_item(NAME(m_setup)); + save_item(NAME(m_param_idx)); + save_item(NAME(m_param)); +} + +void swim1_device::device_reset() +{ + applefdintf_device::device_reset(); + m_mode = 0x40; + m_setup = 0x00; + m_param_idx = 0; + memset(m_param, 0, sizeof(m_param)); + m_floppy = nullptr; + + m_devsel_cb(0); + m_sel35_cb(true); + m_hdsel_cb(false); +} + +void swim1_device::device_timer(emu_timer &, device_timer_id, int, void *) +{ +} + +void swim1_device::set_floppy(floppy_image_device *floppy) +{ + if(m_floppy == floppy) + return; + + if(m_floppy) + m_floppy->mon_w(true); + m_floppy = floppy; + if(m_mode & 0x80) + m_floppy->mon_w(false); + update_phases(); +} + +floppy_image_device *swim1_device::get_floppy() const +{ + return m_floppy; +} + +void swim1_device::show_mode() const +{ + logerror("mode%s %s hdsel=%c %c%s %c%c%s\n", + m_mode & 0x80 ? " motoron" : "", + m_mode & 0x40 ? "ism" : "iwm", + m_mode & 0x20 ? '1' : '0', + m_mode & 0x10 ? 'w' : 'r', + m_mode & 0x08 ? " action" : "", + m_mode & 0x04 ? 'a' : '-', + m_mode & 0x02 ? 'b' : '-', + m_mode & 0x01 ? " clear" : ""); + +} + +u8 swim1_device::read(offs_t offset) +{ + static const char *const names[] = { + "?0", "?1", "?2", "?3", "?4", "?5", "?6", "?7", + "data", "mark", "crc", "param", "phases", "setup", "status", "handshake" + }; + switch(offset) { + case 0x3: case 0xb: { + u8 r = m_param[m_param_idx]; + m_param_idx = (m_param_idx + 1) & 15; + return r; + } + case 0x4: case 0xc: + return m_phases; + case 0x5: case 0xd: + return m_setup; + case 0xe: + return m_mode; + default: + logerror("read %s\n", names[offset & 15]); + break; + } + return 0xff; +} + +void swim1_device::write(offs_t offset, u8 data) +{ + machine().debug_break(); + static const char *const names[] = { + "data", "mark", "crc", "param", "phases", "setup", "mode0", "mode1", + "?8", "?9", "?a", "?b", "?c", "?d", "?e", "?f" + }; + switch(offset) { + case 0x3: case 0xb: { +#if 0 + static const char *const pname[16] = { + "minct", "mult", "ssl", "sss", "sll", "sls", "rpt", "csls", + "lsl", "lss", "lll", "lls", "late", "time0", "early", "time1" + }; +#endif + static const char *const pname[4] = { + "late", "time0", "early", "time1" + }; + logerror("param[%s] = %02x\n", pname[m_param_idx], data); + m_param[m_param_idx] = data; + m_param_idx = (m_param_idx + 1) & 3; + break; + } + case 0x4: { + m_phases = data; + update_phases(); + break; + } + + case 0x5: case 0xd: + m_setup = data; +#if 0 + logerror("setup timer=%s tsm=%s %s ecm=%s %s %s 3.5=%s %s\n", + m_setup & 0x80 ? "on" : "off", + m_setup & 0x40 ? "off" : "on", + m_setup & 0x20 ? "ibm" : "apple", + m_setup & 0x10 ? "on" : "off", + m_setup & 0x08 ? "fclk/2" : "fclk", + m_setup & 0x04 ? "gcr" : "mfm", + m_setup & 0x02 ? "off" : "on", + m_setup & 0x01 ? "hdsel" : "q3"); +#endif + logerror("setup timer=%s tsm=%s %s ecm=%s %s %s 3.5=%s %s\n", + m_setup & 0x80 ? "on" : "off", + m_setup & 0x40 ? "off" : "on", + m_setup & 0x20 ? "ibm" : "apple", + m_setup & 0x10 ? "on" : "off", + m_setup & 0x08 ? "fclk/2" : "fclk", + m_setup & 0x04 ? "gcr" : "mfm", + m_setup & 0x02 ? "off" : "on", + m_setup & 0x01 ? "hdsel" : "q3"); + break; + + case 0x6: + m_mode &= ~data; + m_mode |= 0x40; + m_param_idx = 0; + show_mode(); + break; + + case 0x7: + m_mode |= data; + show_mode(); + break; + + default: + logerror("write %s, %02x\n", names[offset], data); + break; + } +} + diff --git a/src/devices/machine/swim1.h b/src/devices/machine/swim1.h new file mode 100644 index 00000000000..ce47069516f --- /dev/null +++ b/src/devices/machine/swim1.h @@ -0,0 +1,48 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + Apple SWIM1 floppy disk controller + +*********************************************************************/ + +#pragma once + +#ifndef MAME_MACHINE_SWIM1_H +#define MAME_MACHINE_SWIM1_H + +#include "applefdintf.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +class swim1_device : public applefdintf_device +{ +public: + // construction/destruction + swim1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual u8 read(offs_t offset) override; + virtual void write(offs_t offset, u8 data) override; + + virtual void set_floppy(floppy_image_device *floppy) override; + virtual floppy_image_device *get_floppy() const override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + +private: + floppy_image_device *m_floppy; + u8 m_param[4]; + u8 m_mode, m_setup, m_param_idx; + + void show_mode() const; +}; + +DECLARE_DEVICE_TYPE(SWIM1, swim1_device) + +#endif /* MAME_MACHINE_SWIM1_H */ diff --git a/src/devices/machine/swim2.cpp b/src/devices/machine/swim2.cpp new file mode 100644 index 00000000000..165345d1523 --- /dev/null +++ b/src/devices/machine/swim2.cpp @@ -0,0 +1,175 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + Implementation of the Apple SWIM2 floppy disk controller + +*********************************************************************/ + +#include "emu.h" +#include "swim2.h" + +DEFINE_DEVICE_TYPE(SWIM2, swim2_device, "swim2", "Apple SWIM2 (Sander/Wozniak Integrated Machine) version 2 floppy controller") + +swim2_device::swim2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + applefdintf_device(mconfig, SWIM2, tag, owner, clock) +{ +} + +void swim2_device::device_start() +{ + applefdintf_device::device_start(); + + save_item(NAME(m_mode)); + save_item(NAME(m_setup)); + save_item(NAME(m_param_idx)); + save_item(NAME(m_param)); +} + +void swim2_device::device_reset() +{ + applefdintf_device::device_reset(); + + m_mode = 0x40; + m_setup = 0x00; + m_param_idx = 0; + memset(m_param, 0, sizeof(m_param)); + m_floppy = nullptr; + + m_devsel_cb(0); + m_sel35_cb(true); + m_hdsel_cb(false); +} + +void swim2_device::device_timer(emu_timer &, device_timer_id, int, void *) +{ +} + +void swim2_device::set_floppy(floppy_image_device *floppy) +{ + if(m_floppy == floppy) + return; + + if(m_floppy) + m_floppy->mon_w(true); + m_floppy = floppy; + if(m_mode & 0x80) + m_floppy->mon_w(false); + update_phases(); +} + +floppy_image_device *swim2_device::get_floppy() const +{ + return m_floppy; +} + +void swim2_device::show_mode() const +{ + logerror("mode%s %s hdsel=%c %c%s %c%c%s\n", + m_mode & 0x80 ? " motoron" : "", + m_mode & 0x40 ? "ism" : "iwm", + m_mode & 0x20 ? '1' : '0', + m_mode & 0x10 ? 'w' : 'r', + m_mode & 0x08 ? " action" : "", + m_mode & 0x04 ? 'a' : '-', + m_mode & 0x02 ? 'b' : '-', + m_mode & 0x01 ? " clear" : ""); + +} + +u8 swim2_device::read(offs_t offset) +{ + static const char *const names[] = { + "?0", "?1", "?2", "?3", "?4", "?5", "?6", "?7", + "data", "mark", "crc", "param", "phases", "setup", "status", "handshake" + }; + switch(offset) { + case 0x3: case 0xb: { + u8 r = m_param[m_param_idx]; + m_param_idx = (m_param_idx + 1) & 15; + return r; + } + case 0x4: case 0xc: + return m_phases; + case 0x5: case 0xd: + return m_setup; + case 0xe: + return m_mode; + default: + logerror("read %s\n", names[offset & 15]); + break; + } + return 0xff; +} + +void swim2_device::write(offs_t offset, u8 data) +{ + machine().debug_break(); + static const char *const names[] = { + "data", "mark", "crc", "param", "phases", "setup", "mode0", "mode1", + "?8", "?9", "?a", "?b", "?c", "?d", "?e", "?f" + }; + switch(offset) { + case 0x3: case 0xb: { +#if 0 + static const char *const pname[16] = { + "minct", "mult", "ssl", "sss", "sll", "sls", "rpt", "csls", + "lsl", "lss", "lll", "lls", "late", "time0", "early", "time1" + }; +#endif + static const char *const pname[4] = { + "late", "time0", "early", "time1" + }; + logerror("param[%s] = %02x\n", pname[m_param_idx], data); + m_param[m_param_idx] = data; + m_param_idx = (m_param_idx + 1) & 3; + break; + } + case 0x4: { + m_phases = data; + update_phases(); + break; + } + + case 0x5: case 0xd: + m_setup = data; +#if 0 + logerror("setup timer=%s tsm=%s %s ecm=%s %s %s 3.5=%s %s\n", + m_setup & 0x80 ? "on" : "off", + m_setup & 0x40 ? "off" : "on", + m_setup & 0x20 ? "ibm" : "apple", + m_setup & 0x10 ? "on" : "off", + m_setup & 0x08 ? "fclk/2" : "fclk", + m_setup & 0x04 ? "gcr" : "mfm", + m_setup & 0x02 ? "off" : "on", + m_setup & 0x01 ? "hdsel" : "q3"); +#endif + logerror("setup timer=%s tsm=%s %s ecm=%s %s %s 3.5=%s %s\n", + m_setup & 0x80 ? "on" : "off", + m_setup & 0x40 ? "off" : "on", + m_setup & 0x20 ? "ibm" : "apple", + m_setup & 0x10 ? "on" : "off", + m_setup & 0x08 ? "fclk/2" : "fclk", + m_setup & 0x04 ? "gcr" : "mfm", + m_setup & 0x02 ? "off" : "on", + m_setup & 0x01 ? "hdsel" : "q3"); + break; + + case 0x6: + m_mode &= ~data; + m_mode |= 0x40; + m_param_idx = 0; + show_mode(); + break; + + case 0x7: + m_mode |= data; + show_mode(); + break; + + default: + logerror("write %s, %02x\n", names[offset], data); + break; + } +} + diff --git a/src/devices/machine/swim2.h b/src/devices/machine/swim2.h new file mode 100644 index 00000000000..6a29a51356e --- /dev/null +++ b/src/devices/machine/swim2.h @@ -0,0 +1,48 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + Apple SWIM2 floppy disk controller + +*********************************************************************/ + +#pragma once + +#ifndef MAME_MACHINE_SWIM2_H +#define MAME_MACHINE_SWIM2_H + +#include "applefdintf.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +class swim2_device : public applefdintf_device +{ +public: + // construction/destruction + swim2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual u8 read(offs_t offset) override; + virtual void write(offs_t offset, u8 data) override; + + virtual void set_floppy(floppy_image_device *floppy) override; + virtual floppy_image_device *get_floppy() const override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + +private: + floppy_image_device *m_floppy; + u8 m_param[4]; + u8 m_mode, m_setup, m_param_idx; + + void show_mode() const; +}; + +DECLARE_DEVICE_TYPE(SWIM2, swim2_device) + +#endif /* MAME_MACHINE_SWIM2_H */ diff --git a/src/devices/machine/swim3.cpp b/src/devices/machine/swim3.cpp new file mode 100644 index 00000000000..9c836a0dc74 --- /dev/null +++ b/src/devices/machine/swim3.cpp @@ -0,0 +1,173 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + Implementation of the Apple SWIM3 floppy disk controller + +*********************************************************************/ + +#include "emu.h" +#include "swim3.h" + +DEFINE_DEVICE_TYPE(SWIM3, swim3_device, "swim3", "Apple SWIM3 (Sander/Wozniak Integrated Machine) version 3 floppy controller") + +swim3_device::swim3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + applefdintf_device(mconfig, SWIM3, tag, owner, clock) +{ +} + +void swim3_device::device_start() +{ + applefdintf_device::device_start(); + save_item(NAME(m_mode)); + save_item(NAME(m_setup)); + save_item(NAME(m_param_idx)); + save_item(NAME(m_param)); +} + +void swim3_device::device_reset() +{ + applefdintf_device::device_reset(); + m_mode = 0x40; + m_setup = 0x00; + m_param_idx = 0; + memset(m_param, 0, sizeof(m_param)); + m_floppy = nullptr; + + m_devsel_cb(0); + m_sel35_cb(true); + m_hdsel_cb(false); +} + +void swim3_device::device_timer(emu_timer &, device_timer_id, int, void *) +{ +} + +void swim3_device::set_floppy(floppy_image_device *floppy) +{ + if(m_floppy == floppy) + return; + + if(m_floppy) + m_floppy->mon_w(true); + m_floppy = floppy; + if(m_mode & 0x80) + m_floppy->mon_w(false); + update_phases(); +} + +floppy_image_device *swim3_device::get_floppy() const +{ + return m_floppy; +} + +void swim3_device::show_mode() const +{ + logerror("mode%s %s hdsel=%c %c%s %c%c%s\n", + m_mode & 0x80 ? " motoron" : "", + m_mode & 0x40 ? "ism" : "iwm", + m_mode & 0x20 ? '1' : '0', + m_mode & 0x10 ? 'w' : 'r', + m_mode & 0x08 ? " action" : "", + m_mode & 0x04 ? 'a' : '-', + m_mode & 0x02 ? 'b' : '-', + m_mode & 0x01 ? " clear" : ""); + +} + +u8 swim3_device::read(offs_t offset) +{ + static const char *const names[] = { + "?0", "?1", "?2", "?3", "?4", "?5", "?6", "?7", + "data", "mark", "crc", "param", "phases", "setup", "status", "handshake" + }; + switch(offset) { + case 0x3: case 0xb: { + u8 r = m_param[m_param_idx]; + m_param_idx = (m_param_idx + 1) & 15; + return r; + } + case 0x4: case 0xc: + return m_phases; + case 0x5: case 0xd: + return m_setup; + case 0xe: + return m_mode; + default: + logerror("read %s\n", names[offset & 15]); + break; + } + return 0xff; +} + +void swim3_device::write(offs_t offset, u8 data) +{ + machine().debug_break(); + static const char *const names[] = { + "data", "mark", "crc", "param", "phases", "setup", "mode0", "mode1", + "?8", "?9", "?a", "?b", "?c", "?d", "?e", "?f" + }; + switch(offset) { + case 0x3: case 0xb: { +#if 0 + static const char *const pname[16] = { + "minct", "mult", "ssl", "sss", "sll", "sls", "rpt", "csls", + "lsl", "lss", "lll", "lls", "late", "time0", "early", "time1" + }; +#endif + static const char *const pname[4] = { + "late", "time0", "early", "time1" + }; + logerror("param[%s] = %02x\n", pname[m_param_idx], data); + m_param[m_param_idx] = data; + m_param_idx = (m_param_idx + 1) & 3; + break; + } + case 0x4: { + m_phases = data; + update_phases(); + break; + } + + case 0x5: case 0xd: + m_setup = data; +#if 0 + logerror("setup timer=%s tsm=%s %s ecm=%s %s %s 3.5=%s %s\n", + m_setup & 0x80 ? "on" : "off", + m_setup & 0x40 ? "off" : "on", + m_setup & 0x20 ? "ibm" : "apple", + m_setup & 0x10 ? "on" : "off", + m_setup & 0x08 ? "fclk/2" : "fclk", + m_setup & 0x04 ? "gcr" : "mfm", + m_setup & 0x02 ? "off" : "on", + m_setup & 0x01 ? "hdsel" : "q3"); +#endif + logerror("setup timer=%s tsm=%s %s ecm=%s %s %s 3.5=%s %s\n", + m_setup & 0x80 ? "on" : "off", + m_setup & 0x40 ? "off" : "on", + m_setup & 0x20 ? "ibm" : "apple", + m_setup & 0x10 ? "on" : "off", + m_setup & 0x08 ? "fclk/2" : "fclk", + m_setup & 0x04 ? "gcr" : "mfm", + m_setup & 0x02 ? "off" : "on", + m_setup & 0x01 ? "hdsel" : "q3"); + break; + + case 0x6: + m_mode &= ~data; + m_mode |= 0x40; + m_param_idx = 0; + show_mode(); + break; + + case 0x7: + m_mode |= data; + show_mode(); + break; + + default: + logerror("write %s, %02x\n", names[offset], data); + break; + } +} + diff --git a/src/devices/machine/swim3.h b/src/devices/machine/swim3.h new file mode 100644 index 00000000000..076a612377c --- /dev/null +++ b/src/devices/machine/swim3.h @@ -0,0 +1,48 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + Apple SWIM3 floppy disk controller + +*********************************************************************/ + +#pragma once + +#ifndef MAME_MACHINE_SWIM3_H +#define MAME_MACHINE_SWIM3_H + +#include "applefdintf.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +class swim3_device : public applefdintf_device +{ +public: + // construction/destruction + swim3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual u8 read(offs_t offset) override; + virtual void write(offs_t offset, u8 data) override; + + virtual void set_floppy(floppy_image_device *floppy) override; + virtual floppy_image_device *get_floppy() const override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + +private: + floppy_image_device *m_floppy; + u8 m_param[4]; + u8 m_mode, m_setup, m_param_idx; + + void show_mode() const; +}; + +DECLARE_DEVICE_TYPE(SWIM3, swim3_device) + +#endif /* MAME_MACHINE_SWIM3_H */