mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
Made SPG2xx I/O IRQ checking a bit more lean; improved ADC behavior. (#8138) [Ryan Holtz]
This commit is contained in:
parent
f2ba6b059a
commit
990d8233bf
@ -91,48 +91,32 @@ void spg2xx_io_device::device_start()
|
||||
m_chip_sel.resolve_safe();
|
||||
m_pal_read_cb.resolve_safe(0);
|
||||
|
||||
m_timer_irq_cb.resolve();
|
||||
m_uart_adc_irq_cb.resolve();
|
||||
m_external_irq_cb.resolve();
|
||||
m_ffreq_tmr1_irq_cb.resolve();
|
||||
m_ffreq_tmr2_irq_cb.resolve();
|
||||
m_timer_irq_cb.resolve_safe();
|
||||
m_uart_adc_irq_cb.resolve_safe();
|
||||
m_external_irq_cb.resolve_safe();
|
||||
m_ffreq_tmr1_irq_cb.resolve_safe();
|
||||
m_ffreq_tmr2_irq_cb.resolve_safe();
|
||||
|
||||
m_fiq_vector_w.resolve();
|
||||
m_fiq_vector_w.resolve_safe();
|
||||
|
||||
m_tmb1 = timer_alloc(TIMER_TMB1);
|
||||
m_tmb2 = timer_alloc(TIMER_TMB2);
|
||||
m_tmb1->adjust(attotime::never);
|
||||
m_tmb2->adjust(attotime::never);
|
||||
m_tmb1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::tmb_timer_tick<0>), this));
|
||||
m_tmb2 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::tmb_timer_tick<1>), this));
|
||||
|
||||
m_uart_tx_timer = timer_alloc(TIMER_UART_TX);
|
||||
m_uart_tx_timer->adjust(attotime::never);
|
||||
m_uart_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::uart_transmit_tick), this));
|
||||
m_uart_rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::uart_receive_tick), this));
|
||||
|
||||
m_uart_rx_timer = timer_alloc(TIMER_UART_RX);
|
||||
m_uart_rx_timer->adjust(attotime::never);
|
||||
m_4khz_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::system_timer_tick), this));
|
||||
|
||||
m_4khz_timer = timer_alloc(TIMER_4KHZ);
|
||||
m_4khz_timer->adjust(attotime::never);
|
||||
m_timer_src_ab = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::timer_ab_tick), this));
|
||||
m_timer_src_c = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::timer_c_tick), this));
|
||||
m_rng_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::rng_clock_tick), this));
|
||||
m_watchdog_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::watchdog_tick), this));
|
||||
m_spi_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::spi_tx_tick), this));
|
||||
|
||||
m_timer_src_ab = timer_alloc(TIMER_SRC_AB);
|
||||
m_timer_src_ab->adjust(attotime::never);
|
||||
|
||||
m_timer_src_c = timer_alloc(TIMER_SRC_C);
|
||||
m_timer_src_c->adjust(attotime::never);
|
||||
|
||||
m_rng_timer = timer_alloc(TIMER_RNG);
|
||||
m_rng_timer->adjust(attotime::never);
|
||||
|
||||
m_watchdog_timer = timer_alloc(TIMER_WATCHDOG);
|
||||
m_watchdog_timer->adjust(attotime::never);
|
||||
|
||||
m_spi_tx_timer = timer_alloc(TIMER_SPI_TX);
|
||||
m_spi_tx_timer->adjust(attotime::never);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_adc_timer[i] = timer_alloc(TIMER_ADC0 + i);
|
||||
m_adc_timer[i]->adjust(attotime::never);
|
||||
}
|
||||
m_adc_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::adc_convert_tick<0>), this));
|
||||
m_adc_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::adc_convert_tick<1>), this));
|
||||
m_adc_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::adc_convert_tick<2>), this));
|
||||
m_adc_timer[3] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(spg2xx_io_device::adc_convert_tick<3>), this));
|
||||
|
||||
save_item(NAME(m_io_regs));
|
||||
|
||||
@ -275,7 +259,7 @@ void spg2xx_io_device::set_spi_irq(bool set)
|
||||
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(changed);
|
||||
check_data_irq();
|
||||
}
|
||||
|
||||
void spg2xx_io_device::update_spi_irqs()
|
||||
@ -286,7 +270,7 @@ void spg2xx_io_device::update_spi_irqs()
|
||||
set_spi_irq(ovf_set || rxi_set || txi_set);
|
||||
}
|
||||
|
||||
void spg2xx_io_device::do_spi_tx()
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::spi_tx_tick)
|
||||
{
|
||||
if (!BIT(m_io_regs[REG_SPI_CTRL], 15) || m_spi_tx_fifo_count == 0)
|
||||
{
|
||||
@ -387,6 +371,12 @@ void spg2xx_io_device::spi_rx(int state)
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::rng_clock_tick)
|
||||
{
|
||||
clock_rng(0);
|
||||
clock_rng(1);
|
||||
}
|
||||
|
||||
uint16_t spg2xx_io_device::clock_rng(int which)
|
||||
{
|
||||
const uint16_t value = m_io_regs[REG_PRNG1 + which];
|
||||
@ -458,15 +448,7 @@ uint16_t spg2xx_io_device::io_r(offs_t offset)
|
||||
break;
|
||||
|
||||
case REG_ADC_DATA:
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
const uint16_t old = IO_IRQ_STATUS;
|
||||
IO_IRQ_STATUS &= ~0x2000;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(changed);
|
||||
LOGMASKED(LOG_IO_READS | LOG_ADC, "%s: io_r: ADC Data = %04x\n", machine().describe_context(), val);
|
||||
}
|
||||
LOGMASKED(LOG_IO_READS | LOG_ADC, "%s: io_r: ADC Data = %04x\n", machine().describe_context(), val);
|
||||
break;
|
||||
|
||||
case REG_WAKEUP_SOURCE:
|
||||
@ -545,7 +527,6 @@ uint16_t spg2xx_io_device::io_extended_r(offs_t offset)
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_UART, "Remaining count %d, setting up timer\n", m_uart_rx_fifo_count);
|
||||
//uart_receive_tick();
|
||||
if (m_uart_rx_timer->remaining() == attotime::never)
|
||||
m_uart_rx_timer->adjust(attotime::from_ticks(BIT(m_io_regs[REG_UART_CTRL], 5) ? 11 : 10, m_uart_baud_rate));
|
||||
}
|
||||
@ -718,7 +699,7 @@ void spg2xx_io_device::update_timer_b_rate()
|
||||
}
|
||||
}
|
||||
|
||||
void spg2xx_io_device::update_timer_ab_src()
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::timer_ab_tick)
|
||||
{
|
||||
if (m_timer_b_tick_rate == 0)
|
||||
return;
|
||||
@ -741,14 +722,11 @@ void spg2xx_io_device::increment_timer_a()
|
||||
IO_IRQ_STATUS |= 0x0800;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
{
|
||||
//printf("Timer A overflow\n");
|
||||
check_irqs(0x0800);
|
||||
}
|
||||
check_timers_irq();
|
||||
}
|
||||
}
|
||||
|
||||
void spg2xx_io_device::update_timer_c_src()
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::timer_c_tick)
|
||||
{
|
||||
m_io_regs[REG_TIMERB_DATA]++;
|
||||
if (m_io_regs[REG_TIMERB_DATA] == 0)
|
||||
@ -758,10 +736,7 @@ void spg2xx_io_device::update_timer_c_src()
|
||||
IO_IRQ_STATUS |= 0x0400;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
{
|
||||
printf("Timer B overflow\n");
|
||||
check_irqs(0x0400);
|
||||
}
|
||||
check_timers_irq();
|
||||
}
|
||||
}
|
||||
|
||||
@ -954,7 +929,7 @@ void spg2xx_io_device::io_w(offs_t offset, uint16_t data)
|
||||
IO_IRQ_STATUS &= ~0x0800;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(0x0800);
|
||||
check_timers_irq();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -998,7 +973,7 @@ void spg2xx_io_device::io_w(offs_t offset, uint16_t data)
|
||||
IO_IRQ_STATUS &= ~0x0400;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(0x0400);
|
||||
check_timers_irq();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1030,7 +1005,7 @@ void spg2xx_io_device::io_w(offs_t offset, uint16_t data)
|
||||
m_io_regs[REG_INT_CTRL] = data;
|
||||
const uint16_t changed = (IO_IRQ_STATUS & old) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(changed);
|
||||
check_all_irqs(changed);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1046,7 +1021,7 @@ void spg2xx_io_device::io_w(offs_t offset, uint16_t data)
|
||||
IO_IRQ_STATUS |= 0x0100;
|
||||
}
|
||||
if (changed)
|
||||
check_irqs(changed);
|
||||
check_all_irqs(changed);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1099,41 +1074,24 @@ void spg2xx_io_device::io_w(offs_t offset, uint16_t data)
|
||||
const uint16_t old_ctrl = m_io_regs[REG_ADC_CTRL];
|
||||
m_io_regs[REG_ADC_CTRL] = data & ~0x2000;
|
||||
|
||||
const uint16_t channel = (m_io_regs[REG_ADC_CTRL] >> 4) & 3;
|
||||
if (BIT(old_ctrl, 13) && BIT(data, 13))
|
||||
{
|
||||
m_io_regs[REG_ADC_CTRL] &= ~0x2000;
|
||||
IO_IRQ_STATUS &= ~0x2000;
|
||||
check_data_irq();
|
||||
}
|
||||
|
||||
if (BIT(m_io_regs[REG_ADC_CTRL], 0))
|
||||
{
|
||||
// Does anything require the 0->1 check below?
|
||||
// jak_sith (and all the other Star Wars units / GameKeys) break on the high score table if you leave the demo
|
||||
// running or finish a game with a high score, as they write '0x0001' and then don't read any further directional
|
||||
// inputs until 0x2000 is set, but that never happens because the value at the time is already 0x0001.
|
||||
//
|
||||
// If the state of the lowest bit is important to other software, maybe it's more of a status flag than a true
|
||||
// read/write register?
|
||||
|
||||
//if (!BIT(old_ctrl, 0))
|
||||
{
|
||||
m_io_regs[REG_ADC_CTRL] |= 0x2000;
|
||||
if (BIT(m_io_regs[REG_ADC_CTRL], 9))
|
||||
{
|
||||
const uint16_t old = IO_IRQ_STATUS;
|
||||
IO_IRQ_STATUS |= 0x2000;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(changed);
|
||||
}
|
||||
}
|
||||
|
||||
if (BIT(data, 13))
|
||||
{
|
||||
m_io_regs[REG_ADC_CTRL] &= ~0x2000;
|
||||
check_irqs(0x2000);
|
||||
}
|
||||
// Assume ready unless stated otherwise (i.e., conversion request is issued).
|
||||
m_io_regs[REG_ADC_CTRL] |= 0x2000;
|
||||
|
||||
const uint16_t adc_channel = (m_io_regs[REG_ADC_CTRL] >> 4) & 3;
|
||||
if (!BIT(old_ctrl, 12) && BIT(m_io_regs[REG_ADC_CTRL], 12))
|
||||
{
|
||||
m_io_regs[REG_ADC_CTRL] &= ~0x3000;
|
||||
const uint32_t adc_clocks = 16 << ((m_io_regs[REG_ADC_CTRL] >> 2) & 3);
|
||||
m_adc_timer[channel]->adjust(attotime::from_ticks(adc_clocks, 27000000));
|
||||
m_adc_timer[adc_channel]->adjust(attotime::from_ticks(adc_clocks, 27000000));
|
||||
m_io_regs[REG_ADC_DATA] &= ~0x8000;
|
||||
}
|
||||
|
||||
@ -1141,7 +1099,7 @@ void spg2xx_io_device::io_w(offs_t offset, uint16_t data)
|
||||
if (BIT(data, 10))
|
||||
{
|
||||
m_io_regs[REG_ADC_DATA] &= ~0x8000;
|
||||
m_adc_timer[channel]->adjust(attotime::from_hz(8000), 0, attotime::from_hz(8000));
|
||||
m_adc_timer[adc_channel]->adjust(attotime::from_hz(8000), 0, attotime::from_hz(8000));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1288,7 +1246,7 @@ void spg2xx_io_device::io_extended_w(offs_t offset, uint16_t data)
|
||||
IO_IRQ_STATUS &= ~0x0100;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(0x0100);
|
||||
check_data_irq();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1503,111 +1461,57 @@ void spg2xx_io_device::io_extended_w(offs_t offset, uint16_t data)
|
||||
}
|
||||
}
|
||||
|
||||
void spg2xx_io_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
template <int Which>
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::tmb_timer_tick)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_TMB1:
|
||||
{
|
||||
LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE);
|
||||
const uint16_t old = IO_IRQ_STATUS;
|
||||
IO_IRQ_STATUS |= 1;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(0x0001);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIMER_TMB2:
|
||||
{
|
||||
LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE);
|
||||
const uint16_t old = IO_IRQ_STATUS;
|
||||
IO_IRQ_STATUS |= 2;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(0x0002);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIMER_UART_TX:
|
||||
uart_transmit_tick();
|
||||
break;
|
||||
|
||||
case TIMER_UART_RX:
|
||||
uart_receive_tick();
|
||||
break;
|
||||
|
||||
case TIMER_4KHZ:
|
||||
system_timer_tick();
|
||||
break;
|
||||
|
||||
case TIMER_SRC_AB:
|
||||
update_timer_ab_src();
|
||||
break;
|
||||
|
||||
case TIMER_SRC_C:
|
||||
update_timer_c_src();
|
||||
break;
|
||||
|
||||
case TIMER_RNG:
|
||||
clock_rng(0);
|
||||
clock_rng(1);
|
||||
break;
|
||||
|
||||
case TIMER_WATCHDOG:
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
||||
break;
|
||||
|
||||
case TIMER_SPI_TX:
|
||||
do_spi_tx();
|
||||
break;
|
||||
|
||||
case TIMER_ADC0:
|
||||
case TIMER_ADC1:
|
||||
case TIMER_ADC2:
|
||||
case TIMER_ADC3:
|
||||
do_adc_capture(id - TIMER_ADC0);
|
||||
break;
|
||||
}
|
||||
LOGMASKED(LOG_TIMERS, "TMB%d elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", Which + 1, IO_IRQ_STATUS, IO_IRQ_STATUS | (1 << Which), IO_IRQ_ENABLE);
|
||||
const uint16_t old = IO_IRQ_STATUS;
|
||||
IO_IRQ_STATUS |= (1 << Which);
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_tmb_lofreq_key_irq();
|
||||
}
|
||||
|
||||
void spg2xx_io_device::system_timer_tick()
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::watchdog_tick)
|
||||
{
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::system_timer_tick)
|
||||
{
|
||||
const uint16_t old = IO_IRQ_STATUS;
|
||||
uint16_t check_mask = 0x0040;
|
||||
IO_IRQ_STATUS |= 0x0040;
|
||||
|
||||
bool check_lofreq = false;
|
||||
|
||||
m_2khz_divider++;
|
||||
if (m_2khz_divider == 2)
|
||||
{
|
||||
m_2khz_divider = 0;
|
||||
IO_IRQ_STATUS |= 0x0020;
|
||||
check_mask |= 0x0020;
|
||||
|
||||
m_1khz_divider++;
|
||||
if (m_1khz_divider == 2)
|
||||
{
|
||||
m_1khz_divider = 0;
|
||||
IO_IRQ_STATUS |= 0x0010;
|
||||
check_mask |= 0x0010;
|
||||
|
||||
m_4hz_divider++;
|
||||
if (m_4hz_divider == 256)
|
||||
{
|
||||
m_4hz_divider = 0;
|
||||
IO_IRQ_STATUS |= 0x0008;
|
||||
check_mask |= 0x0008;
|
||||
check_lofreq = BIT(IO_IRQ_ENABLE, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
check_irqs(check_mask);
|
||||
check_hifreq_periodic_irq();
|
||||
if (check_lofreq)
|
||||
check_tmb_lofreq_key_irq();
|
||||
}
|
||||
|
||||
void spg2xx_io_device::uart_transmit_tick()
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::uart_transmit_tick)
|
||||
{
|
||||
LOGMASKED(LOG_UART, "uart_transmit_tick: Transmitting %02x, setting TxReady, clearing TxBusy\n", (uint8_t)m_io_regs[REG_UART_TXBUF]);
|
||||
m_uart_tx((uint8_t)m_io_regs[REG_UART_TXBUF]);
|
||||
@ -1619,15 +1523,15 @@ void spg2xx_io_device::uart_transmit_tick()
|
||||
IO_IRQ_STATUS |= 0x0100;
|
||||
m_uart_tx_irq = true;
|
||||
LOGMASKED(LOG_UART, "uart_transmit_tick: Setting UART IRQ bit\n");
|
||||
if (IO_IRQ_STATUS != old)
|
||||
if (IO_IRQ_STATUS != old && BIT(IO_IRQ_ENABLE, 8))
|
||||
{
|
||||
LOGMASKED(LOG_UART, "uart_transmit_tick: Bit newly set, checking IRQs\n");
|
||||
check_irqs(0x0100);
|
||||
check_data_irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spg2xx_io_device::uart_receive_tick()
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::uart_receive_tick)
|
||||
{
|
||||
LOGMASKED(LOG_UART, "uart_receive_tick: Setting RBF and RxRDY\n");
|
||||
m_io_regs[REG_UART_STATUS] |= 0x81;
|
||||
@ -1637,7 +1541,8 @@ void spg2xx_io_device::uart_receive_tick()
|
||||
LOGMASKED(LOG_UART, "uart_receive_tick: RxIntEn is set, setting rx_irq to true and setting UART IRQ\n");
|
||||
m_uart_rx_irq = true;
|
||||
IO_IRQ_STATUS |= 0x0100;
|
||||
check_irqs(0x0100);
|
||||
if (BIT(IO_IRQ_ENABLE, 8))
|
||||
check_data_irq();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1661,59 +1566,56 @@ void spg2xx_io_device::check_extint_irq(int channel)
|
||||
if (old_irq != IO_IRQ_STATUS)
|
||||
{
|
||||
LOGMASKED(LOG_EXTINT, "extint IRQ changed, so checking interrupts\n");
|
||||
check_irqs(mask);
|
||||
check_external_irq();
|
||||
}
|
||||
}
|
||||
|
||||
void spg2xx_io_device::check_irqs(const uint16_t changed)
|
||||
void spg2xx_io_device::check_timers_irq()
|
||||
{
|
||||
LOGMASKED(LOG_TIMERS, "Checking IRQ2 (%04x)\n", IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00);
|
||||
m_timer_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void spg2xx_io_device::check_data_irq()
|
||||
{
|
||||
LOGMASKED(LOG_UART | LOG_SIO | LOG_SPI | LOG_I2C | LOG_ADC, "Checking IRQ3 (%04x)\n", IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100);
|
||||
m_uart_adc_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x6100) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void spg2xx_io_device::check_external_irq()
|
||||
{
|
||||
LOGMASKED(LOG_EXTINT, "Checking IRQ5 (%04x)\n", IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200);
|
||||
m_external_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void spg2xx_io_device::check_hifreq_periodic_irq()
|
||||
{
|
||||
LOGMASKED(LOG_TIMERS, "Checking IRQ6 (%04x)\n", IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070);
|
||||
m_ffreq_tmr1_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void spg2xx_io_device::check_tmb_lofreq_key_irq()
|
||||
{
|
||||
LOGMASKED(LOG_IRQS, "Checking IRQ7 (%04x)\n", IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b);
|
||||
m_ffreq_tmr2_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void spg2xx_io_device::check_all_irqs(const uint16_t changed)
|
||||
{
|
||||
if (changed & 0x0c00) // Timer A, Timer B IRQ
|
||||
{
|
||||
LOGMASKED(LOG_TIMERS, "%ssserting IRQ2 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00), changed);
|
||||
|
||||
if (m_timer_irq_cb)
|
||||
m_timer_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE);
|
||||
else
|
||||
logerror("spg2xx_io_device::check_irqs, attempted to use m_timer_irq_cb without setting it\n");
|
||||
}
|
||||
check_timers_irq();
|
||||
|
||||
if (changed & 0x6100) // UART, SPI, SIO, I2C, ADC IRQ
|
||||
{
|
||||
LOGMASKED(LOG_UART | LOG_SIO | LOG_SPI | LOG_I2C | LOG_ADC, "%ssserting IRQ3 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x6100) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100), changed);
|
||||
if (m_uart_adc_irq_cb)
|
||||
m_uart_adc_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x6100) ? ASSERT_LINE : CLEAR_LINE);
|
||||
else
|
||||
logerror("spg2xx_io_device::check_irqs, attempted to use m_uart_adc_irq_cb without setting it\n");
|
||||
}
|
||||
check_data_irq();
|
||||
|
||||
if (changed & 0x1200) // External IRQ
|
||||
{
|
||||
LOGMASKED(LOG_EXTINT, "%ssserting IRQ5 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200), changed);
|
||||
if (m_external_irq_cb)
|
||||
m_external_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE);
|
||||
else
|
||||
logerror("spg2xx_io_device::check_irqs, attempted to use m_external_irq_cb without setting it\n");
|
||||
|
||||
}
|
||||
check_external_irq();
|
||||
|
||||
if (changed & 0x0070) // 1024Hz, 2048Hz, 4096Hz IRQ
|
||||
{
|
||||
LOGMASKED(LOG_TIMERS, "%ssserting IRQ6 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070), changed); //m_cpu->set_state_unsynced(UNSP_IRQ6_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE);
|
||||
if (m_ffreq_tmr1_irq_cb)
|
||||
m_ffreq_tmr1_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE);
|
||||
else
|
||||
logerror("spg2xx_io_device::check_irqs, attempted to use m_ffreq_tmr1_irq_cb without setting it\n");
|
||||
}
|
||||
check_hifreq_periodic_irq();
|
||||
|
||||
if (changed & 0x008b) // TMB1, TMB2, 4Hz, key change IRQ
|
||||
{
|
||||
LOGMASKED(LOG_IRQS, "%ssserting IRQ7 (%04x, %04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b), changed);
|
||||
if (m_ffreq_tmr2_irq_cb)
|
||||
m_ffreq_tmr2_irq_cb((IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE);
|
||||
else
|
||||
logerror("spg2xx_io_device::check_irqs, attempted to use m_ffreq_tmr2_irq_cb without setting it\n");
|
||||
|
||||
}
|
||||
check_tmb_lofreq_key_irq();
|
||||
}
|
||||
|
||||
uint16_t spg2xx_io_device::do_special_gpio(uint32_t index, uint16_t mask)
|
||||
@ -1784,22 +1686,17 @@ void spg2xx_io_device::do_gpio(uint32_t offset, bool write)
|
||||
m_io_regs[5 * index + 1] = what;
|
||||
}
|
||||
|
||||
void spg2xx_io_device::do_adc_capture(int channel)
|
||||
template <int Which>
|
||||
TIMER_CALLBACK_MEMBER(spg2xx_io_device::adc_convert_tick)
|
||||
{
|
||||
m_io_regs[REG_ADC_DATA] = (m_adc_in[channel]() & 0x0fff) | 0x8000;
|
||||
if (BIT(m_io_regs[REG_ADC_DATA], 11))
|
||||
{
|
||||
//m_io_regs[REG_ADC_DATA] |= 0xf000;
|
||||
}
|
||||
m_io_regs[REG_ADC_DATA] = (m_adc_in[Which]() & 0x0fff) | 0x8000;
|
||||
m_io_regs[REG_ADC_CTRL] |= 0x2000;
|
||||
const uint16_t old = IO_IRQ_STATUS;
|
||||
if (BIT(m_io_regs[REG_ADC_CTRL], 9))
|
||||
{
|
||||
IO_IRQ_STATUS |= 0x2000;
|
||||
const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE);
|
||||
if (changed)
|
||||
if (BIT(m_io_regs[REG_ADC_CTRL], 9) && BIT(IO_IRQ_ENABLE, 13))
|
||||
{
|
||||
check_irqs(changed);
|
||||
check_data_irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,26 +149,26 @@ protected:
|
||||
REG_IO_DRIVE_CTRL
|
||||
};
|
||||
void check_extint_irq(int channel);
|
||||
void check_irqs(const uint16_t changed);
|
||||
|
||||
static const device_timer_id TIMER_TMB1 = 0;
|
||||
static const device_timer_id TIMER_TMB2 = 1;
|
||||
static const device_timer_id TIMER_UART_TX = 4;
|
||||
static const device_timer_id TIMER_UART_RX = 5;
|
||||
static const device_timer_id TIMER_4KHZ = 6;
|
||||
static const device_timer_id TIMER_SRC_AB = 7;
|
||||
static const device_timer_id TIMER_SRC_C = 8;
|
||||
static const device_timer_id TIMER_RNG = 9;
|
||||
static const device_timer_id TIMER_WATCHDOG = 10;
|
||||
static const device_timer_id TIMER_SPI_TX = 11;
|
||||
static const device_timer_id TIMER_ADC0 = 12;
|
||||
static const device_timer_id TIMER_ADC1 = 13;
|
||||
static const device_timer_id TIMER_ADC2 = 14;
|
||||
static const device_timer_id TIMER_ADC3 = 15;
|
||||
void check_timers_irq();
|
||||
void check_data_irq();
|
||||
void check_external_irq();
|
||||
void check_hifreq_periodic_irq();
|
||||
void check_tmb_lofreq_key_irq();
|
||||
void check_all_irqs(const uint16_t changed);
|
||||
|
||||
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;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(timer_ab_tick);
|
||||
TIMER_CALLBACK_MEMBER(timer_c_tick);
|
||||
template <int Which> TIMER_CALLBACK_MEMBER(tmb_timer_tick);
|
||||
TIMER_CALLBACK_MEMBER(uart_transmit_tick);
|
||||
TIMER_CALLBACK_MEMBER(uart_receive_tick);
|
||||
TIMER_CALLBACK_MEMBER(system_timer_tick);
|
||||
TIMER_CALLBACK_MEMBER(rng_clock_tick);
|
||||
TIMER_CALLBACK_MEMBER(watchdog_tick);
|
||||
TIMER_CALLBACK_MEMBER(spi_tx_tick);
|
||||
template <int Which> TIMER_CALLBACK_MEMBER(adc_convert_tick);
|
||||
|
||||
uint16_t clock_rng(int which);
|
||||
|
||||
@ -178,23 +178,13 @@ protected:
|
||||
uint16_t do_special_gpio(uint32_t index, uint16_t mask);
|
||||
|
||||
void update_timer_b_rate();
|
||||
void update_timer_ab_src();
|
||||
void update_timer_c_src();
|
||||
void increment_timer_a();
|
||||
|
||||
void uart_transmit_tick();
|
||||
void uart_receive_tick();
|
||||
|
||||
void system_timer_tick();
|
||||
|
||||
void do_spi_tx();
|
||||
void set_spi_irq(bool set);
|
||||
void update_spi_irqs();
|
||||
|
||||
void do_i2c();
|
||||
|
||||
void do_adc_capture(int channel);
|
||||
|
||||
uint16_t m_io_regs[0x100];
|
||||
|
||||
uint8_t m_uart_rx_fifo[8];
|
||||
|
Loading…
Reference in New Issue
Block a user