mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
Merge pull request #2262 from JoakimLarsson/mac_adb
via6522 shifter support for external clock
This commit is contained in:
commit
4c3c544983
@ -39,7 +39,7 @@
|
|||||||
#define LOG_READ (1U << 3)
|
#define LOG_READ (1U << 3)
|
||||||
#define LOG_INT (1U << 4)
|
#define LOG_INT (1U << 4)
|
||||||
|
|
||||||
//#define VERBOSE (LOG_SHIFT)
|
//#define VERBOSE (LOG_SHIFT|LOG_INT|LOG_SETUP)
|
||||||
//#define LOG_OUTPUT_FUNC printf
|
//#define LOG_OUTPUT_FUNC printf
|
||||||
|
|
||||||
#include "logmacro.h"
|
#include "logmacro.h"
|
||||||
@ -178,8 +178,7 @@ via6522_device::via6522_device(const machine_config &mconfig, const char *tag, d
|
|||||||
m_pcr(0),
|
m_pcr(0),
|
||||||
m_acr(0),
|
m_acr(0),
|
||||||
m_ier(0),
|
m_ier(0),
|
||||||
m_ifr(0),
|
m_ifr(0)
|
||||||
m_shift_state(SHIFTER_IDLE)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,6 +209,7 @@ void via6522_device::device_start()
|
|||||||
m_t2 = timer_alloc(TIMER_T2);
|
m_t2 = timer_alloc(TIMER_T2);
|
||||||
m_ca2_timer = timer_alloc(TIMER_CA2);
|
m_ca2_timer = timer_alloc(TIMER_CA2);
|
||||||
m_shift_timer = timer_alloc(TIMER_SHIFT);
|
m_shift_timer = timer_alloc(TIMER_SHIFT);
|
||||||
|
m_shift_irq_timer = timer_alloc(TIMER_SHIFT_IRQ);
|
||||||
|
|
||||||
/* Default clock is from CPU1 */
|
/* Default clock is from CPU1 */
|
||||||
if (clock() == 0)
|
if (clock() == 0)
|
||||||
@ -362,6 +362,9 @@ 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;
|
||||||
@ -369,19 +372,31 @@ void via6522_device::shift_out()
|
|||||||
|
|
||||||
m_cb2_handler(m_out_cb2);
|
m_cb2_handler(m_out_cb2);
|
||||||
|
|
||||||
if (!SO_T2_RATE(m_acr))
|
if (m_shift_counter == 1 && SO_EXT_CONTROL(m_acr))
|
||||||
{
|
{
|
||||||
if (m_shift_counter == 0)
|
LOGINT("SHIFT EXT out INT request ");
|
||||||
|
set_int(INT_SR); // IRQ on last falling flank for external clock (mode 7)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Check for INT condition, eg the last and raising flank of the 15-0 falling/raising flanks
|
||||||
{
|
{
|
||||||
LOGINT("SHIFT out INT request ");
|
if (!SO_T2_RATE(m_acr)) // The T2 continous shifter doesn't do interrupts (mode 4)
|
||||||
set_int(INT_SR); // TODO: this interrupt is 1-2 clock cycles too early for O2 control mode
|
{
|
||||||
|
if (m_shift_counter == 0 && (SO_O2_CONTROL(m_acr) || SO_T2_CONTROL(m_acr)))
|
||||||
|
{
|
||||||
|
LOGINT("SHIFT O2/T2 out INT request ");
|
||||||
|
set_int(INT_SR); // IRQ on last raising flank for internal clock (mode 5-6)
|
||||||
}
|
}
|
||||||
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);
|
||||||
@ -389,76 +404,51 @@ void via6522_device::shift_in()
|
|||||||
if (m_shift_counter == 0)
|
if (m_shift_counter == 0)
|
||||||
{
|
{
|
||||||
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
|
||||||
|
m_shift_irq_timer->adjust(clocks_to_attotime(2)); // Delay IRQ 2 flanks for all shift INs (mode 1-3)
|
||||||
}
|
}
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
case TIMER_SHIFT_IRQ: // This timer event is a delayed IRQ for improved cycle accuracy
|
||||||
|
set_int(INT_SR); // triggered from shift_in or shift_out on the last rising flank
|
||||||
|
m_shift_irq_timer->adjust(attotime::never); // Not needed really...
|
||||||
|
break;
|
||||||
case TIMER_SHIFT:
|
case TIMER_SHIFT:
|
||||||
LOGSHIFT("SHIFT timer event CB1 %s edge, %d\n", m_out_cb1 & 1 ? "falling" : "raising", m_shift_counter);
|
LOGSHIFT("SHIFT timer event CB1 %s edge, %d\n", m_out_cb1 & 1 ? "falling" : "raising", m_shift_counter);
|
||||||
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)
|
// we call shift methods for all flanks
|
||||||
{
|
|
||||||
if (m_out_cb1 & 1) // last raising flank
|
|
||||||
{
|
|
||||||
shift_in();
|
|
||||||
m_shift_state = SHIFTER_IDLE;
|
|
||||||
m_shift_timer->adjust(attotime::never);
|
|
||||||
LOGSHIFT("Timer stops");
|
|
||||||
}
|
|
||||||
else // last falling flank (just for shift in)
|
|
||||||
{
|
|
||||||
m_shift_timer->adjust(clocks_to_attotime(1));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_out_cb1 & 1) // raising flank
|
|
||||||
{
|
|
||||||
if (SI_T2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr))
|
|
||||||
{
|
|
||||||
shift_in(); // close latch
|
|
||||||
|
|
||||||
// Shift in also on the last flanks
|
|
||||||
if (m_shift_counter == 0)
|
|
||||||
{
|
|
||||||
m_shift_state = SHIFTER_FINISH;
|
|
||||||
m_shift_timer->adjust(clocks_to_attotime(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // falling flank
|
|
||||||
{
|
|
||||||
if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
|
if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
|
||||||
{
|
{
|
||||||
shift_out(); // close latch
|
shift_out();
|
||||||
}
|
}
|
||||||
|
else if (SI_T2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr))
|
||||||
// Let external devices latch also on last raising edge.
|
|
||||||
if ((SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr)) && m_shift_counter == 0)
|
|
||||||
{
|
{
|
||||||
m_shift_state = SHIFTER_FINISH;
|
shift_in();
|
||||||
m_shift_timer->adjust(clocks_to_attotime(1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SO_T2_RATE(m_acr) || m_shift_counter)
|
// If in continous mode or the shifter is still shifting we re-arm the timer
|
||||||
|
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 // otherwise we stop it
|
||||||
|
{
|
||||||
|
m_shift_timer->adjust(attotime::never);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TIMER_T1:
|
case TIMER_T1:
|
||||||
@ -675,21 +665,20 @@ 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();
|
LOGSHIFT(" - read SR starts O2 timer ");
|
||||||
LOGSHIFT("SI_O2 starts 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 +850,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
|
||||||
{
|
{
|
||||||
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 +1025,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 +1040,6 @@ WRITE_LINE_MEMBER( via6522_device::write_cb1 )
|
|||||||
{
|
{
|
||||||
m_latch_b = input_pb();
|
m_latch_b = input_pb();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state && SO_EXT_CONTROL(m_acr))
|
|
||||||
{
|
|
||||||
shift_out();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state && SI_EXT_CONTROL(m_acr))
|
|
||||||
{
|
|
||||||
shift_in();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGINT("CB1 INT request ");
|
LOGINT("CB1 INT request ");
|
||||||
set_int(INT_CB1);
|
set_int(INT_CB1);
|
||||||
|
|
||||||
@ -1071,24 +1049,24 @@ WRITE_LINE_MEMBER( via6522_device::write_cb1 )
|
|||||||
m_cb2_handler(1);
|
m_cb2_handler(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // shift is not controlled by m_pcr
|
|
||||||
{
|
// The shifter shift is not controlled by PCR
|
||||||
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 (SI_EXT_CONTROL(m_acr))
|
||||||
if (state && SI_EXT_CONTROL(m_acr))
|
|
||||||
{
|
{
|
||||||
|
LOGSHIFT("SHIFT IN EXT/CB1 raising edge, %d\n", m_shift_counter);
|
||||||
shift_in();
|
shift_in();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
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 )
|
||||||
|
@ -135,6 +135,7 @@ private:
|
|||||||
static const device_timer_id TIMER_T1 = 1;
|
static const device_timer_id TIMER_T1 = 1;
|
||||||
static const device_timer_id TIMER_T2 = 2;
|
static const device_timer_id TIMER_T2 = 2;
|
||||||
static const device_timer_id TIMER_CA2 = 3;
|
static const device_timer_id TIMER_CA2 = 3;
|
||||||
|
static const device_timer_id TIMER_SHIFT_IRQ = 4;
|
||||||
|
|
||||||
uint16_t get_counter1_value();
|
uint16_t get_counter1_value();
|
||||||
|
|
||||||
@ -206,15 +207,8 @@ private:
|
|||||||
emu_timer *m_ca2_timer;
|
emu_timer *m_ca2_timer;
|
||||||
|
|
||||||
emu_timer *m_shift_timer;
|
emu_timer *m_shift_timer;
|
||||||
|
emu_timer *m_shift_irq_timer;
|
||||||
uint8_t m_shift_counter;
|
uint8_t m_shift_counter;
|
||||||
enum m_shift_state_t
|
|
||||||
{
|
|
||||||
SHIFTER_IDLE,
|
|
||||||
SHIFTER_SHIFT,
|
|
||||||
SHIFTER_FINISH,
|
|
||||||
SHIFTER_IRQ
|
|
||||||
};
|
|
||||||
m_shift_state_t m_shift_state;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user