ay31015: Fix receiver desync when next start bit arrives early

This commit is contained in:
AJR 2018-03-16 01:01:00 -04:00
parent 084d9a4ed3
commit f715fc495c
2 changed files with 51 additions and 15 deletions

View File

@ -79,6 +79,8 @@ Start bit (low), Bit 0, Bit 1... highest bit, Parity bit (if enabled), 1-2 stop
#include "emu.h"
#include "ay31015.h"
//#define VERBOSE 1
#include "logmacro.h"
/* control reg */
@ -147,10 +149,12 @@ ay51013_device::ay51013_device(const machine_config &mconfig, const char *tag, d
}
//-------------------------------------------------
// device_start - device-specific startup
// device_resolve_objects - resolve objects that
// may be needed for other devices to set
// initial conditions at start time
//-------------------------------------------------
void ay31015_device::device_start()
void ay31015_device::device_resolve_objects()
{
m_read_si_cb.resolve();
m_write_so_cb.resolve();
@ -161,7 +165,14 @@ void ay31015_device::device_start()
m_write_fe_cb.resolve();
m_write_pe_cb.resolve();
m_write_eoc_cb.resolve();
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void ay31015_device::device_start()
{
m_rx_timer = timer_alloc(TIMER_RX);
m_rx_timer->adjust(attotime::never);
update_rx_timer();
@ -281,7 +292,10 @@ void ay31015_device::rx_process()
case PREP_TIME: // assist sync by ensuring high bit occurs
m_rx_pulses--;
if (get_si())
{
LOG("Receiver idle\n");
m_rx_state = IDLE;
}
return;
case IDLE:
@ -298,11 +312,15 @@ void ay31015_device::rx_process()
if (m_rx_pulses == 8) // start bit must be low at sample time
{
if (get_si())
{
LOG("Receive false start bit\n");
m_rx_state = IDLE;
}
}
else
if (!m_rx_pulses) // end of start bit
{
LOG("Receive start bit\n");
m_rx_state = PROCESSING;
m_rx_pulses = m_total_pulses;
m_rx_bit_count = 0;
@ -330,6 +348,7 @@ void ay31015_device::rx_process()
m_internal_sample = get_si();
m_rx_parity ^= m_internal_sample; // calculate cumulative parity
m_rx_data |= m_internal_sample << m_rx_bit_count;
LOG("Receive data bit #%d: %d\n", m_rx_bit_count + 1, m_internal_sample);
}
return;
@ -359,7 +378,10 @@ void ay31015_device::rx_process()
case FIRST_STOP_BIT:
m_rx_pulses--;
if (m_rx_pulses == 8) // sample input stream
{
m_internal_sample = get_si();
LOG("Receive stop bit: %d\n", m_internal_sample);
}
else
if (m_rx_pulses == 7) // set error flags
{
@ -393,20 +415,18 @@ void ay31015_device::rx_process()
update_status_pins();
}
else
if (m_rx_pulses == 4)
if (m_rx_pulses == 4 && m_second_stop_bit)
{
if (m_second_stop_bit)
{
/* We should wait for the full first stop bit and
the beginning of the second stop bit */
m_rx_state = SECOND_STOP_BIT;
m_rx_pulses += m_second_stop_bit - 7;
}
else
{
/* We have seen a STOP bit, go back to PREP_TIME */
m_rx_state = PREP_TIME;
}
/* We should wait for the full first stop bit and
the beginning of the second stop bit */
m_rx_state = SECOND_STOP_BIT;
m_rx_pulses += m_second_stop_bit - 7;
}
else
if (!m_rx_pulses)
{
/* We have seen a STOP bit, go back to IDLE */
m_rx_state = IDLE;
}
return;
@ -458,6 +478,7 @@ void ay31015_device::tx_process()
m_status_reg &= ~STATUS_EOC; // we are no longer idle
m_tx_parity = 0;
update_status_pins();
LOG("Transmit start bit\n");
}
m_tx_pulses--;
@ -478,6 +499,7 @@ void ay31015_device::tx_process()
}
else
set_so(0);
LOG("Transmit data bit #%d: %d\n", 9 - (m_tx_pulses >> 4), m_tx_data & 1);
m_tx_data >>= 1; // adjust the shift register
}
@ -503,6 +525,7 @@ void ay31015_device::tx_process()
set_so(1); /* extra bit to set the correct parity */
else
set_so(0); /* it was already correct */
LOG("Transmit parity bit: %d\n", t1);
}
m_tx_pulses--;
@ -515,7 +538,10 @@ void ay31015_device::tx_process()
case FIRST_STOP_BIT:
if (m_tx_pulses == 16)
{
set_so(1); /* create a stop bit (marking and soon idle) */
LOG("Transmit stop bit\n");
}
m_tx_pulses--;
if (!m_tx_pulses)
{
@ -524,10 +550,14 @@ void ay31015_device::tx_process()
{
m_tx_state = SECOND_STOP_BIT;
m_tx_pulses = m_second_stop_bit;
LOG("Transmit second stop bit\n");
}
else
if (m_status_reg & STATUS_TBMT)
{
m_tx_state = IDLE; // if nothing to send, go idle
LOG("Transmitter idle\n");
}
else
{
m_tx_pulses = 16;
@ -538,11 +568,16 @@ void ay31015_device::tx_process()
return;
case SECOND_STOP_BIT:
if (m_tx_pulses == 16)
LOG("Transmit second stop bit\n");
m_tx_pulses--;
if (!m_tx_pulses)
{
if (m_status_reg & STATUS_TBMT)
{
m_tx_state = IDLE; // if nothing to send, go idle
LOG("Transmitter idle\n");
}
else
{
m_tx_pulses = 16;

View File

@ -119,6 +119,7 @@ protected:
ay31015_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_resolve_objects() override;
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;