-scoop: Added skeleton device for Sharp "Scoop" peripheral IC from the Zaurus PDA line. [Ryan Holtz]

-ucb1200: Added skeleton device for Philips UCB1200 audio/telecom codec. [Ryan Holtz]

-sa1110: Added rudimentary framework for the MCP codec interface module. [Ryan Holtz]
This commit is contained in:
Ryan Holtz 2020-12-06 14:51:57 +01:00
parent 8287057888
commit be92cc6c65
12 changed files with 1312 additions and 12 deletions

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
// copyright-holders:Ryan Holtz
/***************************************************************************
Sharp LoCoMo peripheral chip emulation
Sharp LoCoMo peripheral chip emulation skeleton
***************************************************************************/

View File

@ -2,7 +2,7 @@
// copyright-holders:Ryan Holtz
/***************************************************************************
Sharp LoCoMo peripheral chip emulation
Sharp LoCoMo peripheral chip emulation skeleton
***************************************************************************/

View File

@ -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<MCP_AUDIO_UNDERRUN>(0);
}
else
{
m_mcp_regs.mcsr |= (1 << MCSR_ATU_BIT);
m_mcp_irqs->in_w<MCP_AUDIO_UNDERRUN>(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<MCP_TELECOM_UNDERRUN>(0);
}
else
{
m_mcp_regs.mcsr |= (1 << MCSR_TTU_BIT);
m_mcp_irqs->in_w<MCP_TELECOM_UNDERRUN>(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<MCP_AUDIO_RX>((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<MCP_TELECOM_RX>((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<MCP_AUDIO_TX>(0);
}
else
{
m_mcp_regs.mcsr |= (1 << MCSR_ATS_BIT);
if (BIT(m_mcp_regs.mccr0, MCCR0_ATE_BIT))
m_mcp_irqs->in_w<MCP_AUDIO_TX>(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<MCP_TELECOM_TX>(0);
}
else
{
m_mcp_regs.mcsr |= (1 << MCSR_TTS_BIT);
if (BIT(m_mcp_regs.mccr0, MCCR0_TTE_BIT))
m_mcp_irqs->in_w<MCP_TELECOM_TX>(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<MCP_AUDIO_TX>(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<MCP_AUDIO_RX>(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<MCP_TELECOM_TX>(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<MCP_TELECOM_RX>(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<MCP_AUDIO_UNDERRUN>(0);
if (BIT(old, MCSR_ARO_BIT) && !BIT(m_mcp_regs.mcsr, MCSR_ARO_BIT))
m_mcp_irqs->in_w<MCP_AUDIO_OVERRUN>(0);
if (BIT(old, MCSR_TTU_BIT) && !BIT(m_mcp_regs.mcsr, MCSR_TTU_BIT))
m_mcp_irqs->in_w<MCP_TELECOM_UNDERRUN>(0);
if (BIT(old, MCSR_TRO_BIT) && !BIT(m_mcp_regs.mcsr, MCSR_TRO_BIT))
m_mcp_irqs->in_w<MCP_TELECOM_OVERRUN>(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));
}

View File

@ -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 <typename T> void set_codec_tag(T &&tag) { m_codec.set_tag(std::forward<T>(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 <unsigned Line> void gpio_in(int state) { gpio_in(Line, state); }
template <unsigned Line> 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<cpu_device> m_maincpu;
required_device<input_merger_device> m_uart3_irqs;
required_device<input_merger_device> m_mcp_irqs;
optional_device<ucb1200_device> m_codec;
devcb_write_line::array<28> m_gpio_out;
};

View File

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

View File

@ -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 <unsigned Line> auto gpio_out() { return m_gpio_out[Line].bind(); }
template <unsigned Line> 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

View File

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

View File

@ -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 <unsigned Line> auto gpio_out() { return m_gpio_out[Line].bind(); }
template <unsigned Line> void gpio_in(int state) { gpio_in((uint16_t)Line, state); }
template <unsigned N> 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

View File

@ -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<sa1110_periphs_device> m_sa_periphs;
required_device<locomo_device> m_locomo;
required_device<scoop_device> m_scoop;
required_device<ucb1200_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)