Made SPG2xx I/O IRQ checking a bit more lean; improved ADC behavior. (#8138) [Ryan Holtz]

This commit is contained in:
MooglyGuy 2021-06-03 19:29:25 +02:00 committed by GitHub
parent f2ba6b059a
commit 990d8233bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 136 additions and 249 deletions

View File

@ -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();
}
}
}

View File

@ -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];