64h156: Refactored to not device_execute. (nw)

This commit is contained in:
Curt Coder 2014-02-09 21:53:34 +00:00
parent e187bc4a43
commit f44b1831a6
2 changed files with 440 additions and 439 deletions

View File

@ -15,7 +15,7 @@
http://personalpages.tds.net/~rcarlsen/cbm/1541/1541%20EARLY/1540-2.GIF
- write circuitry
- write
- cycle exact VIA
- get these running and we're golden
@ -37,8 +37,6 @@
#define LOG 0
#define ATN (m_atni ^ m_atna)
#define CYCLES_UNTIL_ANALOG_DESYNC 288 // 18 us
@ -51,237 +49,6 @@ const device_type C64H156 = &device_creator<c64h156_device>;
//**************************************************************************
// INLINE HELPERS
//**************************************************************************
//-------------------------------------------------
// set_atn_line -
//-------------------------------------------------
inline void c64h156_device::set_atn_line()
{
m_write_atn(ATN);
}
//-------------------------------------------------
// get_next_edge -
//-------------------------------------------------
inline void c64h156_device::get_next_edge(attotime when)
{
m_edge = m_floppy->get_next_transition(when);
}
//-------------------------------------------------
// receive_bit - receive bit
//-------------------------------------------------
inline void c64h156_device::receive_bit()
{
attotime when = machine().time();
attotime next = when + m_period;
m_bit_sync = (m_edge.is_never() || m_edge >= next) ? 0 : 1;
if (m_bit_sync) {
m_zero_count = 0;
m_cycles_until_random_flux = (rand() % 31) + 289;
get_next_edge(when);
} else {
m_zero_count++;
}
if (m_zero_count >= m_cycles_until_random_flux) {
m_bit_sync = 1;
m_zero_count = 0;
m_cycles_until_random_flux = (rand() % 367) + 33;
}
}
//-------------------------------------------------
// decode_bit -
//-------------------------------------------------
inline void c64h156_device::decode_bit()
{
// UE7
bool ue7_tc = false;
if (!m_last_bit_sync && m_bit_sync)
{
m_ue7 = m_ds;
}
else
{
m_ue7++;
if (m_ue7 == 16)
{
m_ue7 = m_ds;
ue7_tc = true;
}
}
if (LOG) logerror("%s UE7 CTR %01x TC %u, ", machine().time().as_string(),m_ue7, ue7_tc);
// UF4
if (!m_last_bit_sync && m_bit_sync)
{
m_uf4 = 0;
if (LOG) logerror("--");
}
else
{
if (!m_ue7_tc && ue7_tc)
{
m_uf4++;
m_uf4 &= 0x0f;
if (LOG) logerror("++");
}
else
{
if (LOG) logerror(" ");
}
}
m_last_bit_sync = m_bit_sync;
m_ue7_tc = ue7_tc;
int uf4_qa = BIT(m_uf4, 0);
int uf4_qb = BIT(m_uf4, 1);
int uf4_qc = BIT(m_uf4, 2);
int uf4_qd = BIT(m_uf4, 3);
int ue5a = !(uf4_qc || uf4_qd);
if (LOG) logerror("UF4 CTR %01x %u%u%u%u UE5A %u, ", m_uf4, uf4_qd, uf4_qc, uf4_qb, uf4_qa, ue5a);
if (!m_uf4_qb && uf4_qb)
{
// shift bits thru flip-flops
m_u4b = m_u4a;
m_u4a = BIT(m_ud2, 7);
// shift in data bit
m_ud2 <<= 1;
m_ud2 |= ue5a;
if (LOG) logerror("<<");
}
else
{
if (LOG) logerror(" ");
}
if (LOG) logerror("UD2 %u%u%u%u%u%u%u%u%u%u : %02x (%02x), ", m_u4b, m_u4a, BIT(m_ud2, 7), BIT(m_ud2, 6), BIT(m_ud2, 5), BIT(m_ud2, 4), BIT(m_ud2, 3), BIT(m_ud2, 2), BIT(m_ud2, 1), BIT(m_ud2, 0), m_ud2, m_shift & 0xff);
// UE3
int block_sync = !(m_oe && (m_ud2 == 0xff) && m_u4a && m_u4b);
if (LOG) logerror("SYNC %u, ", block_sync);
if (!block_sync)
{
// load UE3
m_ue3 = 8; // pin D is floating and TTL inputs float high
if (LOG) logerror("--");
}
else
{
if (m_block_sync && !m_uf4_qb && uf4_qb)
{
// clock UE3
m_ue3++;
m_ue3 &= 0x0f;
if (LOG) logerror("++");
}
else
{
if (LOG) logerror(" ");
}
}
int ue3_qa = BIT(m_ue3, 0);
int ue3_qb = BIT(m_ue3, 1);
int ue3_qc = BIT(m_ue3, 2);
int uf3a = !(ue3_qa && ue3_qb && ue3_qc);
int uc1b = !uf3a; // schmitt trigger
if (LOG) logerror("UE3 CTR %01x UF3A %u UC1B %u, ", m_ue3, uf3a, uc1b);
int byte_sync = !(uc1b && m_soe && !uf4_qb);
if (LOG) logerror("BYTE %u SOE %u\n", byte_sync, m_soe);
// UD3
#ifdef WRITE_SUPPORTED
int uf3b = !(uc1b && uf4_qa && uf4_qb);
if (!uf3b)
{
m_ud3 = m_via_pa;
}
else if (!m_uf4_qb && uf4_qb)
{
// shift out bits
int ud3_qh = BIT(m_ud3, 0);
m_ud3 >>= 1;
int uf5b = !(!uf4_qb && ud3_qh);
if (!m_oe && m_floppy->wpt_r())
{
// TODO write bit to disk
if (LOG) logerror("WRITE BIT %u\n", uf5b);
}
}
#endif
// prepare for next cycle
if (m_block_sync != block_sync)
{
m_block_sync = block_sync;
m_write_sync(m_block_sync);
}
if (m_byte_sync != byte_sync)
{
m_byte_sync = byte_sync;
if (m_accl)
{
if (!byte_sync)
{
m_accl_yb = m_ud2;
m_accl_byte_sync = byte_sync;
m_write_byte(m_accl_byte_sync);
}
}
else
{
m_write_byte(m_byte_sync);
}
}
m_uf4_qb = uf4_qb;
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@ -290,43 +57,29 @@ inline void c64h156_device::decode_bit()
// c64h156_device - constructor
//-------------------------------------------------
c64h156_device::c64h156_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, C64H156, "64H156", tag, owner, clock, "c64h156", __FILE__),
device_execute_interface(mconfig, *this),
m_icount(0),
m_write_atn(*this),
m_write_sync(*this),
m_write_byte(*this),
m_floppy(NULL),
m_period(attotime::from_hz(clock)),
m_edge(attotime::never),
m_shift(0),
m_mtr(0),
m_accl(0),
m_stp(-1),
m_ds(0),
m_soe(0),
m_oe(0),
m_atni(1),
m_atna(1),
m_last_bit_sync(0),
m_bit_sync(0),
m_byte_sync(1),
m_accl_byte_sync(1),
m_block_sync(1),
m_ue7(0),
m_ue7_tc(0),
m_uf4(0),
m_uf4_qb(0),
m_ud2(0),
m_accl_yb(0),
m_u4a(0),
m_u4b(0),
m_ue3(0),
m_uc1b(0),
m_zero_count(0),
m_cycles_until_random_flux(0)
c64h156_device::c64h156_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, C64H156, "64H156", tag, owner, clock, "c64h156", __FILE__),
m_write_atn(*this),
m_write_sync(*this),
m_write_byte(*this),
m_floppy(NULL),
m_mtr(1),
m_accl(0),
m_stp(0),
m_ds(0),
m_soe(0),
m_oe(1),
m_ted(0),
m_yb(0),
m_atni(0),
m_atna(0),
m_period(attotime::from_hz(clock))
{
cur_live.tm = attotime::never;
cur_live.state = IDLE;
cur_live.next_state = -1;
cur_live.write_position = 0;
cur_live.write_start_time = attotime::never;
}
@ -336,63 +89,305 @@ c64h156_device::c64h156_device(const machine_config &mconfig, const char *tag, d
void c64h156_device::device_start()
{
// set our instruction counter
m_icountptr = &m_icount;
// resolve callbacks
m_write_atn.resolve_safe();
m_write_sync.resolve_safe();
m_write_byte.resolve_safe();
// allocate timer
t_gen = timer_alloc(0);
// register for state saving
save_item(NAME(m_shift));
save_item(NAME(m_mtr));
save_item(NAME(m_accl));
save_item(NAME(m_stp));
save_item(NAME(m_ds));
save_item(NAME(m_soe));
save_item(NAME(m_oe));
save_item(NAME(m_ted));
save_item(NAME(m_yb));
save_item(NAME(m_atni));
save_item(NAME(m_atna));
save_item(NAME(m_last_bit_sync));
save_item(NAME(m_bit_sync));
save_item(NAME(m_byte_sync));
save_item(NAME(m_accl_byte_sync));
save_item(NAME(m_block_sync));
save_item(NAME(m_ue7));
save_item(NAME(m_ue7_tc));
save_item(NAME(m_uf4));
save_item(NAME(m_uf4_qb));
save_item(NAME(m_ud2));
save_item(NAME(m_accl_yb));
save_item(NAME(m_u4a));
save_item(NAME(m_u4b));
save_item(NAME(m_ue3));
save_item(NAME(m_uc1b));
save_item(NAME(m_via_pa));
save_item(NAME(m_ud3));
save_item(NAME(m_zero_count));
save_item(NAME(m_cycles_until_random_flux));
}
//-------------------------------------------------
// execute_run -
// device_reset - device-specific reset
//-------------------------------------------------
void c64h156_device::execute_run()
void c64h156_device::device_reset()
{
do
{
if (m_mtr)
{
receive_bit();
live_abort();
}
//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
void c64h156_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
live_sync();
live_run();
}
void c64h156_device::live_start()
{
cur_live.tm = machine().time();
cur_live.state = RUNNING;
cur_live.next_state = -1;
cur_live.shift_reg = 0;
cur_live.shift_reg_write = 0;
cur_live.cycle_counter = 0;
cur_live.cell_counter = 0;
cur_live.bit_counter = 0;
cur_live.ds = m_ds;
cur_live.oe = m_oe;
cur_live.soe = m_soe;
cur_live.accl = m_accl;
checkpoint_live = cur_live;
live_run();
}
void c64h156_device::checkpoint()
{
get_next_edge(machine().time());
checkpoint_live = cur_live;
}
void c64h156_device::rollback()
{
cur_live = checkpoint_live;
get_next_edge(cur_live.tm);
}
void c64h156_device::start_writing(attotime tm)
{
cur_live.write_start_time = tm;
cur_live.write_position = 0;
}
void c64h156_device::stop_writing(attotime tm)
{
commit(tm);
cur_live.write_start_time = attotime::never;
}
bool c64h156_device::write_next_bit(bool bit, attotime limit)
{
if(cur_live.write_start_time.is_never()) {
cur_live.write_start_time = cur_live.tm;
cur_live.write_position = 0;
}
attotime etime = cur_live.tm + m_period;
if(etime > limit)
return true;
if(bit && cur_live.write_position < ARRAY_LENGTH(cur_live.write_buffer))
cur_live.write_buffer[cur_live.write_position++] = cur_live.tm;
if (LOG) logerror("%s write bit %u (%u)\n", cur_live.tm.as_string(), cur_live.bit_counter, bit);
return false;
}
void c64h156_device::commit(attotime tm)
{
if(cur_live.write_start_time.is_never() || tm == cur_live.write_start_time || !cur_live.write_position)
return;
if (LOG) logerror("%s committing %u transitions since %s\n", tm.as_string(), cur_live.write_position, cur_live.write_start_time.as_string());
m_floppy->write_flux(cur_live.write_start_time, tm, cur_live.write_position, cur_live.write_buffer);
cur_live.write_start_time = tm;
cur_live.write_position = 0;
}
void c64h156_device::live_delay(int state)
{
cur_live.next_state = state;
if(cur_live.tm != machine().time())
t_gen->adjust(cur_live.tm - machine().time());
else
live_sync();
}
void c64h156_device::live_sync()
{
if(!cur_live.tm.is_never()) {
if(cur_live.tm > machine().time()) {
rollback();
live_run(machine().time());
commit(cur_live.tm);
} else {
commit(cur_live.tm);
if(cur_live.next_state != -1) {
cur_live.state = cur_live.next_state;
cur_live.next_state = -1;
}
if(cur_live.state == IDLE) {
stop_writing(cur_live.tm);
cur_live.tm = attotime::never;
}
}
cur_live.next_state = -1;
checkpoint();
}
}
void c64h156_device::live_abort()
{
if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
rollback();
live_run(machine().time());
}
stop_writing(cur_live.tm);
cur_live.tm = attotime::never;
cur_live.state = IDLE;
cur_live.next_state = -1;
cur_live.write_position = 0;
cur_live.write_start_time = attotime::never;
cur_live.sync = 1;
cur_live.byte = 1;
}
void c64h156_device::live_run(attotime limit)
{
if(cur_live.state == IDLE || cur_live.next_state != -1)
return;
for(;;) {
switch(cur_live.state) {
case RUNNING: {
bool syncpoint = false;
if (cur_live.tm > limit)
return;
int bit = get_next_bit(cur_live.tm, limit);
if(bit < 0)
return;
int cell_counter = cur_live.cell_counter;
if (bit) {
cur_live.cycle_counter = cur_live.ds;
cur_live.cell_counter = 0;
} else {
cur_live.cycle_counter++;
}
if (cur_live.cycle_counter == 16) {
cur_live.cycle_counter = cur_live.ds;
cur_live.cell_counter++;
cur_live.cell_counter &= 0xf;
}
if (!BIT(cell_counter, 1) && BIT(cur_live.cell_counter, 1)) {
// read bit
cur_live.shift_reg <<= 1;
cur_live.shift_reg |= !(BIT(cur_live.cell_counter, 3) || BIT(cur_live.cell_counter, 2));
cur_live.shift_reg &= 0x3ff;
if (LOG) logerror("%s read bit %u (%u) >> %03x, oe=%u soe=%u sync=%u byte=%u\n", cur_live.tm.as_string(), cur_live.bit_counter,
!(BIT(cur_live.cell_counter, 3) || BIT(cur_live.cell_counter, 2)), cur_live.shift_reg, cur_live.oe, cur_live.soe, cur_live.sync, cur_live.byte);
// write bit
if (!cur_live.oe) {
write_next_bit(BIT(cur_live.shift_reg_write, 7), limit);
}
syncpoint = true;
}
int sync = !((cur_live.shift_reg == 0x3ff) && cur_live.oe);
if (!sync) {
cur_live.bit_counter = 8;
} else if (!BIT(cell_counter, 1) && BIT(cur_live.cell_counter, 1) && cur_live.sync) {
cur_live.bit_counter++;
cur_live.bit_counter &= 0xf;
}
int byte = !(((cur_live.bit_counter & 7) == 7) && cur_live.soe && !BIT(cur_live.cell_counter, 1));
int load = !(((cur_live.bit_counter & 7) == 7) && BIT(cur_live.cell_counter, 0) && BIT(cur_live.cell_counter, 1));
if (!load) {
cur_live.shift_reg_write = cur_live.yb;
// TODO use data read from disk if via PA is in read mode
//if (LOG) logerror("%s load write shift register %02x\n",cur_live.tm.as_string(),cur_live.shift_reg_write);
} else {
cur_live.shift_reg_write <<= 1;
cur_live.shift_reg_write &= 0xff;
}
// update signals
if (byte != cur_live.byte) {
if (!byte || !cur_live.accl) {
if (LOG) logerror("%s BYTE %u\n", cur_live.tm.as_string(),byte);
cur_live.byte = byte;
syncpoint = true;
}
if (!byte) {
cur_live.accl_yb = cur_live.shift_reg & 0xff;
}
}
if (sync != cur_live.sync) {
if (LOG) logerror("%s SYNC %u\n", cur_live.tm.as_string(),sync);
cur_live.sync = sync;
syncpoint = true;
}
if (syncpoint) {
commit(cur_live.tm);
cur_live.tm += m_period;
live_delay(RUNNING_SYNCPOINT);
return;
}
cur_live.tm += m_period;
break;
}
decode_bit();
case RUNNING_SYNCPOINT: {
m_write_sync(cur_live.sync);
m_write_byte(cur_live.byte);
m_icount--;
} while (m_icount > 0);
cur_live.state = RUNNING;
checkpoint();
break;
}
}
}
}
void c64h156_device::get_next_edge(attotime when)
{
cur_live.edge = m_floppy->get_next_transition(when);
}
int c64h156_device::get_next_bit(attotime &tm, attotime limit)
{
attotime next = tm + m_period;
int bit = (cur_live.edge.is_never() || cur_live.edge >= next) ? 0 : 1;
if (bit) {
get_next_edge(next);
}
return bit && cur_live.oe;
}
@ -402,23 +397,11 @@ void c64h156_device::execute_run()
READ8_MEMBER( c64h156_device::yb_r )
{
UINT8 data = 0;
if (m_soe)
{
if (m_accl)
{
data = m_accl_yb;
}
else
{
data = m_ud2;
}
if (checkpoint_live.accl) {
return checkpoint_live.accl_yb;
} else {
return checkpoint_live.shift_reg;
}
if (LOG) logerror("%s YB read %02x:%02x\n", machine().describe_context(), m_ud2, data);
return data;
}
@ -428,7 +411,15 @@ READ8_MEMBER( c64h156_device::yb_r )
WRITE8_MEMBER( c64h156_device::yb_w )
{
m_via_pa = data;
if (m_yb != data)
{
live_sync();
m_yb = cur_live.yb = data;
checkpoint();
if (LOG) logerror("%s YB %02x\n", machine().time().as_string(), data);
live_run();
}
}
@ -447,38 +438,14 @@ WRITE_LINE_MEMBER( c64h156_device::test_w )
WRITE_LINE_MEMBER( c64h156_device::accl_w )
{
m_accl = state;
}
//-------------------------------------------------
// sync_r - sync read
//-------------------------------------------------
READ_LINE_MEMBER( c64h156_device::sync_r )
{
return m_block_sync;
}
//-------------------------------------------------
// byte_r - byte ready read
//-------------------------------------------------
READ_LINE_MEMBER( c64h156_device::byte_r )
{
int state = 1;
if (m_accl)
if (m_accl != state)
{
state = m_accl_byte_sync;
live_sync();
m_accl = cur_live.accl = state;
checkpoint();
if (LOG) logerror("%s ACCL %u\n", machine().time().as_string(), state);
live_run();
}
else
{
state = m_byte_sync;
}
return state;
}
@ -488,11 +455,17 @@ READ_LINE_MEMBER( c64h156_device::byte_r )
WRITE_LINE_MEMBER( c64h156_device::ted_w )
{
if (m_accl && !m_accl_byte_sync && !state)
if (m_ted != state)
{
m_accl_byte_sync = 1;
m_write_byte(m_accl_byte_sync);
live_sync();
if (m_ted && !state && cur_live.accl && !cur_live.byte) {
cur_live.byte = 1;
m_write_byte(cur_live.byte);
}
m_ted = state;
checkpoint();
if (LOG) logerror("%s TED %u\n", machine().time().as_string(), state);
live_run();
}
}
@ -505,13 +478,21 @@ WRITE_LINE_MEMBER( c64h156_device::mtr_w )
{
if (m_mtr != state)
{
if (LOG) logerror("MTR %u\n", state);
m_floppy->mon_w(!state);
live_sync();
m_mtr = state;
if (LOG) logerror("%s MTR %u\n", machine().time().as_string(), state);
m_floppy->mon_w(!state);
checkpoint();
get_next_edge(machine().time());
if (m_mtr) {
if(cur_live.state == IDLE) {
live_start();
}
} else {
live_abort();
}
live_run();
}
}
@ -522,9 +503,14 @@ WRITE_LINE_MEMBER( c64h156_device::mtr_w )
WRITE_LINE_MEMBER( c64h156_device::oe_w )
{
if (LOG) logerror("OE %u\n", state);
m_oe = state;
if (m_oe != state)
{
live_sync();
m_oe = cur_live.oe = state;
checkpoint();
if (LOG) logerror("%s OE %u\n", machine().time().as_string(), state);
live_run();
}
}
@ -534,19 +520,14 @@ WRITE_LINE_MEMBER( c64h156_device::oe_w )
WRITE_LINE_MEMBER( c64h156_device::soe_w )
{
if (LOG) logerror("SOE %u\n", state);
m_soe = state;
}
//-------------------------------------------------
// atn_r - serial attention read
//-------------------------------------------------
READ_LINE_MEMBER( c64h156_device::atn_r )
{
return ATN;
if (m_soe != state)
{
live_sync();
m_soe = cur_live.soe = state;
checkpoint();
if (LOG) logerror("%s SOE %u\n", machine().time().as_string(), state);
live_run();
}
}
@ -560,7 +541,7 @@ WRITE_LINE_MEMBER( c64h156_device::atni_w )
m_atni = state;
set_atn_line();
m_write_atn(m_atni ^ m_atna);
}
@ -574,7 +555,7 @@ WRITE_LINE_MEMBER( c64h156_device::atna_w )
m_atna = state;
set_atn_line();
m_write_atn(m_atni ^ m_atna);
}
@ -594,9 +575,11 @@ void c64h156_device::set_floppy(floppy_image_device *floppy)
void c64h156_device::stp_w(int stp)
{
if (m_mtr)
if (m_stp != stp)
{
if (m_stp != stp)
live_sync();
if (m_mtr)
{
int track = m_floppy->get_cyl();
int tracks = (stp - track) & 0x03;
@ -618,11 +601,12 @@ void c64h156_device::stp_w(int stp)
m_floppy->stp_w(1);
m_floppy->stp_w(0);
}
m_stp = stp;
}
m_stp = stp;
get_next_edge(machine().time());
checkpoint();
live_run();
}
}
@ -633,7 +617,11 @@ void c64h156_device::stp_w(int stp)
void c64h156_device::ds_w(int ds)
{
if (LOG) logerror("DS %u\n", ds & 0x03);
m_ds = ds & 0x03;
if (m_ds != ds)
{
live_sync();
m_ds = cur_live.ds = ds;
checkpoint();
live_run();
}
}

View File

@ -91,8 +91,7 @@
// ======================> c64h156_device
class c64h156_device : public device_t,
public device_execute_interface
class c64h156_device : public device_t
{
public:
// construction/destruction
@ -104,85 +103,99 @@ public:
DECLARE_READ8_MEMBER( yb_r );
DECLARE_WRITE8_MEMBER( yb_w );
DECLARE_WRITE_LINE_MEMBER( test_w );
DECLARE_WRITE_LINE_MEMBER( accl_w );
DECLARE_READ_LINE_MEMBER( sync_r );
DECLARE_READ_LINE_MEMBER( byte_r );
DECLARE_WRITE_LINE_MEMBER( ted_w );
DECLARE_WRITE_LINE_MEMBER( mtr_w );
DECLARE_WRITE_LINE_MEMBER( oe_w );
DECLARE_WRITE_LINE_MEMBER( soe_w );
DECLARE_READ_LINE_MEMBER( atn_r );
DECLARE_WRITE_LINE_MEMBER( atni_w );
DECLARE_WRITE_LINE_MEMBER( atna_w );
void set_floppy(floppy_image_device *floppy);
DECLARE_READ_LINE_MEMBER( sync_r ) { return checkpoint_live.sync; }
DECLARE_READ_LINE_MEMBER( byte_r ) { return checkpoint_live.byte; }
DECLARE_READ_LINE_MEMBER( atn_r ) { return m_atni ^ m_atna; }
void stp_w(int stp);
void ds_w(int ds);
void set_floppy(floppy_image_device *floppy);
protected:
// device-level overrides
virtual void device_start();
// device_execute_interface overrides
virtual void execute_run();
int m_icount;
inline void set_atn_line();
inline void receive_bit();
inline void decode_bit();
inline void get_next_edge(attotime when);
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
enum {
IDLE,
RUNNING,
RUNNING_SYNCPOINT
};
struct live_info {
attotime tm;
int state, next_state;
int sync;
int byte;
int ds;
int oe;
int soe;
int accl;
UINT8 accl_yb;
attotime edge;
UINT16 shift_reg;
int cycle_counter;
int cell_counter;
int bit_counter;
int zero_counter;
int cycles_until_random_flux;
UINT8 yb;
UINT16 shift_reg_write;
attotime write_start_time;
attotime write_buffer[32];
int write_position;
};
devcb2_write_line m_write_atn;
devcb2_write_line m_write_sync;
devcb2_write_line m_write_byte;
floppy_image_device *m_floppy;
// track
attotime m_period;
attotime m_edge;
UINT16 m_shift;
// motors
int m_mtr; // spindle motor on
// signals
int m_accl; // 1/2 MHz select
int m_mtr;
int m_accl;
int m_stp;
int m_ds; // density select
int m_soe; // serial output enable
int m_oe; // output enable (0 = write, 1 = read)
int m_ds;
int m_soe;
int m_oe;
int m_ted;
UINT8 m_yb;
int m_atni;
int m_atna;
// IEC
int m_atni; // attention input
int m_atna; // attention acknowledge
attotime m_period;
// read logic
int m_last_bit_sync;
int m_bit_sync;
int m_byte_sync;
int m_accl_byte_sync;
int m_block_sync;
int m_ue7;
int m_ue7_tc;
int m_uf4;
int m_uf4_qb;
UINT8 m_ud2;
UINT8 m_accl_yb;
int m_u4a;
int m_u4b;
int m_ue3;
int m_uc1b;
int m_zero_count;
int m_cycles_until_random_flux;
live_info cur_live, checkpoint_live;
emu_timer *t_gen;
// write logic
UINT8 m_via_pa;
UINT8 m_ud3;
void live_start();
void checkpoint();
void rollback();
bool write_next_bit(bool bit, attotime limit);
void start_writing(attotime tm);
void commit(attotime tm);
void stop_writing(attotime tm);
void live_delay(int state);
void live_sync();
void live_abort();
void live_run(attotime limit = attotime::never);
void get_next_edge(attotime when);
int get_next_bit(attotime &tm, attotime limit);
};