mirror of
https://github.com/holub/mame
synced 2025-04-16 13:34:55 +03:00
-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:
parent
8287057888
commit
be92cc6c65
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -2,7 +2,7 @@
|
||||
// copyright-holders:Ryan Holtz
|
||||
/***************************************************************************
|
||||
|
||||
Sharp LoCoMo peripheral chip emulation
|
||||
Sharp LoCoMo peripheral chip emulation skeleton
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// copyright-holders:Ryan Holtz
|
||||
/***************************************************************************
|
||||
|
||||
Sharp LoCoMo peripheral chip emulation
|
||||
Sharp LoCoMo peripheral chip emulation skeleton
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
178
src/devices/machine/scoop.cpp
Normal file
178
src/devices/machine/scoop.cpp
Normal 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;
|
||||
}
|
||||
}
|
42
src/devices/machine/scoop.h
Normal file
42
src/devices/machine/scoop.h
Normal 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
|
376
src/devices/machine/ucb1200.cpp
Normal file
376
src/devices/machine/ucb1200.cpp
Normal 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;
|
||||
}
|
||||
}
|
147
src/devices/machine/ucb1200.h
Normal file
147
src/devices/machine/ucb1200.h
Normal 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
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user