wd_fdc: Add a MON callback so that drives, which are unselected early, do not spin forever.

This commit is contained in:
Michael Zapf 2020-03-20 00:56:15 +01:00
parent 207da844b8
commit f62ad5e394
4 changed files with 86 additions and 60 deletions

View File

@ -4,21 +4,19 @@
Myarc Floppy Disk Controller (DDCC-1) Myarc Floppy Disk Controller (DDCC-1)
Double Density, Double-sided Double Density, Double-sided
May be used with a 1770 or 1772 controller May be used with a 1770 or 1772 controller
EPROM 2764A (8Kx8) in two banks (2x 4000-4fff) EPROM 2764A (8Kx8) in two banks (2x 4000-4fff)
SRAM HM6116 (2Kx8) (5000-57ff) SRAM HM6116 (2Kx8) (5000-57ff)
DIP switches (SW1) set the head step rate. For the 1770 controller, closed DIP switches (SW1) set the head step rate. For the 1770 controller, closed
switches mean 20ms, open switches mean 6ms. For the 1772 controller, closed switches mean 20ms, open switches mean 6ms. For the 1772 controller, closed
means 2ms, open means 6 ms. There is an alternative ROM for the 1772 which means 2ms, open means 6 ms. There is an alternative ROM for the 1772 which
allows for slower step rates (6ms-12ms). allows for slower step rates (6ms-12ms).
Another switch is included (SW2) labeled "Turbo" on schematics, but which Another switch is included (SW2) labeled "Turbo" on schematics, but which
is not present on all boards. It may require a different ROM. is not present on all boards. It may require a different ROM.
Known issue: On error, the drive may continue spinning. Michael Zapf
Michael Zapf
March 2020 March 2020
*******************************************************************************/ *******************************************************************************/
@ -63,13 +61,13 @@ myarc_fdc_device::myarc_fdc_device(const machine_config &mconfig, const char *ta
m_wd1770(*this, WD1770_TAG), m_wd1770(*this, WD1770_TAG),
m_wd1772(*this, WD1772_TAG), m_wd1772(*this, WD1772_TAG),
m_drivelatch(*this, LATCH_TAG), m_drivelatch(*this, LATCH_TAG),
m_buffer_ram(*this, BUFFER_TAG), m_buffer_ram(*this, BUFFER_TAG),
m_pal(*this, PAL_TAG), m_pal(*this, PAL_TAG),
m_dsrrom(nullptr), m_dsrrom(nullptr),
m_banksel(false), m_banksel(false),
m_cardsel(false), m_cardsel(false),
m_selected_drive(0), m_selected_drive(0),
m_address(0) m_address(0)
{ } { }
SETADDRESS_DBIN_MEMBER( myarc_fdc_device::setaddress_dbin ) SETADDRESS_DBIN_MEMBER( myarc_fdc_device::setaddress_dbin )
@ -84,7 +82,7 @@ bool myarc_fdc_device::card_selected()
return m_cardsel; return m_cardsel;
} }
/* /*
Provides the current address to the PAL. Provides the current address to the PAL.
*/ */
uint16_t myarc_fdc_device::get_address() uint16_t myarc_fdc_device::get_address()
{ {
@ -92,7 +90,7 @@ uint16_t myarc_fdc_device::get_address()
} }
/* /*
Debugger access. Debugger access.
*/ */
void myarc_fdc_device::debug_read(offs_t offset, uint8_t* value) void myarc_fdc_device::debug_read(offs_t offset, uint8_t* value)
{ {
@ -102,7 +100,7 @@ void myarc_fdc_device::debug_read(offs_t offset, uint8_t* value)
{ {
*value = m_buffer_ram->pointer()[m_address & 0x07ff]; *value = m_buffer_ram->pointer()[m_address & 0x07ff];
} }
if (m_pal->romen()) if (m_pal->romen())
{ {
// EPROM selected // EPROM selected
@ -113,7 +111,7 @@ void myarc_fdc_device::debug_read(offs_t offset, uint8_t* value)
} }
/* /*
Debugger access. Debugger access.
*/ */
void myarc_fdc_device::debug_write(offs_t offset, uint8_t data) void myarc_fdc_device::debug_write(offs_t offset, uint8_t data)
{ {
@ -127,7 +125,7 @@ void myarc_fdc_device::debug_write(offs_t offset, uint8_t data)
} }
/* /*
Read access to the RAM, EPROM, and controller chip. Read access to the RAM, EPROM, and controller chip.
*/ */
READ8Z_MEMBER(myarc_fdc_device::readz) READ8Z_MEMBER(myarc_fdc_device::readz)
{ {
@ -136,38 +134,38 @@ READ8Z_MEMBER(myarc_fdc_device::readz)
debug_read(offset, value); debug_read(offset, value);
return; return;
} }
if (m_pal->ramsel()) if (m_pal->ramsel())
{ {
// SRAM selected // SRAM selected
*value = m_buffer_ram->pointer()[m_address & 0x07ff]; *value = m_buffer_ram->pointer()[m_address & 0x07ff];
LOGMASKED(LOG_RAM, "Read RAM: %04x -> %02x\n", m_address & 0xffff, *value); LOGMASKED(LOG_RAM, "Read RAM: %04x -> %02x\n", m_address & 0xffff, *value);
} }
if (m_pal->romen()) if (m_pal->romen())
{ {
// EPROM selected // EPROM selected
uint16_t base = m_banksel? 0x1000 : 0; uint16_t base = m_banksel? 0x1000 : 0;
uint8_t* rom = &m_dsrrom[base | (m_address & 0x0fff)]; uint8_t* rom = &m_dsrrom[base | (m_address & 0x0fff)];
*value = *rom; *value = *rom;
if (WORD_ALIGNED(m_address)) if (WORD_ALIGNED(m_address))
{ {
uint16_t val = (*rom << 8) | (*(rom+1)); uint16_t val = (*rom << 8) | (*(rom+1));
LOGMASKED(LOG_EPROM, "Read DSR: %04x (page %d)-> %04x\n", m_address & 0xffff, base>>12, val); LOGMASKED(LOG_EPROM, "Read DSR: %04x (page %d)-> %04x\n", m_address & 0xffff, base>>12, val);
} }
} }
if (m_pal->fdcsel()) if (m_pal->fdcsel())
{ {
// WDC selected // WDC selected
*value = m_wdc->read((m_address >> 1)&0x03); *value = m_wdc->read((m_address >> 1)&0x03);
LOGMASKED(LOG_CONTR, "Read FDC: %04x -> %02x\n", m_address & 0xffff, *value); LOGMASKED(LOG_CONTR, "Read FDC: %04x -> %02x\n", m_address & 0xffff, *value);
} }
} }
/* /*
Write access to RAM and the controller chip. Write access to RAM and the controller chip.
*/ */
void myarc_fdc_device::write(offs_t offset, uint8_t data) void myarc_fdc_device::write(offs_t offset, uint8_t data)
{ {
@ -176,14 +174,14 @@ void myarc_fdc_device::write(offs_t offset, uint8_t data)
debug_write(offset, data); debug_write(offset, data);
return; return;
} }
if (m_pal->ramsel()) if (m_pal->ramsel())
{ {
// SRAM selected // SRAM selected
LOGMASKED(LOG_RAM, "Write RAM: %04x <- %02x\n", m_address & 0xffff, data); LOGMASKED(LOG_RAM, "Write RAM: %04x <- %02x\n", m_address & 0xffff, data);
m_buffer_ram->pointer()[m_address & 0x07ff] = data; m_buffer_ram->pointer()[m_address & 0x07ff] = data;
} }
if (m_pal->fdcsel()) if (m_pal->fdcsel())
{ {
// WDC selected // WDC selected
@ -193,7 +191,7 @@ void myarc_fdc_device::write(offs_t offset, uint8_t data)
} }
/* /*
CRU read access to the LS251 multiplexer. CRU read access to the LS251 multiplexer.
*/ */
READ8Z_MEMBER( myarc_fdc_device::crureadz ) READ8Z_MEMBER( myarc_fdc_device::crureadz )
{ {
@ -227,7 +225,7 @@ READ8Z_MEMBER( myarc_fdc_device::crureadz )
} }
/* /*
CRU write access to the LS259 latch. CRU write access to the LS259 latch.
*/ */
void myarc_fdc_device::cruwrite(offs_t offset, uint8_t data) void myarc_fdc_device::cruwrite(offs_t offset, uint8_t data)
{ {
@ -243,7 +241,7 @@ void myarc_fdc_device::cruwrite(offs_t offset, uint8_t data)
} }
/* /*
Callbacks from the WDC chip Callbacks from the WDC chip
*/ */
WRITE_LINE_MEMBER( myarc_fdc_device::fdc_irq_w ) WRITE_LINE_MEMBER( myarc_fdc_device::fdc_irq_w )
{ {
@ -255,8 +253,19 @@ WRITE_LINE_MEMBER( myarc_fdc_device::fdc_drq_w )
LOGMASKED(LOG_DRQ, "DRQ callback = %d\n", state); LOGMASKED(LOG_DRQ, "DRQ callback = %d\n", state);
} }
WRITE_LINE_MEMBER( myarc_fdc_device::fdc_mon_w )
{
LOGMASKED(LOG_DRIVE, "MON callback = %d\n", state);
// All MON lines are connected
// Do not start the motors when no drive is selected. However, motors
// can always be stopped.
if (m_selected_drive != 0 || state==1)
for (int i=0; i < 3; i++)
if (m_floppy[i] != nullptr) m_floppy[i]->mon_w(state);
}
/* /*
Callbacks from the 74LS259 latch Callbacks from the 74LS259 latch
*/ */
WRITE_LINE_MEMBER( myarc_fdc_device::den_w ) WRITE_LINE_MEMBER( myarc_fdc_device::den_w )
{ {
@ -277,7 +286,7 @@ WRITE_LINE_MEMBER( myarc_fdc_device::sidsel_w )
{ {
LOGMASKED(LOG_DRIVE, "Set side = %d on DSK%d\n", state, m_selected_drive); LOGMASKED(LOG_DRIVE, "Set side = %d on DSK%d\n", state, m_selected_drive);
m_floppy[m_selected_drive-1]->ss_w(state); m_floppy[m_selected_drive-1]->ss_w(state);
} }
} }
// Selects the EPROM bank, and also controls the DDEN line // Selects the EPROM bank, and also controls the DDEN line
@ -291,13 +300,13 @@ WRITE_LINE_MEMBER( myarc_fdc_device::bankdden_w )
WRITE_LINE_MEMBER( myarc_fdc_device::drivesel_w ) WRITE_LINE_MEMBER( myarc_fdc_device::drivesel_w )
{ {
int driveno = 0; int driveno = 0;
// We do not know what happens when two drives are selected // We do not know what happens when two drives are selected
if (m_drivelatch->q7_r() != 0) driveno = 4; if (m_drivelatch->q7_r() != 0) driveno = 4;
if (m_drivelatch->q6_r() != 0) driveno = 3; if (m_drivelatch->q6_r() != 0) driveno = 3;
if (m_drivelatch->q5_r() != 0) driveno = 2; if (m_drivelatch->q5_r() != 0) driveno = 2;
if (m_drivelatch->q4_r() != 0) driveno = 1; if (m_drivelatch->q4_r() != 0) driveno = 1;
if (state == CLEAR_LINE) if (state == CLEAR_LINE)
{ {
// Only when no bit is set, unselect all drives. // Only when no bit is set, unselect all drives.
@ -322,7 +331,6 @@ WRITE_LINE_MEMBER( myarc_fdc_device::drivesel_w )
} }
} }
void myarc_fdc_device::device_start() void myarc_fdc_device::device_start()
{ {
m_dsrrom = memregion(TI99_DSRROM)->base(); m_dsrrom = memregion(TI99_DSRROM)->base();
@ -397,15 +405,20 @@ ROM_END
void myarc_fdc_device::device_add_mconfig(machine_config& config) void myarc_fdc_device::device_add_mconfig(machine_config& config)
{ {
// Cards appeared with one of those controllers // Cards appeared with one of those controllers
WD1770(config, m_wd1770, 8_MHz_XTAL); WD1770(config, m_wd1770, 8_MHz_XTAL);
WD1772(config, m_wd1772, 8_MHz_XTAL); WD1772(config, m_wd1772, 8_MHz_XTAL);
m_wd1770->intrq_wr_callback().set(FUNC(myarc_fdc_device::fdc_irq_w)); m_wd1770->intrq_wr_callback().set(FUNC(myarc_fdc_device::fdc_irq_w));
m_wd1770->drq_wr_callback().set(FUNC(myarc_fdc_device::fdc_drq_w)); m_wd1770->drq_wr_callback().set(FUNC(myarc_fdc_device::fdc_drq_w));
m_wd1770->mon_wr_callback().set(FUNC(myarc_fdc_device::fdc_mon_w));
m_wd1770->set_disable_motor_control(true);
m_wd1772->intrq_wr_callback().set(FUNC(myarc_fdc_device::fdc_irq_w)); m_wd1772->intrq_wr_callback().set(FUNC(myarc_fdc_device::fdc_irq_w));
m_wd1772->drq_wr_callback().set(FUNC(myarc_fdc_device::fdc_drq_w)); m_wd1772->drq_wr_callback().set(FUNC(myarc_fdc_device::fdc_drq_w));
m_wd1772->mon_wr_callback().set(FUNC(myarc_fdc_device::fdc_mon_w));
m_wd1772->set_disable_motor_control(true);
LS259(config, m_drivelatch); // U10 LS259(config, m_drivelatch); // U10
m_drivelatch->q_out_cb<0>().set(FUNC(myarc_fdc_device::den_w)); m_drivelatch->q_out_cb<0>().set(FUNC(myarc_fdc_device::den_w));
m_drivelatch->q_out_cb<1>().set(FUNC(myarc_fdc_device::wdreset_w)); m_drivelatch->q_out_cb<1>().set(FUNC(myarc_fdc_device::wdreset_w));
@ -415,13 +428,13 @@ void myarc_fdc_device::device_add_mconfig(machine_config& config)
m_drivelatch->q_out_cb<5>().set(FUNC(myarc_fdc_device::drivesel_w)); m_drivelatch->q_out_cb<5>().set(FUNC(myarc_fdc_device::drivesel_w));
m_drivelatch->q_out_cb<6>().set(FUNC(myarc_fdc_device::drivesel_w)); m_drivelatch->q_out_cb<6>().set(FUNC(myarc_fdc_device::drivesel_w));
m_drivelatch->q_out_cb<7>().set(FUNC(myarc_fdc_device::drivesel_w)); m_drivelatch->q_out_cb<7>().set(FUNC(myarc_fdc_device::drivesel_w));
// SRAM 6114 2Kx8 // SRAM 6114 2Kx8
RAM(config, BUFFER_TAG).set_default_size("2k").set_default_value(0); RAM(config, BUFFER_TAG).set_default_size("2k").set_default_value(0);
// PAL circuit // PAL circuit
DDCC1_PAL(config, PAL_TAG, 0); DDCC1_PAL(config, PAL_TAG, 0);
// Floppy drives // Floppy drives
FLOPPY_CONNECTOR(config, "0", ccfdc_floppies, "525dd", myarc_fdc_device::floppy_formats).enable_sound(true); FLOPPY_CONNECTOR(config, "0", ccfdc_floppies, "525dd", myarc_fdc_device::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, "1", ccfdc_floppies, "525dd", myarc_fdc_device::floppy_formats).enable_sound(true); FLOPPY_CONNECTOR(config, "1", ccfdc_floppies, "525dd", myarc_fdc_device::floppy_formats).enable_sound(true);
@ -440,8 +453,8 @@ const tiny_rom_entry *myarc_fdc_device::device_rom_region() const
} }
// ======================================================================== // ========================================================================
// PAL circuit on the DDCC-1 board // PAL circuit on the DDCC-1 board
// ======================================================================== // ========================================================================
ddcc1_pal_device::ddcc1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) ddcc1_pal_device::ddcc1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, DDCC1_PAL, tag, owner, clock), : device_t(mconfig, DDCC1_PAL, tag, owner, clock),
@ -462,7 +475,7 @@ bool ddcc1_pal_device::romen()
bool ddcc1_pal_device::fdcsel() bool ddcc1_pal_device::fdcsel()
{ {
// The memory mapping of the DDCC-1 differs from the usual scheme, using // The memory mapping of the DDCC-1 differs from the usual scheme, using
// addresses 5F01, 5F03, 5F05, 5F07 // addresses 5F01, 5F03, 5F05, 5F07
return (((m_board->get_address() & 0xff01)==0x5f01) && (m_board->card_selected())); return (((m_board->get_address() & 0xff01)==0x5f01) && (m_board->card_selected()));
} }

View File

@ -23,11 +23,11 @@
namespace bus { namespace ti99 { namespace peb { namespace bus { namespace ti99 { namespace peb {
class ddcc1_pal_device; class ddcc1_pal_device;
class myarc_fdc_device : public device_t, public device_ti99_peribox_card_interface class myarc_fdc_device : public device_t, public device_ti99_peribox_card_interface
{ {
friend class ddcc1_pal_device; friend class ddcc1_pal_device;
public: public:
myarc_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); myarc_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -48,10 +48,12 @@ private:
ioport_constructor device_input_ports() const override; ioport_constructor device_input_ports() const override;
DECLARE_FLOPPY_FORMATS( floppy_formats ); DECLARE_FLOPPY_FORMATS( floppy_formats );
// Callback methods // Callback methods
DECLARE_WRITE_LINE_MEMBER( fdc_irq_w ); DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
DECLARE_WRITE_LINE_MEMBER( fdc_drq_w ); DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
DECLARE_WRITE_LINE_MEMBER( fdc_mon_w );
DECLARE_WRITE_LINE_MEMBER( den_w ); DECLARE_WRITE_LINE_MEMBER( den_w );
DECLARE_WRITE_LINE_MEMBER( wdreset_w ); DECLARE_WRITE_LINE_MEMBER( wdreset_w );
DECLARE_WRITE_LINE_MEMBER( sidsel_w ); DECLARE_WRITE_LINE_MEMBER( sidsel_w );
@ -67,22 +69,22 @@ private:
// Link to the WD controller on the board. // Link to the WD controller on the board.
wd_fdc_digital_device_base* m_wdc; wd_fdc_digital_device_base* m_wdc;
// Two options for the controller chip. Can be selected by the configuration switch. // Two options for the controller chip. Can be selected by the configuration switch.
required_device<wd1770_device> m_wd1770; required_device<wd1770_device> m_wd1770;
required_device<wd1772_device> m_wd1772; required_device<wd1772_device> m_wd1772;
// Latch // Latch
required_device<ls259_device> m_drivelatch; required_device<ls259_device> m_drivelatch;
// Buffer RAM // Buffer RAM
required_device<ram_device> m_buffer_ram; required_device<ram_device> m_buffer_ram;
// Decoder PAL // Decoder PAL
required_device<ddcc1_pal_device> m_pal; required_device<ddcc1_pal_device> m_pal;
// DSR ROM // DSR ROM
uint8_t* m_dsrrom; uint8_t* m_dsrrom;
// Link to the attached floppy drives // Link to the attached floppy drives
floppy_image_device* m_floppy[4]; floppy_image_device* m_floppy[4];
@ -92,13 +94,13 @@ private:
// Upper bank selected // Upper bank selected
bool m_banksel; bool m_banksel;
// Card enabled // Card enabled
bool m_cardsel; bool m_cardsel;
// Selected drive // Selected drive
int m_selected_drive; int m_selected_drive;
// Recent address // Recent address
int m_address; int m_address;
}; };
@ -115,7 +117,7 @@ public:
bool fdcsel(); bool fdcsel();
bool cs251(); bool cs251();
bool cs259(); bool cs259();
private: private:
void device_start() override { }; void device_start() override { };
void device_config_complete() override; void device_config_complete() override;

View File

@ -87,7 +87,8 @@ wd_fdc_device_base::wd_fdc_device_base(const machine_config &mconfig, device_typ
enp_cb(*this), enp_cb(*this),
sso_cb(*this), sso_cb(*this),
ready_cb(*this), // actually output by the drive, not by the FDC ready_cb(*this), // actually output by the drive, not by the FDC
enmf_cb(*this) enmf_cb(*this),
mon_cb(*this)
{ {
force_ready = false; force_ready = false;
disable_motor_control = false; disable_motor_control = false;
@ -113,6 +114,7 @@ void wd_fdc_device_base::device_start()
sso_cb.resolve(); sso_cb.resolve();
ready_cb.resolve(); ready_cb.resolve();
enmf_cb.resolve(); enmf_cb.resolve();
mon_cb.resolve_safe();
if (!has_enmf && !enmf_cb.isnull()) if (!has_enmf && !enmf_cb.isnull())
logerror("Warning, this chip doesn't have an ENMF line.\n"); logerror("Warning, this chip doesn't have an ENMF line.\n");
@ -217,6 +219,9 @@ void wd_fdc_device_base::set_floppy(floppy_image_device *_floppy)
int next_ready = floppy ? floppy->ready_r() : 1; int next_ready = floppy ? floppy->ready_r() : 1;
if (motor_control)
mon_cb(status & S_MON ? 0 : 1);
if(floppy) { if(floppy) {
if(motor_control && !disable_motor_control) if(motor_control && !disable_motor_control)
floppy->mon_w(status & S_MON ? 0 : 1); floppy->mon_w(status & S_MON ? 0 : 1);
@ -1296,6 +1301,8 @@ void wd_fdc_device_base::spinup()
} }
status |= S_MON|S_SPIN; status |= S_MON|S_SPIN;
mon_cb(0);
if(floppy && !disable_motor_control) if(floppy && !disable_motor_control)
floppy->mon_w(0); floppy->mon_w(0);
} }
@ -1335,6 +1342,7 @@ void wd_fdc_device_base::index_callback(floppy_image_device *floppy, int state)
motor_timeout ++; motor_timeout ++;
if(motor_control && motor_timeout >= 5) { if(motor_control && motor_timeout >= 5) {
status &= ~S_MON; status &= ~S_MON;
mon_cb(1);
if(floppy && !disable_motor_control) if(floppy && !disable_motor_control)
floppy->mon_w(1); floppy->mon_w(1);
} }

View File

@ -57,6 +57,8 @@ public:
auto ready_wr_callback() { return ready_cb.bind(); } auto ready_wr_callback() { return ready_cb.bind(); }
auto enmf_rd_callback() { return enmf_cb.bind(); } auto enmf_rd_callback() { return enmf_cb.bind(); }
auto mon_wr_callback() { return mon_cb.bind(); }
void soft_reset(); void soft_reset();
DECLARE_WRITE_LINE_MEMBER(dden_w); DECLARE_WRITE_LINE_MEMBER(dden_w);
@ -295,6 +297,7 @@ private:
devcb_write_line intrq_cb, drq_cb, hld_cb, enp_cb, sso_cb, ready_cb; devcb_write_line intrq_cb, drq_cb, hld_cb, enp_cb, sso_cb, ready_cb;
devcb_read_line enmf_cb; devcb_read_line enmf_cb;
devcb_write_line mon_cb;
uint8_t format_last_byte; uint8_t format_last_byte;
int format_last_byte_count; int format_last_byte_count;