mirror of
https://github.com/holub/mame
synced 2025-04-26 18:23:08 +03:00
64h156: Refactored to not device_execute. (nw)
This commit is contained in:
parent
e187bc4a43
commit
f44b1831a6
@ -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();
|
||||
|
||||
m_icount--;
|
||||
} while (m_icount > 0);
|
||||
case RUNNING_SYNCPOINT: {
|
||||
m_write_sync(cur_live.sync);
|
||||
m_write_byte(cur_live.byte);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user