iwm: Do a complete clock change on sync write for better flux change time precision

iwm: Increate the flux write buffer size for better performance (complete sector write in a single call)
2gs: Correct the q3 clock value, making (sync) writes reliable
This commit is contained in:
Olivier Galibert 2022-04-24 12:44:37 +02:00
parent 1b3081129d
commit 623e248524
3 changed files with 39 additions and 37 deletions

View File

@ -30,16 +30,6 @@ iwm_device::iwm_device(const machine_config &mconfig, const char *tag, device_t
m_fclk_q3_ratio = q3_clock ? double(q3_clock)/double(clock) : 0; // ~4
}
u64 iwm_device::q3_to_fclk(u64 cycles) const
{
return u64(m_q3_fclk_ratio * double(cycles) + 0.5);
}
u64 iwm_device::fclk_to_q3(u64 cycles) const
{
return u64(m_fclk_q3_ratio * double(cycles) + 0.5);
}
void iwm_device::device_start()
{
applefdintf_device::device_start();
@ -53,6 +43,7 @@ void iwm_device::device_start()
save_item(NAME(m_flux_write));
save_item(NAME(m_flux_write_count));
save_item(NAME(m_q3_clock));
save_item(NAME(m_q3_clock_active));
save_item(NAME(m_active));
save_item(NAME(m_rw));
save_item(NAME(m_rw_state));
@ -88,6 +79,7 @@ void iwm_device::device_reset()
m_rw_bit_count = 0;
m_devsel = 0;
m_devsel_cb(0);
m_q3_clock_active = false;
}
void iwm_device::device_timer(emu_timer &, device_timer_id, int)
@ -199,7 +191,7 @@ u8 iwm_device::control(int offset, u8 data)
if(m_rw != MODE_READ) {
if(m_rw == MODE_WRITE) {
flush_write();
m_flux_write_start = 0;
write_clock_stop();
}
m_rw = MODE_READ;
m_rw_state = S_IDLE;
@ -215,8 +207,7 @@ u8 iwm_device::control(int offset, u8 data)
m_rw_state = S_IDLE;
m_whd |= 0x40;
m_next_state_change = 0;
m_flux_write_start = m_last_sync;
m_flux_write_count = 0;
write_clock_start();
if(m_floppy)
m_floppy->set_write_splice(cycles_to_time(m_flux_write_start));
}
@ -225,7 +216,7 @@ u8 iwm_device::control(int offset, u8 data)
if(m_active == MODE_ACTIVE) {
flush_write();
if(m_mode & 0x04) {
m_flux_write_start = 0;
write_clock_stop();
m_active = MODE_IDLE;
m_rw = MODE_IDLE;
m_rw_state = S_IDLE;
@ -318,12 +309,12 @@ void iwm_device::data_w(u8 data)
u64 iwm_device::time_to_cycles(const attotime &tm) const
{
return tm.as_ticks(clock());
return tm.as_ticks(m_q3_clock_active ? m_q3_clock : clock());
}
attotime iwm_device::cycles_to_time(u64 cycles) const
{
return attotime::from_ticks(cycles, clock());
return attotime::from_ticks(cycles, m_q3_clock_active ? m_q3_clock : clock());
}
bool iwm_device::is_sync() const
@ -333,6 +324,9 @@ bool iwm_device::is_sync() const
u64 iwm_device::half_window_size() const
{
if(m_q3_clock_active)
return m_mode & 0x08 ? 2 : 4;
switch(m_mode & 0x18) {
case 0x00: return 14;
case 0x08: return 7;
@ -344,6 +338,9 @@ u64 iwm_device::half_window_size() const
u64 iwm_device::window_size() const
{
if(m_q3_clock_active)
return m_mode & 0x08 ? 4 : 8;
switch(m_mode & 0x18) {
case 0x00: return 28;
case 0x08: return 14;
@ -358,9 +355,23 @@ u64 iwm_device::read_register_update_delay() const
return m_mode & 0x08 ? 4 : 8;
}
u64 iwm_device::write_sync_half_window_size() const
void iwm_device::write_clock_start()
{
return m_mode & 0x08 ? 2 : 4;
if(is_sync() && m_q3_clock) {
m_q3_clock_active = true;
m_last_sync = machine().time().as_ticks(m_q3_clock);
}
m_flux_write_start = m_last_sync;
m_flux_write_count = 0;
}
void iwm_device::write_clock_stop()
{
if(m_q3_clock_active) {
m_q3_clock_active = false;
m_last_sync = machine().time().as_ticks(clock());
}
m_flux_write_start = 0;
}
void iwm_device::sync()
@ -368,7 +379,7 @@ void iwm_device::sync()
if(!m_active)
return;
u64 next_sync = machine().time().as_ticks(clock());
u64 next_sync = machine().time().as_ticks(m_q3_clock_active ? m_q3_clock : clock());
switch(m_rw) {
case MODE_IDLE:
m_last_sync = next_sync;
@ -463,10 +474,7 @@ void iwm_device::sync()
} else {
m_wsh = m_data;
m_rw_state = SW_WINDOW_MIDDLE;
if(m_q3_clock)
m_next_state_change = q3_to_fclk(fclk_to_q3(m_last_sync) + write_sync_half_window_size());
else
m_next_state_change = m_last_sync + half_window_size();
m_next_state_change = m_last_sync + half_window_size();
}
break;
@ -474,7 +482,7 @@ void iwm_device::sync()
if(m_whd & 0x80) {
logerror("underrun\n");
flush_write(next_sync);
m_flux_write_start = 0;
write_clock_stop();
m_whd &= ~0x40;
m_last_sync = next_sync;
m_rw_state = SW_UNDERRUN;
@ -492,10 +500,7 @@ void iwm_device::sync()
m_flux_write[m_flux_write_count++] = m_last_sync;
m_wsh <<= 1;
m_rw_state = SW_WINDOW_END;
if((m_mode & 0x02) || !m_q3_clock)
m_next_state_change = m_last_sync + half_window_size();
else
m_next_state_change = q3_to_fclk(fclk_to_q3(m_last_sync) + write_sync_half_window_size());
m_next_state_change = m_last_sync + half_window_size();
break;
case SW_WINDOW_END:
@ -512,10 +517,7 @@ void iwm_device::sync()
m_next_state_change = m_last_sync + half_window_size();
}
} else {
if(m_q3_clock)
m_next_state_change = q3_to_fclk(fclk_to_q3(m_last_sync) + write_sync_half_window_size());
else
m_next_state_change = m_last_sync + half_window_size();
m_next_state_change = m_last_sync + half_window_size();
m_rw_state = SW_WINDOW_MIDDLE;
}
break;

View File

@ -62,19 +62,18 @@ private:
double m_q3_fclk_ratio, m_fclk_q3_ratio;
u64 m_last_sync, m_next_state_change, m_sync_update, m_async_update;
u64 m_flux_write_start;
std::array<u64, 16> m_flux_write;
std::array<u64, 65536> m_flux_write;
u32 m_flux_write_count;
u32 m_q3_clock;
int m_active, m_rw, m_rw_state;
u8 m_data, m_whd, m_mode, m_status, m_control, m_rw_bit_count;
u8 m_rsh, m_wsh;
u8 m_devsel;
bool m_q3_clock_active;
u8 control(int offset, u8 data);
u64 time_to_cycles(const attotime &tm) const;
attotime cycles_to_time(u64 cycles) const;
u64 fclk_to_q3(u64 cycles) const;
u64 q3_to_fclk(u64 cycles) const;
void mode_w(u8 data);
void data_w(u8 data);
@ -82,9 +81,10 @@ private:
u64 window_size() const;
u64 half_window_size() const;
u64 read_register_update_delay() const;
u64 write_sync_half_window_size() const;
inline bool is_sync() const;
void flush_write(u64 when = 0);
void write_clock_start();
void write_clock_stop();
};
DECLARE_DEVICE_TYPE(IWM, iwm_device)

View File

@ -4808,7 +4808,7 @@ void apple2gs_state::apple2gs(machine_config &config)
A2BUS_SLOT(config, "sl6", m_a2bus, apple2gs_cards, nullptr);
A2BUS_SLOT(config, "sl7", m_a2bus, apple2gs_cards, nullptr);
IWM(config, m_iwm, A2GS_7M, 1021800*2);
IWM(config, m_iwm, A2GS_7M, A2GS_MASTER_CLOCK/14);
m_iwm->phases_cb().set(FUNC(apple2gs_state::phases_w));
m_iwm->sel35_cb().set(FUNC(apple2gs_state::sel35_w));
m_iwm->devsel_cb().set(FUNC(apple2gs_state::devsel_w));