diff options
Diffstat (limited to 'src/devices/machine/spg2xx_io.cpp')
-rw-r--r-- | src/devices/machine/spg2xx_io.cpp | 119 |
1 files changed, 103 insertions, 16 deletions
diff --git a/src/devices/machine/spg2xx_io.cpp b/src/devices/machine/spg2xx_io.cpp index 8505bb5bd99..f795590c688 100644 --- a/src/devices/machine/spg2xx_io.cpp +++ b/src/devices/machine/spg2xx_io.cpp @@ -27,10 +27,11 @@ DEFINE_DEVICE_TYPE(SPG28X_IO, spg28x_io_device, "spg28x_io", "SPG280-series Syst #define LOG_EXT_MEM (1U << 27) #define LOG_EXTINT (1U << 28) #define LOG_SPI (1U << 29) -#define LOG_IO (LOG_IO_READS | LOG_IO_WRITES | LOG_IRQS | LOG_GPIO | LOG_UART | LOG_I2C | LOG_TIMERS | LOG_EXTINT | LOG_UNKNOWN_IO | LOG_SPI) -#define LOG_ALL (LOG_IO | LOG_VLINES | LOG_SEGMENT | LOG_WATCHDOG | LOG_FIQ | LOG_SIO | LOG_EXT_MEM) +#define LOG_ADC (1U << 30) +#define LOG_IO (LOG_IO_READS | LOG_IO_WRITES | LOG_IRQS | LOG_GPIO | LOG_UART | LOG_I2C | LOG_TIMERS | LOG_EXTINT | LOG_UNKNOWN_IO | LOG_SPI | LOG_ADC) +#define LOG_ALL (LOG_IO | LOG_VLINES | LOG_SEGMENT | LOG_WATCHDOG | LOG_FIQ | LOG_SIO | LOG_EXT_MEM | LOG_ADC) -#define VERBOSE (0) +#define VERBOSE (LOG_ADC) #include "logmacro.h" @@ -127,6 +128,12 @@ void spg2xx_io_device::device_start() 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); + } + save_item(NAME(m_io_regs)); save_item(NAME(m_uart_rx_fifo)); @@ -213,6 +220,20 @@ void spg2xx_io_device::device_reset() m_rng_timer->adjust(attotime::from_hz(1234), 0, attotime::from_hz(1234)); // timer value is arbitrary, maybe should match system clock, but that would result in heavy switching + m_tmb1->adjust(attotime::never); + m_tmb2->adjust(attotime::never); + m_uart_tx_timer->adjust(attotime::never); + m_uart_rx_timer->adjust(attotime::never); + m_timer_src_ab->adjust(attotime::never); + m_timer_src_c->adjust(attotime::never); + m_watchdog_timer->adjust(attotime::never); + m_spi_tx_timer->adjust(attotime::never); + + for (int i = 0; i < 4; i++) + { + m_adc_timer[i]->adjust(attotime::never); + } + m_2khz_divider = 0; m_1khz_divider = 0; m_4hz_divider = 0; @@ -426,7 +447,11 @@ READ16_MEMBER(spg2xx_io_device::io_r) break; case REG_ADC_CTRL: - LOGMASKED(LOG_IO_READS, "%s: io_r: ADC Control = %04x\n", machine().describe_context(), val); + LOGMASKED(LOG_IO_READS | LOG_ADC, "%s: io_r: ADC Control = %04x\n", machine().describe_context(), val); + break; + + case REG_ADC_PAD: + LOGMASKED(LOG_IO_READS | LOG_ADC, "%s: io_r: ADC Pad Control = %04x\n", machine().describe_context(), val); break; case REG_ADC_DATA: @@ -437,7 +462,7 @@ READ16_MEMBER(spg2xx_io_device::io_r) const uint16_t changed = (old & IO_IRQ_ENABLE) ^ (IO_IRQ_STATUS & IO_IRQ_ENABLE); if (changed) check_irqs(changed); - LOGMASKED(LOG_IO_READS, "%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; } @@ -1059,26 +1084,61 @@ WRITE16_MEMBER(spg2xx_io_device::io_w) case REG_ADC_CTRL: { - LOGMASKED(LOG_IO_WRITES, "%s: io_w: ADC Control = %04x\n", machine().describe_context(), data); - m_io_regs[REG_ADC_CTRL] = data & ~0x1000; - if (BIT(data, 0)) + LOGMASKED(LOG_IO_WRITES | LOG_ADC, "%s: io_w: ADC Control = %04x\n", machine().describe_context(), 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(m_io_regs[REG_ADC_CTRL], 0)) { - m_io_regs[REG_ADC_DATA] = 0x8000 | (m_adc_in[BIT(data, 5)]() & 0x7fff); - m_io_regs[REG_ADC_CTRL] |= 0x2000; + 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); + } + } + else 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)); + } + + // Req_Auto_8K + if (BIT(data, 10)) + { + m_adc_timer[channel]->adjust(attotime::from_hz(8000), 0, attotime::from_hz(8000)); + } } - if (BIT(data, 12) && !BIT(m_io_regs[REG_ADC_CTRL], 1)) + else { - 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) + for (int i = 0; i < 4; i++) { - check_irqs(changed); + m_adc_timer[i]->adjust(attotime::never); } } break; } + case REG_ADC_PAD: + LOGMASKED(LOG_IO_WRITES | LOG_ADC, "%s: io_w: ADC Pad Control = %04x\n", machine().describe_context(), data); + m_io_regs[REG_ADC_PAD] = data; + for (int i = 0; i < 4; i++) + { + if (!BIT(data, i)) + { + m_adc_timer[i]->adjust(attotime::never); + } + } + break; + case REG_SLEEP_MODE: LOGMASKED(LOG_IO_WRITES, "%s: io_w: Sleep Mode (%s enter value) = %04x\n", machine().describe_context(), data == 0xaa55 ? "valid" : "invalid", data); m_io_regs[REG_SLEEP_MODE] = data; @@ -1475,6 +1535,13 @@ void spg2xx_io_device::device_timer(emu_timer &timer, device_timer_id id, int pa 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; } } @@ -1676,6 +1743,26 @@ 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) +{ + m_io_regs[REG_ADC_DATA] = m_adc_in[channel]() & 0x0fff; + if (BIT(m_io_regs[REG_ADC_DATA], 11)) + { + //m_io_regs[REG_ADC_DATA] |= 0xf000; + } + 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) + { + check_irqs(changed); + } + } +} + void spg2xx_io_device::do_i2c() { const uint16_t addr = ((m_io_regs[REG_I2C_ADDR] & 0x06) << 7) | (uint8_t)m_io_regs[REG_I2C_SUBADDR]; |