summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2021-01-09 18:43:24 +0100
committer Olivier Galibert <galibert@pobox.com>2021-01-11 16:47:06 +0100
commitf960ef21f6a71b8fb9f490bfdf092f5e5e05f214 (patch)
treece31d4cbcc22dbce25b62ca4c9e303e19baaa77f
parent1fced4ec7c773cef7c77380c8f14a960184e59b1 (diff)
SWIM2: Enough of the write processing to make the timing calibration work.
-rwxr-xr-xsrc/devices/machine/applefdintf.h4
-rw-r--r--src/devices/machine/iwm.h3
-rw-r--r--src/devices/machine/swim1.cpp3
-rw-r--r--src/devices/machine/swim1.h2
-rw-r--r--src/devices/machine/swim2.cpp312
-rw-r--r--src/devices/machine/swim2.h27
-rw-r--r--src/devices/machine/swim3.cpp3
-rw-r--r--src/devices/machine/swim3.h2
-rw-r--r--src/mame/machine/mac.cpp3
9 files changed, 338 insertions, 21 deletions
diff --git a/src/devices/machine/applefdintf.h b/src/devices/machine/applefdintf.h
index c6cc7a2d451..19095e875cc 100755
--- a/src/devices/machine/applefdintf.h
+++ b/src/devices/machine/applefdintf.h
@@ -82,6 +82,10 @@ public:
FLOPPY_CONNECTOR(config, floppy, floppies_35, "", formats_35);
}
+ // Sync the state when something external is going to change, like
+ // the floppy side or rpm.
+ virtual void sync() = 0;
+
protected:
devcb_write8 m_phases_cb, m_devsel_cb;
devcb_write_line m_sel35_cb, m_hdsel_cb;
diff --git a/src/devices/machine/iwm.h b/src/devices/machine/iwm.h
index 7ef2b8a4b4c..9c1f4214a68 100644
--- a/src/devices/machine/iwm.h
+++ b/src/devices/machine/iwm.h
@@ -32,6 +32,8 @@ public:
virtual void set_floppy(floppy_image_device *floppy) override;
virtual floppy_image_device *get_floppy() const override;
+ virtual void sync() override;
+
protected:
virtual void device_start() override;
virtual void device_reset() override;
@@ -65,7 +67,6 @@ private:
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;
diff --git a/src/devices/machine/swim1.cpp b/src/devices/machine/swim1.cpp
index d313d777b42..70991e1b845 100644
--- a/src/devices/machine/swim1.cpp
+++ b/src/devices/machine/swim1.cpp
@@ -171,3 +171,6 @@ void swim1_device::write(offs_t offset, u8 data)
}
}
+void swim1_device::sync()
+{
+}
diff --git a/src/devices/machine/swim1.h b/src/devices/machine/swim1.h
index 86d064a19ae..67f76098b2b 100644
--- a/src/devices/machine/swim1.h
+++ b/src/devices/machine/swim1.h
@@ -30,6 +30,8 @@ public:
virtual void set_floppy(floppy_image_device *floppy) override;
virtual floppy_image_device *get_floppy() const override;
+ virtual void sync() override;
+
protected:
virtual void device_start() override;
virtual void device_reset() override;
diff --git a/src/devices/machine/swim2.cpp b/src/devices/machine/swim2.cpp
index a875917f345..992702bf782 100644
--- a/src/devices/machine/swim2.cpp
+++ b/src/devices/machine/swim2.cpp
@@ -24,6 +24,15 @@ void swim2_device::device_start()
save_item(NAME(m_setup));
save_item(NAME(m_param_idx));
save_item(NAME(m_param));
+ save_item(NAME(m_last_sync));
+ save_item(NAME(m_crc));
+ save_item(NAME(m_fifo));
+ save_item(NAME(m_fifo_pos));
+ save_item(NAME(m_error));
+ save_item(NAME(m_half_cycles_before_change));
+ save_item(NAME(m_current_bit));
+ save_item(NAME(m_tss_sr));
+ save_item(NAME(m_tss_output));
}
void swim2_device::device_reset()
@@ -35,10 +44,19 @@ void swim2_device::device_reset()
m_param_idx = 0;
memset(m_param, 0, sizeof(m_param));
m_floppy = nullptr;
-
+ m_crc = 0xffff;
+ m_fifo[0] = m_fifo[1] = 0;
+ m_fifo_pos = 0;
+ m_error = 0;
+ m_half_cycles_before_change = 0;
+ m_current_bit = 0;
+ m_tss_sr = 0;
+ m_tss_output = 0;
m_devsel_cb(0);
m_sel35_cb(true);
m_hdsel_cb(false);
+
+ m_last_sync = machine().time().as_ticks(clock());
}
void swim2_device::device_timer(emu_timer &, device_timer_id, int, void *)
@@ -63,6 +81,30 @@ floppy_image_device *swim2_device::get_floppy() const
return m_floppy;
}
+void swim2_device::flush_write(u64 when)
+{
+ if(!when)
+ when = m_last_sync;
+
+ if(m_floppy && when > m_flux_write_start) {
+ if(m_flux_write_count && m_flux_write[m_flux_write_count-1] == when)
+ m_flux_write_count--;
+ attotime start = cycles_to_time(m_flux_write_start);
+ attotime end = cycles_to_time(when);
+ std::vector<attotime> fluxes(m_flux_write_count);
+ u32 i = 0;
+ if(m_flux_write_count && m_flux_write[0] == m_flux_write_start)
+ i++;
+ while(i != m_flux_write_count) {
+ fluxes[i] = cycles_to_time(m_flux_write[i]);
+ 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 = when;
+}
+
void swim2_device::show_mode() const
{
logerror("mode%s %s hdsel=%c %c%s %c%c%s\n",
@@ -79,22 +121,81 @@ void swim2_device::show_mode() const
u8 swim2_device::read(offs_t offset)
{
+ sync();
+
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: {
+ switch(offset & 7) {
+ case 0x0: { // data
+ u16 r = fifo_pop();
+ if(!m_error) {
+ if(r == 0xffff)
+ m_error |= 4;
+ else if(r & M_MARK)
+ m_error |= 2;
+ }
+ return r;
+ }
+
+ case 0x1: { // mark
+ u16 r = fifo_pop();
+ if(!m_error && r == 0xffff)
+ m_error |= 4;
+ return r;
+ }
+
+ case 0x2: { // errpr
+ u8 err = m_error;
+ m_error = 0;
+ return err;
+ }
+
+ case 0x3: { // param
u8 r = m_param[m_param_idx];
m_param_idx = (m_param_idx + 1) & 15;
return r;
}
- case 0x4: case 0xc:
+
+ case 0x4: // phases
return m_phases;
- case 0x5: case 0xd:
+
+ case 0x5: // setup
return m_setup;
- case 0xe:
+
+ case 0x6: // mode
return m_mode;
+
+ case 0x7: { // handshake
+ u8 h = 0;
+ if(m_fifo_pos > 0) {
+ if(m_fifo[m_fifo_pos - 1] & M_MARK)
+ h |= 0x01;
+ if(m_fifo[m_fifo_pos - 1] & M_CRC0)
+ h |= 0x02;
+ }
+ // addata on 4
+ if(m_floppy && !m_floppy->wpt_r())
+ h |= 0x08;
+ if(m_error)
+ h |= 0x20;
+ if(m_mode & 0x10) {
+ // write
+ if(m_fifo_pos == 0)
+ h |= 0x40;
+ } else {
+ // read
+ if(m_fifo_pos == 2)
+ h |= 0x40;
+ }
+
+ if(!m_error && m_fifo_pos == 1)
+ h |= 0x80;
+ logerror("handshake %02x\n", h);
+ return h;
+ }
+
default:
logerror("read %s\n", names[offset & 15]);
break;
@@ -104,13 +205,31 @@ u8 swim2_device::read(offs_t offset)
void swim2_device::write(offs_t offset, u8 data)
{
- machine().debug_break();
+ sync();
+
+ u8 prev_mode = m_mode;
+
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: {
+ switch(offset & 7) {
+ case 0:
+ if(fifo_push(data) && !m_error)
+ m_error |= 0x04;
+ break;
+
+ case 1:
+ if(fifo_push(M_MARK | data) && !m_error)
+ m_error |= 0x04;
+ break;
+
+ case 2:
+ if(fifo_push(M_CRC) && !m_error)
+ m_error |= 0x04;
+ break;
+
+ case 3: { // param
static const char *const pname[4] = {
"late", "time0", "early", "time1"
};
@@ -119,33 +238,33 @@ void swim2_device::write(offs_t offset, u8 data)
m_param_idx = (m_param_idx + 1) & 3;
break;
}
- case 0x4: {
+ case 4: { // phases
m_phases = data;
update_phases();
break;
}
- case 0x5: case 0xd:
+ case 5: // setup
m_setup = data;
- 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_sel35_cb(m_setup & 0x02);
+ logerror("setup write=%s %s test=%s %s %s 3.5=%s %s\n",
+ m_setup & 0x40 ? "gcr" : "mfm",
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");
+ m_setup & 0x01 ? "wrinvert" : "wrdirect");
break;
- case 0x6:
+ case 6: // mode clear
m_mode &= ~data;
m_mode |= 0x40;
m_param_idx = 0;
show_mode();
break;
- case 0x7:
+ case 7: // mode set
m_mode |= data;
show_mode();
break;
@@ -154,5 +273,164 @@ void swim2_device::write(offs_t offset, u8 data)
logerror("write %s, %02x\n", names[offset], data);
break;
}
+
+ if(m_mode & 0x01)
+ fifo_clear();
+
+ if((m_mode & 0x18) == 0x18 && ((prev_mode & 0x18) != 0x18)) {
+ // Entering write mode
+ m_current_bit = 0;
+ logerror("%s write start\n", machine().time().to_string());
+ machine().debug_break();
+ } else if((prev_mode & 0x18) == 0x18 && (m_mode & 0x18) != 0x18) {
+ // Exiting write mode
+ flush_write();
+ m_current_bit = 0xff;
+ m_half_cycles_before_change = 0;
+ logerror("%s write end\n", machine().time().to_string());
+ }
+}
+
+u64 swim2_device::time_to_cycles(const attotime &tm) const
+{
+ return tm.as_ticks(clock());
+}
+
+attotime swim2_device::cycles_to_time(u64 cycles) const
+{
+ return attotime::from_ticks(cycles, clock());
+}
+
+void swim2_device::fifo_clear()
+{
+ m_fifo_pos = 0;
+ // must clear the crc to the appropriate r/w-dependant value. No idea yet which it is, but I have my suspicions.
+ m_crc = 0x1234;
+}
+
+bool swim2_device::fifo_push(u16 data)
+{
+ logerror("fifo push %03x\n", data);
+ if(m_fifo_pos == 2)
+ return true;
+ m_fifo[m_fifo_pos ++] = data;
+ return false;
+}
+
+u16 swim2_device::fifo_pop()
+{
+ if(m_fifo_pos == 0)
+ return 0xffff;
+ u16 r = m_fifo[0];
+ m_fifo[0] = m_fifo[1];
+ m_fifo_pos --;
+ return r;
}
+// cell times
+// 1 us: 31.32
+// 1.5us: 47.32
+// 2us: 31.16 63.32
+// 3us: 47.16 94.32
+// 4us: 63.16 125.32
+// 6us: 94.16 188.32
+
+// time1 = 31, time0 = 16 for clock /1 mfm
+// time1 =
+
+// 32 mfm, t1=63, t0=31
+// 16 mfm, t1=31.5, t0=15.5
+// 16 gcr, t1=31.5, t0=31.5
+
+void swim2_device::sync()
+{
+ u64 next_sync = time_to_cycles(machine().time());
+ if(!(m_mode & 0x08)) {
+ m_last_sync = next_sync;
+ return;
+ }
+
+ // We count in half-cycles but only toggle write on full cycles
+
+ u32 cycles = (next_sync - m_last_sync) << 1;
+ // logerror("ACTIVE %s %d-%d (%d)\n", m_mode & 0x10 ? "write" : "read", m_last_sync, next_sync, cycles);
+
+ while(cycles) {
+ // logerror("half cycles avail %d needed %d\n", cycles, m_half_cycles_before_change);
+ if(m_half_cycles_before_change) {
+ if(cycles >= m_half_cycles_before_change) {
+ cycles -= m_half_cycles_before_change;
+ m_half_cycles_before_change = 0;
+ } else {
+ m_half_cycles_before_change -= cycles;
+ cycles = 0;
+ break;
+ }
+ }
+
+ if(m_flux_write_count > 32)
+ flush_write(next_sync - (cycles >> 1));
+
+ if(m_mode & 0x10) {
+ // Write mode
+
+ if(m_tss_output & 0xc) {
+ logerror("SR %03x.%d TSS %c%c\n", m_sr, m_current_bit, m_tss_output & 8 ? m_tss_output & 2 ? '1' : '0' : '.', m_tss_output & 4 ? m_tss_output & 1 ? '1' : '0' : '.');
+ bool bit;
+ if(m_tss_output & 8) {
+ bit = (m_tss_output >> 1) & 1;
+ m_tss_output &= ~0xa;
+ } else {
+ bit = m_tss_output & 1;
+ m_tss_output = 0;
+ }
+ if(bit) {
+ m_flux_write[m_flux_write_count ++] = next_sync - (cycles >> 1);
+ m_half_cycles_before_change = 63;
+ } else
+ m_half_cycles_before_change = m_setup & 0x40 ? 63 : 31;
+ if(m_setup & 8)
+ m_half_cycles_before_change <<= 1;
+ logerror("T%d, %d half cycles\n", bit, m_half_cycles_before_change);
+ continue;
+ }
+ if(m_current_bit == 0xff)
+ fatalerror("Sequence break on write\n");
+
+ if(m_current_bit == 0) {
+ u16 r = fifo_pop();
+ logerror("fifo pop %03x\n", r);
+ if(r == 0xffff && !m_error) {
+ m_error |= 0x01;
+ flush_write();
+ m_current_bit = 0xff;
+ m_half_cycles_before_change = 0;
+ m_mode &= ~8;
+ logerror("write end on underrun\n");
+ break;
+ }
+ if(r & M_CRC) {
+ fatalerror("crc alpha\n");
+ }
+ m_sr = r & (M_MARK | M_CRC | 0xff);
+ m_current_bit = 8;
+ }
+ m_current_bit --;
+ bool bit = (m_sr >> m_current_bit) & 1;
+ m_tss_sr = (m_tss_sr << 1) | bit;
+ if(m_setup & 0x40)
+ m_tss_output = 4 | bit;
+ else {
+ static const u8 tss[4] = { 5, 0xd, 4, 5 };
+ if((m_sr & M_MARK) && (m_tss_sr == 8))
+ m_tss_output = 0xc;
+ else
+ m_tss_output = tss[m_tss_sr & 3];
+ }
+ continue;
+ } else {
+ cycles = 0;
+ }
+ }
+ m_last_sync = next_sync;
+}
diff --git a/src/devices/machine/swim2.h b/src/devices/machine/swim2.h
index dc729fe533e..bbb9e0116cd 100644
--- a/src/devices/machine/swim2.h
+++ b/src/devices/machine/swim2.h
@@ -30,16 +30,39 @@ public:
virtual void set_floppy(floppy_image_device *floppy) override;
virtual floppy_image_device *get_floppy() const override;
+ virtual void sync() 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 {
+ M_MARK = 0x100,
+ M_CRC = 0x200,
+ M_CRC0 = 0x400
+ };
+
floppy_image_device *m_floppy;
u8 m_param[4];
- u8 m_mode, m_setup, m_param_idx;
-
+ u8 m_mode, m_setup, m_error, m_param_idx, m_fifo_pos, m_tss_sr, m_tss_output, m_current_bit;
+ u16 m_fifo[2], m_sr;
+ u16 m_crc;
+ u32 m_half_cycles_before_change;
+
+ u64 m_last_sync;
+ u64 m_flux_write_start;
+ std::array<u64, 36> m_flux_write;
+ u32 m_flux_write_count;
+
+ u64 time_to_cycles(const attotime &tm) const;
+ attotime cycles_to_time(u64 cycles) const;
+
+ void fifo_clear();
+ bool fifo_push(u16 data);
+ u16 fifo_pop();
+ void flush_write(u64 when = 0);
void show_mode() const;
};
diff --git a/src/devices/machine/swim3.cpp b/src/devices/machine/swim3.cpp
index e194deb2f17..53ff0ce7151 100644
--- a/src/devices/machine/swim3.cpp
+++ b/src/devices/machine/swim3.cpp
@@ -171,3 +171,6 @@ void swim3_device::write(offs_t offset, u8 data)
}
}
+void swim3_device::sync()
+{
+}
diff --git a/src/devices/machine/swim3.h b/src/devices/machine/swim3.h
index 6e353dc9740..d9eec0e2bf3 100644
--- a/src/devices/machine/swim3.h
+++ b/src/devices/machine/swim3.h
@@ -30,6 +30,8 @@ public:
virtual void set_floppy(floppy_image_device *floppy) override;
virtual floppy_image_device *get_floppy() const override;
+ virtual void sync() override;
+
protected:
virtual void device_start() override;
virtual void device_reset() override;
diff --git a/src/mame/machine/mac.cpp b/src/mame/machine/mac.cpp
index bcc0697a8bb..1337bc1caa2 100644
--- a/src/mame/machine/mac.cpp
+++ b/src/mame/machine/mac.cpp
@@ -923,7 +923,8 @@ uint16_t mac_state::mac_via_r(offs_t offset)
logerror("mac_via_r: offset=0x%02x\n", offset);
data = m_via1->read(offset);
- m_maincpu->adjust_icount(m_via_cycles);
+ if (!machine().side_effects_disabled())
+ m_maincpu->adjust_icount(m_via_cycles);
return (data & 0xff) | (data << 8);
}