(MESS) pet: Implemented write mode on the Commodore 8050/8250/SFD-1001 floppy drives. [Curt Coder]

(MESS) victor9k: Separated read/write modes in the floppy controller. (nw)
fdc_pll: Removed write_next_bit_prev_cell hack. (nw)
This commit is contained in:
Curt Coder 2015-04-16 00:16:05 +03:00
parent d4c67891c4
commit 19bbe2ac4d
6 changed files with 88 additions and 81 deletions

View File

@ -13,9 +13,7 @@
TODO:
- write mode
- write protect
- separate read/write methods
*/
@ -28,6 +26,8 @@
//**************************************************************************
#define LOG 0
#define LOG_MORE 0
#define LOG_BITS 0
#define GCR_DECODE(_e, _i) \
((BIT(_e, 6) << 7) | (BIT(_i, 7) << 6) | (_e & 0x33) | (BIT(_e, 2) << 3) | (_i & 0x04))
@ -74,7 +74,7 @@ const rom_entry *c8050_fdc_t::device_rom_region() const
//-------------------------------------------------
c8050_fdc_t::c8050_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, C8050_FDC, "C8050 FDC", tag, owner, clock, "c8050fdc", __FILE__),
device_t(mconfig, C8050_FDC, "Commodore 8050 FDC", tag, owner, clock, "c8050fdc", __FILE__),
m_write_sync(*this),
m_write_ready(*this),
m_write_brdy(*this),
@ -89,7 +89,7 @@ c8050_fdc_t::c8050_fdc_t(const machine_config &mconfig, const char *tag, device_
m_ds(0),
m_drv_sel(0),
m_mode_sel(0),
m_rw_sel(0)
m_rw_sel(1)
{
cur_live.tm = attotime::never;
cur_live.state = IDLE;
@ -210,7 +210,8 @@ void c8050_fdc_t::ds_w(int ds)
{
live_sync();
m_ds = cur_live.ds = ds;
pll_reset(cur_live.tm, attotime::from_hz(clock() / (16 - m_ds)));
pll_reset(cur_live.tm);
if (LOG) logerror("%s %s DS %u\n", machine().time().as_string(), machine().describe_context(), ds);
checkpoint();
live_run();
}
@ -240,22 +241,23 @@ void c8050_fdc_t::live_start()
cur_live.rw_sel = m_rw_sel;
cur_live.pi = m_pi;
pll_reset(cur_live.tm, attotime::from_hz(clock() / (16 - m_ds)));
pll_reset(cur_live.tm);
checkpoint_live = cur_live;
pll_save_checkpoint();
live_run();
}
void c8050_fdc_t::pll_reset(const attotime &when, const attotime &clock)
void c8050_fdc_t::pll_reset(const attotime &when)
{
cur_pll.reset(when);
cur_pll.set_clock(clock);
cur_pll.set_clock(attotime::from_hz(clock() / (16 - m_ds)));
}
void c8050_fdc_t::pll_start_writing(const attotime &tm)
{
cur_pll.start_writing(tm);
pll_reset(cur_live.tm);
}
void c8050_fdc_t::pll_commit(floppy_image_device *floppy, const attotime &tm)
@ -266,6 +268,7 @@ void c8050_fdc_t::pll_commit(floppy_image_device *floppy, const attotime &tm)
void c8050_fdc_t::pll_stop_writing(floppy_image_device *floppy, const attotime &tm)
{
cur_pll.stop_writing(floppy, tm);
pll_reset(cur_live.tm);
}
void c8050_fdc_t::pll_save_checkpoint()
@ -285,7 +288,7 @@ int c8050_fdc_t::pll_get_next_bit(attotime &tm, floppy_image_device *floppy, con
bool c8050_fdc_t::pll_write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit)
{
return cur_pll.write_next_bit_prev_cell(bit, tm, floppy, limit);
return cur_pll.write_next_bit(bit, tm, floppy, limit);
}
void c8050_fdc_t::checkpoint()
@ -366,10 +369,33 @@ void c8050_fdc_t::live_run(const attotime &limit)
return;
// read bit
int bit = pll_get_next_bit(cur_live.tm, get_floppy(), limit);
if(bit < 0)
return;
int bit = 0;
if (cur_live.rw_sel) {
bit = pll_get_next_bit(cur_live.tm, get_floppy(), limit);
if(bit < 0)
return;
}
// write bit
int write_bit = BIT(cur_live.shift_reg_write, 9);
if (!cur_live.rw_sel) { // TODO WPS
/*
write precompensation
UA5.A = UM6.Qc
UA5.B = !(!(!BRDY && UM6.Qa) && !(BRDY && E7))
UA5.C0 = UA4.Qb = bit clock delayed 333ns
UA5.C1 = UA4.Qa = bit clock delayed 166ns
UA5.C2 = UA4.Qc = bit clock delayed 499ns
UA5.C3 = UA5.Qb = bit clock delayed 333ns
DATA OUT = !(!BITCLK || !(UA5.Y && !(WRITE_ENABLE && !UM6.Qb)))
*/
if (pll_write_next_bit(write_bit, cur_live.tm, get_floppy(), limit))
return;
}
// clock read shift register
cur_live.shift_reg <<= 1;
cur_live.shift_reg |= bit;
cur_live.shift_reg &= 0x3ff;
@ -378,16 +404,9 @@ void c8050_fdc_t::live_run(const attotime &limit)
int sync = !((cur_live.shift_reg == 0x3ff) && cur_live.rw_sel);
// bit counter
if (cur_live.rw_sel) {
if (!sync) {
cur_live.bit_counter = 0;
} else if (cur_live.sync) {
cur_live.bit_counter++;
if (cur_live.bit_counter == 10) {
cur_live.bit_counter = 0;
}
}
} else {
if (!sync) {
cur_live.bit_counter = 0;
} else if (cur_live.sync) {
cur_live.bit_counter++;
if (cur_live.bit_counter == 10) {
cur_live.bit_counter = 0;
@ -403,8 +422,6 @@ void c8050_fdc_t::live_run(const attotime &limit)
cur_live.e = m_gcr_rom->base()[cur_live.i];
if (LOG) logerror("%s cyl %u bit %u sync %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),bit,sync,cur_live.bit_counter,cur_live.shift_reg,cur_live.i,cur_live.e);
// byte ready
int ready = !(cur_live.bit_counter == 9); // 74190 _RC, should be triggered on the falling edge of the clock
int brdy = ready; // 74190 TC
@ -412,18 +429,19 @@ void c8050_fdc_t::live_run(const attotime &limit)
// GCR error
int error = !(ready || BIT(cur_live.e, 3));
// write bit
if (!cur_live.rw_sel) { // TODO WPS
int write_bit = BIT(cur_live.shift_reg_write, 9);
if (LOG) logerror("%s writing bit %u sr %03x\n",cur_live.tm.as_string(),write_bit,cur_live.shift_reg_write);
pll_write_next_bit(write_bit, cur_live.tm, get_floppy(), limit);
if (LOG_BITS) {
if (cur_live.rw_sel) {
logerror("%s cyl %u bit %u sync %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),bit,sync,cur_live.bit_counter,cur_live.shift_reg,cur_live.i,cur_live.e);
} else {
logerror("%s cyl %u writing bit %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),write_bit,cur_live.bit_counter,cur_live.shift_reg_write,cur_live.i,cur_live.e);
}
}
if (!ready) {
// load write shift register
cur_live.shift_reg_write = GCR_ENCODE(cur_live.e, cur_live.i);
if (LOG) logerror("%s load write shift register %03x\n",cur_live.tm.as_string(),cur_live.shift_reg_write);
if (LOG_BITS) logerror("%s load write shift register %03x\n",cur_live.tm.as_string(),cur_live.shift_reg_write);
} else {
// clock write shift register
cur_live.shift_reg_write <<= 1;
@ -431,13 +449,14 @@ void c8050_fdc_t::live_run(const attotime &limit)
}
if (ready != cur_live.ready) {
if (LOG) logerror("%s READY %u : %02x\n", cur_live.tm.as_string(),ready,GCR_DECODE(cur_live.e, cur_live.i));
if (cur_live.rw_sel && !ready)
if (LOG) logerror("%s READY %u : %02x\n", cur_live.tm.as_string(),ready,GCR_DECODE(cur_live.e, cur_live.i));
cur_live.ready = ready;
syncpoint = true;
}
if (brdy != cur_live.brdy) {
if (LOG) logerror("%s BRDY %u\n", cur_live.tm.as_string(), brdy);
if (LOG_MORE) logerror("%s BRDY %u\n", cur_live.tm.as_string(), brdy);
cur_live.brdy = brdy;
syncpoint = true;
}
@ -449,7 +468,7 @@ void c8050_fdc_t::live_run(const attotime &limit)
}
if (error != cur_live.error) {
if (LOG) logerror("%s ERROR %u\n", cur_live.tm.as_string(), error);
if (LOG_MORE) logerror("%s ERROR %u\n", cur_live.tm.as_string(), error);
cur_live.error = error;
syncpoint = true;
}
@ -462,10 +481,6 @@ void c8050_fdc_t::live_run(const attotime &limit)
}
case RUNNING_SYNCPOINT: {
if (LOG) {
if (!cur_live.sync) logerror("%s SYNC\n",cur_live.tm.as_string());
if (!cur_live.ready && cur_live.bit_counter == 9) logerror("%s DATA %02x\n",cur_live.tm.as_string(),GCR_DECODE(cur_live.e,cur_live.i));
}
m_write_ready(cur_live.ready);
m_write_brdy(cur_live.brdy);
m_write_sync(cur_live.sync);
@ -484,21 +499,18 @@ READ8_MEMBER( c8050_fdc_t::read )
UINT8 e = checkpoint_live.e;
offs_t i = checkpoint_live.i;
UINT8 data = GCR_DECODE(e, i);
if (LOG)logerror("%s %s VIA reads data %02x (%03x)\n", machine().time().as_string(), machine().describe_context(), data, checkpoint_live.shift_reg);
return data;
return GCR_DECODE(e, i);
}
WRITE8_MEMBER( c8050_fdc_t::write )
{
if (LOG) logerror("%s %s PI %02x\n", machine().time().as_string(), machine().describe_context(), data);
if (m_pi != data)
{
live_sync();
m_pi = cur_live.pi = data;
checkpoint();
if (LOG) logerror("%s %s PI %02x\n", machine().time().as_string(), machine().describe_context(), data);
live_run();
}
}
@ -548,9 +560,9 @@ WRITE_LINE_MEMBER( c8050_fdc_t::rw_sel_w )
checkpoint();
if (LOG) logerror("%s %s RW SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
if (m_rw_sel) {
pll_stop_writing(get_floppy(), machine().time());
pll_stop_writing(get_floppy(), cur_live.tm);
} else {
pll_start_writing(machine().time());
pll_start_writing(cur_live.tm);
}
live_run();
}
@ -616,5 +628,5 @@ WRITE_LINE_MEMBER( c8050_fdc_t::odd_hd_w )
WRITE_LINE_MEMBER( c8050_fdc_t::pull_sync_w )
{
if (LOG) logerror("%s %s PULL SYNC %u\n", machine().time().as_string(), machine().describe_context(), state);
if (LOG_MORE) logerror("%s %s PULL SYNC %u\n", machine().time().as_string(), machine().describe_context(), state);
}

View File

@ -150,7 +150,7 @@ protected:
void live_start();
void checkpoint();
void rollback();
void pll_reset(const attotime &when, const attotime &clock);
void pll_reset(const attotime &when);
void pll_start_writing(const attotime &tm);
void pll_commit(floppy_image_device *floppy, const attotime &tm);
void pll_stop_writing(floppy_image_device *floppy, const attotime &tm);

View File

@ -22,7 +22,6 @@ void fdc_pll_t::set_clock(const attotime &_period)
void fdc_pll_t::reset(const attotime &when)
{
ctime = when;
write_ctime = when;
phase_adjust = attotime::zero;
freq_hist = 0;
write_position = 0;
@ -66,7 +65,6 @@ int fdc_pll_t::get_next_bit(attotime &tm, floppy_image_device *floppy, const att
if(next > limit)
return -1;
write_ctime = ctime;
ctime = next;
tm = next;
@ -132,20 +130,3 @@ bool fdc_pll_t::write_next_bit(bool bit, attotime &tm, floppy_image_device *flop
ctime = etime;
return false;
}
bool fdc_pll_t::write_next_bit_prev_cell(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit)
{
if(write_start_time.is_never()) {
write_start_time = write_ctime;
write_position = 0;
}
attotime etime = write_ctime + period;
if(etime > limit)
return true;
if(bit && write_position < ARRAY_LENGTH(write_buffer))
write_buffer[write_position++] = write_ctime + period/2;
return false;
}

View File

@ -12,7 +12,6 @@ class fdc_pll_t {
public:
attotime ctime, period, min_period, max_period, period_adjust_base, phase_adjust;
attotime write_ctime;
attotime write_start_time;
attotime write_buffer[32];
int write_position;
@ -22,7 +21,6 @@ public:
void reset(const attotime &when);
int get_next_bit(attotime &tm, floppy_image_device *floppy, const attotime &limit);
bool write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit);
bool write_next_bit_prev_cell(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit);
void start_writing(const attotime &tm);
void commit(floppy_image_device *floppy, const attotime &tm);
void stop_writing(floppy_image_device *floppy, const attotime &tm);

View File

@ -54,6 +54,7 @@
#define LOG 0
#define LOG_VIA 0
#define LOG_SCP 0
#define LOG_BITS 0
#define I8048_TAG "5d"
#define M6522_4_TAG "1f"
@ -1069,22 +1070,23 @@ void victor_9000_fdc_t::live_start()
cur_live.wrsync = m_wrsync;
cur_live.erase = m_erase;
pll_reset(cur_live.tm, attotime::from_nsec(2130));
pll_reset(cur_live.tm);
checkpoint_live = cur_live;
pll_save_checkpoint();
live_run();
}
void victor_9000_fdc_t::pll_reset(const attotime &when, const attotime &clock)
void victor_9000_fdc_t::pll_reset(const attotime &when)
{
cur_pll.reset(when);
cur_pll.set_clock(clock);
cur_pll.set_clock(attotime::from_nsec(2130));
}
void victor_9000_fdc_t::pll_start_writing(const attotime &tm)
{
cur_pll.start_writing(tm);
pll_reset(cur_live.tm);
}
void victor_9000_fdc_t::pll_commit(floppy_image_device *floppy, const attotime &tm)
@ -1095,6 +1097,7 @@ void victor_9000_fdc_t::pll_commit(floppy_image_device *floppy, const attotime &
void victor_9000_fdc_t::pll_stop_writing(floppy_image_device *floppy, const attotime &tm)
{
cur_pll.stop_writing(floppy, tm);
pll_reset(cur_live.tm);
}
void victor_9000_fdc_t::pll_save_checkpoint()
@ -1114,7 +1117,7 @@ int victor_9000_fdc_t::pll_get_next_bit(attotime &tm, floppy_image_device *flopp
bool victor_9000_fdc_t::pll_write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, const attotime &limit)
{
return cur_pll.write_next_bit_prev_cell(bit, tm, floppy, limit);
return cur_pll.write_next_bit(bit, tm, floppy, limit);
}
void victor_9000_fdc_t::checkpoint()
@ -1197,10 +1200,22 @@ void victor_9000_fdc_t::live_run(const attotime &limit)
return;
// read bit
int bit = pll_get_next_bit(cur_live.tm, get_floppy(), limit);
if(bit < 0)
return;
int bit = 0;
if (cur_live.drw) {
bit = pll_get_next_bit(cur_live.tm, get_floppy(), limit);
if(bit < 0)
return;
}
// write bit
int write_bit = 0;
if (!cur_live.drw) { // TODO WPS
write_bit = BIT(cur_live.shift_reg_write, 9);
if (pll_write_next_bit(write_bit, cur_live.tm, get_floppy(), limit))
return;
}
// clock read shift register
cur_live.shift_reg <<= 1;
cur_live.shift_reg |= bit;
cur_live.shift_reg &= 0x3ff;
@ -1261,11 +1276,12 @@ void victor_9000_fdc_t::live_run(const attotime &limit)
// GCR error
int gcr_err = !(brdy || BIT(cur_live.e, 3));
// write bit
if (!cur_live.drw) { // TODO WPS
int write_bit = BIT(cur_live.shift_reg_write, 9);
if (LOG) logerror("%s writing bit %u sr %03x\n",cur_live.tm.as_string(),write_bit,cur_live.shift_reg_write);
pll_write_next_bit(write_bit, cur_live.tm, get_floppy(), limit);
if (LOG_BITS) {
if (cur_live.drw) {
logerror("%s cyl %u bit %u sync %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),bit,sync,cur_live.bit_counter,cur_live.shift_reg,cur_live.i,cur_live.e);
} else {
logerror("%s cyl %u writing bit %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),write_bit,cur_live.bit_counter,cur_live.shift_reg_write,cur_live.i,cur_live.e);
}
}
if (!brdy) {

View File

@ -218,7 +218,7 @@ private:
floppy_image_device* get_floppy();
void live_start();
void pll_reset(const attotime &when, const attotime &clock);
void pll_reset(const attotime &when);
void pll_start_writing(const attotime &tm);
void pll_commit(floppy_image_device *floppy, const attotime &tm);
void pll_stop_writing(floppy_image_device *floppy, const attotime &tm);