via6522: refactored shifter supporting more fetures and fixed a few bugs

This commit is contained in:
Joakim Larsson Edstrom 2017-04-27 22:53:39 +02:00
parent 2e0b32497c
commit 70caa17943

View File

@ -39,8 +39,9 @@
#define LOG_READ (1U << 3) #define LOG_READ (1U << 3)
#define LOG_INT (1U << 4) #define LOG_INT (1U << 4)
#define VERBOSE (LOG_SETUP | LOG_SHIFT | LOG_INT)
//#define VERBOSE (LOG_SHIFT) //#define VERBOSE (LOG_SHIFT)
//#define LOG_OUTPUT_FUNC printf #define LOG_OUTPUT_FUNC printf
#include "logmacro.h" #include "logmacro.h"
@ -362,26 +363,35 @@ void via6522_device::clear_int(int data)
void via6522_device::shift_out() void via6522_device::shift_out()
{ {
// Only shift out msb on falling flank
if (m_shift_counter & 1)
{
LOGSHIFT(" %s shift Out SR: %02x->", tag(), m_sr); LOGSHIFT(" %s shift Out SR: %02x->", tag(), m_sr);
m_out_cb2 = (m_sr >> 7) & 1; m_out_cb2 = (m_sr >> 7) & 1;
m_sr = (m_sr << 1) | m_out_cb2; m_sr = (m_sr << 1) | m_out_cb2;
LOGSHIFT("%02x CB2: %d\n", m_sr, m_out_cb2); LOGSHIFT("%02x CB2: %d\n", m_sr, m_out_cb2);
m_cb2_handler(m_out_cb2); m_cb2_handler(m_out_cb2);
}
if (!SO_T2_RATE(m_acr)) else // Check for INT condition, eg the last and raising flank of the 15-0 falling/raising flanks
{
if (!SO_T2_RATE(m_acr)) // The T2 continous shifter doesn't do interrupts
{ {
if (m_shift_counter == 0) if (m_shift_counter == 0)
{ {
LOGINT("SHIFT out INT request "); LOGINT("SHIFT out INT request ");
set_int(INT_SR); // TODO: this interrupt is 1-2 clock cycles too early for O2 control mode set_int(INT_SR); // TODO: this interrupt is 1-2 clock cycles too early for O2 control mode
} }
m_shift_counter = (m_shift_counter - 1) & 7;
} }
}
m_shift_counter = (m_shift_counter - 1) & 0x0f; // Count all flanks
} }
void via6522_device::shift_in() void via6522_device::shift_in()
{ {
// Only shift in data on raising flank
if ( !(m_shift_counter & 1) )
{
LOGSHIFT("%s shift In SR: %02x->", tag(), m_sr); LOGSHIFT("%s shift In SR: %02x->", tag(), m_sr);
m_sr = (m_sr << 1) | (m_in_cb2 & 1); m_sr = (m_sr << 1) | (m_in_cb2 & 1);
LOGSHIFT("%02x\n", m_sr); LOGSHIFT("%02x\n", m_sr);
@ -391,10 +401,10 @@ void via6522_device::shift_in()
LOGINT("SHIFT in INT request "); LOGINT("SHIFT in INT request ");
set_int(INT_SR);// TODO: this interrupt is 1-2 clock cycles too early for O2 control mode set_int(INT_SR);// TODO: this interrupt is 1-2 clock cycles too early for O2 control mode
} }
m_shift_counter = (m_shift_counter - 1) & 7; }
m_shift_counter = (m_shift_counter - 1) & 0x0f; // Count all flanks
} }
void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{ {
switch (id) switch (id)
@ -404,10 +414,18 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
m_out_cb1 ^= 1; m_out_cb1 ^= 1;
m_cb1_handler(m_out_cb1); m_cb1_handler(m_out_cb1);
if ((SO_O2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr)) && m_shift_state == SHIFTER_FINISH) #if 0
// if ((SO_O2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr)) && m_shift_state == SHIFTER_FINISH)
if (m_shift_state == SHIFTER_FINISH)
{ {
if (m_out_cb1 & 1) // last raising flank if (m_out_cb1 & 1) // last raising flank
{ {
#if 0
if (SO_O2_CONTROL(m_acr))
shift_out();
else
#endif
if (SI_O2_CONTROL(m_acr))
shift_in(); shift_in();
m_shift_state = SHIFTER_IDLE; m_shift_state = SHIFTER_IDLE;
m_shift_timer->adjust(attotime::never); m_shift_timer->adjust(attotime::never);
@ -419,7 +437,18 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
} }
break; break;
} }
#endif
#if 1
// we call shift methods for all flanks
if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
{
shift_out();
}
else if (SI_T2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr))
{
shift_in();
}
#else
if (m_out_cb1 & 1) // raising flank if (m_out_cb1 & 1) // raising flank
{ {
if (SI_T2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr)) if (SI_T2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr))
@ -433,6 +462,8 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
m_shift_timer->adjust(clocks_to_attotime(1)); m_shift_timer->adjust(clocks_to_attotime(1));
} }
} }
else if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
m_shift_counter = (m_shift_counter - 1) & 7;
} }
else // falling flank else // falling flank
{ {
@ -440,6 +471,8 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
{ {
shift_out(); // close latch shift_out(); // close latch
} }
else if (SI_T2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr))
m_shift_counter = (m_shift_counter - 1) & 7;
// Let external devices latch also on last raising edge. // Let external devices latch also on last raising edge.
if ((SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr)) && m_shift_counter == 0) if ((SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr)) && m_shift_counter == 0)
@ -448,17 +481,22 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
m_shift_timer->adjust(clocks_to_attotime(1)); m_shift_timer->adjust(clocks_to_attotime(1));
} }
} }
#endif
if (SO_T2_RATE(m_acr) || m_shift_counter) if (SO_T2_RATE(m_acr) || (m_shift_counter != 0x0f))
{ {
if (SI_O2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr)) if (SI_O2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
{ {
m_shift_timer->adjust(clocks_to_attotime(1)); m_shift_timer->adjust(clocks_to_attotime(1));
} }
else else if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SI_T2_CONTROL(m_acr))
{ {
m_shift_timer->adjust(clocks_to_attotime(m_t2ll + 2)); m_shift_timer->adjust(clocks_to_attotime(m_t2ll + 2));
} }
else
{
m_shift_timer->adjust(attotime::never); // In case we change mode before counter expire
}
} }
break; break;
case TIMER_T1: case TIMER_T1:
@ -675,21 +713,21 @@ READ8_MEMBER( via6522_device::read )
val = m_sr; val = m_sr;
m_out_cb1 = 1; m_out_cb1 = 1;
m_cb1_handler(m_out_cb1); m_cb1_handler(m_out_cb1);
m_shift_counter = 8; m_shift_counter = 0x0f;
clear_int(INT_SR); clear_int(INT_SR);
LOGSHIFT("ACR: %02x ", m_acr); LOGSHIFT(" - ACR: %02x ", m_acr);
if (SI_O2_CONTROL(m_acr)) if (SI_O2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
{ {
m_shift_timer->adjust(clocks_to_attotime(1)); m_shift_timer->adjust(clocks_to_attotime(8)); // 8 flanks to start shifter from a read
shift_in(); // shift_in();
LOGSHIFT("SI_O2 starts timer "); LOGSHIFT(" - read SR starts O2 timer ");
} }
else if (SI_T2_CONTROL(m_acr)) else if (SI_T2_CONTROL(m_acr) || SO_T2_CONTROL(m_acr))
{ {
m_shift_timer->adjust(clocks_to_attotime(m_t2ll + 2)); m_shift_timer->adjust(clocks_to_attotime(m_t2ll + 2));
LOGSHIFT("SI_T2 starts timer "); LOGSHIFT(" - read SR starts T2 timer ");
} }
else if (! (SO_O2_CONTROL(m_acr) || SO_T2_CONTROL(m_acr) || SO_T2_RATE(m_acr))) else if (! SO_T2_RATE(m_acr))
{ {
m_shift_timer->adjust(attotime::never); m_shift_timer->adjust(attotime::never);
LOGSHIFT("Timer stops"); LOGSHIFT("Timer stops");
@ -861,23 +899,23 @@ WRITE8_MEMBER( via6522_device::write )
m_cb1_handler(m_out_cb1); m_cb1_handler(m_out_cb1);
} }
m_shift_counter = 8; m_shift_counter = 0x0f;
clear_int(INT_SR); clear_int(INT_SR);
LOGSHIFT(" - ACR is: %02x ", m_acr); LOGSHIFT(" - ACR is: %02x ", m_acr);
if (SO_O2_CONTROL(m_acr)) if (SO_O2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr))
{ {
m_shift_timer->adjust(clocks_to_attotime(1)); // Let CB1 clock it on into to remote device m_shift_timer->adjust(clocks_to_attotime(8)); // 8 flanks to start shifte from a write
LOGSHIFT("SO_O2 starts timer"); LOGSHIFT(" - write SR starts O2 timer");
} }
else if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr)) else if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SI_T2_CONTROL(m_acr))
{ {
m_shift_timer->adjust(clocks_to_attotime(m_t2ll + 2)); m_shift_timer->adjust(clocks_to_attotime(m_t2ll + 2));
LOGSHIFT("SO_T2 starts timer"); LOGSHIFT(" - write starts T2 timer");
} }
else if (! (SI_O2_CONTROL(m_acr) || SI_T2_CONTROL(m_acr))) else // if (! (SI_O2_CONTROL(m_acr) || SI_T2_CONTROL(m_acr)))
{ {
m_shift_timer->adjust(attotime::never); // In case we change mode before counter expire m_shift_timer->adjust(attotime::never); // In case we change mode before counter expire
LOGSHIFT("Timer stops"); LOGSHIFT(" - timer stops");
} }
LOGSHIFT("\n"); LOGSHIFT("\n");
break; break;
@ -1036,7 +1074,7 @@ WRITE8_MEMBER( via6522_device::write_pb )
} }
/*------------------------------------------------- /*-------------------------------------------------
cb1_w - interface setting VIA port CB1 input write_cb1 - interface setting VIA port CB1 input
-------------------------------------------------*/ -------------------------------------------------*/
WRITE_LINE_MEMBER( via6522_device::write_cb1 ) WRITE_LINE_MEMBER( via6522_device::write_cb1 )
@ -1051,17 +1089,19 @@ WRITE_LINE_MEMBER( via6522_device::write_cb1 )
{ {
m_latch_b = input_pb(); m_latch_b = input_pb();
} }
#if 0
if (!state && SO_EXT_CONTROL(m_acr)) if (!state && SO_EXT_CONTROL(m_acr))
{ {
LOGSHIFT("SHIFT OUT EXT/CB1 %s edge, %d\n", m_in_cb1 & 1 ? "raising" : "falling", m_shift_counter);
shift_out(); shift_out();
} }
if (state && SI_EXT_CONTROL(m_acr)) if (state && SI_EXT_CONTROL(m_acr))
{ {
LOGSHIFT("SHIFT IN EXT/CB1 %s edge, %d\n", m_in_cb1 & 1 ? "raising" : "falling", m_shift_counter);
shift_in(); shift_in();
} }
#endif
LOGINT("CB1 INT request "); LOGINT("CB1 INT request ");
set_int(INT_CB1); set_int(INT_CB1);
@ -1071,24 +1111,35 @@ WRITE_LINE_MEMBER( via6522_device::write_cb1 )
m_cb2_handler(1); m_cb2_handler(1);
} }
} }
#if 0
else // shift is not controlled by m_pcr else // shift is not controlled by m_pcr
{ {
if (!state && SO_EXT_CONTROL(m_acr)) #endif
// if (!state && SO_EXT_CONTROL(m_acr))
if (SO_EXT_CONTROL(m_acr))
{ {
LOGSHIFT("SHIFT OUT EXT/CB1 falling edge, %d\n", m_shift_counter);
shift_out(); shift_out();
} }
// else if (state && SI_EXT_CONTROL(m_acr))
if (state && SI_EXT_CONTROL(m_acr)) else if (SI_EXT_CONTROL(m_acr))
{ {
LOGSHIFT("SHIFT IN EXT/CB1 raising edge, %d\n", m_shift_counter);
shift_in(); shift_in();
} }
#if 0
else if ( (!state && SI_EXT_CONTROL(m_acr)) || (state && SO_EXT_CONTROL(m_acr)) )
{
m_shift_counter = (m_shift_counter - 1) & 7;
} }
#endif
// }
} }
} }
/*------------------------------------------------- /*-------------------------------------------------
cb2_w - interface setting VIA port CB2 input write_cb2 - interface setting VIA port CB2 input
-------------------------------------------------*/ -------------------------------------------------*/
WRITE_LINE_MEMBER( via6522_device::write_cb2 ) WRITE_LINE_MEMBER( via6522_device::write_cb2 )