diff options
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 |
commit | f960ef21f6a71b8fb9f490bfdf092f5e5e05f214 (patch) | |
tree | ce31d4cbcc22dbce25b62ca4c9e303e19baaa77f | |
parent | 1fced4ec7c773cef7c77380c8f14a960184e59b1 (diff) |
SWIM2: Enough of the write processing to make the timing calibration work.
-rwxr-xr-x | src/devices/machine/applefdintf.h | 4 | ||||
-rw-r--r-- | src/devices/machine/iwm.h | 3 | ||||
-rw-r--r-- | src/devices/machine/swim1.cpp | 3 | ||||
-rw-r--r-- | src/devices/machine/swim1.h | 2 | ||||
-rw-r--r-- | src/devices/machine/swim2.cpp | 312 | ||||
-rw-r--r-- | src/devices/machine/swim2.h | 27 | ||||
-rw-r--r-- | src/devices/machine/swim3.cpp | 3 | ||||
-rw-r--r-- | src/devices/machine/swim3.h | 2 | ||||
-rw-r--r-- | src/mame/machine/mac.cpp | 3 |
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); } |