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)
Double Density, Double-sided
May be used with a 1770 or 1772 controller
EPROM 2764A (8Kx8) in two banks (2x 4000-4fff)
SRAM HM6116 (2Kx8) (5000-57ff)
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
means 2ms, open means 6 ms. There is an alternative ROM for the 1772 which
allows for slower step rates (6ms-12ms).
Another switch is included (SW2) labeled "Turbo" on schematics, but which
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
*******************************************************************************/
@ -63,13 +61,13 @@ myarc_fdc_device::myarc_fdc_device(const machine_config &mconfig, const char *ta
m_wd1770(*this, WD1770_TAG),
m_wd1772(*this, WD1772_TAG),
m_drivelatch(*this, LATCH_TAG),
m_buffer_ram(*this, BUFFER_TAG),
m_pal(*this, PAL_TAG),
m_dsrrom(nullptr),
m_banksel(false),
m_cardsel(false),
m_selected_drive(0),
m_address(0)
m_buffer_ram(*this, BUFFER_TAG),
m_pal(*this, PAL_TAG),
m_dsrrom(nullptr),
m_banksel(false),
m_cardsel(false),
m_selected_drive(0),
m_address(0)
{ }
SETADDRESS_DBIN_MEMBER( myarc_fdc_device::setaddress_dbin )
@ -84,7 +82,7 @@ bool myarc_fdc_device::card_selected()
return m_cardsel;
}
/*
Provides the current address to the PAL.
Provides the current address to the PAL.
*/
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)
{
@ -102,7 +100,7 @@ void myarc_fdc_device::debug_read(offs_t offset, uint8_t* value)
{
*value = m_buffer_ram->pointer()[m_address & 0x07ff];
}
if (m_pal->romen())
{
// 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)
{
@ -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)
{
@ -136,38 +134,38 @@ READ8Z_MEMBER(myarc_fdc_device::readz)
debug_read(offset, value);
return;
}
if (m_pal->ramsel())
{
// SRAM selected
*value = m_buffer_ram->pointer()[m_address & 0x07ff];
LOGMASKED(LOG_RAM, "Read RAM: %04x -> %02x\n", m_address & 0xffff, *value);
}
if (m_pal->romen())
{
// EPROM selected
uint16_t base = m_banksel? 0x1000 : 0;
uint8_t* rom = &m_dsrrom[base | (m_address & 0x0fff)];
*value = *rom;
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);
}
}
}
if (m_pal->fdcsel())
{
// WDC selected
*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)
{
@ -176,14 +174,14 @@ void myarc_fdc_device::write(offs_t offset, uint8_t data)
debug_write(offset, data);
return;
}
if (m_pal->ramsel())
{
// SRAM selected
LOGMASKED(LOG_RAM, "Write RAM: %04x <- %02x\n", m_address & 0xffff, data);
m_buffer_ram->pointer()[m_address & 0x07ff] = data;
}
if (m_pal->fdcsel())
{
// 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 )
{
@ -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)
{
@ -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 )
{
@ -255,8 +253,19 @@ WRITE_LINE_MEMBER( myarc_fdc_device::fdc_drq_w )
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 )
{
@ -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);
m_floppy[m_selected_drive-1]->ss_w(state);
}
}
}
// 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 )
{
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->q6_r() != 0) driveno = 3;
if (m_drivelatch->q5_r() != 0) driveno = 2;
if (m_drivelatch->q4_r() != 0) driveno = 1;
if (state == CLEAR_LINE)
{
// 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()
{
m_dsrrom = memregion(TI99_DSRROM)->base();
@ -397,15 +405,20 @@ ROM_END
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);
WD1772(config, m_wd1772, 8_MHz_XTAL);
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->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->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
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));
@ -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<6>().set(FUNC(myarc_fdc_device::drivesel_w));
m_drivelatch->q_out_cb<7>().set(FUNC(myarc_fdc_device::drivesel_w));
// 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
DDCC1_PAL(config, PAL_TAG, 0);
// Floppy drives
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);
@ -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)
: device_t(mconfig, DDCC1_PAL, tag, owner, clock),
@ -462,7 +475,7 @@ bool ddcc1_pal_device::romen()
bool ddcc1_pal_device::fdcsel()
{
// 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()));
}

View File

@ -23,11 +23,11 @@
namespace bus { namespace ti99 { namespace peb {
class ddcc1_pal_device;
class myarc_fdc_device : public device_t, public device_ti99_peribox_card_interface
{
friend class ddcc1_pal_device;
public:
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;
DECLARE_FLOPPY_FORMATS( floppy_formats );
// Callback methods
DECLARE_WRITE_LINE_MEMBER( fdc_irq_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( wdreset_w );
DECLARE_WRITE_LINE_MEMBER( sidsel_w );
@ -67,22 +69,22 @@ private:
// Link to the WD controller on the board.
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<wd1772_device> m_wd1772;
// Latch
required_device<ls259_device> m_drivelatch;
// Buffer RAM
required_device<ram_device> m_buffer_ram;
// Decoder PAL
required_device<ddcc1_pal_device> m_pal;
// DSR ROM
uint8_t* m_dsrrom;
// Link to the attached floppy drives
floppy_image_device* m_floppy[4];
@ -92,13 +94,13 @@ private:
// Upper bank selected
bool m_banksel;
// Card enabled
bool m_cardsel;
// Selected drive
int m_selected_drive;
// Recent address
int m_address;
};
@ -115,7 +117,7 @@ public:
bool fdcsel();
bool cs251();
bool cs259();
private:
void device_start() 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),
sso_cb(*this),
ready_cb(*this), // actually output by the drive, not by the FDC
enmf_cb(*this)
enmf_cb(*this),
mon_cb(*this)
{
force_ready = false;
disable_motor_control = false;
@ -113,6 +114,7 @@ void wd_fdc_device_base::device_start()
sso_cb.resolve();
ready_cb.resolve();
enmf_cb.resolve();
mon_cb.resolve_safe();
if (!has_enmf && !enmf_cb.isnull())
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;
if (motor_control)
mon_cb(status & S_MON ? 0 : 1);
if(floppy) {
if(motor_control && !disable_motor_control)
floppy->mon_w(status & S_MON ? 0 : 1);
@ -1296,6 +1301,8 @@ void wd_fdc_device_base::spinup()
}
status |= S_MON|S_SPIN;
mon_cb(0);
if(floppy && !disable_motor_control)
floppy->mon_w(0);
}
@ -1335,6 +1342,7 @@ void wd_fdc_device_base::index_callback(floppy_image_device *floppy, int state)
motor_timeout ++;
if(motor_control && motor_timeout >= 5) {
status &= ~S_MON;
mon_cb(1);
if(floppy && !disable_motor_control)
floppy->mon_w(1);
}

View File

@ -57,6 +57,8 @@ public:
auto ready_wr_callback() { return ready_cb.bind(); }
auto enmf_rd_callback() { return enmf_cb.bind(); }
auto mon_wr_callback() { return mon_cb.bind(); }
void soft_reset();
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_read_line enmf_cb;
devcb_write_line mon_cb;
uint8_t format_last_byte;
int format_last_byte_count;