diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index b2ebdd9f5bb..012119a8a7e 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -2897,6 +2897,17 @@ if (MACHINES["SCN_PCI"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/scoop.h,MACHINES["SCOOP"] = true +--------------------------------------------------- +if (MACHINES["SCOOP"]~=null) then + files { + MAME_DIR .. "src/devices/machine/scoop.cpp", + MAME_DIR .. "src/devices/machine/scoop.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/scnxx562.h,MACHINES["DUSCC"] = true @@ -3269,6 +3280,18 @@ if (MACHINES["TUBE"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/ucb1200.h,MACHINES["UCB1200"] = true +--------------------------------------------------- + +if (MACHINES["UCB1200"]~=null) then + files { + MAME_DIR .. "src/devices/machine/ucb1200.cpp", + MAME_DIR .. "src/devices/machine/ucb1200.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/upd1990a.h,MACHINES["UPD1990A"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 28bf0d93e66..2d6f3b6fc0b 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -624,6 +624,7 @@ MACHINES["S3C24XX"] = true MACHINES["SATURN"] = true MACHINES["SCC68070"] = true MACHINES["SCN_PCI"] = true +--MACHINES["SCOOP"] = true MACHINES["SCSI"] = true MACHINES["SCUDSP"] = true MACHINES["SDA2006"] = true @@ -656,6 +657,7 @@ MACHINES["TSB12LV01A"] = true --MACHINES["TTL74153"] = true --MACHINES["TTL74181"] = true --MACHINES["TTL7474"] = true +--MACHINES["UCB1200"] = true MACHINES["UPD1990A"] = true MACHINES["UPD4992"] = true MACHINES["UPD4701"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 50f9262c362..0188badce30 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -659,6 +659,7 @@ MACHINES["SCC68070"] = true --MACHINES["SCSI"] = true MACHINES["SCC2698B"] = true MACHINES["SCN_PCI"] = true +MACHINES["SCOOP"] = true MACHINES["SCUDSP"] = true MACHINES["SECFLASH"] = true MACHINES["SEIBU_COP"] = true @@ -703,6 +704,7 @@ MACHINES["TTL74381"] = true MACHINES["TTL74543"] = true MACHINES["TTL7474"] = true MACHINES["TUBE"] = true +MACHINES["UCB1200"] = true MACHINES["UPD1990A"] = true --MACHINES["UPD4992"] = true MACHINES["UPD4701"] = true diff --git a/src/devices/machine/locomo.cpp b/src/devices/machine/locomo.cpp index f54f1bedce4..4eb6c54008d 100644 --- a/src/devices/machine/locomo.cpp +++ b/src/devices/machine/locomo.cpp @@ -2,7 +2,7 @@ // copyright-holders:Ryan Holtz /*************************************************************************** - Sharp LoCoMo peripheral chip emulation + Sharp LoCoMo peripheral chip emulation skeleton ***************************************************************************/ diff --git a/src/devices/machine/locomo.h b/src/devices/machine/locomo.h index 86d6eeef8fe..7f870b8f778 100644 --- a/src/devices/machine/locomo.h +++ b/src/devices/machine/locomo.h @@ -2,7 +2,7 @@ // copyright-holders:Ryan Holtz /*************************************************************************** - Sharp LoCoMo peripheral chip emulation + Sharp LoCoMo peripheral chip emulation skeleton ***************************************************************************/ diff --git a/src/devices/machine/sa1110.cpp b/src/devices/machine/sa1110.cpp index 1c79d1a943d..9824b210341 100644 --- a/src/devices/machine/sa1110.cpp +++ b/src/devices/machine/sa1110.cpp @@ -12,13 +12,14 @@ #define LOG_UNKNOWN (1 << 1) #define LOG_UART (1 << 2) #define LOG_UART_HF (1 << 3) -#define LOG_OSTIMER (1 << 4) -#define LOG_RTC (1 << 5) -#define LOG_POWER (1 << 6) -#define LOG_RESET (1 << 7) -#define LOG_GPIO (1 << 8) -#define LOG_INTC (1 << 9) -#define LOG_ALL (LOG_UNKNOWN | LOG_UART | LOG_OSTIMER | LOG_RTC | LOG_POWER | LOG_RESET | LOG_GPIO | LOG_INTC) +#define LOG_MCP (1 << 4) +#define LOG_OSTIMER (1 << 5) +#define LOG_RTC (1 << 6) +#define LOG_POWER (1 << 7) +#define LOG_RESET (1 << 8) +#define LOG_GPIO (1 << 9) +#define LOG_INTC (1 << 10) +#define LOG_ALL (LOG_UNKNOWN | LOG_UART | LOG_MCP | LOG_OSTIMER | LOG_RTC | LOG_POWER | LOG_RESET | LOG_GPIO | LOG_INTC) #define VERBOSE (LOG_ALL) #include "logmacro.h" @@ -30,6 +31,8 @@ sa1110_periphs_device::sa1110_periphs_device(const machine_config &mconfig, cons , device_serial_interface(mconfig, *this) , m_maincpu(*this, finder_base::DUMMY_TAG) , m_uart3_irqs(*this, "uart3irq") + , m_mcp_irqs(*this, "mcpirq") + , m_codec(*this, finder_base::DUMMY_TAG) , m_gpio_out(*this) { } @@ -353,6 +356,357 @@ void sa1110_periphs_device::uart3_w(offs_t offset, uint32_t data, uint32_t mem_m } } +/* + + Intel SA-1110 MCP - Serial Port 4 + + pg. 306 to 346 Intel StrongARM SA-1110 Microprocessor Developer's Manual + +*/ + +WRITE_LINE_MEMBER(sa1110_periphs_device::mcp_irq_callback) +{ + set_irq_line(INT_MCP, state); +} + +TIMER_CALLBACK_MEMBER(sa1110_periphs_device::mcp_audio_tx_callback) +{ + if (!m_codec) + return; + + const uint16_t sample = m_mcp_regs.audio_tx_fifo[m_mcp_regs.audio_tx_fifo_read_idx]; + m_codec->audio_sample_in(sample); + + if (m_mcp_regs.audio_tx_fifo_count) + { + m_mcp_regs.audio_tx_fifo_count--; + m_mcp_regs.audio_tx_fifo_read_idx = (m_mcp_regs.audio_tx_fifo_read_idx + 1) % ARRAY_LENGTH(m_mcp_regs.audio_tx_fifo); + + m_mcp_regs.mcsr &= ~(1 << MCSR_ATU_BIT); + m_mcp_irqs->in_w(0); + } + else + { + m_mcp_regs.mcsr |= (1 << MCSR_ATU_BIT); + m_mcp_irqs->in_w(1); + } + + m_mcp_regs.mcsr |= (1 << MCSR_ANF_BIT); +} + +TIMER_CALLBACK_MEMBER(sa1110_periphs_device::mcp_telecom_tx_callback) +{ + if (!m_codec) + return; + + const uint16_t sample = m_mcp_regs.telecom_tx_fifo[m_mcp_regs.telecom_tx_fifo_read_idx]; + m_codec->telecom_sample_in(sample); + + if (m_mcp_regs.telecom_tx_fifo_count) + { + m_mcp_regs.telecom_tx_fifo_count--; + m_mcp_regs.telecom_tx_fifo_read_idx = (m_mcp_regs.telecom_tx_fifo_read_idx + 1) % ARRAY_LENGTH(m_mcp_regs.telecom_tx_fifo); + + m_mcp_regs.mcsr &= ~(1 << MCSR_TTU_BIT); + m_mcp_irqs->in_w(0); + } + else + { + m_mcp_regs.mcsr |= (1 << MCSR_TTU_BIT); + m_mcp_irqs->in_w(1); + } + + m_mcp_regs.mcsr |= (1 << MCSR_TNF_BIT); +} + +uint16_t sa1110_periphs_device::mcp_read_audio_fifo() +{ + const uint16_t data = m_mcp_regs.audio_rx_fifo[m_mcp_regs.audio_rx_fifo_read_idx]; + if (m_mcp_regs.audio_rx_fifo_count) + { + m_mcp_regs.audio_rx_fifo_count--; + m_mcp_regs.audio_rx_fifo_read_idx = (m_mcp_regs.audio_rx_fifo_read_idx + 1) % ARRAY_LENGTH(m_mcp_regs.audio_rx_fifo); + + const bool half_full = m_mcp_regs.audio_rx_fifo_count >= 4; + m_mcp_regs.mcsr &= ~(1 << MCSR_ARS_BIT); + if (half_full) + { + m_mcp_regs.mcsr |= (1 << MCSR_ARS_BIT); + } + bool fifo_interrupt = BIT(m_mcp_regs.mccr0, MCCR0_ARE_BIT) && half_full; + m_mcp_irqs->in_w((int)fifo_interrupt); + + if (m_mcp_regs.audio_rx_fifo_count) + m_mcp_regs.mcsr &= ~(1 << MCSR_ANE_BIT); + else + m_mcp_regs.mcsr |= (1 << MCSR_ANE_BIT); + } + return data; +} + +uint16_t sa1110_periphs_device::mcp_read_telecom_fifo() +{ + const uint16_t data = m_mcp_regs.telecom_rx_fifo[m_mcp_regs.telecom_rx_fifo_read_idx]; + if (m_mcp_regs.telecom_rx_fifo_count) + { + m_mcp_regs.telecom_rx_fifo_count--; + m_mcp_regs.telecom_rx_fifo_read_idx = (m_mcp_regs.telecom_rx_fifo_read_idx + 1) % ARRAY_LENGTH(m_mcp_regs.telecom_rx_fifo); + + const bool half_full = m_mcp_regs.telecom_rx_fifo_count >= 4; + m_mcp_regs.mcsr &= ~(1 << MCSR_TRS_BIT); + if (half_full) + { + m_mcp_regs.mcsr |= (1 << MCSR_TRS_BIT); + } + bool fifo_interrupt = BIT(m_mcp_regs.mccr0, MCCR0_TRE_BIT) && half_full; + m_mcp_irqs->in_w((int)fifo_interrupt); + + if (m_mcp_regs.telecom_rx_fifo_count) + m_mcp_regs.mcsr &= ~(1 << MCSR_TNE_BIT); + else + m_mcp_regs.mcsr |= (1 << MCSR_TNE_BIT); + } + return data; +} + +attotime sa1110_periphs_device::mcp_get_audio_frame_rate() +{ + const uint32_t bit_rate = BIT(m_mcp_regs.mccr1, MCCR1_CFS_BIT) ? 9585000 : 11981000; + const uint64_t ticks = 32 * ((m_mcp_regs.mccr0 & MCCR0_ASD_MASK) >> MCCR0_ASD_BIT); + return attotime::from_ticks(ticks, bit_rate); +} + +attotime sa1110_periphs_device::mcp_get_telecom_frame_rate() +{ + const uint32_t bit_rate = BIT(m_mcp_regs.mccr1, MCCR1_CFS_BIT) ? 9585000 : 11981000; + const uint64_t ticks = 32 * ((m_mcp_regs.mccr0 & MCCR0_TSD_MASK) >> MCCR0_TSD_BIT); + return attotime::from_ticks(ticks, bit_rate); +} + +void sa1110_periphs_device::mcp_update_sample_rate() +{ + const attotime audio_rate = mcp_get_audio_frame_rate(); + m_mcp_regs.audio_tx_timer->adjust(audio_rate, 0, audio_rate); + + const attotime telecom_rate = mcp_get_telecom_frame_rate(); + m_mcp_regs.telecom_tx_timer->adjust(telecom_rate, 0, telecom_rate); +} + +void sa1110_periphs_device::mcp_set_enabled(bool enabled) +{ + if (enabled) + { + mcp_update_sample_rate(); + } + else + { + m_mcp_regs.audio_tx_timer->adjust(attotime::never); + m_mcp_regs.telecom_tx_timer->adjust(attotime::never); + } +} + +void sa1110_periphs_device::mcp_audio_tx_fifo_push(const uint16_t value) +{ + if (m_mcp_regs.audio_rx_fifo_count == ARRAY_LENGTH(m_mcp_regs.audio_tx_fifo)) + return; + + m_mcp_regs.audio_tx_fifo[m_mcp_regs.audio_tx_fifo_write_idx] = value; + m_mcp_regs.audio_rx_fifo_write_idx = (m_mcp_regs.audio_tx_fifo_write_idx + 1) % ARRAY_LENGTH(m_mcp_regs.audio_tx_fifo); + m_mcp_regs.audio_rx_fifo_count++; + + if (m_mcp_regs.audio_tx_fifo_count == ARRAY_LENGTH(m_mcp_regs.audio_tx_fifo)) + m_mcp_regs.mcsr &= ~(1 << MCSR_ANF_BIT); + + if (m_mcp_regs.audio_tx_fifo_count >= 4) + { + m_mcp_regs.mcsr &= ~(1 << MCSR_ATS_BIT); + if (BIT(m_mcp_regs.mccr0, MCCR0_ATE_BIT)) + m_mcp_irqs->in_w(0); + } + else + { + m_mcp_regs.mcsr |= (1 << MCSR_ATS_BIT); + if (BIT(m_mcp_regs.mccr0, MCCR0_ATE_BIT)) + m_mcp_irqs->in_w(1); + } +} + +void sa1110_periphs_device::mcp_telecom_tx_fifo_push(const uint16_t value) +{ + if (m_mcp_regs.telecom_rx_fifo_count == ARRAY_LENGTH(m_mcp_regs.telecom_tx_fifo)) + return; + + m_mcp_regs.telecom_tx_fifo[m_mcp_regs.telecom_tx_fifo_write_idx] = value; + m_mcp_regs.telecom_rx_fifo_write_idx = (m_mcp_regs.telecom_tx_fifo_write_idx + 1) % ARRAY_LENGTH(m_mcp_regs.telecom_tx_fifo); + m_mcp_regs.telecom_rx_fifo_count++; + + if (m_mcp_regs.telecom_tx_fifo_count == ARRAY_LENGTH(m_mcp_regs.telecom_tx_fifo)) + m_mcp_regs.mcsr &= ~(1 << MCSR_TNF_BIT); + + if (m_mcp_regs.audio_tx_fifo_count >= 4) + { + m_mcp_regs.mcsr &= ~(1 << MCSR_TTS_BIT); + if (BIT(m_mcp_regs.mccr0, MCCR0_TTE_BIT)) + m_mcp_irqs->in_w(0); + } + else + { + m_mcp_regs.mcsr |= (1 << MCSR_TTS_BIT); + if (BIT(m_mcp_regs.mccr0, MCCR0_TTE_BIT)) + m_mcp_irqs->in_w(1); + } +} + +void sa1110_periphs_device::mcp_codec_read(offs_t offset) +{ + if (!m_codec) + return; + + const uint16_t data = m_codec->read(offset); + m_mcp_regs.mcdr2 &= 0xffff0000; + m_mcp_regs.mcdr2 |= data; + + m_mcp_regs.mcsr |= (1 << MCSR_CRC_BIT); + m_mcp_regs.mcsr &= ~(1 << MCSR_CWC_BIT); +} + +void sa1110_periphs_device::mcp_codec_write(offs_t offset, uint16_t data) +{ + if (!m_codec) + return; + + m_codec->write(offset, data); + m_mcp_regs.mcsr |= (1 << MCSR_CWC_BIT); + m_mcp_regs.mcsr &= ~(1 << MCSR_CRC_BIT); +} + +uint32_t sa1110_periphs_device::mcp_r(offs_t offset, uint32_t mem_mask) +{ + switch (offset) + { + case REG_MCCR0: + LOGMASKED(LOG_MCP, "%s: mcp_r: MCP Control Register 0: %08x & %08x\n", machine().describe_context(), m_mcp_regs.mccr0, mem_mask); + return m_mcp_regs.mccr0; + case REG_MCDR0: + { + const uint16_t data = mcp_read_audio_fifo() << 4; + LOGMASKED(LOG_MCP, "%s: mcp_r: MCP Data Register 0: %08x & %08x\n", machine().describe_context(), data, mem_mask); + return data; + } + case REG_MCDR1: + { + const uint16_t data = mcp_read_telecom_fifo() << 4; + LOGMASKED(LOG_MCP, "%s: mcp_r: MCP Data Register 1: %08x & %08x\n", machine().describe_context(), data, mem_mask); + return data; + } + case REG_MCDR2: + LOGMASKED(LOG_MCP, "%s: mcp_r: MCP Data Register 2: %08x & %08x\n", machine().describe_context(), m_mcp_regs.mcdr2, mem_mask); + LOGMASKED(LOG_MCP, "%s: Value: %04x\n", machine().describe_context(), (uint16_t)m_mcp_regs.mcdr2); + LOGMASKED(LOG_MCP, "%s: Read/Write: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcdr2, 16)); + LOGMASKED(LOG_MCP, "%s: Address: %01x\n", machine().describe_context(), (m_mcp_regs.mcdr2 >> 17) & 0xf); + return m_mcp_regs.mcdr2; + case REG_MCSR: + LOGMASKED(LOG_MCP, "%s: mcp_r: MCP Status Register: %08x & %08x\n", machine().describe_context(), m_mcp_regs.mcsr, mem_mask); + LOGMASKED(LOG_MCP, "%s: Audio Xmit FIFO Service Request: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 0)); + LOGMASKED(LOG_MCP, "%s: Audio Recv FIFO Service Request: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 1)); + LOGMASKED(LOG_MCP, "%s: Telecom Xmit FIFO Service Request: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 2)); + LOGMASKED(LOG_MCP, "%s: Telecom Recv FIFO Service Request: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 3)); + LOGMASKED(LOG_MCP, "%s: Audio Xmit FIFO Underrun: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 4)); + LOGMASKED(LOG_MCP, "%s: Audio Recv FIFO Overrun: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 5)); + LOGMASKED(LOG_MCP, "%s: Telcom Xmit FIFO Underrun: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 6)); + LOGMASKED(LOG_MCP, "%s: Telcom Recv FIFO Overrun: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 7)); + LOGMASKED(LOG_MCP, "%s: Audio Xmit FIFO Not Full: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 8)); + LOGMASKED(LOG_MCP, "%s: Audio Recv FIFO Not Empty: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 9)); + LOGMASKED(LOG_MCP, "%s: Telcom Xmit FIFO Not Full: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 10)); + LOGMASKED(LOG_MCP, "%s: Telcom Recv FIFO Not Empty: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 11)); + LOGMASKED(LOG_MCP, "%s: Codec Write Complete: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 12)); + LOGMASKED(LOG_MCP, "%s: Codec Read Complete: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 13)); + LOGMASKED(LOG_MCP, "%s: Audio Codec Enabled: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 14)); + LOGMASKED(LOG_MCP, "%s: Telecom Codec Enabled: %d\n", machine().describe_context(), BIT(m_mcp_regs.mcsr, 15)); + return m_mcp_regs.mcsr; + default: + LOGMASKED(LOG_MCP | LOG_UNKNOWN, "%s: ostimer_r: Unknown address: %08x & %08x\n", machine().describe_context(), MCP_BASE_ADDR | (offset << 2), mem_mask); + return 0; + } +} + +void sa1110_periphs_device::mcp_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset) + { + case REG_MCCR0: + { + LOGMASKED(LOG_MCP, "%s: mcp_w: MCP Control Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + LOGMASKED(LOG_MCP, "%s: Audio Sample Rate Divisor: %02x\n", machine().describe_context(), data & MCCR0_ASD_MASK); + LOGMASKED(LOG_MCP, "%s: Telecom Sample Rate Divisor: %02x\n", machine().describe_context(), (data & MCCR0_TSD_MASK) >> MCCR0_TSD_BIT); + LOGMASKED(LOG_MCP, "%s: MCP Enable: %d\n", machine().describe_context(), BIT(data, MCCR0_MCE_BIT)); + LOGMASKED(LOG_MCP, "%s: Clock Select: %s\n", machine().describe_context(), BIT(data, MCCR0_ECS_BIT) ? "External" : "Internal"); + LOGMASKED(LOG_MCP, "%s: A/D Data Sampling Mode: %s Valid\n", machine().describe_context(), BIT(data, MCCR0_ADM_BIT) ? "First" : "Each"); + LOGMASKED(LOG_MCP, "%s: Telecom Tx FIFO Interrupt Enable: %d\n", machine().describe_context(), BIT(data, MCCR0_TTE_BIT)); + LOGMASKED(LOG_MCP, "%s: Telecom Rx FIFO Interrupt Enable: %d\n", machine().describe_context(), BIT(data, MCCR0_TRE_BIT)); + LOGMASKED(LOG_MCP, "%s: Audio Tx FIFO Interrupt Enable: %d\n", machine().describe_context(), BIT(data, MCCR0_ATE_BIT)); + LOGMASKED(LOG_MCP, "%s: Audio Rx FIFO Interrupt Enable: %d\n", machine().describe_context(), BIT(data, MCCR0_ARE_BIT)); + LOGMASKED(LOG_MCP, "%s: Loopback Enable: %d\n", machine().describe_context(), BIT(data, MCCR0_LBM_BIT)); + LOGMASKED(LOG_MCP, "%s: External Clock Prescaler: %d\n", machine().describe_context(), ((data & MCCR0_ECP_MASK) >> MCCR0_ECP_BIT) + 1); + const uint32_t old = m_mcp_regs.mccr0; + COMBINE_DATA(&m_mcp_regs.mccr0); + const uint32_t changed = old ^ m_mcp_regs.mccr0; + if (BIT(m_mcp_regs.mcsr, MCSR_ATS_BIT) && BIT(changed, MCCR0_ATE_BIT)) + m_mcp_irqs->in_w(BIT(m_mcp_regs.mcsr, MCSR_ATS_BIT)); + if (BIT(m_mcp_regs.mcsr, MCSR_ARS_BIT) && BIT(changed, MCCR0_ARE_BIT)) + m_mcp_irqs->in_w(BIT(m_mcp_regs.mcsr, MCSR_ARS_BIT)); + if (BIT(m_mcp_regs.mcsr, MCSR_TTS_BIT) && BIT(changed, MCCR0_TTE_BIT)) + m_mcp_irqs->in_w(BIT(m_mcp_regs.mcsr, MCSR_TTS_BIT)); + if (BIT(m_mcp_regs.mcsr, MCSR_TRS_BIT) && BIT(changed, MCCR0_TRE_BIT)) + m_mcp_irqs->in_w(BIT(m_mcp_regs.mcsr, MCSR_TRS_BIT)); + if (BIT(old, MCCR0_MCE_BIT) != BIT(m_mcp_regs.mccr0, MCCR0_MCE_BIT)) + mcp_set_enabled(BIT(m_mcp_regs.mccr0, MCCR0_MCE_BIT)); + break; + } + case REG_MCDR0: + LOGMASKED(LOG_MCP, "%s: mcp_w: MCP Data Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + mcp_audio_tx_fifo_push((uint16_t)data); + break; + case REG_MCDR1: + LOGMASKED(LOG_MCP, "%s: mcp_w: MCP Data Register 1 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + mcp_telecom_tx_fifo_push((uint16_t)data); + break; + case REG_MCDR2: + { + const offs_t addr = (data & MCDR2_ADDR_MASK) >> MCDR2_ADDR_BIT; + LOGMASKED(LOG_MCP, "%s: mcp_w: MCP Data Register 2 = %08x & %08x\n", machine().describe_context(), data, mem_mask); + COMBINE_DATA(&m_mcp_regs.mcdr2); + m_mcp_regs.mcdr2 &= ~(1 << MCDR2_RW_BIT); + + if (BIT(data, MCDR2_RW_BIT)) + mcp_codec_write(addr, (uint16_t)data); + else + mcp_codec_read(addr); + break; + } + case REG_MCSR: + { + LOGMASKED(LOG_MCP, "%s: mcp_w: MCP Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask); + const uint32_t old = m_mcp_regs.mcsr; + const uint32_t sticky_mask = (1 << MCSR_ATU_BIT) | (1 << MCSR_ARO_BIT) | (1 << MCSR_TTU_BIT) | (1 << MCSR_TRO_BIT); + m_mcp_regs.mcsr &= ~(data & mem_mask & sticky_mask); + if (BIT(old, MCSR_ATU_BIT) && !BIT(m_mcp_regs.mcsr, MCSR_ATU_BIT)) + m_mcp_irqs->in_w(0); + if (BIT(old, MCSR_ARO_BIT) && !BIT(m_mcp_regs.mcsr, MCSR_ARO_BIT)) + m_mcp_irqs->in_w(0); + if (BIT(old, MCSR_TTU_BIT) && !BIT(m_mcp_regs.mcsr, MCSR_TTU_BIT)) + m_mcp_irqs->in_w(0); + if (BIT(old, MCSR_TRO_BIT) && !BIT(m_mcp_regs.mcsr, MCSR_TRO_BIT)) + m_mcp_irqs->in_w(0); + break; + } + default: + LOGMASKED(LOG_MCP | LOG_UNKNOWN, "%s: mcp_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), MCP_BASE_ADDR | (offset << 2), + data, mem_mask); + break; + } +} + /* Intel SA-1110 Operating System Timer @@ -1035,6 +1389,29 @@ void sa1110_periphs_device::device_start() save_item(NAME(m_uart_regs.tx_fifo_count)); save_item(NAME(m_uart_regs.rx_break_interlock)); + save_item(NAME(m_mcp_regs.mccr0)); + save_item(NAME(m_mcp_regs.mccr1)); + save_item(NAME(m_mcp_regs.mcdr2)); + save_item(NAME(m_mcp_regs.mcsr)); + save_item(NAME(m_mcp_regs.audio_rx_fifo)); + save_item(NAME(m_mcp_regs.audio_rx_fifo_read_idx)); + save_item(NAME(m_mcp_regs.audio_rx_fifo_write_idx)); + save_item(NAME(m_mcp_regs.audio_rx_fifo_count)); + save_item(NAME(m_mcp_regs.audio_tx_fifo)); + save_item(NAME(m_mcp_regs.audio_tx_fifo_read_idx)); + save_item(NAME(m_mcp_regs.audio_tx_fifo_write_idx)); + save_item(NAME(m_mcp_regs.audio_tx_fifo_count)); + m_mcp_regs.audio_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1110_periphs_device::mcp_audio_tx_callback), this)); + save_item(NAME(m_mcp_regs.telecom_rx_fifo)); + save_item(NAME(m_mcp_regs.telecom_rx_fifo_read_idx)); + save_item(NAME(m_mcp_regs.telecom_rx_fifo_write_idx)); + save_item(NAME(m_mcp_regs.telecom_rx_fifo_count)); + save_item(NAME(m_mcp_regs.telecom_tx_fifo)); + save_item(NAME(m_mcp_regs.telecom_tx_fifo_read_idx)); + save_item(NAME(m_mcp_regs.telecom_tx_fifo_write_idx)); + save_item(NAME(m_mcp_regs.telecom_tx_fifo_count)); + m_mcp_regs.telecom_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1110_periphs_device::mcp_telecom_tx_callback), this)); + save_item(NAME(m_ostmr_regs.osmr)); save_item(NAME(m_ostmr_regs.oscr)); save_item(NAME(m_ostmr_regs.ossr)); @@ -1103,6 +1480,30 @@ void sa1110_periphs_device::device_reset() transmit_register_reset(); receive_register_reset(); + // init MCP regs + m_mcp_regs.mccr0 = 0; + m_mcp_regs.mccr1 = 0; + m_mcp_regs.mcdr2 = 0; + m_mcp_regs.mcsr = (1 << MCSR_ANF_BIT) | (1 << MCSR_TNF_BIT); + memset(m_mcp_regs.audio_rx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_mcp_regs.audio_rx_fifo)); + m_mcp_regs.audio_rx_fifo_read_idx = 0; + m_mcp_regs.audio_rx_fifo_write_idx = 0; + m_mcp_regs.audio_rx_fifo_count = 0; + memset(m_mcp_regs.audio_tx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_mcp_regs.audio_tx_fifo)); + m_mcp_regs.audio_tx_fifo_read_idx = 0; + m_mcp_regs.audio_tx_fifo_write_idx = 0; + m_mcp_regs.audio_tx_fifo_count = 0; + m_mcp_regs.audio_tx_timer->adjust(attotime::never); + memset(m_mcp_regs.telecom_rx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_mcp_regs.telecom_rx_fifo)); + m_mcp_regs.telecom_rx_fifo_read_idx = 0; + m_mcp_regs.telecom_rx_fifo_write_idx = 0; + m_mcp_regs.telecom_rx_fifo_count = 0; + memset(m_mcp_regs.telecom_tx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_mcp_regs.telecom_tx_fifo)); + m_mcp_regs.telecom_tx_fifo_read_idx = 0; + m_mcp_regs.telecom_tx_fifo_write_idx = 0; + m_mcp_regs.telecom_tx_fifo_count = 0; + m_mcp_regs.telecom_tx_timer->adjust(attotime::never); + // init OS timers memset(m_ostmr_regs.osmr, 0, sizeof(uint32_t) * 4); m_ostmr_regs.ower = 0; @@ -1134,4 +1535,5 @@ void sa1110_periphs_device::device_reset() void sa1110_periphs_device::device_add_mconfig(machine_config &config) { INPUT_MERGER_ANY_HIGH(config, m_uart3_irqs).output_handler().set(FUNC(sa1110_periphs_device::uart3_irq_callback)); + INPUT_MERGER_ANY_HIGH(config, m_mcp_irqs).output_handler().set(FUNC(sa1110_periphs_device::mcp_irq_callback)); } diff --git a/src/devices/machine/sa1110.h b/src/devices/machine/sa1110.h index 115285dbf7b..cd823fb9934 100644 --- a/src/devices/machine/sa1110.h +++ b/src/devices/machine/sa1110.h @@ -15,6 +15,7 @@ #include "cpu/arm7/arm7core.h" #include "machine/input_merger.h" +#include "machine/ucb1200.h" #include "diserial.h" @@ -30,16 +31,20 @@ public: sa1110_periphs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template void set_codec_tag(T &&tag) { m_codec.set_tag(std::forward(tag)); } + // device_serial overrides virtual void rcv_complete() override; // Rx completed receiving byte virtual void tra_complete() override; // Tx completed sending byte virtual void tra_callback() override; // Tx send bit - void gpio_in(const uint32_t line, const int state); + template void gpio_in(int state) { gpio_in(Line, state); } template auto gpio_out() { return m_gpio_out[Line].bind(); } uint32_t uart3_r(offs_t offset, uint32_t mem_mask = ~0); void uart3_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + uint32_t mcp_r(offs_t offset, uint32_t mem_mask = ~0); + void mcp_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); uint32_t ostimer_r(offs_t offset, uint32_t mem_mask = ~0); void ostimer_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); uint32_t rtc_r(offs_t offset, uint32_t mem_mask = ~0); @@ -73,12 +78,27 @@ protected: void uart_set_receive_irq_enabled(bool enabled); void uart_set_transmit_irq_enabled(bool enabled); + DECLARE_WRITE_LINE_MEMBER(mcp_irq_callback); + TIMER_CALLBACK_MEMBER(mcp_audio_tx_callback); + TIMER_CALLBACK_MEMBER(mcp_telecom_tx_callback); + void mcp_update_sample_rate(); + void mcp_set_enabled(bool enabled); + uint16_t mcp_read_audio_fifo(); + uint16_t mcp_read_telecom_fifo(); + attotime mcp_get_audio_frame_rate(); + attotime mcp_get_telecom_frame_rate(); + void mcp_audio_tx_fifo_push(const uint16_t value); + void mcp_telecom_tx_fifo_push(const uint16_t value); + void mcp_codec_read(offs_t offset); + void mcp_codec_write(offs_t offset, uint16_t data); + TIMER_CALLBACK_MEMBER(ostimer_tick_cb); void ostimer_update_count(); void ostimer_update_match_timer(int channel); TIMER_CALLBACK_MEMBER(rtc_tick_cb); + void gpio_in(const uint32_t line, const int state); void gpio_update_interrupts(const uint32_t changed_mask); void gpio_update_direction(const uint32_t old_gpdr); void gpio_update_outputs(const uint32_t old_latch, const uint32_t changed); @@ -99,6 +119,13 @@ protected: REG_UTSR0 = (0x0000001c >> 2), REG_UTSR1 = (0x00000020 >> 2), + MCP_BASE_ADDR = 0x80060000, + REG_MCCR0 = (0x00000000 >> 2), + REG_MCDR0 = (0x00000008 >> 2), + REG_MCDR1 = (0x0000000c >> 2), + REG_MCDR2 = (0x00000010 >> 2), + REG_MCSR = (0x00000018 >> 2), + OSTMR_BASE_ADDR = 0x90000000, REG_OSMR0 = (0x00000000 >> 2), REG_OSMR1 = (0x00000004 >> 2), @@ -176,6 +203,44 @@ protected: UTSR1_FRE_BIT = 4, UTSR1_ROR_BIT = 5, + MCCR0_ASD_BIT = 0, + MCCR0_ASD_MASK = 0x0000007f, + MCCR0_TSD_BIT = 8, + MCCR0_TSD_MASK = 0x00007f00, + MCCR0_MCE_BIT = 16, + MCCR0_ECS_BIT = 17, + MCCR0_ADM_BIT = 18, + MCCR0_TTE_BIT = 19, + MCCR0_TRE_BIT = 20, + MCCR0_ATE_BIT = 21, + MCCR0_ARE_BIT = 22, + MCCR0_LBM_BIT = 23, + MCCR0_ECP_BIT = 24, + MCCR0_ECP_MASK = 0x03000000, + + MCCR1_CFS_BIT = 20, + + MCDR2_RW_BIT = 16, + MCDR2_ADDR_BIT = 17, + MCDR2_ADDR_MASK = 0x001e0000, + + MCSR_ATS_BIT = 0, + MCSR_ARS_BIT = 1, + MCSR_TTS_BIT = 2, + MCSR_TRS_BIT = 3, + MCSR_ATU_BIT = 4, + MCSR_ARO_BIT = 5, + MCSR_TTU_BIT = 6, + MCSR_TRO_BIT = 7, + MCSR_ANF_BIT = 8, + MCSR_ANE_BIT = 9, + MCSR_TNF_BIT = 10, + MCSR_TNE_BIT = 11, + MCSR_CWC_BIT = 12, + MCSR_CRC_BIT = 13, + MCSR_ACE_BIT = 14, + MCSR_TCE_BIT = 15, + RTSR_AL_BIT = 0, RTSR_AL_MASK = (1 << RTSR_AL_BIT), RTSR_HZ_BIT = 1, @@ -233,6 +298,19 @@ protected: UART3_EIF = 5, }; + // MCP interrupt sources + enum : unsigned + { + MCP_AUDIO_TX = 0, + MCP_AUDIO_RX = 1, + MCP_TELECOM_TX = 2, + MCP_TELECOM_RX = 3, + MCP_AUDIO_UNDERRUN = 4, + MCP_AUDIO_OVERRUN = 5, + MCP_TELECOM_UNDERRUN = 6, + MCP_TELECOM_OVERRUN = 7 + }; + struct uart_regs { uint32_t utcr[4]; @@ -252,6 +330,36 @@ protected: bool rx_break_interlock; }; + struct mcp_regs + { + uint32_t mccr0; + uint32_t mccr1; + uint32_t mcdr2; + uint32_t mcsr; + + uint16_t audio_rx_fifo[8]; + int audio_rx_fifo_read_idx; + int audio_rx_fifo_write_idx; + int audio_rx_fifo_count; + + uint16_t audio_tx_fifo[8]; + int audio_tx_fifo_read_idx; + int audio_tx_fifo_write_idx; + int audio_tx_fifo_count; + emu_timer *audio_tx_timer; + + uint16_t telecom_rx_fifo[8]; + int telecom_rx_fifo_read_idx; + int telecom_rx_fifo_write_idx; + int telecom_rx_fifo_count; + + uint16_t telecom_tx_fifo[8]; + int telecom_tx_fifo_read_idx; + int telecom_tx_fifo_write_idx; + int telecom_tx_fifo_count; + emu_timer *telecom_tx_timer; + }; + struct ostimer_regs { uint32_t osmr[4]; @@ -314,6 +422,7 @@ protected: }; uart_regs m_uart_regs; + mcp_regs m_mcp_regs; ostimer_regs m_ostmr_regs; rtc_regs m_rtc_regs; power_regs m_power_regs; @@ -323,6 +432,8 @@ protected: required_device m_maincpu; required_device m_uart3_irqs; + required_device m_mcp_irqs; + optional_device m_codec; devcb_write_line::array<28> m_gpio_out; }; diff --git a/src/devices/machine/scoop.cpp b/src/devices/machine/scoop.cpp new file mode 100644 index 00000000000..ace4ee78b81 --- /dev/null +++ b/src/devices/machine/scoop.cpp @@ -0,0 +1,178 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + Sharp Scoop peripheral chip emulation skeleton + +***************************************************************************/ + +#include "emu.h" +#include "scoop.h" + +#define LOG_UNKNOWN (1 << 1) +#define LOG_READS (1 << 2) +#define LOG_WRITES (1 << 3) +#define LOG_ALL (LOG_UNKNOWN | LOG_READS | LOG_WRITES) + +#define VERBOSE (LOG_ALL) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(SCOOP, scoop_device, "scoop", "Sharp SCOOP peripheral interface") + +scoop_device::scoop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SCOOP, tag, owner, clock) + , m_gpio_out(*this) +{ +} + +void scoop_device::device_start() +{ + m_gpio_out.resolve_all_safe(); + + save_item(NAME(m_gpwr)); + save_item(NAME(m_gpio_in_latch)); + save_item(NAME(m_gpcr)); +} + +void scoop_device::device_reset() +{ + m_gpwr = 0; + m_gpio_in_latch = 0; + m_gpcr = 0; +} + +void scoop_device::gpio_in(const uint16_t line, const int state) +{ + m_gpio_in_latch &= ~(1 << line); + m_gpio_in_latch |= (state << line); +} + +void scoop_device::update_gpio_direction(const uint16_t old_dir) +{ + const uint16_t new_outputs = ~old_dir & m_gpcr; + if (new_outputs) + { + for (uint32_t line = 0; line < 13; line++) + { + if (BIT(new_outputs, line)) + { + m_gpio_out[line](BIT(m_gpwr, line)); + } + } + } +} + +void scoop_device::update_gpio_outputs(const uint16_t old_latch, const uint16_t changed) +{ + uint16_t remaining_changed = changed; + + for (uint32_t line = 0; line < 13 && remaining_changed != 0; line++) + { + if (BIT(remaining_changed, line)) + { + m_gpio_out[line](BIT(m_gpwr, line)); + remaining_changed &= ~(1 << line); + } + } +} + +uint32_t scoop_device::read(offs_t offset) +{ + switch (offset) + { + case 0x00/4: + LOGMASKED(LOG_READS, "%s: read: MCR: %04x\n", machine().describe_context(), 0); + return 0; + case 0x04/4: + LOGMASKED(LOG_READS, "%s: read: CDR: %04x\n", machine().describe_context(), 0); + return 0; + case 0x08/4: + LOGMASKED(LOG_READS, "%s: read: CSR: %04x\n", machine().describe_context(), 0); + return 0; + case 0x0c/4: + LOGMASKED(LOG_READS, "%s: read: CPR: %04x\n", machine().describe_context(), 0); + return 0; + case 0x10/4: + LOGMASKED(LOG_READS, "%s: read: CCR: %04x\n", machine().describe_context(), 0); + return 0; + case 0x14/4: + LOGMASKED(LOG_READS, "%s: read: IRR: %04x\n", machine().describe_context(), 0); + return 0; + case 0x18/4: + LOGMASKED(LOG_READS, "%s: read: IMR: %04x\n", machine().describe_context(), 0); + return 0; + case 0x1c/4: + LOGMASKED(LOG_READS, "%s: read: ISR: %04x\n", machine().describe_context(), 0); + return 0; + case 0x20/4: + LOGMASKED(LOG_READS, "%s: read: GPCR: %04x\n", machine().describe_context(), m_gpcr); + return m_gpcr; + case 0x24/4: + LOGMASKED(LOG_READS, "%s: read: GPWR: %04x\n", machine().describe_context(), m_gpwr); + return m_gpwr; + case 0x28/4: + { + const uint16_t combined = (m_gpwr & m_gpcr) | (m_gpio_in_latch & ~m_gpcr); + LOGMASKED(LOG_READS, "%s: read: GPRR: %04x\n", machine().describe_context(), combined); + return combined; + } + default: + LOGMASKED(LOG_READS | LOG_UNKNOWN, "%s: read: Unknown Register: %04x\n", machine().describe_context(), offset << 2); + return 0; + } +} + +void scoop_device::write(offs_t offset, uint32_t data) +{ + switch (offset) + { + case 0x00/4: + LOGMASKED(LOG_WRITES, "%s: write: MCR: %04x\n", machine().describe_context(), (uint16_t)data); + break; + case 0x04/4: + LOGMASKED(LOG_WRITES, "%s: write: CDR: %04x\n", machine().describe_context(), (uint16_t)data); + break; + case 0x08/4: + LOGMASKED(LOG_WRITES, "%s: write: CSR: %04x\n", machine().describe_context(), (uint16_t)data); + break; + case 0x0c/4: + LOGMASKED(LOG_WRITES, "%s: write: CPR: %04x\n", machine().describe_context(), (uint16_t)data); + break; + case 0x10/4: + LOGMASKED(LOG_WRITES, "%s: write: CCR: %04x\n", machine().describe_context(), (uint16_t)data); + break; + case 0x14/4: + LOGMASKED(LOG_WRITES, "%s: write: IRR: %04x\n", machine().describe_context(), (uint16_t)data); + break; + case 0x18/4: + LOGMASKED(LOG_WRITES, "%s: write: IMR: %04x\n", machine().describe_context(), (uint16_t)data); + break; + case 0x1c/4: + LOGMASKED(LOG_WRITES, "%s: write: ISR: %04x\n", machine().describe_context(), (uint16_t)data); + break; + case 0x20/4: + { + LOGMASKED(LOG_WRITES, "%s: write: GPCR: %04x\n", machine().describe_context(), (uint16_t)data); + const uint16_t old = m_gpcr; + m_gpcr = data; + if (old != m_gpcr) + update_gpio_direction(old); + break; + } + case 0x24/4: + { + LOGMASKED(LOG_WRITES, "%s: write: GPWR: %04x\n", machine().describe_context(), (uint16_t)data); + const uint16_t old = m_gpwr; + m_gpwr = data; + if (old != m_gpwr) + update_gpio_outputs(old, old ^ m_gpwr); + break; + } + case 0x28/4: + LOGMASKED(LOG_WRITES, "%s: write: GPRR (ignored): %04x\n", machine().describe_context(), (uint16_t)data); + break; + default: + LOGMASKED(LOG_WRITES | LOG_UNKNOWN, "%s: write: Unknown Register: %04x = %04x\n", machine().describe_context(), offset << 2, (uint16_t)data); + break; + } +} diff --git a/src/devices/machine/scoop.h b/src/devices/machine/scoop.h new file mode 100644 index 00000000000..48aae34361d --- /dev/null +++ b/src/devices/machine/scoop.h @@ -0,0 +1,42 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + Sharp Scoop peripheral chip emulation skeleton + +***************************************************************************/ + +#ifndef MAME_MACHINE_SCOOP +#define MAME_MACHINE_SCOOP + +#pragma once + +class scoop_device : public device_t +{ +public: + scoop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + template auto gpio_out() { return m_gpio_out[Line].bind(); } + template void gpio_in(int state) { gpio_in((uint16_t)Line, state); } + + uint32_t read(offs_t offset); + void write(offs_t offset, uint32_t data); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + void gpio_in(const uint16_t line, const int state); + void update_gpio_direction(const uint16_t old_dir); + void update_gpio_outputs(const uint16_t old_latch, const uint16_t changed); + + uint16_t m_gpwr; + uint16_t m_gpio_in_latch; + uint16_t m_gpcr; + + devcb_write_line::array<13> m_gpio_out; +}; + +DECLARE_DEVICE_TYPE(SCOOP, scoop_device) + +#endif // MAME_MACHINE_SCOOP diff --git a/src/devices/machine/ucb1200.cpp b/src/devices/machine/ucb1200.cpp new file mode 100644 index 00000000000..ae88612f23b --- /dev/null +++ b/src/devices/machine/ucb1200.cpp @@ -0,0 +1,376 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + Philips UCB1200 Advanced modem/audio analog front-end skeleton + +***************************************************************************/ + +#include "emu.h" +#include "ucb1200.h" + +#define LOG_UNKNOWN (1 << 1) +#define LOG_READS (1 << 2) +#define LOG_WRITES (1 << 3) +#define LOG_ALL (LOG_UNKNOWN | LOG_READS | LOG_WRITES) + +#define VERBOSE (LOG_ALL) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(UCB1200, ucb1200_device, "ucb1200", "Philips UCB1200 modem/audio codec") + +ucb1200_device::ucb1200_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, UCB1200, tag, owner, clock) + , m_gpio_out(*this) + , m_audio_out(*this) + , m_telecom_out(*this) + , m_irq_out(*this) + , m_adc_in(*this) +{ +} + +void ucb1200_device::device_start() +{ + m_gpio_out.resolve_all_safe(); + m_audio_out.resolve_safe(); + m_telecom_out.resolve_safe(); + m_irq_out.resolve_safe(); + m_adc_in.resolve_all_safe(0xffff); + + save_item(NAME(m_gpio_out_latch)); + save_item(NAME(m_gpio_in_latch)); + save_item(NAME(m_gpio_dir)); + save_item(NAME(m_rising_int_en)); + save_item(NAME(m_falling_int_en)); + save_item(NAME(m_int_status)); + save_item(NAME(m_telecom_ctrl_a)); + save_item(NAME(m_telecom_ctrl_b)); + save_item(NAME(m_audio_ctrl_a)); + save_item(NAME(m_audio_ctrl_b)); + save_item(NAME(m_touch_ctrl)); + save_item(NAME(m_adc_ctrl)); + save_item(NAME(m_adc_data)); + save_item(NAME(m_id)); + save_item(NAME(m_mode)); +} + +void ucb1200_device::device_reset() +{ + m_gpio_out_latch = 0; + m_gpio_in_latch = 0; + m_gpio_dir = 0; + m_rising_int_en = 0; + m_falling_int_en = 0; + m_int_status = 0; + m_telecom_ctrl_a = 0x10 << TEL_DIV_BIT; + m_telecom_ctrl_b = 0; + m_audio_ctrl_a = 0x06 << AUD_DIV_BIT; + m_audio_ctrl_b = 0; + m_touch_ctrl = 0; + m_adc_ctrl = 0; + m_adc_data = 0; + m_id = 0x1004; + m_mode = 0; +} + +void ucb1200_device::gpio_in(const uint16_t line, const int state) +{ + const uint16_t mask = (1 << line); + const uint16_t old_latch = m_gpio_in_latch; + m_gpio_in_latch &= ~mask; + m_gpio_in_latch |= (state << line); + + const bool old_irq = (m_int_status != 0); + if (old_latch != m_gpio_in_latch && !BIT(m_gpio_dir, line)) + { + if (state && BIT(m_rising_int_en, line)) + m_int_status |= mask; + else if (!state && BIT(m_falling_int_en, line)) + m_int_status |= mask; + } + + if (!old_irq && m_int_status != 0) + m_irq_out(1); +} + +void ucb1200_device::update_gpio_direction(const uint16_t old_dir) +{ + const uint16_t new_outputs = ~old_dir & m_gpio_dir; + if (new_outputs) + { + for (uint32_t line = 0; line < 10; line++) + { + if (BIT(new_outputs, line)) + { + m_gpio_out[line](BIT(m_gpio_out_latch, line)); + } + } + } + + // TODO: Do we need to check rising/falling edges based on the transition from output to input? +} + +void ucb1200_device::update_gpio_outputs(const uint16_t old_latch, const uint16_t changed) +{ + uint16_t remaining_changed = changed; + + for (uint32_t line = 0; line < 10 && remaining_changed != 0; line++) + { + if (BIT(remaining_changed, line)) + { + m_gpio_out[line](BIT(m_gpio_out_latch, line)); + remaining_changed &= ~(1 << line); + } + } +} + +void ucb1200_device::audio_sample_in(const uint16_t sample) +{ + // TODO: Handle incoming audio samples +} + +void ucb1200_device::telecom_sample_in(const uint16_t sample) +{ + // TODO: Handle incoming telecom samples +} + +void ucb1200_device::adc_begin_conversion() +{ + const uint16_t adc_input = (m_adc_ctrl & ADC_INPUT_MASK) >> ADC_INPUT_BIT; + switch (adc_input) + { + case ADC_INPUT_TSPX: + case ADC_INPUT_TSMX: + case ADC_INPUT_TSPY: + case ADC_INPUT_TSMY: + default: + m_adc_data = 0; + break; + case ADC_INPUT_AD0: + case ADC_INPUT_AD1: + case ADC_INPUT_AD2: + case ADC_INPUT_AD3: + m_adc_data = m_adc_in[adc_input - ADC_INPUT_AD0](); + m_adc_data <<= ADC_DATA_BIT; + m_adc_data &= ADC_DATA_MASK; + break; + } + + m_adc_data |= (1 << ADC_DAT_VAL_BIT); +} + +uint16_t ucb1200_device::read(offs_t offset) +{ + switch (offset) + { + case 0: + { + const uint16_t data = (m_gpio_out_latch & m_gpio_dir) | (m_gpio_in_latch & ~m_gpio_dir); + LOGMASKED(LOG_READS, "%s: read: GPIO Data Register: %04x\n", machine().describe_context(), data); + return data; + } + case 1: + LOGMASKED(LOG_READS, "%s: read: GPIO Direction Register: %04x\n", machine().describe_context(), m_gpio_dir); + return m_gpio_dir; + case 2: + LOGMASKED(LOG_READS, "%s: read: GPIO Rising-Edge Interrupt Enable Register: %04x\n", machine().describe_context(), m_rising_int_en); + return m_rising_int_en; + case 3: + LOGMASKED(LOG_READS, "%s: read: GPIO Falling-Edge Interrupt Enable Register: %04x\n", machine().describe_context(), m_falling_int_en); + return m_falling_int_en; + case 4: + LOGMASKED(LOG_READS, "%s: read: Interrupt Clear/Status Register: %04x\n", machine().describe_context(), m_int_status); + return m_int_status; + case 5: + LOGMASKED(LOG_READS, "%s: read: Telecom Control Register A: %04x\n", machine().describe_context(), m_telecom_ctrl_a); + return m_telecom_ctrl_a; + case 6: + LOGMASKED(LOG_READS, "%s: read: Telecom Control Register B: %04x\n", machine().describe_context(), m_telecom_ctrl_b); + return m_telecom_ctrl_b; + case 7: + LOGMASKED(LOG_READS, "%s: read: Audio Control Register A: %04x\n", machine().describe_context(), m_audio_ctrl_a); + return m_audio_ctrl_a; + case 8: + LOGMASKED(LOG_READS, "%s: read: Audio Control Register B: %04x\n", machine().describe_context(), m_audio_ctrl_b); + return m_audio_ctrl_b; + case 9: + LOGMASKED(LOG_READS, "%s: read: Touchscreen Control Register: %04x\n", machine().describe_context(), m_touch_ctrl); + return m_touch_ctrl; + case 10: + LOGMASKED(LOG_READS, "%s: read: ADC Control Register: %04x\n", machine().describe_context(), m_adc_ctrl); + return m_adc_ctrl; + case 11: + LOGMASKED(LOG_READS, "%s: read: ADC Data Register: %04x\n", machine().describe_context(), m_adc_data); + return m_adc_data; + case 12: + LOGMASKED(LOG_READS, "%s: read: ID Register: %04x\n", machine().describe_context(), m_id); + return m_id; + case 13: + LOGMASKED(LOG_READS, "%s: read: Mode Register: %04x\n", machine().describe_context(), m_mode); + return m_mode; + case 14: + LOGMASKED(LOG_READS, "%s: read: Reserved Register: %04x\n", machine().describe_context(), 0); + return 0; + case 15: + LOGMASKED(LOG_READS, "%s: read: NULL Register: %04x\n", machine().describe_context(), 0xffff); + return 0xffff; + default: + LOGMASKED(LOG_READS | LOG_UNKNOWN, "%s: read: Unknown Register: %d\n", machine().describe_context(), offset); + return 0; + } +} + +void ucb1200_device::write(offs_t offset, uint16_t data) +{ + switch (offset) + { + case 0: + { + LOGMASKED(LOG_WRITES, "%s: write: GPIO Data Register: %04x\n", machine().describe_context(), data); + const uint16_t old = m_gpio_out_latch; + m_gpio_out_latch = data; + const uint16_t changed = (old ^ m_gpio_out_latch) & m_gpio_dir; + if (changed) + update_gpio_outputs(old, changed); + break; + } + case 1: + { + LOGMASKED(LOG_WRITES, "%s: write: GPIO Direction Register: %04x\n", machine().describe_context(), data); + const uint16_t old = m_gpio_dir; + m_gpio_dir = data; + if (old != m_gpio_dir) + update_gpio_direction(old); + break; + } + case 2: + LOGMASKED(LOG_WRITES, "%s: write: GPIO Rising-Edge Interrupt Enable Register: %04x\n", machine().describe_context(), data); + m_rising_int_en = data; + break; + case 3: + LOGMASKED(LOG_WRITES, "%s: write: GPIO Falling-Edge Interrupt Enable Register: %04x\n", machine().describe_context(), data); + m_falling_int_en = data; + break; + case 4: + { + LOGMASKED(LOG_WRITES, "%s: write: Interrupt Clear/Status Register: %04x\n", machine().describe_context(), data); + const uint16_t old = m_int_status; + m_int_status &= ~data; + if (old != 0 && m_int_status == 0) + m_irq_out(0); + break; + } + case 5: + LOGMASKED(LOG_WRITES, "%s: write: Telecom Control Register A: %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_WRITES, "%s: Telecom Codec Sample Rate Divisor: %02x\n", machine().describe_context(), (data & TEL_DIV_MASK) >> TEL_DIV_BIT); + LOGMASKED(LOG_WRITES, "%s: Telecom Codec Loopback: %d\n", machine().describe_context(), BIT(data, TEL_LOOP_BIT)); + m_telecom_ctrl_a = data; + break; + case 6: + { + LOGMASKED(LOG_WRITES, "%s: write: Telecom Control Register B: %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_WRITES, "%s: Telecom Voice Band Filter: %d\n", machine().describe_context(), BIT(data, TEL_VOICE_ENA_BIT)); + LOGMASKED(LOG_WRITES, "%s: Telecom Clip Detect Clear: %d\n", machine().describe_context(), BIT(data, TEL_CLIP_BIT)); + LOGMASKED(LOG_WRITES, "%s: Telecom Input Attenuation: %d\n", machine().describe_context(), BIT(data, TEL_ATT_BIT)); + LOGMASKED(LOG_WRITES, "%s: Telecom Sidetone Suppression: %d\n", machine().describe_context(), BIT(data, TEL_SIDE_ENA_BIT)); + LOGMASKED(LOG_WRITES, "%s: Telecom Output Mute: %d\n", machine().describe_context(), BIT(data, TEL_MUTE_BIT)); + LOGMASKED(LOG_WRITES, "%s: Telecom Input Enable: %d\n", machine().describe_context(), BIT(data, TEL_IN_ENA_BIT)); + LOGMASKED(LOG_WRITES, "%s: Telecom Output Enable: %d\n", machine().describe_context(), BIT(data, TEL_OUT_ENA_BIT)); + + const uint16_t old_clip = m_telecom_ctrl_b & (1 << TEL_CLIP_BIT); + const uint16_t new_clip = data & (1 << TEL_CLIP_BIT); + + m_telecom_ctrl_b = data; + + if (new_clip) + m_telecom_ctrl_b &= ~(1 << TEL_CLIP_BIT); + else if (old_clip) + m_telecom_ctrl_b |= (1 << TEL_CLIP_BIT); + break; + } + case 7: + LOGMASKED(LOG_WRITES, "%s: write: Audio Control Register A: %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_WRITES, "%s: Audio Codec Sample Rate Divisor: %02x\n", machine().describe_context(), (data & AUD_DIV_MASK) >> AUD_DIV_BIT); + LOGMASKED(LOG_WRITES, "%s: Audio Input Gain: %02x\n", machine().describe_context(), (data & AUD_GAIN_MASK) >> AUD_GAIN_BIT); + m_audio_ctrl_a = data; + break; + case 8: + { + LOGMASKED(LOG_WRITES, "%s: write: Audio Control Register B: %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_WRITES, "%s: Audio Output Attenuation: %02x\n", machine().describe_context(), (data & AUD_ATT_MASK) >> AUD_ATT_BIT); + LOGMASKED(LOG_WRITES, "%s: Audio Clip Detect Clear: %d\n", machine().describe_context(), BIT(data, AUD_CLIP_BIT)); + LOGMASKED(LOG_WRITES, "%s: Audio Codec Loopback: %d\n", machine().describe_context(), BIT(data, AUD_LOOP_BIT)); + LOGMASKED(LOG_WRITES, "%s: Audio Output Mute: %d\n", machine().describe_context(), BIT(data, AUD_MUTE_BIT)); + LOGMASKED(LOG_WRITES, "%s: Audio Input Enable: %d\n", machine().describe_context(), BIT(data, AUD_IN_ENA_BIT)); + LOGMASKED(LOG_WRITES, "%s: Audio Output Enable: %d\n", machine().describe_context(), BIT(data, AUD_OUT_ENA_BIT)); + + const uint16_t old_clip = m_audio_ctrl_b & (1 << AUD_CLIP_BIT); + const uint16_t new_clip = data & (1 << AUD_CLIP_BIT); + + m_audio_ctrl_b = data; + + if (new_clip) + m_audio_ctrl_b &= ~(1 << AUD_CLIP_BIT); + else if (old_clip) + m_audio_ctrl_b |= (1 << AUD_CLIP_BIT); + break; + } + case 9: + { + static const char *const s_tsc_modes[4] = { "Interrupt", "Pressure", "Position [2]", "Position [3]" }; + LOGMASKED(LOG_WRITES, "%s: write: Touchscreen Control Register: %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_WRITES, "%s: TSMX Pin Powered: %d\n", machine().describe_context(), BIT(data, TSMX_POW_BIT)); + LOGMASKED(LOG_WRITES, "%s: TSPX Pin Powered: %d\n", machine().describe_context(), BIT(data, TSPX_POW_BIT)); + LOGMASKED(LOG_WRITES, "%s: TSMY Pin Powered: %d\n", machine().describe_context(), BIT(data, TSMY_POW_BIT)); + LOGMASKED(LOG_WRITES, "%s: TSPY Pin Powered: %d\n", machine().describe_context(), BIT(data, TSPY_POW_BIT)); + LOGMASKED(LOG_WRITES, "%s: TSMX Pin Grounded: %d\n", machine().describe_context(), BIT(data, TSMX_GND_BIT)); + LOGMASKED(LOG_WRITES, "%s: TSPX Pin Grounded: %d\n", machine().describe_context(), BIT(data, TSPX_GND_BIT)); + LOGMASKED(LOG_WRITES, "%s: TSMY Pin Grounded: %d\n", machine().describe_context(), BIT(data, TSMY_GND_BIT)); + LOGMASKED(LOG_WRITES, "%s: TSPY Pin Grounded: %d\n", machine().describe_context(), BIT(data, TSPY_GND_BIT)); + LOGMASKED(LOG_WRITES, "%s: Touch Screen Mode: %s\n", machine().describe_context(), s_tsc_modes[(data & TSC_MODE_MASK) >> TSC_MODE_BIT]); + LOGMASKED(LOG_WRITES, "%s: Touch Screen Bias Circuit Active: %d\n", machine().describe_context(), BIT(data, TSC_BIAS_ENA_BIT)); + m_touch_ctrl &= ~TOUCH_WRITE_MASK; + m_touch_ctrl |= data & TOUCH_WRITE_MASK; + break; + } + case 10: + { + static const char *const s_adc_inputs[8] = { "TSPX", "TSMX", "TSPY", "TSMY", "AD0", "AD1", "AD2", "AD3" }; + LOGMASKED(LOG_WRITES, "%s: write: ADC Control Register: %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_WRITES, "%s: ADC Sync Mode: %d\n", machine().describe_context(), BIT(data, ADC_SYNC_ENA_BIT)); + LOGMASKED(LOG_WRITES, "%s: Connect Internal Vref to VREFBYP Pin: %d\n", machine().describe_context(), BIT(data, VREFBYP_CON_BIT)); + LOGMASKED(LOG_WRITES, "%s: ADC Input Select: %s\n", machine().describe_context(), s_adc_inputs[(data & ADC_INPUT_MASK) >> ADC_INPUT_BIT]); + LOGMASKED(LOG_WRITES, "%s: Apply External Voltage to VREFBYP Pin: %d\n", machine().describe_context(), BIT(data, EXT_REF_ENA_BIT)); + LOGMASKED(LOG_WRITES, "%s: ADC Conversion Start: %d\n", machine().describe_context(), BIT(data, ADC_START_BIT)); + LOGMASKED(LOG_WRITES, "%s: ADC Enabled: %d\n", machine().describe_context(), BIT(data, ADC_ENA_BIT)); + const uint16_t old = m_adc_ctrl; + m_adc_ctrl = data; + if (!BIT(old, ADC_START_BIT) && BIT(data, ADC_START_BIT) && BIT(data, ADC_ENA_BIT)) + adc_begin_conversion(); + break; + } + case 11: + LOGMASKED(LOG_WRITES, "%s: write: ADC Data Register (ignored): %04x\n", machine().describe_context(), data); + break; + case 12: + LOGMASKED(LOG_WRITES, "%s: write: ID Register (ignored): %04x\n", machine().describe_context(), data); + break; + case 13: + LOGMASKED(LOG_WRITES, "%s: write: Mode Register: %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_WRITES, "%s: Analog Audio Test Mode: %d\n", machine().describe_context(), BIT(data, AUD_TEST_BIT)); + LOGMASKED(LOG_WRITES, "%s: Analog Telecom Test Mode: %d\n", machine().describe_context(), BIT(data, TEL_TEST_BIT)); + LOGMASKED(LOG_WRITES, "%s: Production Test Mode: %02x\n", machine().describe_context(), (data & PROD_TEST_MODE_MASK) >> PROD_TEST_MODE_BIT); + LOGMASKED(LOG_WRITES, "%s: Dynamic Data Valid Flag Mode: %d\n", machine().describe_context(), BIT(data, DYN_VFLAG_ENA_BIT)); + LOGMASKED(LOG_WRITES, "%s: Audio Offset-Cancelling: %d\n", machine().describe_context(), BIT(data, AUD_OFF_CAN_BIT)); + break; + case 14: + LOGMASKED(LOG_WRITES, "%s: write: Reserved Register (ignored): %04x\n", machine().describe_context(), data); + break; + case 15: + LOGMASKED(LOG_WRITES, "%s: write: NULL Register (ignored): %04x\n", machine().describe_context(), data); + break; + default: + LOGMASKED(LOG_WRITES | LOG_UNKNOWN, "%s: write: Unknown Register: %d = %04x\n", machine().describe_context(), offset, data); + break; + } +} diff --git a/src/devices/machine/ucb1200.h b/src/devices/machine/ucb1200.h new file mode 100644 index 00000000000..a17104e4e96 --- /dev/null +++ b/src/devices/machine/ucb1200.h @@ -0,0 +1,147 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + Philips UCB1200 Advanced modem/audio analog front-end skeleton + +***************************************************************************/ + +#ifndef MAME_MACHINE_UCB1200 +#define MAME_MACHINE_UCB1200 + +#pragma once + +class ucb1200_device : public device_t +{ +public: + ucb1200_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + template auto gpio_out() { return m_gpio_out[Line].bind(); } + template void gpio_in(int state) { gpio_in((uint16_t)Line, state); } + template auto adc_in() { return m_adc_in[N].bind(); } + auto audio_sample_out() { return m_audio_out.bind(); } + auto telecom_sample_out() { return m_telecom_out.bind(); } + auto irq_out() { return m_irq_out.bind(); } + + void audio_sample_in(const uint16_t sample); + void telecom_sample_in(const uint16_t sample); + + uint16_t read(offs_t offset); + void write(offs_t offset, uint16_t data); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + void gpio_in(const uint16_t line, const int state); + void update_gpio_direction(const uint16_t old_dir); + void update_gpio_outputs(const uint16_t old_latch, const uint16_t changed); + + void adc_begin_conversion(); + + // register contents + enum : uint16_t + { + SIB_ZERO_BIT = 15, + + IO_INT0_BIT = 0, + ADC_INT_BIT = 11, + TSPX_INT_BIT = 12, + TSMX_INT_BIT = 13, + TCLIP_INT_BIT = 14, + ACLIP_INT_BIT = 15, + + TEL_DIV_BIT = 0, + TEL_DIV_MASK = 0x007f, + TEL_LOOP_BIT = 7, + + TEL_VOICE_ENA_BIT = 3, + TEL_CLIP_BIT = 4, + TEL_ATT_BIT = 6, + TEL_SIDE_ENA_BIT = 11, + TEL_MUTE_BIT = 13, + TEL_IN_ENA_BIT = 14, + TEL_OUT_ENA_BIT = 15, + + AUD_DIV_BIT = 0, + AUD_DIV_MASK = 0x007f, + AUD_GAIN_BIT = 7, + AUD_GAIN_MASK = 0x0f80, + + AUD_ATT_BIT = 0, + AUD_ATT_MASK = 0x001f, + AUD_CLIP_BIT = 6, + AUD_LOOP_BIT = 8, + AUD_MUTE_BIT = 13, + AUD_IN_ENA_BIT = 14, + AUD_OUT_ENA_BIT = 15, + + TSMX_POW_BIT = 0, + TSPX_POW_BIT = 1, + TSMY_POW_BIT = 2, + TSPY_POW_BIT = 3, + TSMX_GND_BIT = 4, + TSPX_GND_BIT = 5, + TSMY_GND_BIT = 6, + TSPY_GND_BIT = 7, + TSC_MODE_BIT = 8, + TSC_MODE_MASK = 0x0300, + TSC_BIAS_ENA_BIT = 11, + TSPX_LOW_BIT = 12, + TSMX_LOW_BIT = 13, + TOUCH_WRITE_MASK = 0x0fff, + + ADC_SYNC_ENA_BIT = 0, + VREFBYP_CON_BIT = 1, + ADC_INPUT_BIT = 2, + ADC_INPUT_MASK = 0x001c, + ADC_INPUT_TSPX = 0, + ADC_INPUT_TSMX = 1, + ADC_INPUT_TSPY = 2, + ADC_INPUT_TSMY = 3, + ADC_INPUT_AD0 = 4, + ADC_INPUT_AD1 = 5, + ADC_INPUT_AD2 = 6, + ADC_INPUT_AD3 = 7, + EXT_REF_ENA_BIT = 5, + ADC_START_BIT = 7, + ADC_ENA_BIT = 15, + + ADC_DATA_BIT = 5, + ADC_DATA_MASK = 0x7fe0, + ADC_DAT_VAL_BIT = 15, + + AUD_TEST_BIT = 0, + TEL_TEST_BIT = 1, + PROD_TEST_MODE_BIT = 2, + PROD_TEST_MODE_MASK = 0x003c, + DYN_VFLAG_ENA_BIT = 12, + AUD_OFF_CAN_BIT = 13 + }; + + uint16_t m_gpio_out_latch; + uint16_t m_gpio_in_latch; + uint16_t m_gpio_dir; + uint16_t m_rising_int_en; + uint16_t m_falling_int_en; + uint16_t m_int_status; + uint16_t m_telecom_ctrl_a; + uint16_t m_telecom_ctrl_b; + uint16_t m_audio_ctrl_a; + uint16_t m_audio_ctrl_b; + uint16_t m_touch_ctrl; + uint16_t m_adc_ctrl; + uint16_t m_adc_data; + uint16_t m_id; + uint16_t m_mode; + + devcb_write_line::array<10> m_gpio_out; + devcb_write16 m_audio_out; + devcb_write16 m_telecom_out; + devcb_write_line m_irq_out; + devcb_read16::array<4> m_adc_in; +}; + +DECLARE_DEVICE_TYPE(UCB1200, ucb1200_device) + +#endif // MAME_MACHINE_UCB1200 diff --git a/src/mame/drivers/zaurus.cpp b/src/mame/drivers/zaurus.cpp index 26ac249277d..0f1661f8eb1 100644 --- a/src/mame/drivers/zaurus.cpp +++ b/src/mame/drivers/zaurus.cpp @@ -5,7 +5,6 @@ Sharp Zaurus PDA skeleton driver (SL, ARM/Linux based, 4th generation) TODO: - - ARM TLB look-up errors? - Dumps are questionable ========================================================================================================================================= @@ -1406,7 +1405,9 @@ Note: #include "machine/locomo.h" #include "machine/pxa255.h" #include "machine/sa1110.h" +#include "machine/scoop.h" #include "machine/timer.h" +#include "machine/ucb1200.h" #include "emupal.h" #include "screen.h" #include "speaker.h" @@ -1445,6 +1446,8 @@ public: : zaurus_state(mconfig, type, tag) , m_sa_periphs(*this, "sa_periphs") , m_locomo(*this, "locomo") + , m_scoop(*this, "scoop") + , m_codec(*this, "codec") { } void zaurus_sa1110(machine_config &config); @@ -1456,6 +1459,8 @@ private: required_device m_sa_periphs; required_device m_locomo; + required_device m_scoop; + required_device m_codec; }; class zaurus_pxa_state : public zaurus_state @@ -1485,7 +1490,9 @@ void zaurus_sa_state::main_map(address_map &map) { map(0x00000000, 0x00ffffff).rom().region("firmware", 0); map(0x40000000, 0x40001fff).rw(m_locomo, FUNC(locomo_device::read), FUNC(locomo_device::write)); + map(0x40800000, 0x4080002b).rw(m_scoop, FUNC(scoop_device::read), FUNC(scoop_device::write)); map(0x80050000, 0x80050023).rw(m_sa_periphs, FUNC(sa1110_periphs_device::uart3_r), FUNC(sa1110_periphs_device::uart3_w)); + map(0x80060000, 0x8006001b).rw(m_sa_periphs, FUNC(sa1110_periphs_device::mcp_r), FUNC(sa1110_periphs_device::mcp_w)); map(0x90000000, 0x9000001f).rw(m_sa_periphs, FUNC(sa1110_periphs_device::ostimer_r), FUNC(sa1110_periphs_device::ostimer_w)); map(0x90010000, 0x9001000f).rw(m_sa_periphs, FUNC(sa1110_periphs_device::rtc_r), FUNC(sa1110_periphs_device::rtc_w)); map(0x90020000, 0x9002001f).rw(m_sa_periphs, FUNC(sa1110_periphs_device::power_r), FUNC(sa1110_periphs_device::power_w)); @@ -1512,7 +1519,10 @@ void zaurus_pxa_state::main_map(address_map &map) void zaurus_sa_state::device_reset_after_children() { - m_sa_periphs->gpio_in(1, 1); + m_sa_periphs->gpio_in<1>(1); + m_sa_periphs->gpio_in<24>(1); + //m_scoop->gpio_in<2>(1); // DIAG_BOOT1 + //m_scoop->gpio_in<3>(1); // DIAG_BOOT2 } INPUT_CHANGED_MEMBER( zaurus_pxa_state::system_start ) @@ -1542,8 +1552,15 @@ void zaurus_sa_state::zaurus_sa1110(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &zaurus_sa_state::main_map); SA1110_PERIPHERALS(config, m_sa_periphs, SA1110_CLOCK, m_maincpu); + m_sa_periphs->set_codec_tag(m_codec); LOCOMO(config, m_locomo); + SCOOP(config, m_scoop); + + UCB1200(config, m_codec); + m_codec->adc_in<0>().set_constant(460); // Battery temperature monitor. HACK: Value is arbitrary, taken from Linux + m_codec->adc_in<1>().set_constant(255); // Battery voltage monitor. HACK: Value is arbitrary, taken from Linux + m_codec->irq_out().set(m_sa_periphs, FUNC(sa1110_periphs_device::gpio_in<23>)); } void zaurus_pxa_state::zaurus_pxa250(machine_config &config)