Example #1
0
static void z80ctc_timercallback (int param)
{
	int which = param >> 2;
	int ch = param & 3;
	z80ctc *ctc = ctcs + which;

	/* down counter has reached zero - see if we should interrupt */
	if ((ctc->mode[ch] & INTERRUPT) == INTERRUPT_ON)
	{
		if( !(ctc->int_state[ch] & Z80_INT_REQ) )
		{
			ctc->int_state[ch] |= Z80_INT_REQ;
			z80ctc_interrupt_check( ctc );
		}
	}
	/* generate the clock pulse */
	if (ctc->zc[ch])
	{
		(*ctc->zc[ch])(0,1);
		(*ctc->zc[ch])(0,0);
	}

	/* reset the down counter */
	ctc->down[ch] = ctc->tconst[ch];
}
Example #2
0
void z80ctc_reset (int which)
{
	z80ctc *ctc = ctcs + which;
	int i;

	/* set up defaults */
	for (i = 0; i < 4; i++)
	{
		ctc->mode[i] = RESET_ACTIVE;
		ctc->tconst[i] = 0x100;
		timer_adjust(ctc->timer[i], TIME_NEVER, 0, 0);
		ctc->int_state[i] = 0;
	}
	z80ctc_interrupt_check( ctc );
}
Example #3
0
void z80ctc_reset (int which)
{
	z80ctc *ctc = ctcs + which;
	int i;

	/* set up defaults */
	for (i = 0; i < 4; i++)
	{
		ctc->mode[i] = RESET_ACTIVE;
		ctc->tconst[i] = 0x100;
		if (ctc->timer[i])
			timer_remove (ctc->timer[i]);
		ctc->timer[i] = NULL;
		ctc->int_state[i] = 0;
	}
	z80ctc_interrupt_check( ctc );
}
Example #4
0
/* when operate RETI , soud be call this function for request pending interrupt */
void z80ctc_reti( int which )
{
	z80ctc *ctc = ctcs + which;
	int ch;

	for( ch = 0 ; ch < 4 ; ch++ )
	{
		if( ctc->int_state[ch] & Z80_INT_IEO )
		{
			/* highest served interrupt found */
			/* clear interrupt status */
			ctc->int_state[ch] &= ~Z80_INT_IEO;
			/* search next interrupt */
			break;
		}
	}
	/* set next interrupt stattus */
	z80ctc_interrupt_check( ctc );
}
Example #5
0
int z80ctc_interrupt( int which )
{
	z80ctc *ctc = ctcs + which;
	int ch;

	for( ch = 0 ; ch < 4 ; ch++ )
	{
		if( ctc->int_state[ch] )
		{
			if( ctc->int_state[ch] == Z80_INT_REQ)
				ctc->int_state[ch] = Z80_INT_IEO;
			break;
		}
	}
	if( ch > 3 )
	{
		if (errorlog) fprintf(errorlog,"CTC entry INT : non IRQ\n");
		ch = 0;
	}
	z80ctc_interrupt_check( ctc );
	return ctc->vector + ch * 2;
}
Example #6
0
void z80ctc_w (int which, int offset, int data)
{
	z80ctc *ctc = ctcs + which;
	int mode, ch;

	/* keep channel within range, and get the current mode */
	ch = offset & 3;
	mode = ctc->mode[ch];

	/* if we're waiting for a time constant, this is it */
	if ((mode & CONSTANT) == CONSTANT_LOAD)
	{
		/* set the time constant (0 -> 0x100) */
		ctc->tconst[ch] = data ? data : 0x100;

		/* clear the internal mode -- we're no longer waiting */
		ctc->mode[ch] &= ~CONSTANT;

		/* also clear the reset, since the constant gets it going again */
		ctc->mode[ch] &= ~RESET;

		/* if we're in timer mode.... */
		if ((mode & MODE) == MODE_TIMER)
		{
			/* if we're triggering on the time constant, reset the down counter now */
			if ((mode & TRIGGER) == TRIGGER_AUTO)
			{
				double clock = ((mode & PRESCALER) == PRESCALER_16) ? ctc->invclock16 : ctc->invclock256;
				if (ctc->timer[ch])
					timer_remove (ctc->timer[ch]);
				if (!(ctc->notimer & (1<<ch)))
					ctc->timer[ch] = timer_pulse (clock * (double)ctc->tconst[ch], (which << 2) + ch, z80ctc_timercallback);
			}

			/* else set the bit indicating that we're waiting for the appropriate trigger */
			else
				ctc->mode[ch] |= WAITING_FOR_TRIG;
		}

		/* also set the down counter in case we're clocking externally */
		ctc->down[ch] = ctc->tconst[ch];

		/* all done here */
		return;
	}

	/* if we're writing the interrupt vector, handle it specially */
#if 0	/* Tatsuyuki Satoh changes */
	/* The 'Z80family handbook' wrote,                            */
	/* interrupt vector is able to set for even channel (0 or 2)  */
	if ((data & CONTROL) == CONTROL_VECTOR && (ch&1) == 0)
#else
	if ((data & CONTROL) == CONTROL_VECTOR && ch == 0)
#endif
	{
		ctc->vector = data & 0xf8;
		if (errorlog) fprintf (errorlog, "CTC Vector = %02x\n", ctc->vector);
		return;
	}

	/* this must be a control word */
	if ((data & CONTROL) == CONTROL_WORD)
	{
		/* set the new mode */
		ctc->mode[ch] = data;
		if (errorlog) fprintf (errorlog,"CTC ch.%d mode = %02x\n", ch, data);

		/* if we're being reset, clear out any pending timers for this channel */
		if ((data & RESET) == RESET_ACTIVE)
		{
			if (ctc->timer[ch])
				timer_remove (ctc->timer[ch]);
			ctc->timer[ch] = NULL;

			if( ctc->int_state[ch] != 0 )
			{
				/* clear interrupt service , request */
				ctc->int_state[ch] = 0;
				z80ctc_interrupt_check( ctc );
			}
		}

		/* all done here */
		return;
	}
}