summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/ss50/dc5.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/ss50/dc5.cpp')
-rw-r--r--src/devices/bus/ss50/dc5.cpp326
1 files changed, 207 insertions, 119 deletions
diff --git a/src/devices/bus/ss50/dc5.cpp b/src/devices/bus/ss50/dc5.cpp
index 52bf89a9976..2229e896add 100644
--- a/src/devices/bus/ss50/dc5.cpp
+++ b/src/devices/bus/ss50/dc5.cpp
@@ -31,7 +31,11 @@
#include "dc5.h"
#include "machine/wd_fdc.h"
#include "imagedev/floppy.h"
+#include "formats/cp68_dsk.h"
+#include "formats/fdos_dsk.h"
#include "formats/flex_dsk.h"
+#include "formats/os9_dsk.h"
+#include "formats/uniflex_dsk.h"
class ss50_dc5_device : public device_t, public ss50_card_interface
{
@@ -40,43 +44,46 @@ public:
: device_t(mconfig, SS50_DC5, tag, owner, clock)
, ss50_card_interface(mconfig, *this)
, m_fdc(*this, "fdc")
- , m_floppy0(*this, "fdc:0")
- , m_floppy1(*this, "fdc:1")
- , m_floppy2(*this, "fdc:2")
- , m_floppy3(*this, "fdc:3")
- , m_interrupt_select(*this, "interrupt_select")
- , m_address_mode(*this, "address_mode")
- , m_two_control_regs(*this, "two_control_regs")
- , m_ctrl_reg_bit7_side_select(*this, "ctrl_reg_bit7_side_select")
- , m_expected_clock(*this, "expected_clock")
- , m_expected_density(*this, "expected_density")
- , m_expected_sectors(*this, "expected_sectors")
- , m_track_zero_expected_sectors(*this, "track_zero_expected_sectors")
+ , m_floppy(*this, "fdc:%u", 0U)
+ , m_interrupt_select(*this, "INTERRUPT_SELECT")
+ , m_address_mode(*this, "ADDRESS_MODE")
+ , m_two_control_regs(*this, "TWO_CONTROL_REGS")
+ , m_force_ready(*this, "FORCE_READY")
+ , m_ctrl_reg_bit7_side_select(*this, "CTRL_REG_BIT7_SIDE_SELECT")
+ , m_expected_clock(*this, "EXPECTED_CLOCK")
+ , m_expected_density(*this, "EXPECTED_DENSITY")
+ , m_expected_sectors(*this, "EXPECTED_SECTORS")
+ , m_track_zero_expected_sectors(*this, "TRACK_ZERO_EXPECTED_SECTORS")
{
}
+ DECLARE_INPUT_CHANGED_MEMBER(force_ready_change);
+ DECLARE_INPUT_CHANGED_MEMBER(ctrl_reg_bit7_side_select_change);
+ DECLARE_INPUT_CHANGED_MEMBER(expected_clock_change);
+
protected:
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual uint8_t register_read(offs_t offset) override;
virtual void register_write(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_intrq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_sso_w );
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_sso_w(int state);
- DECLARE_FLOPPY_FORMATS(floppy_formats);
+ static void floppy_formats(format_registration &fr);
uint8_t m_fdc_status; // for floppy controller
uint8_t m_control_register;
uint8_t m_motor_timer_out;
emu_timer *m_floppy_motor_timer;
floppy_image_device *m_fdc_selected_floppy; // Current selected floppy.
- uint8_t m_fdc_side; // Current floppy side.
- uint32_t m_fdc_clock; // Current clock frequency.
+ uint8_t m_fdc_side; // Current floppy side.
+ uint8_t m_fdc_clock_div; // Current clock frequency divisor.
+ uint8_t m_fdc_prog_clock_div; // Programmed clock frequency divisor.
TIMER_CALLBACK_MEMBER(floppy_motor_callback);
@@ -88,13 +95,11 @@ private:
uint8_t validate_fdc_sector_size(uint8_t cmd);
required_device<wd2797_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
- required_device<floppy_connector> m_floppy2;
- required_device<floppy_connector> m_floppy3;
+ required_device_array<floppy_connector, 4> m_floppy;
required_ioport m_interrupt_select;
required_ioport m_address_mode;
required_ioport m_two_control_regs;
+ required_ioport m_force_ready;
required_ioport m_ctrl_reg_bit7_side_select;
required_ioport m_expected_clock;
required_ioport m_expected_density;
@@ -104,22 +109,33 @@ private:
static INPUT_PORTS_START( dc5 )
- PORT_START("interrupt_select")
- PORT_DIPNAME(0xf, 0, "Interrupt select")
+ PORT_START("INTERRUPT_SELECT")
+ PORT_DIPNAME(0x3, 0, "Interrupt select")
PORT_DIPSETTING(0, "N/C")
PORT_DIPSETTING(1, "IRQ")
PORT_DIPSETTING(2, "NMI/FIRQ")
- PORT_START("address_mode")
- PORT_DIPNAME(0xf, 1, "Address mode")
+ PORT_START("ADDRESS_MODE")
+ PORT_DIPNAME(0x1, 1, "Address mode")
PORT_DIPSETTING(0, "4 address")
PORT_DIPSETTING(1, "16 address")
- PORT_START("two_control_regs")
- PORT_DIPNAME(0xf, 0, "Two control registers")
+ PORT_START("TWO_CONTROL_REGS")
+ PORT_DIPNAME(0x1, 0, "Two control registers")
PORT_DIPSETTING(0, "No, DC4 compatible")
PORT_DIPSETTING(1, "Yes, DC5 extension")
+ // The DC5 has two modes for controlling the FDC 'ready' input. One
+ // mode forces the 'ready' line for a period triggered by the chip
+ // select, along with the motors. The other mode detects index pulses
+ // from the disk to control the 'ready' line. Flex2 for the 6800
+ // generally needs the 'ready' line forced and Flex9 can use the index
+ // pulse detection to determine if disks are present.
+ PORT_START("FORCE_READY")
+ PORT_CONFNAME(0x1, 0, "Force ready") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ss50_dc5_device::force_ready_change), 0)
+ PORT_CONFSETTING(0, DEF_STR(No))
+ PORT_CONFSETTING(1, DEF_STR(Yes))
+
// This config setting allows checking of the FDC clock rate and
// overriding it to assist driver development. The DC5 supports
// programming of the clock rate via the second control register, and
@@ -131,53 +147,57 @@ static INPUT_PORTS_START( dc5 )
// 3.5" 'standard' - 1.2MHz
// 3.5" HD - 2.0MHz
// 8" 360rpm - 2.4MHz
- PORT_START("expected_clock")
- PORT_CONFNAME(0xffffff, 0, "FDC expected clock rate")
+ PORT_START("EXPECTED_CLOCK")
+ PORT_CONFNAME(0xf, 0, "FDC expected clock rate") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ss50_dc5_device::expected_clock_change), 0)
PORT_CONFSETTING(0, "-")
- PORT_CONFSETTING(1000000, "1.0 MHz")
- PORT_CONFSETTING(1200000, "1.2 MHz")
- PORT_CONFSETTING(2000000, "2.0 MHz")
- PORT_CONFSETTING(2400000, "2.4 MHz")
+ PORT_CONFSETTING(12, "1.0 MHz")
+ PORT_CONFSETTING(10, "1.2 MHz")
+ PORT_CONFSETTING(6, "2.0 MHz")
+ PORT_CONFSETTING(5, "2.4 MHz")
// It is not uncommon to see drivers using bit 7 of the control
// register as a side selection. This conflicts with the DC5, and
// earlier controllers in this series, which use bit 7 to inhibit
// drive selection. These drivers need to be corrected, but this
// option helps identify this issue and work around it.
- PORT_START("ctrl_reg_bit7_side_select")
- PORT_CONFNAME(0x01, 0, "Control register bit 7")
+ PORT_START("CTRL_REG_BIT7_SIDE_SELECT")
+ PORT_CONFNAME(0x1, 0, "Control register bit 7") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(ss50_dc5_device::ctrl_reg_bit7_side_select_change), 0)
PORT_CONFSETTING(0, "Inhibits drive selection")
PORT_CONFSETTING(1, "Erroneous side select")
- // Debug aid to hard code the density. The FLEX format uses single
- // density for track zero. Many virtual disks 'fix' the format to be
- // purely double density and often without properly implement driver
- // support for that. This setting is an aid to report unexpected
- // usage, and it attempts to correct that.
- PORT_START("expected_density")
- PORT_CONFNAME(0xff, 0, "Expected density")
+ // Debug aid to hard code the density. The OS9 format can use single
+ // density for track zero head zero. The FLEX format can use single
+ // density for track zero on all heads, and many virtual disks 'fix'
+ // the format to be purely double density and often without properly
+ // implementing driver support for that. This setting is an aid to
+ // report unexpected usage, and it attempts to correct that.
+ PORT_START("EXPECTED_DENSITY")
+ PORT_CONFNAME(0x7, 0, "Expected density")
PORT_CONFSETTING(0, "-")
PORT_CONFSETTING(1, "single density") // Purely single density.
- PORT_CONFSETTING(2, "double density, with single density track zero") // The default FLEX double density format.
- PORT_CONFSETTING(3, "double density") // Purely double density.
+ PORT_CONFSETTING(2, "double density, with single density track zero head zero") // OS9 format
+ PORT_CONFSETTING(3, "double density, with single density track zero all heads") // The default FLEX double density format.
+ PORT_CONFSETTING(4, "double density") // Purely double density.
// Debug aid, to check that the sector head or side is set as expected
// for the sector ID being read for the FLEX floppy disk format. Many
// FLEX disk images were developed for vitural machines that have
- // little regard for the actual head and can work off the sector ID
- // and their drivers can set the head incorrectly. E.g. a disk with 18
- // sectors per side might have a drive set to switch heads for sectors
- // above 10. Another issue is that double density disk images are
- // often 'fixed' so that they are pure double density without being
- // single density onthe first track, and the drivers might still set
- // the head based track zero being single density. This aid is not
- // intended to be a substitute for fixing the drivers but it does help
- // work through the issues while patching the disks.
- PORT_START("expected_sectors")
- PORT_CONFNAME(0xff, 0, "Expected sectors per side")
+ // little regard for the actual number of heads and can work off the
+ // sector ID and their drivers can set the head incorrectly. E.g. a
+ // disk with 18 sectors per side might have a driver incorrectly switch
+ // heads for sectors above 10. Another issue is that double density
+ // disk images are often 'fixed' so that they are pure double density
+ // without being single density on the first track, and the drivers
+ // might still set the head based on track zero being single
+ // density. This aid is not intended to be a substitute for fixing the
+ // drivers but it does help work through the issues while patching the
+ // disks.
+ PORT_START("EXPECTED_SECTORS")
+ PORT_CONFNAME(0xff, 0, "FLEX expected sectors per side")
PORT_CONFSETTING(0, "-")
PORT_CONFSETTING(10, "10") // 5 1/4" single density 256B
PORT_CONFSETTING(15, "15") // 8" single density 256B
+ PORT_CONFSETTING(16, "16") // 5 1/4" double density 256B
PORT_CONFSETTING(18, "18") // 5 1/4" double density 256B
PORT_CONFSETTING(26, "26") // 8" double density 256B
PORT_CONFSETTING(36, "36") // 3.5" 1.4M QD 256B
@@ -185,11 +205,12 @@ static INPUT_PORTS_START( dc5 )
// 6800 disks did format track zero in single density and if the
// driver sticks to that and if using a double density disk then set a
// single density size here.
- PORT_START("track_zero_expected_sectors")
- PORT_CONFNAME(0xff, 0, "Track zero expected sectors per side")
+ PORT_START("TRACK_ZERO_EXPECTED_SECTORS")
+ PORT_CONFNAME(0xff, 0, "FLEX track zero expected sectors per side")
PORT_CONFSETTING(0, "-")
PORT_CONFSETTING(10, "10") // 5 1/4" single density 256B
PORT_CONFSETTING(15, "15") // 8" single density 256B
+ PORT_CONFSETTING(16, "16") // 5 1/4" double density 256B
PORT_CONFSETTING(18, "18") // 5 1/4" double density 256B
PORT_CONFSETTING(26, "26") // 8" double density 256B
PORT_CONFSETTING(36, "36") // 3.5" 1.4M QD 256B
@@ -211,11 +232,16 @@ ioport_constructor ss50_dc5_device::device_input_ports() const
// machine configuration
//-------------------------------------------------
-FLOPPY_FORMATS_MEMBER( ss50_dc5_device::floppy_formats )
- FLOPPY_FLEX_FORMAT
-FLOPPY_FORMATS_END
+void ss50_dc5_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_FLEX_FORMAT);
+ fr.add(FLOPPY_CP68_FORMAT);
+ fr.add(FLOPPY_FDOS_FORMAT);
+ fr.add(FLOPPY_OS9_FORMAT);
+ fr.add(FLOPPY_UNIFLEX_FORMAT);
+}
-// todo: implement floppy controller cards as slot devices and do this properly
static void flex_floppies(device_slot_interface &device)
{
device.option_add("sssd35", FLOPPY_525_SSSD_35T); // 35 trks ss sd 5.25
@@ -235,11 +261,9 @@ static void flex_floppies(device_slot_interface &device)
void ss50_dc5_device::device_add_mconfig(machine_config &config)
{
- WD2797(config, m_fdc, 1_MHz_XTAL);
- FLOPPY_CONNECTOR(config, "fdc:0", flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:1", flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:2", flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:3", flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
+ WD2797(config, m_fdc, 12_MHz_XTAL / 12); // divider is selectable
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
m_fdc->intrq_wr_callback().set(FUNC(ss50_dc5_device::fdc_intrq_w));
m_fdc->drq_wr_callback().set(FUNC(ss50_dc5_device::fdc_drq_w));
@@ -249,10 +273,11 @@ void ss50_dc5_device::device_add_mconfig(machine_config &config)
void ss50_dc5_device::device_reset()
{
// Initialize to the expected rate if any, otherwise to 1MHz.
- uint32_t clock = m_expected_clock->read();
- clock = clock ? clock : 1000000;
- m_fdc->set_unscaled_clock(clock);
- m_fdc_clock = clock;
+ m_fdc_prog_clock_div = 12;
+ uint8_t expected_clock_div = m_expected_clock->read();
+ uint8_t clock_div = expected_clock_div ? expected_clock_div : m_fdc_prog_clock_div;
+ m_fdc->set_unscaled_clock(12_MHz_XTAL / clock_div);
+ m_fdc_clock_div = clock_div;
// The reset state of DDEN for the DC5 is one, so selecting single density.
m_fdc->dden_w(1);
@@ -263,11 +288,37 @@ void ss50_dc5_device::device_start()
m_fdc_status = 0;
m_control_register = 0;
m_fdc_side = 0;
- m_floppy_motor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ss50_dc5_device::floppy_motor_callback),this));
+ m_floppy_motor_timer = timer_alloc(FUNC(ss50_dc5_device::floppy_motor_callback), this);
m_motor_timer_out = 0;
+ m_fdc->set_force_ready(0);
+ m_fdc_prog_clock_div = 12;
+
+ save_item(NAME(m_fdc_status));
+ save_item(NAME(m_control_register));
+ save_item(NAME(m_motor_timer_out));
+ save_item(NAME(m_fdc_side));
+ save_item(NAME(m_fdc_clock_div));
+ save_item(NAME(m_fdc_prog_clock_div));
}
+INPUT_CHANGED_MEMBER(ss50_dc5_device::force_ready_change)
+{
+ control_register_update();
+}
+
+INPUT_CHANGED_MEMBER(ss50_dc5_device::ctrl_reg_bit7_side_select_change)
+{
+ control_register_update();
+}
+
+INPUT_CHANGED_MEMBER(ss50_dc5_device::expected_clock_change)
+{
+ uint8_t clock_div = newval ? newval : m_fdc_prog_clock_div;
+ m_fdc->set_unscaled_clock(12_MHz_XTAL / clock_div);
+ m_fdc_clock_div = clock_div;
+}
+
/* Shared floppy support. */
void ss50_dc5_device::floppy_motor_trigger()
@@ -309,7 +360,7 @@ void ss50_dc5_device::validate_floppy_side(uint8_t cmd)
if (m_fdc_side != expected_side)
{
- logerror("%s Unexpected size %d for track %d sector %d expected side %d\n", machine().describe_context(), m_fdc_side, track, sector, expected_side);
+ logerror("%s Unexpected side %d for track %d sector %d expected side %d\n", machine().describe_context(), m_fdc_side, track, sector, expected_side);
if (m_fdc_selected_floppy)
{
m_fdc_selected_floppy->ss_w(expected_side);
@@ -317,8 +368,7 @@ void ss50_dc5_device::validate_floppy_side(uint8_t cmd)
}
}
}
-
- if (expected_sectors)
+ else if (expected_sectors)
{
uint8_t expected_side = sector > expected_sectors ? 1 : 0;
@@ -348,17 +398,17 @@ uint8_t ss50_dc5_device::validate_fdc_dden(uint8_t dden)
return 1;
case 2:
{
- // Double density with track zero single density.
+ // Double density with track zero head zero single density.
uint8_t track = m_fdc->track_r();
- if (track == 0)
+ if (track == 0 && m_fdc_side == 0)
{
- // If this path is call on an update of the
+ // If this path is called on an update of the
// second control register then the track need
// not be accurate so this message might not
// be accurate.
if (!dden)
- logerror("%s Unexpected DDEN %d for single density trak 0\n", machine().describe_context(), dden);
+ logerror("%s Unexpected DDEN %d for single density track 0 head 0\n", machine().describe_context(), dden);
return 1;
}
if (dden)
@@ -366,6 +416,25 @@ uint8_t ss50_dc5_device::validate_fdc_dden(uint8_t dden)
return 0;
}
case 3:
+ {
+ // Double density with track zero all heads single density.
+ uint8_t track = m_fdc->track_r();
+
+ if (track == 0)
+ {
+ // If this path is called on an update of the
+ // second control register then the track need
+ // not be accurate so this message might not
+ // be accurate.
+ if (!dden)
+ logerror("%s Unexpected DDEN %d for single density track 0\n", machine().describe_context(), dden);
+ return 1;
+ }
+ if (dden)
+ logerror("%s Unexpected DDEN %d for double density\n", machine().describe_context(), dden);
+ return 0;
+ }
+ case 4:
// Pure double density.
if (dden)
logerror("%s Unexpected DDEN %d for double density\n", machine().describe_context(), dden);
@@ -384,7 +453,7 @@ uint8_t ss50_dc5_device::validate_fdc_sso(uint8_t cmd)
uint32_t two_regs = m_two_control_regs->read();
if (two_regs)
{
- // How if drivers are attempting to use SSO to control the
+ // If drivers are attempting to use SSO to control the
// density then that might need correcting so report such
// usage.
logerror("%s Unexpected SSO flag set in two control registers mode\n", machine().describe_context());
@@ -426,7 +495,7 @@ uint8_t ss50_dc5_device::validate_fdc_sector_size(uint8_t cmd)
return cmd;
}
-WRITE_LINE_MEMBER( ss50_dc5_device::fdc_intrq_w )
+void ss50_dc5_device::fdc_intrq_w(int state)
{
if (state)
m_fdc_status |= 0x40;
@@ -436,16 +505,12 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_intrq_w )
uint8_t selection = m_interrupt_select->read();
if (selection == 1)
- {
write_irq(state);
- }
else if (selection == 2)
- {
write_firq(state);
- }
}
-WRITE_LINE_MEMBER( ss50_dc5_device::fdc_drq_w )
+void ss50_dc5_device::fdc_drq_w(int state)
{
if (state)
m_fdc_status |= 0x80;
@@ -453,7 +518,7 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_drq_w )
m_fdc_status &= 0x7f;
}
-WRITE_LINE_MEMBER( ss50_dc5_device::fdc_sso_w )
+void ss50_dc5_device::fdc_sso_w(int state)
{
// The DC4 and DC5 invert the SSO output and wire it to the DDEN input
// to allow selection of single or double density.
@@ -477,13 +542,13 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_sso_w )
break;
case 2:
{
- // Double density with track zero single density.
+ // Double density with track zero head zero single density.
uint8_t track = m_fdc->track_r();
- if (track == 0)
+ if (track == 0 && m_fdc_side == 0)
{
if (state)
- logerror("Unexpected SSO %d for single density trak 0\n", state);
+ logerror("Unexpected SSO %d for single density track 0 head 0\n", state);
m_fdc->dden_w(1);
}
else
@@ -495,6 +560,25 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_sso_w )
break;
}
case 3:
+ {
+ // Double density with track zero all heads single density.
+ uint8_t track = m_fdc->track_r();
+
+ if (track == 0)
+ {
+ if (state)
+ logerror("Unexpected SSO %d for single density track 0\n", state);
+ m_fdc->dden_w(1);
+ }
+ else
+ {
+ if (!state)
+ logerror("Unexpected SSO %d for double density\n", state);
+ m_fdc->dden_w(0);
+ }
+ break;
+ }
+ case 4:
// Pure double density.
if (!state)
logerror("Unexpected SSO %d for double density\n", state);
@@ -513,10 +597,12 @@ void ss50_dc5_device::control_register_update()
// The floppy drives do not gate the motor based on the select input,
// so the motors run, or not, irrespective of the drive selection.
uint8_t motor = m_motor_timer_out ? CLEAR_LINE : ASSERT_LINE;
- m_floppy0->get_device()->mon_w(motor);
- m_floppy1->get_device()->mon_w(motor);
- m_floppy2->get_device()->mon_w(motor);
- m_floppy3->get_device()->mon_w(motor);
+ for (auto &floppy : m_floppy)
+ {
+ floppy_image_device *fd = floppy->get_device();
+ if (fd)
+ fd->mon_w(motor);
+ }
// The DC2, DC3, DC4, DC5 have a drive inhibit feature controlled by
// bit 7, and the drives are de-selected if the motor timer has timed
@@ -530,13 +616,7 @@ void ss50_dc5_device::control_register_update()
floppy_image_device *floppy = nullptr;
if ((bit7_side_select || !inhibit) && m_motor_timer_out)
- {
- uint8_t drive = m_control_register & 3;
- if (drive == 0) floppy = m_floppy0->get_device();
- if (drive == 1) floppy = m_floppy1->get_device();
- if (drive == 2) floppy = m_floppy2->get_device();
- if (drive == 3) floppy = m_floppy3->get_device();
- }
+ floppy = m_floppy[m_control_register & 3]->get_device();
if (floppy != m_fdc_selected_floppy)
{
@@ -560,13 +640,17 @@ void ss50_dc5_device::control_register_update()
// the most useful choice because drivers in error are
// most likely just writing to the wrong bit rather
// than inconsistently to both bits. This allows
- // incremental correction of driver while spotting
+ // incremental correction of drivers while spotting
// remaining uses of bit 7 for side selection.
side |= bit7;
}
floppy->ss_w(side);
m_fdc_side = side;
}
+
+ // Force the FDC 'ready' line on if the motor line is asserted, but
+ // only when this forced mode is enabled.
+ m_fdc->set_force_ready(m_motor_timer_out && m_force_ready->read());
}
@@ -594,7 +678,7 @@ uint8_t ss50_dc5_device::register_read(offs_t offset)
uint32_t two_regs = m_two_control_regs->read();
// Note: access to this control register does not trigger the
- // motor on and and does not reset the motor timer.
+ // motor on and does not reset the motor timer.
if (!two_regs || (offset & 2) == 0)
{
@@ -661,7 +745,7 @@ void ss50_dc5_device::register_write(offs_t offset, uint8_t data)
// Osc20 and osc12 control a clock divider.
uint8_t osc12 = BIT(data, 2);
uint8_t osc20 = BIT(data, 3);
- uint32_t clock = 1000000;
+ uint8_t clock_div = 12;
// Note: supporting 2.4MHz is here is an extension to
// the published DC5 design, and appears necessary to
@@ -676,24 +760,28 @@ void ss50_dc5_device::register_write(offs_t offset, uint8_t data)
// 8" drives run at 300rpm; is there an error in the
// rates elsewhere?
if (osc20 && osc12)
- clock = 2400000;
+ clock_div = 5;
else if (osc20)
- clock = 2000000;
+ clock_div = 6;
else if (osc12)
- clock = 1200000;
+ clock_div = 10;
+
+ // Note the programmed clock divisor, in case the
+ // expected changes.
+ m_fdc_prog_clock_div = clock_div;
- // Compare to the expected clock rate if any.
- uint32_t expected_clock = m_expected_clock->read();
- if (expected_clock && clock != expected_clock)
+ // Compare to the expected clock divisor if any.
+ uint32_t expected_clock_div = m_expected_clock->read();
+ if (expected_clock_div && clock_div != expected_clock_div)
{
- logerror("%s Unexpected clock rate of %dHz expected %dHz.\n", machine().describe_context(), clock, expected_clock);
- clock = expected_clock;
+ logerror("%s Unexpected clock rate of %dHz expected %dHz.\n", machine().describe_context(), 12'000'000 / clock_div, 12'000'000 / expected_clock_div);
+ clock_div = expected_clock_div;
}
- if (clock != m_fdc_clock)
+ if (clock_div != m_fdc_clock_div)
{
- m_fdc->set_unscaled_clock(clock);
- m_fdc_clock = clock;
+ m_fdc->set_unscaled_clock(12_MHz_XTAL / clock_div);
+ m_fdc_clock_div = clock_div;
}
#if 0