Esempio n. 1
0
/**
 * @brief load the display data register
 */
void alto2_cpu_device::f2_late_dwt_load_ddr()
{
	LOG((LOG_DWT,2,"    DDR<- BUS (%#o)\n", m_bus));
	m_dsp.fifo[m_dsp.wa] = m_bus;
	m_dsp.wa = (m_dsp.wa + 1) % ALTO2_DISPLAY_FIFO;
	UINT8 a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa];
	if (FIFO_STOPWAKE(a38))
		m_task_wakeup &= ~(1 << task_dwt);
	LOG((LOG_DWT,2, "   DWT push %04x into FIFO[%02o]%s\n",
		m_bus, (m_dsp.wa - 1) & (ALTO2_DISPLAY_FIFO - 1),
		FIFO_STOPWAKE(a38) ? " STOPWAKE" : ""));
}
Esempio n. 2
0
/**
 * @brief function called by the CPU to enter the next display state
 *
 * There are 32 states per scanline and 875 scanlines per frame.
 */
void alto2_cpu_device::display_state_machine()
{
	LOG((this,LOG_DISPL,5,"DSP%03o:", m_dsp.state));
	if (020 == m_dsp.state)
	{
		LOG((this,LOG_DISPL,2," HLC=%d", m_dsp.hlc));
	}

	const uint8_t a63 = m_disp_a63[m_dsp.state];
	if (A63_HLCGATE(a63))
	{
		// count horizontal line counters and wrap
		m_dsp.hlc += 1;
		if (m_dsp.hlc > A2_DISP_HLC_END) {
			m_dsp.hlc = A2_DISP_HLC_START;
			m_dsp.scanline = 0;
		} else if (m_dsp.hlc == 1024) {
			m_dsp.scanline = 1;
		}
		// wake up the memory refresh task _twice_ on each scanline
		m_task_wakeup |= 1 << task_mrt;
	}
	// PROM a66 is disabled, if any of HLC256 or HLC512 are high
	const uint8_t a66 = (HLC256 | HLC512) ? 017 : m_disp_a66[m_dsp.hlc & 0377];

	// next address from PROM a63, use A4 from HLC1
	const uint8_t next = ((HLC1 ^ 1) << 4) | A63_NEXT(a63);

	if (A66_VBLANK(a66))
	{
		LOG((this,LOG_DISPL,1, " VBLANK"));
		// Rising edge of VBLANK?
		if (!A66_VBLANK(m_dsp.a66)) {
			// synchronize on MAME video timing
			if (!m_dsp.vblank) {
				m_display_time += A2_DISP_BITTIME(1);
				return;
			}
			m_dsp.vblank = false;
		}

		// VSYNC is always within VBLANK, thus we handle it only here
		if (A66_VSYNC(a66) && !A66_VSYNC(m_dsp.a66))
		{
			LOG((this,LOG_DISPL,1, " VSYNC/ (wake DVT)"));
			/*
			 * The display vertical task DVT is woken once per field
			 * at the beginning of vertical retrace.
			 */
			m_task_wakeup |= 1 << task_dvt;
		}
		m_dsp.inverse = 0xffff;
	}
	else
	{
		// Falling edge of VBLANK?
		if (A66_VBLANK(m_dsp.a66))
		{
			/*
			 * VBLANKPULSE:
			 * The display horizontal task DHT is woken once at the
			 * beginning of each field, and thereafter whenever the
			 * display word task blocks.
			 *
			 * The DHT can block itself, in which case neither it nor
			 * the word task can be woken until the start of the
			 * next field.
			 */
			LOG((this,LOG_DISPL,1, " VBLANKPULSE (wake DHT)"));
			m_dsp.dht_blocks = false;
			m_dsp.dwt_blocks = false;
			m_task_wakeup |= 1 << task_dht;
			/*
			 * VBLANKPULSE also resets the cursor task block flip flop,
			 * which is built from two NAND gates a40c and a40d (74H01).
			 */
			m_dsp.curt_blocks = false;
		}
		if (!A63_HBLANK(a63) && A63_HBLANK(m_dsp.a63))
		{
			m_dsp.scanline += 2;
			// Falling edge of a63 HBLANK starts unloading of FIFO words
			LOG((this,LOG_DISPL,1, " HBLANK\\ UNLOAD"));
			m_unload_time = A2_DISP_BITTIME(m_dsp.halfclock ? 40+32 : 40+16);
			m_unload_word = 0;
		}
	}

	/*
	 * The wakeup request for the display word task (DWT) is controlled by
	 * the state of the 16 word FIFO. If DWT has not executed a BLOCK,
	 * if DHT is not blocked, and if the buffer is not full, DWT wakeups
	 * are generated.
	 */
	uint8_t a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa];
	if (!m_dsp.dwt_blocks && !m_dsp.dht_blocks && !FIFO_STOPWAKE(a38))
	{
		m_task_wakeup |= 1 << task_dwt;
		LOG((this,LOG_DISPL,1, " (wake DWT)"));
	}

	// Stop waking up the DWT when SCANEND is active
	if (A63_SCANEND(a63))
	{
		m_task_wakeup &= ~(1 << task_dwt);
		LOG((this,LOG_DISPL,1, " SCANEND"));
	}

	LOG((this,LOG_DISPL,1, "%s", A63_HBLANK(a63) ? " HBLANK": ""));

	if (A63_HSYNC(a63))
	{
		// Active HSYNC
		if (!A63_HSYNC(m_dsp.a63))
		{
			// Rising edge of HSYNC => CLRBUF
			LOG((this,LOG_DISPL,1, " HSYNC/ (CLRBUF)"));
			/*
			 * The hardware sets the buffer empty and clears the DWT block
			 * flip-flop at the beginning of horizontal retrace for
			 * every scanline.
			 */
			m_dsp.wa = 0;
			m_dsp.ra = 0;
			m_dsp.dwt_blocks = false;
			// now take the new values from the last SETMODE<-
			m_dsp.inverse = GET_SETMODE_INVERSE(m_dsp.setmode) ? 0xffff : 0x0000;
			m_dsp.halfclock = GET_SETMODE_SPEEDY(m_dsp.setmode) ? true : false;
			// stop the CPU execution loop from calling unload_word()
			m_unload_time = -1;
		}
		else
		{
			LOG((this,LOG_DISPL,1, " HSYNC"));
		}
	}
	else
	// Falling edge of HSYNC?
	if (A63_HSYNC(m_dsp.a63))
	{
		/*
		 * CLRBUF' also resets the 2nd cursor task block flip flop,
		 * which is built from two NAND gates a30c and a30d (74H00).
		 * If both flip flops are reset, the NOR gate a20d (74S02)
		 * decodes this as WAKECURT signal.
		 */
		m_dsp.curt_wakeup = true;
		if (!m_dsp.curt_blocks)
			m_task_wakeup |= 1 << task_curt;
	}

	LOG((this,LOG_DISPL,1, " NEXT:%03o\n", next));

	m_dsp.a63 = a63;
	m_dsp.a66 = a66;
	m_dsp.state = next;
	m_display_time += A2_DISP_BITTIME(32);
}