summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Ryan Holtz <ryan.holtz@arrowheadgs.com>2020-12-24 18:58:45 +0100
committer Ryan Holtz <ryan.holtz@arrowheadgs.com>2020-12-24 18:59:14 +0100
commit7ebdb0bd9793158ea00de6962825e34fe93421ce (patch)
treef9c9975cd332b37515d5111cacb7ae77c2ea3588
parent3ec0a6596975ffb5e386d746b9179125cf518a25 (diff)
New machines marked as NOT_WORKING
------------------ Hewlett-Packard Jornada 720 [Ryan Holtz] * arm7: Fixed interaction between instruction prefetching with the MMU enabled. [Ryan Holtz] * sa111: Added skeleton device for Intel SA-1111 Microprocessor Companion Chip. [Ryan Holtz] * sed1356: Added skeleton device for Epson/Seiko SED1356 video controller. [Ryan Holtz] * sa1110: Various cleanups. Added rudimentary SSP module support. [Ryan Holtz]
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--scripts/src/video.lua11
-rw-r--r--scripts/target/mame/arcade.lua2
-rw-r--r--scripts/target/mame/mess.lua3
-rw-r--r--src/devices/cpu/arm7/arm7.cpp206
-rw-r--r--src/devices/cpu/arm7/arm7.h8
-rw-r--r--src/devices/cpu/arm7/arm7dasm.cpp3
-rw-r--r--src/devices/machine/sa1110.cpp286
-rw-r--r--src/devices/machine/sa1110.h63
-rw-r--r--src/devices/machine/sa1111.cpp1733
-rw-r--r--src/devices/machine/sa1111.h591
-rw-r--r--src/devices/video/sed1356.cpp1579
-rw-r--r--src/devices/video/sed1356.h547
-rw-r--r--src/mame/drivers/jornada.cpp301
-rw-r--r--src/mame/mame.lst3
-rw-r--r--src/mame/mess.flt1
16 files changed, 5209 insertions, 140 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index 6a31c46a513..c4c8ce57edf 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -2888,6 +2888,18 @@ end
---------------------------------------------------
--
+--@src/devices/machine/sa1111.h,MACHINES["SA1111"] = true
+---------------------------------------------------
+
+if (MACHINES["SA1111"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/sa1111.cpp",
+ MAME_DIR .. "src/devices/machine/sa1111.h",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/machine/saa1043.h,MACHINES["SAA1043"] = true
---------------------------------------------------
diff --git a/scripts/src/video.lua b/scripts/src/video.lua
index fd16d493c0d..ab977f66f82 100644
--- a/scripts/src/video.lua
+++ b/scripts/src/video.lua
@@ -888,6 +888,17 @@ end
--------------------------------------------------
--
+--@src/devices/video/sed1356.h,VIDEOS["SED1356"] = true
+--------------------------------------------------
+if (VIDEOS["SED1356"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/video/sed1356.cpp",
+ MAME_DIR .. "src/devices/video/sed1356.h",
+ }
+end
+
+--------------------------------------------------
+--
--@src/devices/video/sed1500.h,VIDEOS["SED1500"] = true
--------------------------------------------------
if (VIDEOS["SED1500"]~=null) then
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 18f01cec358..d8dcff07668 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -364,6 +364,7 @@ VIDEOS["SCN2674"] = true
VIDEOS["PWM_DISPLAY"] = true
--VIDEOS["SED1200"] = true
--VIDEOS["SED1330"] = true
+--VIDEOS["SED1356"] = true
--VIDEOS["SED1500"] = true
--VIDEOS["SED1520"] = true
VIDEOS["SNES_PPU"] = true
@@ -623,6 +624,7 @@ MACHINES["S3520CF"] = true
MACHINES["S3C24XX"] = true
--MACHINES["S3C44B0"] = true
--MACHINES["SA1110"] = true
+--MACHINES["SA1111"] = true
MACHINES["SATURN"] = true
MACHINES["SCC68070"] = true
MACHINES["SCN_PCI"] = true
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index b0692d43719..190609d9776 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -394,6 +394,7 @@ VIDEOS["PWM_DISPLAY"] = true
VIDEOS["SDA5708"] = true
VIDEOS["SED1200"] = true
VIDEOS["SED1330"] = true
+VIDEOS["SED1356"] = true
VIDEOS["SED1500"] = true
VIDEOS["SED1520"] = true
VIDEOS["SNES_PPU"] = true
@@ -655,6 +656,7 @@ MACHINES["S3520CF"] = true
MACHINES["S3C24XX"] = true
MACHINES["S3C44B0"] = true
MACHINES["SA1110"] = true
+MACHINES["SA1111"] = true
MACHINES["SAA1043"] = true
MACHINES["SATURN"] = true
MACHINES["SCC68070"] = true
@@ -2596,6 +2598,7 @@ files {
MAME_DIR .. "src/mame/drivers/hp2640.cpp",
MAME_DIR .. "src/mame/drivers/hp95lx.cpp",
MAME_DIR .. "src/mame/drivers/hp9825.cpp",
+ MAME_DIR .. "src/mame/drivers/jornada.cpp",
}
createMESSProjects(_target, _subtarget, "hec2hrp")
diff --git a/src/devices/cpu/arm7/arm7.cpp b/src/devices/cpu/arm7/arm7.cpp
index 608d84a8612..4bed8a39093 100644
--- a/src/devices/cpu/arm7/arm7.cpp
+++ b/src/devices/cpu/arm7/arm7.cpp
@@ -42,7 +42,7 @@ TODO:
#define LOG_COPRO_UNKNOWN (1 << 4)
#define LOG_COPRO_RESERVED (1 << 5)
-#define VERBOSE (0) //(LOG_MMU | LOG_COPRO_READS | LOG_COPRO_WRITES)
+#define VERBOSE (0) // (LOG_MMU | LOG_COPRO_READS | LOG_COPRO_WRITES | LOG_COPRO_UNKNOWN | LOG_COPRO_RESERVED)
#include "logmacro.h"
#define PRINT_HAPYFSH2 (0)
@@ -100,6 +100,7 @@ arm7_cpu_device::arm7_cpu_device(const machine_config &mconfig, device_type type
memset(m_insn_prefetch_buffer, 0, sizeof(uint32_t) * 3);
memset(m_insn_prefetch_address, 0, sizeof(uint32_t) * 3);
+ memset(m_insn_prefetch_valid, 0, sizeof(bool) * 3);
m_insn_prefetch_count = 0;
m_insn_prefetch_index = 0;
}
@@ -444,7 +445,7 @@ int arm7_cpu_device::detect_fault(int desc_lvl1, int ap, int flags)
}
-bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags, bool no_exception)
+bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags)
{
if (addr < 0x2000000)
{
@@ -474,41 +475,31 @@ bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags, bool no_except
{
addr = ( desc_lvl1 & COPRO_TLB_SECTION_PAGE_MASK ) | ( addr & ~COPRO_TLB_SECTION_PAGE_MASK );
}
- else
+ else if (flags & ARM7_TLB_ABORT_D)
{
- if (no_exception)
- return false;
-
- if (flags & ARM7_TLB_ABORT_D)
- {
- uint8_t domain = (desc_lvl1 >> 5) & 0xF;
- LOGMASKED(LOG_MMU, "ARM7: Section Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15]);
- m_faultStatus[0] = ((fault == FAULT_DOMAIN) ? (9 << 0) : (13 << 0)) | (domain << 4); // 9 = section domain fault, 13 = section permission fault
- m_faultAddress = addr;
- m_pendingAbtD = true;
- update_irq_state();
- LOGMASKED(LOG_MMU, "vaddr %08X desc_lvl1 %08X domain %d permission %d ap %d s %d r %d mode %d read %d write %d\n",
- addr, desc_lvl1, domain, (m_domainAccessControl >> ((desc_lvl1 >> 4) & 0x1e)) & 3, (desc_lvl1 >> 10) & 3, (m_control & COPRO_CTRL_SYSTEM) ? 1 : 0, (m_control & COPRO_CTRL_ROM) ? 1 : 0,
- m_r[eCPSR] & MODE_FLAG, flags & ARM7_TLB_READ ? 1 : 0, flags & ARM7_TLB_WRITE ? 1 : 0);
- }
- else if (flags & ARM7_TLB_ABORT_P)
- {
- LOGMASKED(LOG_MMU, "ARM7: Section Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15]);
- m_pendingAbtP = true;
- update_irq_state();
- }
+ uint8_t domain = (desc_lvl1 >> 5) & 0xF;
+ LOGMASKED(LOG_MMU, "ARM7: Section Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15]);
+ m_faultStatus[0] = ((fault == FAULT_DOMAIN) ? (9 << 0) : (13 << 0)) | (domain << 4); // 9 = section domain fault, 13 = section permission fault
+ m_faultAddress = addr;
+ m_pendingAbtD = true;
+ update_irq_state();
+ LOGMASKED(LOG_MMU, "vaddr %08X desc_lvl1 %08X domain %d permission %d ap %d s %d r %d mode %d read %d write %d\n",
+ addr, desc_lvl1, domain, (m_domainAccessControl >> ((desc_lvl1 >> 4) & 0x1e)) & 3, (desc_lvl1 >> 10) & 3, (m_control & COPRO_CTRL_SYSTEM) ? 1 : 0, (m_control & COPRO_CTRL_ROM) ? 1 : 0,
+ m_r[eCPSR] & MODE_FLAG, flags & ARM7_TLB_READ ? 1 : 0, flags & ARM7_TLB_WRITE ? 1 : 0);
+ return false;
+ }
+ else if (flags & ARM7_TLB_ABORT_P)
+ {
+ LOGMASKED(LOG_MMU, "ARM7: Section Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15]);
return false;
}
}
else if (tlb_type == COPRO_TLB_UNMAPPED)
{
- if (no_exception)
- return false;
-
// Unmapped, generate a translation fault
if (flags & ARM7_TLB_ABORT_D)
{
- LOGMASKED(LOG_MMU, "ARM7: Translation fault on unmapped virtual address, PC = %08x, vaddr = %08x\n", m_r[eR15], addr);
+ LOGMASKED(LOG_MMU, "ARM7: Translation fault on unmapped virtual address (D), PC = %08x, vaddr = %08x\n", m_r[eR15], addr);
m_faultStatus[0] = (5 << 0); // 5 = section translation fault
m_faultAddress = addr;
m_pendingAbtD = true;
@@ -516,9 +507,7 @@ bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags, bool no_except
}
else if (flags & ARM7_TLB_ABORT_P)
{
- LOGMASKED(LOG_MMU, "ARM7: Translation fault on unmapped virtual address, PC = %08x, vaddr = %08x\n", m_r[eR15], addr);
- m_pendingAbtP = true;
- update_irq_state();
+ LOGMASKED(LOG_MMU, "ARM7: Translation fault on unmapped virtual address (P), PC = %08x, vaddr = %08x\n", m_r[eR15], addr);
}
return false;
}
@@ -533,17 +522,14 @@ bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags, bool no_except
fatalerror("ARM7: Not Yet Implemented: Coarse Table, Section Domain fault on virtual address, vaddr = %08x, domain = %08x, PC = %08x\n", addr, domain, m_r[eR15]);
}
- switch( desc_lvl2 & 3 )
+ switch (desc_lvl2 & 3)
{
case COPRO_TLB_UNMAPPED:
- if (no_exception)
- return false;
-
// Unmapped, generate a translation fault
if (flags & ARM7_TLB_ABORT_D)
{
uint8_t domain = (desc_lvl1 >> 5) & 0xF;
- LOGMASKED(LOG_MMU, "ARM7: Translation fault on unmapped virtual address, vaddr = %08x, PC %08X\n", addr, m_r[eR15]);
+ LOGMASKED(LOG_MMU, "ARM7: Translation fault on unmapped virtual address (D), lvl2, vaddr = %08x, PC %08X\n", addr, m_r[eR15]);
m_faultStatus[0] = (7 << 0) | (domain << 4); // 7 = page translation fault
m_faultAddress = addr;
m_pendingAbtD = true;
@@ -551,9 +537,7 @@ bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags, bool no_except
}
else if (flags & ARM7_TLB_ABORT_P)
{
- LOGMASKED(LOG_MMU, "ARM7: Translation fault on unmapped virtual address, vaddr = %08x, PC %08X\n", addr, m_r[eR15]);
- m_pendingAbtP = true;
- update_irq_state();
+ LOGMASKED(LOG_MMU, "ARM7: Translation fault on unmapped virtual address (P), lvl2, vaddr = %08x, PC %08X\n", addr, m_r[eR15]);
}
return false;
case COPRO_TLB_LARGE_PAGE:
@@ -567,44 +551,36 @@ bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags, bool no_except
int fault = detect_fault(desc_lvl1, ap, flags);
if (fault == FAULT_NONE)
{
- addr = ( desc_lvl2 & COPRO_TLB_SMALL_PAGE_MASK ) | ( addr & ~COPRO_TLB_SMALL_PAGE_MASK );
+ addr = (desc_lvl2 & COPRO_TLB_SMALL_PAGE_MASK) | (addr & ~COPRO_TLB_SMALL_PAGE_MASK);
+ break;
}
- else if (no_exception)
+ else if (flags & ARM7_TLB_ABORT_D)
{
- return false;
+ uint8_t domain = (desc_lvl1 >> 5) & 0xF;
+ // hapyfish expects a data abort when something tries to write to a read-only memory location from user mode
+ LOGMASKED(LOG_MMU, "ARM7: Page Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15]);
+ m_faultStatus[0] = ((fault == FAULT_DOMAIN) ? (11 << 0) : (15 << 0)) | (domain << 4); // 11 = page domain fault, 15 = page permission fault
+ m_faultAddress = addr;
+ m_pendingAbtD = true;
+ update_irq_state();
+ LOGMASKED(LOG_MMU, "vaddr %08X desc_lvl2 %08X domain %d permission %d ap %d s %d r %d mode %d read %d write %d\n",
+ addr, desc_lvl2, domain, permission, ap, (m_control & COPRO_CTRL_SYSTEM) ? 1 : 0, (m_control & COPRO_CTRL_ROM) ? 1 : 0,
+ m_r[eCPSR] & MODE_FLAG, flags & ARM7_TLB_READ ? 1 : 0, flags & ARM7_TLB_WRITE ? 1 : 0);
}
- else
+ else if (flags & ARM7_TLB_ABORT_P)
{
- if (flags & ARM7_TLB_ABORT_D)
- {
- uint8_t domain = (desc_lvl1 >> 5) & 0xF;
- // hapyfish expects a data abort when something tries to write to a read-only memory location from user mode
- LOGMASKED(LOG_MMU, "ARM7: Page Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15]);
- m_faultStatus[0] = ((fault == FAULT_DOMAIN) ? (11 << 0) : (15 << 0)) | (domain << 4); // 11 = page domain fault, 15 = page permission fault
- m_faultAddress = addr;
- m_pendingAbtD = true;
- update_irq_state();
- LOGMASKED(LOG_MMU, "vaddr %08X desc_lvl2 %08X domain %d permission %d ap %d s %d r %d mode %d read %d write %d\n",
- addr, desc_lvl2, domain, permission, ap, (m_control & COPRO_CTRL_SYSTEM) ? 1 : 0, (m_control & COPRO_CTRL_ROM) ? 1 : 0,
- m_r[eCPSR] & MODE_FLAG, flags & ARM7_TLB_READ ? 1 : 0, flags & ARM7_TLB_WRITE ? 1 : 0);
- }
- else if (flags & ARM7_TLB_ABORT_P)
- {
- LOGMASKED(LOG_MMU, "ARM7: Page Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15]);
- m_pendingAbtP = true;
- update_irq_state();
- }
- return false;
+ LOGMASKED(LOG_MMU, "ARM7: Page Table, Section %s fault on virtual address, vaddr = %08x, PC = %08x\n", (fault == FAULT_DOMAIN) ? "domain" : "permission", addr, m_r[eR15]);
}
+ return false;
}
break;
case COPRO_TLB_TINY_PAGE:
// Tiny page descriptor
- if( ( desc_lvl1 & 3 ) == 1 )
+ if ((desc_lvl1 & 3) == 1)
{
LOGMASKED(LOG_MMU, "ARM7: It would appear that we're looking up a tiny page from a coarse TLB lookup. This is bad. vaddr = %08x\n", addr);
}
- addr = ( desc_lvl2 & COPRO_TLB_TINY_PAGE_MASK ) | ( addr & ~COPRO_TLB_TINY_PAGE_MASK );
+ addr = (desc_lvl2 & COPRO_TLB_TINY_PAGE_MASK) | (addr & ~COPRO_TLB_TINY_PAGE_MASK);
break;
}
}
@@ -616,7 +592,7 @@ bool arm7_cpu_device::arm7_tlb_translate(offs_t &addr, int flags, bool no_except
bool arm7_cpu_device::memory_translate(int spacenum, int intention, offs_t &address)
{
/* only applies to the program address space and only does something if the MMU's enabled */
- if( spacenum == AS_PROGRAM && ( m_control & COPRO_CTRL_MMU_EN ) )
+ if (spacenum == AS_PROGRAM && (m_control & COPRO_CTRL_MMU_EN))
{
return arm7_tlb_translate(address, 0);
}
@@ -655,6 +631,7 @@ void arm7_cpu_device::device_start()
save_item(NAME(m_insn_prefetch_index));
save_item(NAME(m_insn_prefetch_buffer));
save_item(NAME(m_insn_prefetch_address));
+ save_item(NAME(m_insn_prefetch_valid));
save_item(NAME(m_r));
save_item(NAME(m_pendingIrq));
save_item(NAME(m_pendingFiq));
@@ -835,11 +812,14 @@ void arm7_cpu_device::update_insn_prefetch(uint32_t curr_pc)
for (uint32_t i = 0; i < to_fetch; i++)
{
uint32_t index = (i + start_index) % m_insn_prefetch_depth;
- if ((m_control & COPRO_CTRL_MMU_EN) && !arm7_tlb_translate(pc, ARM7_TLB_ABORT_P | ARM7_TLB_READ, true))
+ m_insn_prefetch_valid[index] = true;
+ offs_t physical_pc = pc;
+ if ((m_control & COPRO_CTRL_MMU_EN) && !arm7_tlb_translate(physical_pc, ARM7_TLB_ABORT_P | ARM7_TLB_READ))
{
+ m_insn_prefetch_valid[index] = false;
break;
}
- uint32_t op = m_pr32(pc);
+ uint32_t op = m_pr32(physical_pc);
//printf("ipb[%d] <- %08x(%08x)\n", index, op, pc);
m_insn_prefetch_buffer[index] = op;
m_insn_prefetch_address[index] = pc;
@@ -848,38 +828,28 @@ void arm7_cpu_device::update_insn_prefetch(uint32_t curr_pc)
}
}
-uint16_t arm7_cpu_device::insn_fetch_thumb(uint32_t pc)
+bool arm7_cpu_device::insn_fetch_thumb(uint32_t pc, uint32_t &out_insn)
{
if (pc & 2)
{
- uint16_t insn = (uint16_t)(m_insn_prefetch_buffer[m_insn_prefetch_index] >> m_prefetch_word1_shift);
- m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_count;
+ out_insn = (uint16_t)(m_insn_prefetch_buffer[m_insn_prefetch_index] >> m_prefetch_word1_shift);
+ bool valid = m_insn_prefetch_valid[m_insn_prefetch_index];
+ m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_depth;
m_insn_prefetch_count--;
- return insn;
+ return valid;
}
- return (uint16_t)(m_insn_prefetch_buffer[m_insn_prefetch_index] >> m_prefetch_word0_shift);
+ out_insn = (uint16_t)(m_insn_prefetch_buffer[m_insn_prefetch_index] >> m_prefetch_word0_shift);
+ return m_insn_prefetch_valid[m_insn_prefetch_index];
}
-uint32_t arm7_cpu_device::insn_fetch_arm(uint32_t pc)
+bool arm7_cpu_device::insn_fetch_arm(uint32_t pc, uint32_t &out_insn)
{
//printf("ipb[%d] = %08x\n", m_insn_prefetch_index, m_insn_prefetch_buffer[m_insn_prefetch_index]);
- uint32_t insn = m_insn_prefetch_buffer[m_insn_prefetch_index];
- m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_count;
+ out_insn = m_insn_prefetch_buffer[m_insn_prefetch_index];
+ bool valid = m_insn_prefetch_valid[m_insn_prefetch_index];
+ m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_depth;
m_insn_prefetch_count--;
- return insn;
-}
-
-int arm7_cpu_device::get_insn_prefetch_index(uint32_t address)
-{
- address &= ~3;
- for (uint32_t i = 0; i < m_insn_prefetch_depth; i++)
- {
- if (m_insn_prefetch_address[i] == address)
- {
- return (int)i;
- }
- }
- return -1;
+ return valid;
}
void arm7_cpu_device::execute_run()
@@ -1096,17 +1066,13 @@ void arm7_cpu_device::execute_run()
// "In Thumb state, bit [0] is undefined and must be ignored. Bits [31:1] contain the PC."
raddr = pc & (~1);
- if ( m_control & COPRO_CTRL_MMU_EN )
+ if (!insn_fetch_thumb(raddr, insn))
{
- if (!arm7_tlb_translate(raddr, ARM7_TLB_ABORT_P | ARM7_TLB_READ))
- {
- goto skip_exec;
- }
+ m_pendingAbtP = true;
+ update_irq_state();
+ goto skip_exec;
}
-
- insn = insn_fetch_thumb(raddr);
(this->*thumb_handler[(insn & 0xffc0) >> 6])(pc, insn);
-
}
else
{
@@ -1117,25 +1083,12 @@ void arm7_cpu_device::execute_run()
// "In ARM state, bits [1:0] of r15 are undefined and must be ignored. Bits [31:2] contain the PC."
raddr = pc & (~3);
- if ( m_control & COPRO_CTRL_MMU_EN )
+ if (!insn_fetch_arm(raddr, insn))
{
- if (!arm7_tlb_translate(raddr, ARM7_TLB_ABORT_P | ARM7_TLB_READ))
- {
- goto skip_exec;
- }
- }
-
-#if 0
- if (MODE26)
- {
- uint32_t temp1, temp2;
- temp1 = GET_CPSR & 0xF00000C3;
- temp2 = (R15 & 0xF0000000) | ((R15 & 0x0C000000) >> (26 - 6)) | (R15 & 0x00000003);
- if (temp1 != temp2) fatalerror( "%08X: 32-bit and 26-bit modes are out of sync (%08X %08X)\n", pc, temp1, temp2);
+ m_pendingAbtP = true;
+ update_irq_state();
+ goto skip_exec;
}
-#endif
-
- insn = insn_fetch_arm(raddr);
int op_offset = 0;
/* process condition codes for this instruction */
@@ -1353,14 +1306,15 @@ uint32_t arm7_cpu_device::arm7_rt_r_callback(offs_t offset)
data = COPRO_CTRL | 0x70; // bits 4-6 always read back as "1" (bit 3 too in XScale)
break;
case 2: // Translation Table Base
+ LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, TLB Base, PC = %08x\n", m_r[eR15]);
data = COPRO_TLB_BASE;
break;
case 3: // Domain Access Control
- LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Domain Access Control\n");
+ LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Domain Access Control, PC = %08x\n", m_r[eR15]);
data = COPRO_DOMAIN_ACCESS_CONTROL;
break;
case 5: // Fault Status
- LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Fault Status\n");
+ LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Fault Status, PC = %08x\n", m_r[eR15]);
switch (op3)
{
case 0: data = COPRO_FAULT_STATUS_D; break;
@@ -1368,11 +1322,11 @@ uint32_t arm7_cpu_device::arm7_rt_r_callback(offs_t offset)
}
break;
case 6: // Fault Address
- LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Fault Address\n");
+ LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Fault Address, PC = %08x\n", m_r[eR15]);
data = COPRO_FAULT_ADDRESS;
break;
case 13: // Read Process ID (PID)
- LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Read PID\n");
+ LOGMASKED(LOG_COPRO_READS, "arm7_rt_r_callback, Read PID, PC = %08x\n", m_r[eR15]);
data = COPRO_FCSE_PID;
break;
case 14: // Read Breakpoint
@@ -1449,12 +1403,12 @@ void arm7_cpu_device::arm7_rt_w_callback(offs_t offset, uint32_t data)
COPRO_CTRL = data & COPRO_CTRL_MASK;
break;
case 2: // Translation Table Base
- LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Base = %08x (%d) (%d)\n", data, op2, op3);
+ LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Base = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]);
COPRO_TLB_BASE = data;
m_tlb_base_mask = data & COPRO_TLB_BASE_MASK;
break;
case 3: // Domain Access Control
- LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Domain Access Control = %08x (%d) (%d)\n", data, op2, op3);
+ LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Domain Access Control = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]);
COPRO_DOMAIN_ACCESS_CONTROL = data;
for (int i = 0; i < 32; i += 2)
{
@@ -1462,7 +1416,7 @@ void arm7_cpu_device::arm7_rt_w_callback(offs_t offset, uint32_t data)
}
break;
case 5: // Fault Status
- LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Fault Status = %08x (%d) (%d)\n", data, op2, op3);
+ LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Fault Status = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]);
switch (op3)
{
case 0: COPRO_FAULT_STATUS_D = data; break;
@@ -1470,20 +1424,20 @@ void arm7_cpu_device::arm7_rt_w_callback(offs_t offset, uint32_t data)
}
break;
case 6: // Fault Address
- LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Fault Address = %08x (%d) (%d)\n", data, op2, op3);
+ LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Fault Address = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]);
COPRO_FAULT_ADDRESS = data;
break;
case 7: // Cache Operations
// LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Cache Ops = %08x (%d) (%d)\n", data, op2, op3);
break;
case 8: // TLB Operations
- LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops = %08x (%d) (%d)\n", data, op2, op3);
+ LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]);
break;
case 9: // Read Buffer Operations
- LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Read Buffer Ops = %08x (%d) (%d)\n", data, op2, op3);
+ LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Read Buffer Ops = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]);
break;
case 13: // Write Process ID (PID)
- LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Write PID = %08x (%d) (%d)\n", data, op2, op3);
+ LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Write PID = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]);
COPRO_FCSE_PID = data;
m_pid_offset = (((COPRO_FCSE_PID >> 25) & 0x7F)) * 0x2000000;
break;
diff --git a/src/devices/cpu/arm7/arm7.h b/src/devices/cpu/arm7/arm7.h
index b303d515a8c..02d422ec0f9 100644
--- a/src/devices/cpu/arm7/arm7.h
+++ b/src/devices/cpu/arm7/arm7.h
@@ -147,15 +147,15 @@ protected:
uint32_t m_r[/*NUM_REGS*/37];
void update_insn_prefetch(uint32_t curr_pc);
- virtual uint16_t insn_fetch_thumb(uint32_t pc);
- uint32_t insn_fetch_arm(uint32_t pc);
- int get_insn_prefetch_index(uint32_t address);
+ bool insn_fetch_thumb(uint32_t pc, uint32_t &out_insn);
+ bool insn_fetch_arm(uint32_t pc, uint32_t &out_insn);
uint32_t m_insn_prefetch_depth;
uint32_t m_insn_prefetch_count;
uint32_t m_insn_prefetch_index;
uint32_t m_insn_prefetch_buffer[3];
uint32_t m_insn_prefetch_address[3];
+ bool m_insn_prefetch_valid[3];
const uint32_t m_prefetch_word0_shift;
const uint32_t m_prefetch_word1_shift;
@@ -235,7 +235,7 @@ protected:
void arm9ops_e(uint32_t insn);
void set_cpsr(uint32_t val);
- bool arm7_tlb_translate(offs_t &addr, int flags, bool no_exception = false);
+ bool arm7_tlb_translate(offs_t &addr, int flags);
uint32_t arm7_tlb_get_second_level_descriptor( uint32_t granularity, uint32_t first_desc, uint32_t vaddr );
int detect_fault(int desc_lvl1, int ap, int flags);
void arm7_check_irq_state();
diff --git a/src/devices/cpu/arm7/arm7dasm.cpp b/src/devices/cpu/arm7/arm7dasm.cpp
index e5c9520cea4..bb17b736952 100644
--- a/src/devices/cpu/arm7/arm7dasm.cpp
+++ b/src/devices/cpu/arm7/arm7dasm.cpp
@@ -150,7 +150,8 @@ void arm7_disassembler::WriteRegisterOperand1( std::ostream &stream, uint32_t op
util::stream_format(
stream,
- ", R%d", /* Operand 1 register, Operand 2 register, shift type */
+ ",%sR%d", /* Operand 1 register, (optional) sign, Operand 2 register, shift type */
+ (opcode&0x800000)?" ":"-",
(opcode >> 0) & 0xf);
//check for LSL 0
diff --git a/src/devices/machine/sa1110.cpp b/src/devices/machine/sa1110.cpp
index 9824b210341..81fb66643b2 100644
--- a/src/devices/machine/sa1110.cpp
+++ b/src/devices/machine/sa1110.cpp
@@ -13,13 +13,15 @@
#define LOG_UART (1 << 2)
#define LOG_UART_HF (1 << 3)
#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 LOG_SSP (1 << 5)
+#define LOG_OSTIMER (1 << 6)
+#define LOG_OSTIMER_HF (1 << 7)
+#define LOG_RTC (1 << 8)
+#define LOG_POWER (1 << 9)
+#define LOG_RESET (1 << 10)
+#define LOG_GPIO (1 << 11)
+#define LOG_INTC (1 << 12)
+#define LOG_ALL (LOG_UNKNOWN | LOG_UART | LOG_MCP | LOG_SSP | LOG_OSTIMER | LOG_RTC | LOG_POWER | LOG_RESET | LOG_GPIO | LOG_INTC)
#define VERBOSE (LOG_ALL)
#include "logmacro.h"
@@ -34,6 +36,7 @@ sa1110_periphs_device::sa1110_periphs_device(const machine_config &mconfig, cons
, m_mcp_irqs(*this, "mcpirq")
, m_codec(*this, finder_base::DUMMY_TAG)
, m_gpio_out(*this)
+ , m_ssp_out(*this)
{
}
@@ -709,6 +712,238 @@ void sa1110_periphs_device::mcp_w(offs_t offset, uint32_t data, uint32_t mem_mas
/*
+ Intel SA-1110 SSP - Synchronous Serial Port
+
+ pg. 331 to 347 Intel StrongARM SA-1110 Microprocessor Developer's Manual
+
+*/
+
+TIMER_CALLBACK_MEMBER(sa1110_periphs_device::ssp_rx_callback)
+{
+ // TODO: Implement receiving data serially rather than in bulk.
+}
+
+TIMER_CALLBACK_MEMBER(sa1110_periphs_device::ssp_tx_callback)
+{
+ // TODO: Implement transmitting data serially rather than in bulk.
+ if (m_ssp_regs.tx_fifo_count)
+ {
+ const uint16_t data = m_ssp_regs.tx_fifo[m_ssp_regs.tx_fifo_read_idx];
+ m_ssp_out(data);
+
+ m_ssp_regs.tx_fifo_read_idx = (m_ssp_regs.tx_fifo_read_idx + 1) % ARRAY_LENGTH(m_ssp_regs.tx_fifo);
+ m_ssp_regs.tx_fifo_count--;
+
+ m_ssp_regs.sssr |= (1 << SSSR_TNF_BIT);
+
+ ssp_update_tx_level();
+ }
+}
+
+void sa1110_periphs_device::ssp_update_enable_state()
+{
+ if (BIT(m_ssp_regs.sscr0, SSCR0_SSE_BIT))
+ {
+ if (m_ssp_regs.tx_fifo_count != ARRAY_LENGTH(m_ssp_regs.tx_fifo))
+ m_ssp_regs.sssr |= (1 << SSSR_TNF_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_TNF_BIT);
+
+ if (m_ssp_regs.rx_fifo_count != 0)
+ m_ssp_regs.sssr |= (1 << SSSR_RNE_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_RNE_BIT);
+
+ if (m_ssp_regs.tx_fifo_count != 0)
+ m_ssp_regs.sssr |= (1 << SSSR_BSY_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_BSY_BIT);
+
+ if (m_ssp_regs.tx_fifo_count <= 4)
+ m_ssp_regs.sssr |= (1 << SSSR_TFS_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_TFS_BIT);
+
+ if (m_ssp_regs.rx_fifo_count >= 4)
+ m_ssp_regs.sssr |= (1 << SSSR_RFS_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_RFS_BIT);
+
+ uint64_t bit_count = (m_ssp_regs.sscr0 & SSCR0_DSS_MASK) >> SSCR0_DSS_BIT;
+ uint32_t clock_rate = 2 * (((m_ssp_regs.sscr0 & SSCR0_SCR_MASK) >> SSCR0_SCR_BIT) + 1);
+ attotime packet_rate = attotime::from_ticks(bit_count * clock_rate, 3686400);
+ m_ssp_regs.rx_timer->adjust(packet_rate, 0, packet_rate);
+ m_ssp_regs.tx_timer->adjust(packet_rate, 0, packet_rate);
+ }
+ else
+ {
+ m_ssp_regs.sssr &= ~(1 << SSSR_TFS_BIT);
+ m_ssp_regs.sssr &= ~(1 << SSSR_RFS_BIT);
+
+ m_ssp_regs.rx_fifo_read_idx = 0;
+ m_ssp_regs.rx_fifo_write_idx = 0;
+ m_ssp_regs.rx_fifo_count = 0;
+ m_ssp_regs.tx_fifo_read_idx = 0;
+ m_ssp_regs.tx_fifo_write_idx = 0;
+ m_ssp_regs.tx_fifo_count = 0;
+
+ m_ssp_regs.rx_timer->adjust(attotime::never);
+ m_ssp_regs.tx_timer->adjust(attotime::never);
+ }
+}
+
+void sa1110_periphs_device::ssp_update_rx_level()
+{
+ if (m_ssp_regs.rx_fifo_count >= 4)
+ m_ssp_regs.sssr |= (1 << SSSR_RFS_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_RFS_BIT);
+}
+
+void sa1110_periphs_device::ssp_rx_fifo_push(const uint16_t data)
+{
+ if (m_ssp_regs.rx_fifo_count < ARRAY_LENGTH(m_ssp_regs.rx_fifo))
+ {
+ m_ssp_regs.rx_fifo[m_ssp_regs.rx_fifo_write_idx] = data;
+ m_ssp_regs.rx_fifo_write_idx = (m_ssp_regs.rx_fifo_write_idx + 1) % ARRAY_LENGTH(m_ssp_regs.rx_fifo);
+ m_ssp_regs.rx_fifo_count++;
+
+ m_ssp_regs.sssr |= (1 << SSSR_RNE_BIT);
+
+ ssp_update_rx_level();
+ }
+}
+
+void sa1110_periphs_device::ssp_update_tx_level()
+{
+ if (m_ssp_regs.tx_fifo_count <= 4)
+ m_ssp_regs.sssr |= (1 << SSSR_TFS_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_TFS_BIT);
+}
+
+void sa1110_periphs_device::ssp_tx_fifo_push(const uint16_t data)
+{
+ if (m_ssp_regs.tx_fifo_count < ARRAY_LENGTH(m_ssp_regs.tx_fifo))
+ {
+ m_ssp_regs.tx_fifo[m_ssp_regs.tx_fifo_write_idx] = data;
+ m_ssp_regs.tx_fifo_write_idx = (m_ssp_regs.tx_fifo_write_idx + 1) % ARRAY_LENGTH(m_ssp_regs.tx_fifo);
+ m_ssp_regs.tx_fifo_count++;
+
+ if (m_ssp_regs.tx_fifo_count != ARRAY_LENGTH(m_ssp_regs.tx_fifo))
+ m_ssp_regs.sssr |= (1 << SSSR_TNF_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_TNF_BIT);
+
+ ssp_update_tx_level();
+ }
+
+ if (m_ssp_regs.tx_fifo_count || m_ssp_regs.rx_fifo_count)
+ m_ssp_regs.sssr |= (1 << SSSR_BSY_BIT);
+ else
+ m_ssp_regs.sssr &= ~(1 << SSSR_BSY_BIT);
+}
+
+uint16_t sa1110_periphs_device::ssp_rx_fifo_pop()
+{
+ uint16_t data = m_ssp_regs.rx_fifo[m_ssp_regs.rx_fifo_read_idx];
+ if (m_ssp_regs.rx_fifo_count)
+ {
+ m_ssp_regs.rx_fifo_read_idx = (m_ssp_regs.rx_fifo_read_idx + 1) % ARRAY_LENGTH(m_ssp_regs.rx_fifo);
+ m_ssp_regs.rx_fifo_count--;
+
+ if (m_ssp_regs.rx_fifo_count == 0)
+ m_ssp_regs.sssr &= ~(1 << SSSR_RNE_BIT);
+
+ ssp_update_rx_level();
+ }
+ return data;
+}
+
+uint32_t sa1110_periphs_device::ssp_r(offs_t offset, uint32_t mem_mask)
+{
+ switch (offset)
+ {
+ case REG_SSCR0:
+ LOGMASKED(LOG_SSP, "%s: ssp_r: SSP Control Register 0: %08x & %08x\n", machine().describe_context(), m_ssp_regs.sscr0, mem_mask);
+ return m_ssp_regs.sscr0;
+ case REG_SSCR1:
+ LOGMASKED(LOG_SSP, "%s: ssp_r: SSP Control Register 1: %08x & %08x\n", machine().describe_context(), m_ssp_regs.sscr1, mem_mask);
+ return m_ssp_regs.sscr1;
+ case REG_SSDR:
+ {
+ const uint32_t data = ssp_rx_fifo_pop();
+ LOGMASKED(LOG_SSP, "%s: ssp_r: SSP Data Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+ }
+ case REG_SSSR:
+ LOGMASKED(LOG_SSP, "%s: ssp_r: SSP Status Register: %08x & %08x\n", machine().describe_context(), m_ssp_regs.sssr, mem_mask);
+ LOGMASKED(LOG_SSP, "%s: Transmit FIFO Not Full: %d\n", machine().describe_context(), BIT(m_ssp_regs.sssr, SSSR_TNF_BIT));
+ LOGMASKED(LOG_SSP, "%s: Receive FIFO Not Empty: %d\n", machine().describe_context(), BIT(m_ssp_regs.sssr, SSSR_RNE_BIT));
+ LOGMASKED(LOG_SSP, "%s: SSP Busy: %d\n", machine().describe_context(), BIT(m_ssp_regs.sssr, SSSR_BSY_BIT));
+ LOGMASKED(LOG_SSP, "%s: Transmit FIFO Service Request: %d\n", machine().describe_context(), BIT(m_ssp_regs.sssr, SSSR_TFS_BIT));
+ LOGMASKED(LOG_SSP, "%s: Receive FIFO Service Request: %d\n", machine().describe_context(), BIT(m_ssp_regs.sssr, SSSR_RFS_BIT));
+ LOGMASKED(LOG_SSP, "%s: Receive Overrun: %d\n", machine().describe_context(), BIT(m_ssp_regs.sssr, SSSR_ROR_BIT));
+ return m_ssp_regs.sssr;
+ default:
+ LOGMASKED(LOG_SSP | LOG_UNKNOWN, "%s: ssp_r: Unknown address: %08x & %08x\n", machine().describe_context(), SSP_BASE_ADDR | (offset << 2), mem_mask);
+ return 0;
+ }
+}
+
+void sa1110_periphs_device::ssp_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ switch (offset)
+ {
+ case REG_SSCR0:
+ {
+ static const char *const s_dss_sizes[16] =
+ {
+ "Invalid [1]", "Invalid [2]", "Invalid [3]", "4-bit",
+ "5-bit", "6-bit", "7-bit", "8-bit",
+ "9-bit", "10-bit", "11-bit", "12-bit",
+ "13-bit", "14-bit", "15-bit", "16-bit"
+ };
+ static const char *const s_frf_formats[4] = { "Motorola SPI", "TI Synchronous Serial", "National Microwire", "Reserved" };
+ LOGMASKED(LOG_SSP, "%s: ssp_w: SSP Control Register 0: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SSP, "%s: Data Size Select: %s\n", machine().describe_context(), s_dss_sizes[(data & SSCR0_DSS_MASK) >> SSCR0_DSS_BIT]);
+ LOGMASKED(LOG_SSP, "%s: Frame Format: %s\n", machine().describe_context(), s_frf_formats[(data & SSCR0_FRF_MASK) >> SSCR0_FRF_BIT]);
+ LOGMASKED(LOG_SSP, "%s: SSP Enable: %d\n", machine().describe_context(), BIT(data, SSCR0_SSE_BIT));
+ LOGMASKED(LOG_SSP, "%s: Serial Clock Rate Divisor: %d\n", machine().describe_context(), 2 * (data & SSCR0_DSS_MASK) >> SSCR0_DSS_BIT);
+ const uint32_t old = m_ssp_regs.sscr0;
+ COMBINE_DATA(&m_ssp_regs.sscr0);
+ if (BIT(old ^ m_ssp_regs.sscr0, SSCR0_SSE_BIT))
+ ssp_update_enable_state();
+ break;
+ }
+ case REG_SSCR1:
+ {
+ LOGMASKED(LOG_SSP, "%s: ssp_w: SSP Control Register 1: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SSP, "%s: Receive FIFO Interrupt Enable: %d\n", machine().describe_context(), BIT(data, SSCR1_RIE_BIT));
+ LOGMASKED(LOG_SSP, "%s: Transmit FIFO Interrupt Enable: %d\n", machine().describe_context(), BIT(data, SSCR1_TIE_BIT));
+ LOGMASKED(LOG_SSP, "%s: Loopback Mode Enable: %d\n", machine().describe_context(), BIT(data, SSCR1_LBM_BIT));
+ LOGMASKED(LOG_SSP, "%s: Serial Clock Polarity: %d\n", machine().describe_context(), BIT(data, SSCR1_SPO_BIT));
+ LOGMASKED(LOG_SSP, "%s: Serial Clock Phase: %d\n", machine().describe_context(), BIT(data, SSCR1_SPH_BIT));
+ LOGMASKED(LOG_SSP, "%s: External Clock Select: %d\n", machine().describe_context(), BIT(data, SSCR1_ECS_BIT));
+ COMBINE_DATA(&m_ssp_regs.sscr1);
+ break;
+ }
+ case REG_SSDR:
+ LOGMASKED(LOG_SSP, "%s: ssp_w: SSP Data Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ ssp_tx_fifo_push((uint16_t)data);
+ break;
+ case REG_SSSR:
+ LOGMASKED(LOG_SSP, "%s: ssp_w: SSP Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SSP, "%s: Clear Receive Overrun: %d\n", machine().describe_context(), BIT(data, SSSR_ROR_BIT));
+ break;
+ default:
+ LOGMASKED(LOG_SSP | LOG_UNKNOWN, "%s: ssp_w: Unknown address: %08x = %08x & %08x\n", machine().describe_context(), SSP_BASE_ADDR | (offset << 2), data, mem_mask);
+ break;
+ }
+}
+
+/*
+
Intel SA-1110 Operating System Timer
pg. 92 to 96 Intel StrongARM SA-1110 Microprocessor Developer's Manual
@@ -730,6 +965,9 @@ void sa1110_periphs_device::ostimer_update_count()
{
const attotime time_delta = machine().time() - m_ostmr_regs.last_count_sync;
const uint64_t ticks_elapsed = time_delta.as_ticks(INTERNAL_OSC);
+ if (ticks_elapsed == 0ULL) // Accrue time until we can tick at least once
+ return;
+
const uint32_t wrapped_ticks = (uint32_t)ticks_elapsed;
m_ostmr_regs.oscr += wrapped_ticks;
m_ostmr_regs.last_count_sync = machine().time();
@@ -762,7 +1000,7 @@ uint32_t sa1110_periphs_device::ostimer_r(offs_t offset, uint32_t mem_mask)
LOGMASKED(LOG_OSTIMER, "%s: ostimer_r: OS Timer Match Register 3: %08x & %08x\n", machine().describe_context(), m_ostmr_regs.osmr[3], mem_mask);
return m_ostmr_regs.osmr[3];
case REG_OSCR:
- LOGMASKED(LOG_OSTIMER, "%s: ostimer_r: OS Timer Counter Register: %08x & %08x\n", machine().describe_context(), m_ostmr_regs.oscr, mem_mask);
+ LOGMASKED(LOG_OSTIMER_HF, "%s: ostimer_r: OS Timer Counter Register: %08x & %08x\n", machine().describe_context(), m_ostmr_regs.oscr, mem_mask);
return m_ostmr_regs.oscr;
case REG_OSSR:
LOGMASKED(LOG_OSTIMER, "%s: ostimer_r: OS Timer Status Register: %08x & %08x\n", machine().describe_context(), m_ostmr_regs.ossr, mem_mask);
@@ -1225,7 +1463,7 @@ void sa1110_periphs_device::gpio_w(offs_t offset, uint32_t data, uint32_t mem_ma
}
case REG_GPCR:
{
- LOGMASKED(LOG_GPIO, "%s: gpio_w: GPIO Pin Output Clear Register (ignored): %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_GPIO, "%s: gpio_w: GPIO Pin Output Clear Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
const uint32_t old = m_gpio_regs.output_latch;
m_gpio_regs.output_latch &= ~(data & mem_mask);
const uint32_t changed = ((old ^ m_gpio_regs.output_latch) & m_gpio_regs.gpdr) & ~m_gpio_regs.gafr;
@@ -1412,6 +1650,20 @@ void sa1110_periphs_device::device_start()
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_ssp_regs.sscr0));
+ save_item(NAME(m_ssp_regs.sscr1));
+ save_item(NAME(m_ssp_regs.sssr));
+ save_item(NAME(m_ssp_regs.rx_fifo));
+ save_item(NAME(m_ssp_regs.rx_fifo_read_idx));
+ save_item(NAME(m_ssp_regs.rx_fifo_write_idx));
+ save_item(NAME(m_ssp_regs.rx_fifo_count));
+ m_ssp_regs.rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1110_periphs_device::ssp_rx_callback), this));
+ save_item(NAME(m_ssp_regs.tx_fifo));
+ save_item(NAME(m_ssp_regs.tx_fifo_read_idx));
+ save_item(NAME(m_ssp_regs.tx_fifo_write_idx));
+ save_item(NAME(m_ssp_regs.tx_fifo_count));
+ m_ssp_regs.tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1110_periphs_device::ssp_tx_callback), this));
+
save_item(NAME(m_ostmr_regs.osmr));
save_item(NAME(m_ostmr_regs.oscr));
save_item(NAME(m_ostmr_regs.ossr));
@@ -1459,6 +1711,7 @@ void sa1110_periphs_device::device_start()
save_item(NAME(m_intc_regs.icpr));
m_gpio_out.resolve_all_safe();
+ m_ssp_out.resolve_safe();
}
void sa1110_periphs_device::device_reset()
@@ -1504,6 +1757,21 @@ void sa1110_periphs_device::device_reset()
m_mcp_regs.telecom_tx_fifo_count = 0;
m_mcp_regs.telecom_tx_timer->adjust(attotime::never);
+ // init SSP regs
+ m_ssp_regs.sscr0 = 0;
+ m_ssp_regs.sscr1 = 0;
+ m_ssp_regs.sssr = (1 << SSSR_TNF_BIT);
+ memset(m_ssp_regs.rx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_ssp_regs.rx_fifo));
+ m_ssp_regs.rx_fifo_read_idx = 0;
+ m_ssp_regs.rx_fifo_write_idx = 0;
+ m_ssp_regs.rx_fifo_count = 0;
+ m_ssp_regs.rx_timer->adjust(attotime::never);
+ memset(m_ssp_regs.tx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_ssp_regs.tx_fifo));
+ m_ssp_regs.tx_fifo_read_idx = 0;
+ m_ssp_regs.tx_fifo_write_idx = 0;
+ m_ssp_regs.tx_fifo_count = 0;
+ m_ssp_regs.tx_timer->adjust(attotime::never);
+
// init OS timers
memset(m_ostmr_regs.osmr, 0, sizeof(uint32_t) * 4);
m_ostmr_regs.ower = 0;
diff --git a/src/devices/machine/sa1110.h b/src/devices/machine/sa1110.h
index cd823fb9934..a25e616d9eb 100644
--- a/src/devices/machine/sa1110.h
+++ b/src/devices/machine/sa1110.h
@@ -41,10 +41,15 @@ public:
template <unsigned Line> void gpio_in(int state) { gpio_in(Line, state); }
template <unsigned Line> auto gpio_out() { return m_gpio_out[Line].bind(); }
+ void ssp_in(uint16_t data) { ssp_rx_fifo_push(data); }
+ auto ssp_out() { return m_ssp_out.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 ssp_r(offs_t offset, uint32_t mem_mask = ~0);
+ void ssp_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);
@@ -92,6 +97,15 @@ protected:
void mcp_codec_read(offs_t offset);
void mcp_codec_write(offs_t offset, uint16_t data);
+ TIMER_CALLBACK_MEMBER(ssp_rx_callback);
+ TIMER_CALLBACK_MEMBER(ssp_tx_callback);
+ void ssp_update_enable_state();
+ void ssp_update_rx_level();
+ void ssp_update_tx_level();
+ void ssp_rx_fifo_push(const uint16_t data);
+ void ssp_tx_fifo_push(const uint16_t data);
+ uint16_t ssp_rx_fifo_pop();
+
TIMER_CALLBACK_MEMBER(ostimer_tick_cb);
void ostimer_update_count();
void ostimer_update_match_timer(int channel);
@@ -126,6 +140,12 @@ protected:
REG_MCDR2 = (0x00000010 >> 2),
REG_MCSR = (0x00000018 >> 2),
+ SSP_BASE_ADDR = 0x80070000,
+ REG_SSCR0 = (0x00000060 >> 2),
+ REG_SSCR1 = (0x00000064 >> 2),
+ REG_SSDR = (0x0000006c >> 2),
+ REG_SSSR = (0x00000074 >> 2),
+
OSTMR_BASE_ADDR = 0x90000000,
REG_OSMR0 = (0x00000000 >> 2),
REG_OSMR1 = (0x00000004 >> 2),
@@ -241,6 +261,28 @@ protected:
MCSR_ACE_BIT = 14,
MCSR_TCE_BIT = 15,
+ SSCR0_DSS_BIT = 0,
+ SSCR0_DSS_MASK = 0x0000000f,
+ SSCR0_FRF_BIT = 4,
+ SSCR0_FRF_MASK = 0x00000030,
+ SSCR0_SSE_BIT = 7,
+ SSCR0_SCR_BIT = 8,
+ SSCR0_SCR_MASK = 0x0000ff00,
+
+ SSCR1_RIE_BIT = 0,
+ SSCR1_TIE_BIT = 1,
+ SSCR1_LBM_BIT = 2,
+ SSCR1_SPO_BIT = 3,
+ SSCR1_SPH_BIT = 4,
+ SSCR1_ECS_BIT = 5,
+
+ SSSR_TNF_BIT = 1,
+ SSSR_RNE_BIT = 2,
+ SSSR_BSY_BIT = 3,
+ SSSR_TFS_BIT = 4,
+ SSSR_RFS_BIT = 5,
+ SSSR_ROR_BIT = 6,
+
RTSR_AL_BIT = 0,
RTSR_AL_MASK = (1 << RTSR_AL_BIT),
RTSR_HZ_BIT = 1,
@@ -360,6 +402,25 @@ protected:
emu_timer *telecom_tx_timer;
};
+ struct ssp_regs
+ {
+ uint32_t sscr0;
+ uint32_t sscr1;
+ uint32_t sssr;
+
+ uint16_t rx_fifo[8];
+ int rx_fifo_read_idx;
+ int rx_fifo_write_idx;
+ int rx_fifo_count;
+ emu_timer *rx_timer;
+
+ uint16_t tx_fifo[8];
+ int tx_fifo_read_idx;
+ int tx_fifo_write_idx;
+ int tx_fifo_count;
+ emu_timer *tx_timer;
+ };
+
struct ostimer_regs
{
uint32_t osmr[4];
@@ -423,6 +484,7 @@ protected:
uart_regs m_uart_regs;
mcp_regs m_mcp_regs;
+ ssp_regs m_ssp_regs;
ostimer_regs m_ostmr_regs;
rtc_regs m_rtc_regs;
power_regs m_power_regs;
@@ -436,6 +498,7 @@ protected:
optional_device<ucb1200_device> m_codec;
devcb_write_line::array<28> m_gpio_out;
+ devcb_write16 m_ssp_out;
};
DECLARE_DEVICE_TYPE(SA1110_PERIPHERALS, sa1110_periphs_device)
diff --git a/src/devices/machine/sa1111.cpp b/src/devices/machine/sa1111.cpp
new file mode 100644
index 00000000000..cc63d657c87
--- /dev/null
+++ b/src/devices/machine/sa1111.cpp
@@ -0,0 +1,1733 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/***************************************************************************
+
+ Intel SA1111 Microprocessor Companion Chip skeleton
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sa1111.h"
+
+#define LOG_UNKNOWN (1 << 1)
+#define LOG_SBI (1 << 2)
+#define LOG_SK (1 << 3)
+#define LOG_USB (1 << 4)
+#define LOG_AUDIO (1 << 5)
+#define LOG_SSP (1 << 6)
+#define LOG_SSP_HF (1 << 7)
+#define LOG_TRACK (1 << 8)
+#define LOG_MOUSE (1 << 9)
+#define LOG_GPIO (1 << 10)
+#define LOG_INTC (1 << 11)
+#define LOG_CARD (1 << 12)
+#define LOG_ALL (LOG_UNKNOWN | LOG_SBI | LOG_SK | LOG_USB | LOG_AUDIO | LOG_SSP | LOG_TRACK | LOG_MOUSE | LOG_GPIO | LOG_INTC | LOG_CARD)
+
+#define VERBOSE (LOG_ALL)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(SA1111, sa1111_device, "sa1111", "Intel SA1111 Microprocessor Companion Chip")
+
+sa1111_device::sa1111_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SA1111, tag, owner, clock)
+ , m_gpio_out(*this)
+ , m_ssp_out(*this)
+{
+}
+
+void sa1111_device::map(address_map &map)
+{
+ map(0x0000, 0x1fff).rw(FUNC(sa1111_device::unknown_r), FUNC(sa1111_device::unknown_w));
+
+ map(0x0000, 0x0003).rw(FUNC(sa1111_device::skcr_r), FUNC(sa1111_device::skcr_w));
+ map(0x0004, 0x0007).rw(FUNC(sa1111_device::smcr_r), FUNC(sa1111_device::smcr_w));
+ map(0x0008, 0x000b).r(FUNC(sa1111_device::skid_r));
+
+ map(0x0200, 0x0203).rw(FUNC(sa1111_device::skpcr_r), FUNC(sa1111_device::skpcr_w));
+ map(0x0204, 0x0207).rw(FUNC(sa1111_device::skcdr_r), FUNC(sa1111_device::skcdr_w));
+ map(0x0208, 0x020b).rw(FUNC(sa1111_device::skaud_r), FUNC(sa1111_device::skaud_w));
+ map(0x020c, 0x020f).rw(FUNC(sa1111_device::skpmc_r), FUNC(sa1111_device::skpmc_w));
+ map(0x0210, 0x0213).rw(FUNC(sa1111_device::skptc_r), FUNC(sa1111_device::skptc_w));
+ map(0x0214, 0x0217).rw(FUNC(sa1111_device::skpen0_r), FUNC(sa1111_device::skpen0_w));
+ map(0x0218, 0x021b).rw(FUNC(sa1111_device::skpwm0_r), FUNC(sa1111_device::skpwm0_w));
+ map(0x021c, 0x021f).rw(FUNC(sa1111_device::skpen1_r), FUNC(sa1111_device::skpen1_w));
+ map(0x0220, 0x0223).rw(FUNC(sa1111_device::skpwm1_r), FUNC(sa1111_device::skpwm1_w));
+
+ map(0x0400, 0x0457).rw(FUNC(sa1111_device::ohci_r), FUNC(sa1111_device::ohci_w));
+ map(0x0518, 0x051b).r(FUNC(sa1111_device::usb_status_r));
+ map(0x051c, 0x051f).rw(FUNC(sa1111_device::usb_reset_r), FUNC(sa1111_device::usb_reset_w));
+ map(0x0520, 0x0523).w(FUNC(sa1111_device::usb_int_test_w));
+ map(0x0530, 0x055f).r(FUNC(sa1111_device::usb_fifo_r));
+
+ map(0x0600, 0x0603).rw(FUNC(sa1111_device::sacr0_r), FUNC(sa1111_device::sacr0_w));
+ map(0x0604, 0x0607).rw(FUNC(sa1111_device::sacr1_r), FUNC(sa1111_device::sacr1_w));
+ map(0x0608, 0x060b).rw(FUNC(sa1111_device::sacr2_r), FUNC(sa1111_device::sacr2_w));
+ map(0x060c, 0x060f).r(FUNC(sa1111_device::sasr0_r));
+ map(0x0610, 0x0613).r(FUNC(sa1111_device::sasr1_r));
+ map(0x0618, 0x061b).w(FUNC(sa1111_device::sascr_w));
+ map(0x061c, 0x061f).rw(FUNC(sa1111_device::l3car_r), FUNC(sa1111_device::l3car_w));
+ map(0x0620, 0x0623).rw(FUNC(sa1111_device::l3cdr_r), FUNC(sa1111_device::l3cdr_w));
+ map(0x0624, 0x0627).rw(FUNC(sa1111_device::accar_r), FUNC(sa1111_device::accar_w));
+ map(0x0628, 0x062b).rw(FUNC(sa1111_device::accdr_r), FUNC(sa1111_device::accdr_w));
+ map(0x062c, 0x062f).rw(FUNC(sa1111_device::acsar_r), FUNC(sa1111_device::acsar_w));
+ map(0x0630, 0x0633).rw(FUNC(sa1111_device::acsdr_r), FUNC(sa1111_device::acsdr_w));
+ map(0x0634, 0x0637).rw(FUNC(sa1111_device::sadtcs_r), FUNC(sa1111_device::sadtcs_w));
+ map(0x0638, 0x063b).rw(FUNC(sa1111_device::sadtsa_r), FUNC(sa1111_device::sadtsa_w));
+ map(0x063c, 0x063f).rw(FUNC(sa1111_device::sadtca_r), FUNC(sa1111_device::sadtca_w));
+ map(0x0640, 0x0643).rw(FUNC(sa1111_device::sadtsb_r), FUNC(sa1111_device::sadtsb_w));
+ map(0x0644, 0x0647).rw(FUNC(sa1111_device::sadtcb_r), FUNC(sa1111_device::sadtcb_w));
+ map(0x0648, 0x064b).rw(FUNC(sa1111_device::sadrcs_r), FUNC(sa1111_device::sadrcs_w));
+ map(0x064c, 0x064f).rw(FUNC(sa1111_device::sadrsa_r), FUNC(sa1111_device::sadrsa_w));
+ map(0x0650, 0x0653).rw(FUNC(sa1111_device::sadrca_r), FUNC(sa1111_device::sadrca_w));
+ map(0x0654, 0x0657).rw(FUNC(sa1111_device::sadrsb_r), FUNC(sa1111_device::sadrsb_w));
+ map(0x0658, 0x065b).rw(FUNC(sa1111_device::sadrcb_r), FUNC(sa1111_device::sadrcb_w));
+ map(0x065c, 0x065f).w(FUNC(sa1111_device::saitr_w));
+ map(0x0680, 0x06bf).rw(FUNC(sa1111_device::sadr_r), FUNC(sa1111_device::sadr_w));
+
+ map(0x0800, 0x0803).rw(FUNC(sa1111_device::sspcr0_r), FUNC(sa1111_device::sspcr0_w));
+ map(0x0804, 0x0807).rw(FUNC(sa1111_device::sspcr1_r), FUNC(sa1111_device::sspcr1_w));
+ map(0x0810, 0x0813).rw(FUNC(sa1111_device::sspsr_r), FUNC(sa1111_device::sspsr_w));
+ map(0x0814, 0x0817).w(FUNC(sa1111_device::sspitr_w));
+ map(0x0840, 0x087f).rw(FUNC(sa1111_device::sspdr_r), FUNC(sa1111_device::sspdr_w));
+
+ map(0x0a00, 0x0a03).rw(FUNC(sa1111_device::track_kbdcr_r), FUNC(sa1111_device::track_kbdcr_w));
+ map(0x0a04, 0x0a07).rw(FUNC(sa1111_device::track_kbdstat_r), FUNC(sa1111_device::track_kbdstat_w));
+ map(0x0a08, 0x0a0b).rw(FUNC(sa1111_device::track_kbddata_r), FUNC(sa1111_device::track_kbddata_w));
+ map(0x0a0c, 0x0a0f).rw(FUNC(sa1111_device::track_kbdclkdiv_r), FUNC(sa1111_device::track_kbdclkdiv_w));
+ map(0x0a10, 0x0a13).rw(FUNC(sa1111_device::track_kbdprecnt_r), FUNC(sa1111_device::track_kbdprecnt_w));
+ map(0x0a14, 0x0a17).w(FUNC(sa1111_device::track_kbditr_w));
+
+ map(0x0c00, 0x0c03).rw(FUNC(sa1111_device::mouse_kbdcr_r), FUNC(sa1111_device::mouse_kbdcr_w));
+ map(0x0c04, 0x0c07).rw(FUNC(sa1111_device::mouse_kbdstat_r), FUNC(sa1111_device::mouse_kbdstat_w));
+ map(0x0c08, 0x0c0b).rw(FUNC(sa1111_device::mouse_kbddata_r), FUNC(sa1111_device::mouse_kbddata_w));
+ map(0x0c0c, 0x0c0f).rw(FUNC(sa1111_device::mouse_kbdclkdiv_r), FUNC(sa1111_device::mouse_kbdclkdiv_w));
+ map(0x0c10, 0x0c13).rw(FUNC(sa1111_device::mouse_kbdprecnt_r), FUNC(sa1111_device::mouse_kbdprecnt_w));
+ map(0x0c14, 0x0c17).w(FUNC(sa1111_device::mouse_kbditr_w));
+
+ map(0x1000, 0x1003).rw(FUNC(sa1111_device::ddr_r<0>), FUNC(sa1111_device::ddr_w<0>));
+ map(0x1004, 0x1007).rw(FUNC(sa1111_device::drr_r<0>), FUNC(sa1111_device::dwr_w<0>));
+ map(0x1008, 0x100b).rw(FUNC(sa1111_device::sdr_r<0>), FUNC(sa1111_device::sdr_w<0>));
+ map(0x100c, 0x100f).rw(FUNC(sa1111_device::ssr_r<0>), FUNC(sa1111_device::ssr_w<0>));
+ map(0x1010, 0x1013).rw(FUNC(sa1111_device::ddr_r<1>), FUNC(sa1111_device::ddr_w<1>));
+ map(0x1014, 0x1017).rw(FUNC(sa1111_device::drr_r<1>), FUNC(sa1111_device::dwr_w<1>));
+ map(0x1018, 0x101b).rw(FUNC(sa1111_device::sdr_r<1>), FUNC(sa1111_device::sdr_w<1>));
+ map(0x101c, 0x101f).rw(FUNC(sa1111_device::ssr_r<1>), FUNC(sa1111_device::ssr_w<1>));
+ map(0x1020, 0x1023).rw(FUNC(sa1111_device::ddr_r<2>), FUNC(sa1111_device::ddr_w<2>));
+ map(0x1024, 0x1027).rw(FUNC(sa1111_device::drr_r<2>), FUNC(sa1111_device::dwr_w<2>));
+ map(0x1028, 0x102b).rw(FUNC(sa1111_device::sdr_r<2>), FUNC(sa1111_device::sdr_w<2>));
+ map(0x102c, 0x102f).rw(FUNC(sa1111_device::ssr_r<2>), FUNC(sa1111_device::ssr_w<2>));
+
+ map(0x1600, 0x1603).rw(FUNC(sa1111_device::inttest_r<0>), FUNC(sa1111_device::inttest_w<0>));
+ map(0x1604, 0x1607).rw(FUNC(sa1111_device::inttest_r<1>), FUNC(sa1111_device::inttest_w<1>));
+ map(0x1608, 0x160b).rw(FUNC(sa1111_device::inten_r<0>), FUNC(sa1111_device::inten_w<0>));
+ map(0x160c, 0x160f).rw(FUNC(sa1111_device::inten_r<1>), FUNC(sa1111_device::inten_w<1>));
+ map(0x1610, 0x1613).rw(FUNC(sa1111_device::intpol_r<0>), FUNC(sa1111_device::intpol_w<0>));
+ map(0x1614, 0x1617).rw(FUNC(sa1111_device::intpol_r<1>), FUNC(sa1111_device::intpol_w<1>));
+ map(0x1618, 0x161b).rw(FUNC(sa1111_device::inttstsel_r), FUNC(sa1111_device::inttstsel_w));
+ map(0x161c, 0x161f).rw(FUNC(sa1111_device::intstat_r<0>), FUNC(sa1111_device::intclr_w<0>));
+ map(0x1620, 0x1623).rw(FUNC(sa1111_device::intstat_r<1>), FUNC(sa1111_device::intclr_w<1>));
+ map(0x1624, 0x1627).w(FUNC(sa1111_device::intset_w<0>));
+ map(0x1628, 0x162b).w(FUNC(sa1111_device::intset_w<1>));
+ map(0x162c, 0x162f).rw(FUNC(sa1111_device::wake_en_r<0>), FUNC(sa1111_device::wake_en_w<0>));
+ map(0x1630, 0x1633).rw(FUNC(sa1111_device::wake_en_r<1>), FUNC(sa1111_device::wake_en_w<1>));
+ map(0x1634, 0x1637).rw(FUNC(sa1111_device::wake_pol_r<0>), FUNC(sa1111_device::wake_pol_w<0>));
+ map(0x1638, 0x163b).rw(FUNC(sa1111_device::wake_pol_r<1>), FUNC(sa1111_device::wake_pol_w<1>));
+
+ map(0x1800, 0x1803).rw(FUNC(sa1111_device::pccr_r), FUNC(sa1111_device::pccr_w));
+ map(0x1804, 0x1807).rw(FUNC(sa1111_device::pcssr_r), FUNC(sa1111_device::pcssr_w));
+ map(0x1808, 0x180b).r(FUNC(sa1111_device::pcsr_r));
+}
+
+uint32_t sa1111_device::unknown_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_UNKNOWN, "%s: unknown_r: Unknown Register: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
+ return 0;
+}
+
+void sa1111_device::unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_UNKNOWN, "%s: unknown_w: Unknown Register: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
+}
+
+/*
+
+ Intel SA-1111 System Bus Interface
+
+ pg. 33 to 50 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+uint32_t sa1111_device::skcr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SBI, "%s: skcr_r: Control Register: %08x & %08x\n", machine().describe_context(), m_sbi_regs.skcr, mem_mask);
+ return m_sbi_regs.skcr;
+}
+
+uint32_t sa1111_device::smcr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SBI, "%s: smcr_r: Shared Memory Controller Register: %08x & %08x\n", machine().describe_context(), m_sbi_regs.smcr, mem_mask);
+ return m_sbi_regs.smcr;
+}
+
+uint32_t sa1111_device::skid_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SBI, "%s: skid_r: ID Register: %08x & %08x\n", machine().describe_context(), m_sbi_regs.skid, mem_mask);
+ return m_sbi_regs.skid;
+}
+
+void sa1111_device::skcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SBI, "%s: skcr_w: Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SBI, "%s: Use External Clock: %d\n", machine().describe_context(), BIT(data, SKCR_PLLB_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enable System Bus Clocks: %d\n", machine().describe_context(), BIT(data, SKCR_RCLK_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enter Sleep Mode: %d\n", machine().describe_context(), BIT(data, SKCR_SLEEP_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enter Doze Mode: %d\n", machine().describe_context(), BIT(data, SKCR_DOZE_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enable System PLL: %d\n", machine().describe_context(), BIT(data, SKCR_VCO_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enable Scan Test: %d\n", machine().describe_context(), BIT(data, SKCR_SCANTST_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enable Clock Test: %d\n", machine().describe_context(), BIT(data, SKCR_CLKTST_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enable RDY Response: %d\n", machine().describe_context(), BIT(data, SKCR_RDY_BIT));
+ LOGMASKED(LOG_SBI, "%s: Audio Feature Select: %s\n", machine().describe_context(), BIT(data, SKCR_SLAC_BIT) ? "AC Link" : "I2S");
+ LOGMASKED(LOG_SBI, "%s: Out-Only Pad Control: %d\n", machine().describe_context(), BIT(data, SKCR_OPPC_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enable PII Test: %d\n", machine().describe_context(), BIT(data, SKCR_PII_BIT));
+ LOGMASKED(LOG_SBI, "%s: USB IO Cell Test: %d\n", machine().describe_context(), BIT(data, SKCR_UIOTEN_BIT));
+ LOGMASKED(LOG_SBI, "%s: Enable /OE on SDRAM DMA Read Cycles: %d\n", machine().describe_context(), 1 - BIT(data, SKCR_OEEN_BIT));
+ COMBINE_DATA(&m_sbi_regs.skcr);
+}
+
+void sa1111_device::smcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SBI, "%s: smcr_w: Shared Memory Controller Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SBI, "%s: DRAM Type: %s\n", machine().describe_context(), BIT(data, SMCR_DTIM_BIT) ? "SDRAM" : "Unknown");
+ LOGMASKED(LOG_SBI, "%s: Shared-Memory Grant Enable: %d\n", machine().describe_context(), BIT(data, SMCR_MBGE_BIT));
+ LOGMASKED(LOG_SBI, "%s: DRAM Row Address Bits: %d\n", machine().describe_context(), 9 + ((data & SMCR_DRAC_MASK) >> SMCR_DRAC_BIT));
+ LOGMASKED(LOG_SBI, "%s: CAS Latency: %d\n", machine().describe_context(), 2 + BIT(data, SMCR_CLAT_BIT));
+ COMBINE_DATA(&m_sbi_regs.smcr);
+}
+
+/*
+
+ Intel SA-1111 System Controller
+
+ pg. 59 to 66 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+uint32_t sa1111_device::skpcr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpcr_r: Power Control Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skpcr, mem_mask);
+ return m_sk_regs.skpcr;
+}
+
+uint32_t sa1111_device::skcdr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skcdr_r: Clock Divider Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skcdr, mem_mask);
+ return m_sk_regs.skcdr;
+}
+
+uint32_t sa1111_device::skaud_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skaud_r: Audio Clock Divider Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skaud, mem_mask);
+ return m_sk_regs.skaud;
+}
+
+uint32_t sa1111_device::skpmc_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpmc_r: PS/2 Mouse Clock Divider Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skpmc, mem_mask);
+ return m_sk_regs.skpmc;
+}
+
+uint32_t sa1111_device::skptc_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skptc_r: PS/2 Track Pad Clock Divider Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skptc, mem_mask);
+ return m_sk_regs.skptc;
+}
+
+uint32_t sa1111_device::skpen0_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpen0_r: PWM0 Enable Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skpen0, mem_mask);
+ return m_sk_regs.skpen0;
+}
+
+uint32_t sa1111_device::skpwm0_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpwm0_r: PWM0 Clock Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skpwm0, mem_mask);
+ return m_sk_regs.skpwm0;
+}
+
+uint32_t sa1111_device::skpen1_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpen1_r: PWM1 Enable Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skpen1, mem_mask);
+ return m_sk_regs.skpen1;
+}
+
+uint32_t sa1111_device::skpwm1_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpwm1_r: PWM1 Clock Register: %08x & %08x\n", machine().describe_context(), m_sk_regs.skpwm1, mem_mask);
+ return m_sk_regs.skpwm1;
+}
+
+void sa1111_device::skpcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpcr_w: Power Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SK, "%s: USB Host Controller Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_UCLKE_BIT));
+ LOGMASKED(LOG_SK, "%s: Audio Controller AC Link Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_ACCLKE_BIT));
+ LOGMASKED(LOG_SK, "%s: Audio Controller I2S Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_ISCLKE_BIT));
+ LOGMASKED(LOG_SK, "%s: Audio Controller L3 Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_L3CLKE_BIT));
+ LOGMASKED(LOG_SK, "%s: SSP Controller Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_SCLKE_BIT));
+ LOGMASKED(LOG_SK, "%s: PS/2 Mouse Port Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_PMCLKE_BIT));
+ LOGMASKED(LOG_SK, "%s: PS/2 Track Pad Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_PTCLKE_BIT));
+ LOGMASKED(LOG_SK, "%s: Shared Memory Controller Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_DCLKE_BIT));
+ LOGMASKED(LOG_SK, "%s: PWM Clock Enable: %d\n", machine().describe_context(), BIT(data, SKPCR_PWMCLKE_BIT));
+ COMBINE_DATA(&m_sk_regs.skpcr);
+}
+
+void sa1111_device::skcdr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ static const int s_opd_values[4] = { 1, 4, 2, 8 };
+ LOGMASKED(LOG_SK, "%s: skcdr_w: Clock Divider Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SK, "%s: Feedback Divider: %02x\n", machine().describe_context(), (data & SKCDR_FBD_MASK) >> SKCDR_FBD_BIT);
+ LOGMASKED(LOG_SK, "%s: Input Divider: %02x\n", machine().describe_context(), (data & SKCDR_IPD_MASK) >> SKCDR_IPD_BIT);
+ LOGMASKED(LOG_SK, "%s: Output Divider: %d\n", machine().describe_context(), s_opd_values[(data & SKCDR_OPD_MASK) >> SKCDR_OPD_BIT]);
+ LOGMASKED(LOG_SK, "%s: PLL-Bypass Output Phase: %s\n", machine().describe_context(), BIT(data, SKCDR_OPS_BIT) ? "Inverted" : "In-Phase");
+ COMBINE_DATA(&m_sk_regs.skcdr);
+}
+
+void sa1111_device::skaud_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skaud_w: Audio Clock Divider Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SK, "%s: Audio Clock Divider: %02x\n", machine().describe_context(), ((data & SKAUD_ACD_MASK) >> SKAUD_ACD_BIT) + 1);
+ COMBINE_DATA(&m_sk_regs.skaud);
+}
+
+void sa1111_device::skpmc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpmc_w: PS/2 Mouse Clock Divider Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SK, "%s: PS/2 Clock Divider: %02x\n", machine().describe_context(), ((data & SKPMC_PMCD_MASK) >> SKPMC_PMCD_BIT) + 1);
+ COMBINE_DATA(&m_sk_regs.skpmc);
+}
+
+void sa1111_device::skptc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skptc_w: PS/2 Track Pad Clock Divider Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SK, "%s: PS/2 Clock Divider: %02x\n", machine().describe_context(), ((data & SKPTC_PTCD_MASK) >> SKPTC_PTCD_BIT) + 1);
+ COMBINE_DATA(&m_sk_regs.skptc);
+}
+
+void sa1111_device::skpen0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpen0_w: PWM0 Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_sk_regs.skpen0);
+}
+
+void sa1111_device::skpwm0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpwm0_w: PWM0 Clock Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SK, "%s: PWM0 Duty Cycle: %02x\n", machine().describe_context(), (data & SKPWM0_PWM0CK_MASK) >> SKPWM0_PWM0CK_BIT);
+ COMBINE_DATA(&m_sk_regs.skpwm0);
+}
+
+void sa1111_device::skpen1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpen1_w: PWM1 Enable Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_sk_regs.skpen1);
+}
+
+void sa1111_device::skpwm1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SK, "%s: skpwm1_w: PWM1 Clock Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SK, "%s: PWM1 Duty Cycle: %02x\n", machine().describe_context(), (data & SKPWM1_PWM1CK_MASK) >> SKPWM1_PWM1CK_BIT);
+ COMBINE_DATA(&m_sk_regs.skpwm1);
+}
+
+/*
+
+ Intel SA-1111 USB Host Interface Controller
+
+ pg. 67 to 77 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+uint32_t sa1111_device::ohci_r(offs_t offset, uint32_t mem_mask)
+{
+ static const char *const s_ohci_names[22] =
+ {
+ "Revision", "Control", "Command Status", "Interrupt Status",
+ "Interrupt Enable", "Interrupt Disable", "HCCA", "Period Current ED",
+ "Control Head ED", "Control Current ED", "Bulk Head ED", "Bulk Current ED",
+ "Done Head", "Fm Interval", "Fm Remaining", "Fm Number",
+ "Periodic Start", "LS Threshold", "Rh Descriptor A", "Rh Descriptor B",
+ "Rh Status", "Rh Port Status<1>"
+ };
+ LOGMASKED(LOG_USB, "%s: ohci_r: %s: %08x & %08x\n", machine().describe_context(), s_ohci_names[offset], m_usb_regs.ohci[offset], mem_mask);
+ return m_usb_regs.ohci[offset];
+}
+
+uint32_t sa1111_device::usb_status_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint32_t data = m_usb_regs.status;
+ LOGMASKED(LOG_USB, "%s: usb_status_r: Status Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_USB, "%s: HCI Remote Wake-Up Event: %d\n", machine().describe_context(), BIT(data, USBSTAT_IHRW_BIT));
+ LOGMASKED(LOG_USB, "%s: HCI Buffer Active: %d\n", machine().describe_context(), BIT(data, USBSTAT_IHBA_BIT));
+ LOGMASKED(LOG_USB, "%s: Normal HCI Interrupt Active: %d\n", machine().describe_context(), BIT(data, USBSTAT_NHT_BIT));
+ LOGMASKED(LOG_USB, "%s: HCI Interface Clear Signals Active: %d\n", machine().describe_context(), BIT(data, USBSTAT_NHFCT_BIT));
+ LOGMASKED(LOG_USB, "%s: Port Over-Current: %d\n", machine().describe_context(), BIT(data, USBSTAT_UPRT_BIT));
+ return data;
+}
+
+uint32_t sa1111_device::usb_reset_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_USB, "%s: usb_reset_r: Reset Register: %08x & %08x\n", machine().describe_context(), m_usb_regs.reset, mem_mask);
+ return m_usb_regs.reset;
+}
+
+uint32_t sa1111_device::usb_fifo_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_USB, "%s: usb_fifo_r: Data FIFO RAM %02x: %08x & %08x\n", machine().describe_context(), offset, m_usb_regs.fifo[offset], mem_mask);
+ return m_usb_regs.fifo[offset];
+}
+
+void sa1111_device::ohci_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ static const char *const s_ohci_names[22] =
+ {
+ "Revision", "Control", "Command Status", "Interrupt Status",
+ "Interrupt Enable", "Interrupt Disable", "HCCA", "Period Current ED",
+ "Control Head ED", "Control Current ED", "Bulk Head ED", "Bulk Current ED",
+ "Done Head", "Fm Interval", "Fm Remaining", "Fm Number",
+ "Periodic Start", "LS Threshold", "Rh Descriptor A", "Rh Descriptor B",
+ "Rh Status", "Rh Port Status<1>"
+ };
+ LOGMASKED(LOG_USB, "%s: ohci_w: %s = %08x & %08x\n", machine().describe_context(), s_ohci_names[offset], data, mem_mask);
+ COMBINE_DATA(&m_usb_regs.ohci[offset]);
+}
+
+void sa1111_device::usb_reset_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_USB, "%s: usb_reset_w: Reset Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_USB, "%s: Reset ASB Master Interface: %d\n", machine().describe_context(), BIT(data, USBRST_FIR_BIT));
+ LOGMASKED(LOG_USB, "%s: Reset USB Host Controller: %d\n", machine().describe_context(), BIT(data, USBRST_FHR_BIT));
+ LOGMASKED(LOG_USB, "%s: Reset Host Controller Clock-Gen Block: %d\n", machine().describe_context(), BIT(data, USBRST_CGR_BIT));
+ LOGMASKED(LOG_USB, "%s: Scale-down 1ms Clock: %d\n", machine().describe_context(), BIT(data, USBRST_SSDC_BIT));
+ LOGMASKED(LOG_USB, "%s: Interrupt Test Enable: %d\n", machine().describe_context(), BIT(data, USBRST_UIT_BIT));
+ LOGMASKED(LOG_USB, "%s: Enable Sleep Standby: %d\n", machine().describe_context(), BIT(data, USBRST_SSE_BIT));
+ LOGMASKED(LOG_USB, "%s: USB Power Sense Polarity: %s\n", machine().describe_context(), BIT(data, USBRST_PSPL_BIT) ? "Active-Low" : "Active-High");
+ LOGMASKED(LOG_USB, "%s: PwrCtrlPolLow Polarity: %s\n", machine().describe_context(), BIT(data, USBRST_PCPL_BIT) ? "Active-Low" : "Active-High");
+ COMBINE_DATA(&m_usb_regs.reset);
+}
+
+void sa1111_device::usb_int_test_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_USB, "%s: usb_int_test_w: Interrupt Test Register = %08x & %08x\n", machine().describe_context(), m_usb_regs.int_test, mem_mask);
+ LOGMASKED(LOG_USB, "%s: Force HCI Remote Wake-Up Interrupt: %d\n", machine().describe_context(), BIT(data, USBINT_IHRWT_BIT));
+ LOGMASKED(LOG_USB, "%s: Force HCI Buffer Active Interrupt: %d\n", machine().describe_context(), BIT(data, USBINT_IHBAT_BIT));
+ LOGMASKED(LOG_USB, "%s: Force Normal HC Interrupt: %d\n", machine().describe_context(), BIT(data, USBINT_NHT_BIT));
+ LOGMASKED(LOG_USB, "%s: Force HCI Interface Transfer Abort Interrupt: %d\n", machine().describe_context(), BIT(data, USBINT_NHFCT_BIT));
+ LOGMASKED(LOG_USB, "%s: Force USB Port Resume Interrupt: %d\n", machine().describe_context(), BIT(data, USBINT_UPRT_BIT));
+ COMBINE_DATA(&m_usb_regs.int_test);
+}
+
+/*
+
+ Intel SA-1111 Serial Audio Controller
+
+ pg. 79 to 108 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+TIMER_CALLBACK_MEMBER(sa1111_device::audio_rx_callback)
+{
+}
+
+TIMER_CALLBACK_MEMBER(sa1111_device::audio_tx_callback)
+{
+}
+
+uint32_t sa1111_device::sacr0_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sacr0_r: Serial Audio Common Control Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.sacr0, mem_mask);
+ return m_audio_regs.sacr0;
+}
+
+uint32_t sa1111_device::sacr1_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sacr1_r: Serial Audio Alternate Mode Control Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.sacr1, mem_mask);
+ return m_audio_regs.sacr1;
+}
+
+uint32_t sa1111_device::sacr2_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sacr2_r: Serial Audio AC-Link Control Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.sacr2, mem_mask);
+ return m_audio_regs.sacr2;
+}
+
+uint32_t sa1111_device::sasr0_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint32_t data = m_audio_regs.sasr0;
+ LOGMASKED(LOG_AUDIO, "%s: sasr0_r: Serial Audio Status Register 0: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Not Full: %d\n", machine().describe_context(), BIT(data, SASR0_TNF_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Not Empty: %d\n", machine().describe_context(), BIT(data, SASR0_RNE_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Serial Audio Controller Busy: %d\n", machine().describe_context(), BIT(data, SASR0_BSY_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SASR0_TFS_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SASR0_RFS_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Underrun: %d\n", machine().describe_context(), BIT(data, SASR0_TUR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Overrun: %d\n", machine().describe_context(), BIT(data, SASR0_ROR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Level: %02x\n", machine().describe_context(), (data & SASR0_TFL_MASK) >> SASR0_TFL_BIT);
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Level: %02x\n", machine().describe_context(), (data & SASR0_RFL_MASK) >> SASR0_RFL_BIT);
+ LOGMASKED(LOG_AUDIO, "%s: L3 Control Bus Data Write Done: %d\n", machine().describe_context(), BIT(data, SASR0_L3WD_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: L3 Control Bus Data Read Done: %d\n", machine().describe_context(), BIT(data, SASR0_L3RD_BIT));
+ return data;
+}
+
+uint32_t sa1111_device::sasr1_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint32_t data = m_audio_regs.sasr1;
+ LOGMASKED(LOG_AUDIO, "%s: sasr1_r: Serial Audio Status Register 1: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Not Full: %d\n", machine().describe_context(), BIT(data, SASR1_TNF_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Not Empty: %d\n", machine().describe_context(), BIT(data, SASR1_RNE_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Serial Audio Controller Busy: %d\n", machine().describe_context(), BIT(data, SASR1_BSY_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SASR1_TFS_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SASR1_RFS_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Underrun: %d\n", machine().describe_context(), BIT(data, SASR1_TUR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Overrun: %d\n", machine().describe_context(), BIT(data, SASR1_ROR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Level: %02x\n", machine().describe_context(), (data & SASR1_TFL_MASK) >> SASR1_TFL_BIT);
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Level: %02x\n", machine().describe_context(), (data & SASR1_RFL_MASK) >> SASR1_RFL_BIT);
+ LOGMASKED(LOG_AUDIO, "%s: AC-Link Command Address and Data Transmitted: %d\n", machine().describe_context(), BIT(data, SASR1_CADT_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: AC-Link Status Address and Data Received: %d\n", machine().describe_context(), BIT(data, SASR1_SADR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Read Status Time-Out: %d\n", machine().describe_context(), BIT(data, SASR1_RSTO_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: AC'97 Codec BIT_CLK in Low-Power Mode: %d\n", machine().describe_context(), BIT(data, SASR1_CLPM_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: AC'97 Codec Ready: %d\n", machine().describe_context(), BIT(data, SASR1_CRDY_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Received Slot 3 Valid (Left Channel Valid): %d\n", machine().describe_context(), BIT(data, SASR1_RS3V_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Received Slot 4 Valid (Right Channel Valid): %d\n", machine().describe_context(), BIT(data, SASR1_RS4V_BIT));
+ return data;
+}
+
+uint32_t sa1111_device::l3car_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: l3car_r: L3 Control Bus Address Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.l3car, mem_mask);
+ return m_audio_regs.l3car;
+}
+
+uint32_t sa1111_device::l3cdr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: l3car_r: L3 Control Bus Data Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.l3cdr, mem_mask);
+ return m_audio_regs.l3cdr;
+}
+
+uint32_t sa1111_device::accar_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: accar_r: AC-Link Command Address Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.accar, mem_mask);
+ return m_audio_regs.accar;
+}
+
+uint32_t sa1111_device::accdr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: accdr_r: AC-Link Command Data Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.accdr, mem_mask);
+ return m_audio_regs.accdr;
+}
+
+uint32_t sa1111_device::acsar_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: acsar_r: AC-Link Status Address Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.acsar, mem_mask);
+ return m_audio_regs.acsar;
+}
+
+uint32_t sa1111_device::acsdr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: acsdr_r: AC-Link Status Data Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.acsdr, mem_mask);
+ return m_audio_regs.acsdr;
+}
+
+uint32_t sa1111_device::sadtcs_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtcs_r: Serial Audio DMA Transmit Control/Status Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadtcs, mem_mask);
+ return m_audio_regs.sadtcs;
+}
+
+uint32_t sa1111_device::sadtsa_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtsa_r: Serial Audio DMA Transmit Buffer Start Address Register A: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadtsa, mem_mask);
+ return m_audio_regs.sadtsa;
+}
+
+uint32_t sa1111_device::sadtca_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtca_r: Serial Audio DMA Transmit Buffer Count Register A: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadtca, mem_mask);
+ return m_audio_regs.sadtca;
+}
+
+uint32_t sa1111_device::sadtsb_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtsb_r: Serial Audio DMA Transmit Buffer Start Address Register B: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadtsb, mem_mask);
+ return m_audio_regs.sadtsb;
+}
+
+uint32_t sa1111_device::sadtcb_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtcb_r: Serial Audio DMA Transmit Buffer Count Register B: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadtcb, mem_mask);
+ return m_audio_regs.sadtcb;
+}
+
+uint32_t sa1111_device::sadrcs_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrcs_r: Serial Audio DMA Receive Control/Status Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadrcs, mem_mask);
+ return m_audio_regs.sadrcs;
+}
+
+uint32_t sa1111_device::sadrsa_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrsa_r: Serial Audio DMA Receive Buffer Start Address Register A: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadrsa, mem_mask);
+ return m_audio_regs.sadrsa;
+}
+
+uint32_t sa1111_device::sadrca_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrca_r: Serial Audio DMA Receive Buffer Count Register A: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadrca, mem_mask);
+ return m_audio_regs.sadrca;
+}
+
+uint32_t sa1111_device::sadrsb_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrsb_r: Serial Audio DMA Receive Buffer Start Address Register B: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadrsb, mem_mask);
+ return m_audio_regs.sadrsb;
+}
+
+uint32_t sa1111_device::sadrcb_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrcb_r: Serial Audio DMA Receive Buffer Count Register B: %08x & %08x\n", machine().describe_context(), m_audio_regs.sadrcb, mem_mask);
+ return m_audio_regs.sadrcb;
+}
+
+uint32_t sa1111_device::sadr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadr_r: Serial Audio Data Register: %08x & %08x\n", machine().describe_context(), m_audio_regs.rx_fifo[m_audio_regs.rx_fifo_read_idx], mem_mask);
+ return m_audio_regs.rx_fifo[m_audio_regs.rx_fifo_read_idx];
+}
+
+void sa1111_device::sacr0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sacr0_w: Serial Audio Common Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Enable Serial Audio Controller: %d\n", machine().describe_context(), BIT(data, SACR0_ENB_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: BIT_CLK Pin Direction: %s\n", machine().describe_context(), BIT(data, SACR0_BCKD_BIT) ? "Input" : "Output");
+ LOGMASKED(LOG_AUDIO, "%s: Reset SAC Control and FIFOs: %d\n", machine().describe_context(), BIT(data, SACR0_RST_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Threshold: %02x\n", machine().describe_context(), (data & SACR0_TFTH_MASK) >> SACR0_TFTH_BIT);
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Threshold: %02x\n", machine().describe_context(), (data & SACR0_RFTH_MASK) >> SACR0_RFTH_BIT);
+ COMBINE_DATA(&m_audio_regs.sacr0);
+}
+
+void sa1111_device::sacr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sacr1_w: Serial Audio Alternate Mode Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Alternade Mode Operation: %s\n", machine().describe_context(), BIT(data, SACR1_AMSL_BIT) ? "MSB-Justified" : "I2S");
+ LOGMASKED(LOG_AUDIO, "%s: Enable L3 Control Bus: %d\n", machine().describe_context(), BIT(data, SACR1_L3EN_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: L3 Control Bus Data Multi-Byte Transfer: %s\n", machine().describe_context(), BIT(data, SACR1_L3MB_BIT) ? "Multiple-Byte" : "Last Byte");
+ LOGMASKED(LOG_AUDIO, "%s: Disable Recording Function: %d\n", machine().describe_context(), BIT(data, SACR1_DREC_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Disable Replaying Function: %d\n", machine().describe_context(), BIT(data, SACR1_DRPL_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Enable L3 and I2S/MSB-Justified Loopback: %d\n", machine().describe_context(), BIT(data, SACR1_ENLBF_BIT));
+ COMBINE_DATA(&m_audio_regs.sacr1);
+}
+
+void sa1111_device::sacr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sacr2_w: Serial Audio AC-Link Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Transmit Slot 3 Valid (Left Out Valid): %d\n", machine().describe_context(), BIT(data, SACR2_TS3V_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit Slot 4 Valid (Right Out Valid): %d\n", machine().describe_context(), BIT(data, SACR2_TS4V_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Wake Up AC'97 Codec: %d\n", machine().describe_context(), BIT(data, SACR2_WKUP_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Disable Recording of AC-Link Interface: %d\n", machine().describe_context(), BIT(data, SACR2_DREC_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Disable Replaying of AC-Link Interface: %d\n", machine().describe_context(), BIT(data, SACR2_DRPL_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Enable AC-Link Loopback: %d\n", machine().describe_context(), BIT(data, SACR2_ENLBF_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Specify Reset# Signal to SYS_CLK Output: %s\n", machine().describe_context(), BIT(data, SACR2_RESET_BIT) ? "Inactive" : "Active-Low");
+ COMBINE_DATA(&m_audio_regs.sacr2);
+}
+
+void sa1111_device::sascr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sascr_w: Serial Audio Status Clear Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Clear Transmit FIFO Underrun: %d\n", machine().describe_context(), BIT(data, SASCR_TUR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Clear Receive FIFO Overrun: %d\n", machine().describe_context(), BIT(data, SASCR_ROR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Clear L3C/AC-Link Data Sent Status Bit: %d\n", machine().describe_context(), BIT(data, SASCR_DTS_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Clear L3C/AC-Link Data Read Done Status Bit: %d\n", machine().describe_context(), BIT(data, SASCR_RDD_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Clear AC-Link Read Status Time-Out Bit: %d\n", machine().describe_context(), BIT(data, SASCR_STO_BIT));
+
+ if (BIT(data, SASCR_TUR_BIT))
+ {
+ m_audio_regs.sasr0 &= ~(1 << SASR0_TUR_BIT);
+ m_audio_regs.sasr1 &= ~(1 << SASR1_TUR_BIT);
+ }
+ if (BIT(data, SASCR_ROR_BIT))
+ {
+ m_audio_regs.sasr0 &= ~(1 << SASR0_ROR_BIT);
+ m_audio_regs.sasr1 &= ~(1 << SASR1_ROR_BIT);
+ }
+ if (BIT(data, SASCR_DTS_BIT))
+ {
+ m_audio_regs.sasr0 &= ~(1 << SASR0_L3WD_BIT);
+ m_audio_regs.sasr1 &= ~(1 << SASR1_CADT_BIT);
+ }
+ if (BIT(data, SASCR_RDD_BIT))
+ {
+ m_audio_regs.sasr0 &= ~(1 << SASR0_L3RD_BIT);
+ m_audio_regs.sasr1 &= ~(1 << SASR1_SADR_BIT);
+ }
+ if (BIT(data, SASCR_STO_BIT))
+ m_audio_regs.sasr1 &= ~(1 << SASR1_RSTO_BIT);
+}
+
+void sa1111_device::l3car_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: l3car_w: L3 Control Bus Address Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.l3car);
+}
+
+void sa1111_device::l3cdr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: l3cdr_w: L3 Control Bus Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.l3cdr);
+}
+
+void sa1111_device::accar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: accar_w: AC-Link Command Address Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.accar);
+}
+
+void sa1111_device::accdr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: accdr_w: AC-Link Command Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.accdr);
+}
+
+void sa1111_device::acsar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: acsar_w: AC-Link Status Address Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.acsar);
+}
+
+void sa1111_device::acsdr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: acsdr_w: AC-Link Status Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.acsdr);
+}
+
+void sa1111_device::sadtcs_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtcs_w: Serial Audio DMA Transmit Control/Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Serial Audio DMA Transmit Enable: %d\n", machine().describe_context(), BIT(data, SADTCS_TDEN_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Clear Serial Audio DMA Transmit Buffer Done A: %d\n", machine().describe_context(), BIT(data, SADTCS_TDBDA_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Serial Audio DMA Transmit Buffer Start Transfer A: %d\n", machine().describe_context(), BIT(data, SADTCS_TDSTA_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Clear Serial Audio DMA Transmit Buffer Done B: %d\n", machine().describe_context(), BIT(data, SADTCS_TDBDB_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Serial Audio DMA Transmit Buffer Start Transfer B: %d\n", machine().describe_context(), BIT(data, SADTCS_TDSTB_BIT));
+
+ m_audio_regs.sadtcs &= ~(1 << SADTCS_TDEN_BIT);
+ m_audio_regs.sadtcs |= data & (1 << SADTCS_TDEN_BIT);
+
+ if (BIT(data, SADTCS_TDBDA_BIT))
+ m_audio_regs.sadtcs &= ~(1 << SADTCS_TDBDA_BIT);
+ if (BIT(data, SADTCS_TDBDB_BIT))
+ m_audio_regs.sadtcs &= ~(1 << SADTCS_TDBDB_BIT);
+
+ if (BIT(m_audio_regs.sadtcs, SADTCS_TDEN_BIT))
+ {
+ if (BIT(data, SADTCS_TDSTA_BIT))
+ {
+ m_audio_regs.sadtcs &= ~(1 << SADTCS_TDBDA_BIT);
+ // TODO: Begin DMA transmit of Buffer A
+ }
+ if (BIT(data, SADTCS_TDSTB_BIT))
+ {
+ m_audio_regs.sadtcs &= ~(1 << SADTCS_TDBDB_BIT);
+ // TODO: Begin DMA transmit of Buffer B
+ }
+ }
+}
+
+void sa1111_device::sadtsa_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtsa_w: Serial Audio DMA Transmit Buffer Start Address Register A = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.sadtsa);
+}
+
+void sa1111_device::sadtca_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtca_w: Serial Audio DMA Transmit Buffer Count Register A = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.sadtca);
+}
+
+void sa1111_device::sadtsb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtsb_w: Serial Audio DMA Transmit Buffer Start Address Register B = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.sadtsb);
+}
+
+void sa1111_device::sadtcb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadtcb_w: Serial Audio DMA Transmit Buffer Count Register B = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.sadtcb);
+}
+
+void sa1111_device::sadrcs_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrcs_w: Serial Audio DMA Receive Control/Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Serial Audio DMA Receive Enable: %d\n", machine().describe_context(), BIT(data, SADRCS_RDEN_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Clear Serial Audio DMA Receive Buffer Done A: %d\n", machine().describe_context(), BIT(data, SADRCS_RDBDA_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Serial Audio DMA Receive Buffer Start Transfer A: %d\n", machine().describe_context(), BIT(data, SADRCS_RDSTA_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Clear Serial Audio DMA Receive Buffer Done B: %d\n", machine().describe_context(), BIT(data, SADRCS_RDBDB_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Serial Audio DMA Receive Buffer Start Transfer B: %d\n", machine().describe_context(), BIT(data, SADRCS_RDSTB_BIT));
+
+ m_audio_regs.sadrcs &= ~(1 << SADRCS_RDEN_BIT);
+ m_audio_regs.sadrcs |= data & (1 << SADRCS_RDEN_BIT);
+
+ if (BIT(data, SADRCS_RDBDA_BIT))
+ m_audio_regs.sadrcs &= ~(1 << SADRCS_RDBDA_BIT);
+ if (BIT(data, SADRCS_RDBDB_BIT))
+ m_audio_regs.sadrcs &= ~(1 << SADRCS_RDBDB_BIT);
+
+ if (BIT(m_audio_regs.sadrcs, SADRCS_RDEN_BIT))
+ {
+ if (BIT(data, SADRCS_RDSTA_BIT))
+ {
+ m_audio_regs.sadrcs &= ~(1 << SADRCS_RDBDA_BIT);
+ // TODO: Begin DMA receive of Buffer A
+ }
+ if (BIT(data, SADRCS_RDSTB_BIT))
+ {
+ m_audio_regs.sadrcs &= ~(1 << SADRCS_RDBDB_BIT);
+ // TODO: Begin DMA receive of Buffer B
+ }
+ }
+}
+
+void sa1111_device::sadrsa_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrsa_w: Serial Audio DMA Receive Buffer Start Address Register A = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.sadrsa);
+}
+
+void sa1111_device::sadrca_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrca_w: Serial Audio DMA Receive Buffer Count Register A = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.sadrca);
+}
+
+void sa1111_device::sadrsb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrsb_w: Serial Audio DMA Receive Buffer Start Address Register B = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.sadrsb);
+}
+
+void sa1111_device::sadrcb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadrcb_w: Serial Audio DMA Receive Buffer Count Register B = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_audio_regs.sadrcb);
+}
+
+void sa1111_device::saitr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: saitr_w: Serial Audio Interrupt Test Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SAITR_TFS_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SAITR_RFS_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Transmit FIFO Underrun: %d\n", machine().describe_context(), BIT(data, SAITR_TUR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Receive FIFO Overrun: %d\n", machine().describe_context(), BIT(data, SAITR_ROR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Command Address/Data Transfer Done: %d\n", machine().describe_context(), BIT(data, SAITR_CADT_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Status Address/Data Receive Done: %d\n", machine().describe_context(), BIT(data, SAITR_SADR_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: Read Status Time-Out: %d\n", machine().describe_context(), BIT(data, SAITR_RSTO_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: DMA Transmit Buffer Done A: %d\n", machine().describe_context(), BIT(data, SAITR_TDBDA_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: DMA Transmit Buffer Done B: %d\n", machine().describe_context(), BIT(data, SAITR_TDBDB_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: DMA Receive Buffer Done A: %d\n", machine().describe_context(), BIT(data, SAITR_RDBDA_BIT));
+ LOGMASKED(LOG_AUDIO, "%s: DMA Receive Buffer Done B: %d\n", machine().describe_context(), BIT(data, SAITR_RDBDB_BIT));
+}
+
+void sa1111_device::sadr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_AUDIO, "%s: sadr_w: Serial Audio Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ // TODO: Push into audio FIFO
+}
+
+/*
+
+ Intel SA-1111 SSP Serial Port
+
+ pg. 109 to 124 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+TIMER_CALLBACK_MEMBER(sa1111_device::ssp_rx_callback)
+{
+ // TODO: Implement receiving serial data rather than in bulk.
+}
+
+TIMER_CALLBACK_MEMBER(sa1111_device::ssp_tx_callback)
+{
+ // TODO: Implement transmitting data serially rather than in bulk.
+ if (m_ssp_regs.tx_fifo_count)
+ {
+ const uint16_t data = m_ssp_regs.tx_fifo[m_ssp_regs.tx_fifo_read_idx];
+ m_ssp_out(data);
+
+ m_ssp_regs.tx_fifo_read_idx = (m_ssp_regs.tx_fifo_read_idx + 1) % ARRAY_LENGTH(m_ssp_regs.tx_fifo);
+ m_ssp_regs.tx_fifo_count--;
+
+ m_ssp_regs.sspsr |= (1 << SSPSR_TNF_BIT);
+
+ ssp_update_tx_level();
+ }
+}
+
+void sa1111_device::ssp_update_enable_state()
+{
+ if (BIT(m_ssp_regs.sspcr0, SSPCR0_SSPEN_BIT))
+ {
+ const uint32_t tfl = (m_ssp_regs.sspsr & SSPSR_TFL_MASK) >> SSPSR_TFL_BIT;
+ const uint32_t rfl = (m_ssp_regs.sspsr & SSPSR_RFL_MASK) >> SSPSR_RFL_BIT;
+ const uint32_t tft = (m_ssp_regs.sspsr & SSPCR1_TFT_MASK) >> SSPCR1_TFT_BIT;
+ const uint32_t rft = (m_ssp_regs.sspsr & SSPCR1_RFT_MASK) >> SSPCR1_RFT_BIT;
+
+ if (tfl != (ARRAY_LENGTH(m_ssp_regs.tx_fifo) - 1))
+ m_ssp_regs.sspsr |= (1 << SSPSR_TNF_BIT);
+ else
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_TNF_BIT);
+
+ if (rfl != 0)
+ m_ssp_regs.sspsr |= (1 << SSPSR_RNE_BIT);
+ else
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_RNE_BIT);
+
+ if (tfl != 0 || rfl != 0)
+ m_ssp_regs.sspsr |= (1 << SSPSR_BSY_BIT);
+ else
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_BSY_BIT);
+
+ if (tfl <= tft)
+ m_ssp_regs.sspsr |= (1 << SSPSR_TFS_BIT);
+ else
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_TFS_BIT);
+
+ if (rfl <= rft)
+ m_ssp_regs.sspsr |= (1 << SSPSR_RFS_BIT);
+ else
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_RFS_BIT);
+
+ uint64_t bit_count = (m_ssp_regs.sspcr0 & SSPCR0_DSS_MASK) >> SSPCR0_DSS_BIT;
+ uint32_t clock_rate = 2 * (((m_ssp_regs.sspcr0 & SSPCR0_SCR_MASK) >> SSPCR0_SCR_BIT) + 1);
+ attotime packet_rate = attotime::from_ticks(bit_count * clock_rate, 3686400);
+ m_ssp_regs.rx_timer->adjust(packet_rate, 0, packet_rate);
+ m_ssp_regs.tx_timer->adjust(packet_rate, 0, packet_rate);
+ }
+ else
+ {
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_TFS_BIT);
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_RFS_BIT);
+
+ m_ssp_regs.rx_fifo_read_idx = 0;
+ m_ssp_regs.rx_fifo_write_idx = 0;
+ m_ssp_regs.rx_fifo_count = 0;
+ m_ssp_regs.tx_fifo_read_idx = 0;
+ m_ssp_regs.tx_fifo_write_idx = 0;
+ m_ssp_regs.tx_fifo_count = 0;
+
+ m_ssp_regs.rx_timer->adjust(attotime::never);
+ m_ssp_regs.tx_timer->adjust(attotime::never);
+ }
+}
+
+void sa1111_device::ssp_update_rx_level()
+{
+ const uint32_t rfl = m_ssp_regs.rx_fifo_count;
+ m_ssp_regs.sspsr &= ~SSPSR_RFL_MASK;
+ m_ssp_regs.sspsr |= (rfl << SSPSR_RFL_BIT);
+
+ const uint32_t rft = (m_ssp_regs.sspcr1 & SSPCR1_RFT_MASK) >> SSPCR1_RFT_BIT;
+ if (rfl >= rft)
+ m_ssp_regs.sspsr |= (1 << SSPSR_RFS_BIT);
+ else
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_RFS_BIT);
+}
+
+void sa1111_device::ssp_rx_fifo_push(const uint16_t data)
+{
+ if (m_ssp_regs.rx_fifo_count < ARRAY_LENGTH(m_ssp_regs.rx_fifo))
+ {
+ m_ssp_regs.rx_fifo[m_ssp_regs.rx_fifo_write_idx] = data;
+ m_ssp_regs.rx_fifo_write_idx = (m_ssp_regs.rx_fifo_write_idx + 1) % ARRAY_LENGTH(m_ssp_regs.rx_fifo);
+ m_ssp_regs.rx_fifo_count++;
+
+ m_ssp_regs.sspsr |= (1 << SSPSR_RNE_BIT);
+
+ ssp_update_rx_level();
+ }
+}
+
+void sa1111_device::ssp_update_tx_level()
+{
+ const uint32_t tfl = m_ssp_regs.tx_fifo_count;
+ m_ssp_regs.sspsr &= ~SSPSR_TFL_MASK;
+ m_ssp_regs.sspsr |= (tfl << SSPSR_TFL_BIT);
+
+ const uint32_t tft = (m_ssp_regs.sspcr1 & SSPCR1_TFT_MASK) >> SSPCR1_TFT_BIT;
+ if (tfl >= tft)
+ m_ssp_regs.sspsr |= (1 << SSPSR_TFS_BIT);
+ else
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_TFS_BIT);
+}
+
+void sa1111_device::ssp_tx_fifo_push(const uint16_t data)
+{
+ if (m_ssp_regs.tx_fifo_count < ARRAY_LENGTH(m_ssp_regs.tx_fifo))
+ {
+ m_ssp_regs.tx_fifo[m_ssp_regs.tx_fifo_write_idx] = data;
+ m_ssp_regs.tx_fifo_write_idx = (m_ssp_regs.tx_fifo_write_idx + 1) % ARRAY_LENGTH(m_ssp_regs.tx_fifo);
+ m_ssp_regs.tx_fifo_count++;
+
+ if (m_ssp_regs.tx_fifo_count != ARRAY_LENGTH(m_ssp_regs.tx_fifo))
+ m_ssp_regs.sspsr |= (1 << SSPSR_TNF_BIT);
+ else
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_TNF_BIT);
+
+ ssp_update_tx_level();
+ }
+}
+
+uint16_t sa1111_device::ssp_rx_fifo_pop()
+{
+ uint16_t data = m_ssp_regs.rx_fifo[m_ssp_regs.rx_fifo_read_idx];
+ if (m_ssp_regs.rx_fifo_count)
+ {
+ m_ssp_regs.rx_fifo_read_idx = (m_ssp_regs.rx_fifo_read_idx + 1) % ARRAY_LENGTH(m_ssp_regs.rx_fifo);
+ m_ssp_regs.rx_fifo_count--;
+
+ if (m_ssp_regs.rx_fifo_count == 0)
+ m_ssp_regs.sspsr &= ~(1 << SSPSR_RNE_BIT);
+
+ ssp_update_rx_level();
+ }
+ return data;
+}
+
+uint32_t sa1111_device::sspcr0_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SSP, "%s: sspcr0_r: SSP Control Register 0: %08x & %08x\n", machine().describe_context(), m_ssp_regs.sspcr0, mem_mask);
+ return m_ssp_regs.sspcr0;
+}
+
+uint32_t sa1111_device::sspcr1_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SSP, "%s: sspcr1_r: SSP Control Register 1: %08x & %08x\n", machine().describe_context(), m_ssp_regs.sspcr1, mem_mask);
+ return m_ssp_regs.sspcr1;
+}
+
+uint32_t sa1111_device::sspsr_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint32_t data = m_ssp_regs.sspsr;
+ LOGMASKED(LOG_SSP_HF, "%s: sspsr_r: SSP Status Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SSP_HF, "%s: Transmit FIFO Not Full: %d\n", machine().describe_context(), BIT(data, SSPSR_TNF_BIT));
+ LOGMASKED(LOG_SSP_HF, "%s: Receive FIFO Not Empty: %d\n", machine().describe_context(), BIT(data, SSPSR_RNE_BIT));
+ LOGMASKED(LOG_SSP_HF, "%s: Transmit/Receive In Progress: %d\n", machine().describe_context(), BIT(data, SSPSR_BSY_BIT));
+ LOGMASKED(LOG_SSP_HF, "%s: Transmit FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SSPSR_TFS_BIT));
+ LOGMASKED(LOG_SSP_HF, "%s: Receive FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SSPSR_RFS_BIT));
+ LOGMASKED(LOG_SSP_HF, "%s: Receive FIFO Overrun: %d\n", machine().describe_context(), BIT(data, SSPSR_ROR_BIT));
+ LOGMASKED(LOG_SSP_HF, "%s: Transmit FIFO Level: %02x\n", machine().describe_context(), (data & SSPSR_TFL_MASK) >> SSPSR_TFL_BIT);
+ LOGMASKED(LOG_SSP_HF, "%s: Receive FIFO Level: %02x\n", machine().describe_context(), (data & SSPSR_RFL_MASK) >> SSPSR_RFL_BIT);
+ return data;
+}
+
+uint32_t sa1111_device::sspdr_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint32_t data = ssp_rx_fifo_pop();
+ LOGMASKED(LOG_SSP, "%s: sspdr_r: SSP Data Read Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void sa1111_device::sspcr0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ static const char *const s_dss_sizes[16] =
+ {
+ "Invalid [1]", "Invalid [2]", "Invalid [3]", "4-bit",
+ "5-bit", "6-bit", "7-bit", "8-bit",
+ "9-bit", "10-bit", "11-bit", "12-bit",
+ "13-bit", "14-bit", "15-bit", "16-bit"
+ };
+ static const char *const s_frf_formats[4] = { "Motorola SPI", "TI Synchronous Serial", "National Microwire", "Reserved" };
+ LOGMASKED(LOG_SSP, "%s: sspcr0_w: SSP Control Register 0 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SSP, "%s: Data Size Select: %s\n", machine().describe_context(), s_dss_sizes[(data & SSPCR0_DSS_MASK) >> SSPCR0_DSS_BIT]);
+ LOGMASKED(LOG_SSP, "%s: Frame Format: %s\n", machine().describe_context(), s_frf_formats[(data & SSPCR0_FRF_MASK) >> SSPCR0_FRF_BIT]);
+ LOGMASKED(LOG_SSP, "%s: SSP Enable: %d\n", machine().describe_context(), BIT(data, SSPCR0_SSPEN_BIT));
+ LOGMASKED(LOG_SSP, "%s: Serial Clock Rate Divisor: %03x\n", machine().describe_context(), (data & SSPCR0_SCR_MASK) >> SSPCR0_SCR_BIT);
+ const uint32_t old = m_ssp_regs.sspcr0;
+ COMBINE_DATA(&m_ssp_regs.sspcr0);
+ const uint32_t changed = old ^ m_ssp_regs.sspcr0;
+ if (BIT(changed, SSPCR0_SSPEN_BIT))
+ ssp_update_enable_state();
+}
+
+void sa1111_device::sspcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SSP, "%s: sspcr1_w: SSP Control Register 1 = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SSP, "%s: Loopback Mode: %d\n", machine().describe_context(), BIT(data, SSPCR1_LBM_BIT));
+ LOGMASKED(LOG_SSP, "%s: Clock Polarity, Idle State: %s\n", machine().describe_context(), BIT(data, SSPCR1_SPO_BIT) ? "High" : "Low");
+ LOGMASKED(LOG_SSP, "%s: Clock Phase: %d\n", machine().describe_context(), BIT(data, SSPCR1_SPH_BIT));
+ LOGMASKED(LOG_SSP, "%s: Transmit FIFO Threshold: %02x\n", machine().describe_context(), (data & SSPCR1_TFT_MASK) >> SSPCR1_TFT_BIT);
+ LOGMASKED(LOG_SSP, "%s: Receive FIFO Threshold: %02x\n", machine().describe_context(), (data & SSPCR1_RFT_MASK) >> SSPCR1_RFT_BIT);
+ COMBINE_DATA(&m_ssp_regs.sspcr1);
+}
+
+void sa1111_device::sspsr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SSP, "%s: sspsr_w: SSP Status Register (ignored, all read-only flags) = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+void sa1111_device::sspitr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SSP, "%s: sspitr_w: SSP Interrupt Test Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_SSP, "%s: Transmit FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SSPITR_TFS_BIT));
+ LOGMASKED(LOG_SSP, "%s: Receive FIFO Service Request: %d\n", machine().describe_context(), BIT(data, SSPITR_RFS_BIT));
+ LOGMASKED(LOG_SSP, "%s: Receive FIFO Overrun: %d\n", machine().describe_context(), BIT(data, SSPITR_ROR_BIT));
+ COMBINE_DATA(&m_ssp_regs.sspitr);
+}
+
+void sa1111_device::sspdr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SSP, "%s: sspdr_w: SSP Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ ssp_tx_fifo_push((uint16_t)data);
+}
+
+/*
+
+ Intel SA-1111 PS/2 Trackpad and Mouse Interfaces
+
+ pg. 125 to 131 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+uint32_t sa1111_device::track_kbdcr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbdcr_r: Track Pad Control Register: %08x & %08x\n", machine().describe_context(), m_track_regs.kbdcr, mem_mask);
+ return m_track_regs.kbdcr;
+}
+
+uint32_t sa1111_device::track_kbdstat_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint32_t data = m_track_regs.kbdstat;
+ LOGMASKED(LOG_TRACK, "%s: track_kbdstat_r: Track Pad Status Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_TRACK, "%s: KBCLK Pin State: %d\n", machine().describe_context(), BIT(data, KBDSTAT_KBC_BIT));
+ LOGMASKED(LOG_TRACK, "%s: KBDATA Pin State: %d\n", machine().describe_context(), BIT(data, KBDSTAT_KBD_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Data Byte Parity Bit: %d\n", machine().describe_context(), BIT(data, KBDSTAT_RXP_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Track Pad Enabled: %d\n", machine().describe_context(), BIT(data, KBDSTAT_ENA_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Receiver Busy: %d\n", machine().describe_context(), BIT(data, KBDSTAT_RXB_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Receiver Full: %d\n", machine().describe_context(), BIT(data, KBDSTAT_RXF_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Transmitter Busy: %d\n", machine().describe_context(), BIT(data, KBDSTAT_TXB_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Transmitter Empty: %d\n", machine().describe_context(), BIT(data, KBDSTAT_TXE_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Stop Bit Error: %d\n", machine().describe_context(), BIT(data, KBDSTAT_STP_BIT));
+ return data;
+}
+
+uint32_t sa1111_device::track_kbddata_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbddata_r: Track Pad Received Data Byte: %08x & %08x\n", machine().describe_context(), m_track_regs.kbddata_rx, mem_mask);
+ return m_track_regs.kbddata_rx;
+}
+
+uint32_t sa1111_device::track_kbdclkdiv_r(offs_t offset, uint32_t mem_mask)
+{
+ static const char *const s_clkdiv_values[4] = { "8MHz", "4MHz", "2MHz", "Reserved" };
+ LOGMASKED(LOG_TRACK, "%s: track_kbdclkdiv_r: Track Pad Clock Division Register: %08x & %08x\n", machine().describe_context(), m_track_regs.kbdclkdiv, mem_mask);
+ LOGMASKED(LOG_TRACK, "%s: Incoming KbdClk: %s\n", machine().describe_context(), s_clkdiv_values[(m_track_regs.kbdclkdiv & KBDCLKDIV_DV_MASK) >> KBDCLKDIV_DV_BIT]);
+ return m_track_regs.kbdclkdiv;
+}
+
+uint32_t sa1111_device::track_kbdprecnt_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbdprecnt_r: Track Pad Clock Precount Register: %08x & %08x\n", machine().describe_context(), m_track_regs.kbdprecnt, mem_mask);
+ return m_track_regs.kbdprecnt;
+}
+
+uint32_t sa1111_device::mouse_kbdcr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbdcr_r: Mouse Control Register: %08x & %08x\n", machine().describe_context(), m_mouse_regs.kbdcr, mem_mask);
+ return m_mouse_regs.kbdcr;
+}
+
+uint32_t sa1111_device::mouse_kbdstat_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint32_t data = m_mouse_regs.kbdstat;
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbdstat_r: Mouse Status Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_MOUSE, "%s: KBCLK Pin State: %d\n", machine().describe_context(), BIT(data, KBDSTAT_KBC_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: KBDATA Pin State: %d\n", machine().describe_context(), BIT(data, KBDSTAT_KBD_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Data Byte Parity Bit: %d\n", machine().describe_context(), BIT(data, KBDSTAT_RXP_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Mouse Enabled: %d\n", machine().describe_context(), BIT(data, KBDSTAT_ENA_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Receiver Busy: %d\n", machine().describe_context(), BIT(data, KBDSTAT_RXB_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Receiver Full: %d\n", machine().describe_context(), BIT(data, KBDSTAT_RXF_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Transmitter Busy: %d\n", machine().describe_context(), BIT(data, KBDSTAT_TXB_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Transmitter Empty: %d\n", machine().describe_context(), BIT(data, KBDSTAT_TXE_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Stop Bit Error: %d\n", machine().describe_context(), BIT(data, KBDSTAT_STP_BIT));
+ return data;
+}
+
+uint32_t sa1111_device::mouse_kbddata_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbddata_r: Mouse Received Data Byte: %08x & %08x\n", machine().describe_context(), m_mouse_regs.kbddata_rx, mem_mask);
+ return m_mouse_regs.kbddata_rx;
+}
+
+uint32_t sa1111_device::mouse_kbdclkdiv_r(offs_t offset, uint32_t mem_mask)
+{
+ static const char *const s_clkdiv_values[4] = { "8MHz", "4MHz", "2MHz", "Reserved" };
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbdclkdiv_r: Mouse Clock Division Register: %08x & %08x\n", machine().describe_context(), m_mouse_regs.kbdclkdiv, mem_mask);
+ LOGMASKED(LOG_MOUSE, "%s: Incoming KbdClk: %s\n", machine().describe_context(), s_clkdiv_values[(m_mouse_regs.kbdclkdiv & KBDCLKDIV_DV_MASK) >> KBDCLKDIV_DV_BIT]);
+ return m_mouse_regs.kbdclkdiv;
+}
+
+uint32_t sa1111_device::mouse_kbdprecnt_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbdprecnt_r: Mouse Clock Precount Register: %08x & %08x\n", machine().describe_context(), m_mouse_regs.kbdprecnt, mem_mask);
+ return m_mouse_regs.kbdprecnt;
+}
+
+void sa1111_device::track_kbdcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbdcr_w: Track Pad Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_TRACK, "%s: Force TPCLK Low: %d\n", machine().describe_context(), BIT(data, KBDCR_FKC_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Force TPDATA Low: %d\n", machine().describe_context(), BIT(data, KBDCR_FKD_BIT));
+ LOGMASKED(LOG_TRACK, "%s: Enable Track Pad: %d\n", machine().describe_context(), BIT(data, KBDCR_ENA_BIT));
+ COMBINE_DATA(&m_track_regs.kbdcr);
+}
+
+void sa1111_device::track_kbdstat_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbdstat_w: Track Pad Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ m_track_regs.kbdstat &= ~(data & mem_mask & (1 << KBDSTAT_STP_BIT));
+}
+
+void sa1111_device::track_kbddata_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbddata_w: Track Pad Transmit Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_track_regs.kbddata_tx);
+}
+
+void sa1111_device::track_kbdclkdiv_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbdclkdiv_w: Track Pad Clock Division Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_track_regs.kbdclkdiv);
+}
+
+void sa1111_device::track_kbdprecnt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbdprecnt_w: Track Pad Clock Precount Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_track_regs.kbdprecnt);
+}
+
+void sa1111_device::track_kbditr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TRACK, "%s: track_kbditr_w: Track Pad Interrupt Test Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_track_regs.kbditr);
+}
+
+void sa1111_device::mouse_kbdcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbdcr_w: Mouse Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_MOUSE, "%s: Force TPCLK Low: %d\n", machine().describe_context(), BIT(data, KBDCR_FKC_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Force TPDATA Low: %d\n", machine().describe_context(), BIT(data, KBDCR_FKD_BIT));
+ LOGMASKED(LOG_MOUSE, "%s: Enable Mouse: %d\n", machine().describe_context(), BIT(data, KBDCR_ENA_BIT));
+ COMBINE_DATA(&m_mouse_regs.kbdcr);
+}
+
+void sa1111_device::mouse_kbdstat_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbdstat_w: Mouse Status Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ m_mouse_regs.kbdstat &= ~(data & mem_mask & (1 << KBDSTAT_STP_BIT));
+}
+
+void sa1111_device::mouse_kbddata_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbddata_w: Mouse Transmit Data Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_mouse_regs.kbddata_tx);
+}
+
+void sa1111_device::mouse_kbdclkdiv_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbdclkdiv_w: Mouse Clock Division Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_mouse_regs.kbdclkdiv);
+}
+
+void sa1111_device::mouse_kbdprecnt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbdprecnt_w: Mouse Clock Precount Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_mouse_regs.kbdprecnt);
+}
+
+void sa1111_device::mouse_kbditr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_MOUSE, "%s: mouse_kbditr_w: Mouse Interrupt Test Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_mouse_regs.kbditr);
+}
+
+/*
+
+ Intel SA-1111 General-Purpose I/O Interface
+
+ pg. 133 to 138 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+void sa1111_device::gpio_in(const uint32_t line, const int state)
+{
+}
+
+void sa1111_device::gpio_update_direction(const uint32_t block, const uint32_t old_dir)
+{
+}
+
+void sa1111_device::gpio_update_outputs(const uint32_t block, const uint32_t old_latch)
+{
+}
+
+template <unsigned Block>
+uint32_t sa1111_device::ddr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_GPIO, "%s: ddr_r: GPIO Block %c Data Direction: %08x & %08x\n", machine().describe_context(), 'A' + Block, m_gpio_regs.ddr[Block], mem_mask);
+ return m_gpio_regs.ddr[Block];
+}
+
+template <unsigned Block>
+uint32_t sa1111_device::drr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_GPIO, "%s: drr_r: GPIO Block %c Data Value Register: %08x & %08x\n", machine().describe_context(), 'A' + Block, m_gpio_regs.level[Block], mem_mask);
+ return m_gpio_regs.level[Block];
+}
+
+template <unsigned Block>
+uint32_t sa1111_device::sdr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_GPIO, "%s: sdr_r: GPIO Block %c Sleep Direction: %08x & %08x\n", machine().describe_context(), 'A' + Block, m_gpio_regs.sdr[Block], mem_mask);
+ return m_gpio_regs.sdr[Block];
+}
+
+template <unsigned Block>
+uint32_t sa1111_device::ssr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_GPIO, "%s: ssr_r: GPIO Block %c Sleep State: %08x & %08x\n", machine().describe_context(), 'A' + Block, m_gpio_regs.ssr[Block], mem_mask);
+ return m_gpio_regs.ssr[Block];
+}
+
+template <unsigned Block>
+void sa1111_device::ddr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_GPIO, "%s: ddr_w: GPIO Block %c Data Direction = %08x & %08x\n", machine().describe_context(), 'A' + Block, data, mem_mask);
+ const uint32_t old = m_gpio_regs.ddr[Block];
+ COMBINE_DATA(&m_gpio_regs.ddr[Block]);
+ if (old != m_gpio_regs.ddr[Block])
+ gpio_update_direction(Block, old);
+}
+
+template <unsigned Block>
+void sa1111_device::dwr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_GPIO, "%s: dwr_w: GPIO Block %c Data Value Register = %08x & %08x\n", machine().describe_context(), 'A' + Block, data, mem_mask);
+ const uint32_t old = m_gpio_regs.out_latch[Block];
+ COMBINE_DATA(&m_gpio_regs.out_latch[Block]);
+ if (old != m_gpio_regs.out_latch[Block])
+ gpio_update_outputs(Block, old);
+}
+
+template <unsigned Block>
+void sa1111_device::sdr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_GPIO, "%s: sdr_w: GPIO Block %c Sleep Direction = %08x & %08x\n", machine().describe_context(), 'A' + Block, data, mem_mask);
+ COMBINE_DATA(&m_gpio_regs.sdr[Block]);
+}
+
+template <unsigned Block>
+void sa1111_device::ssr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_GPIO, "%s: ssr_w: GPIO Block %c Sleep State = %08x & %08x\n", machine().describe_context(), 'A' + Block, data, mem_mask);
+ COMBINE_DATA(&m_gpio_regs.ssr[0]);
+}
+
+/*
+
+ Intel SA-1111 Interrupt Controller
+
+ pg. 139 to 146 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+template <unsigned Set>
+uint32_t sa1111_device::inttest_r(offs_t offset, uint32_t mem_mask)
+{
+ if (Set == 0)
+ {
+ const uint32_t any_interrupts = ((m_intc_regs.inttest[0] | m_intc_regs.inttest[1]) != 0) ? 1 : 0;
+ LOGMASKED(LOG_INTC, "%s: inttest_r: Interrupt Test Register %d: %08x & %08x\n", machine().describe_context(), Set, any_interrupts, mem_mask);
+ return any_interrupts;
+ }
+ else
+ {
+ LOGMASKED(LOG_INTC, "%s: inttest_r: Interrupt Test Register %d: %08x & %08x\n", machine().describe_context(), Set, 0, mem_mask);
+ return 0;
+ }
+}
+
+template <unsigned Set>
+uint32_t sa1111_device::inten_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: inten_r: Interrupt Enable Register %d: %08x & %08x\n", machine().describe_context(), Set, m_intc_regs.inten[Set], mem_mask);
+ return m_intc_regs.inten[Set];
+}
+
+template <unsigned Set>
+uint32_t sa1111_device::intpol_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: intpol_r: Interrupt Polarity Register %d: %08x & %08x\n", machine().describe_context(), Set, m_intc_regs.intpol[Set], mem_mask);
+ return m_intc_regs.intpol[Set];
+}
+
+uint32_t sa1111_device::inttstsel_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: inttstsel_r: Interrupt Test Mode Select Register: %08x & %08x\n", machine().describe_context(), m_intc_regs.inttstsel, mem_mask);
+ return m_intc_regs.inttstsel;
+}
+
+template <unsigned Set>
+uint32_t sa1111_device::intstat_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: intstat_r: Interrupt Status Register %d: %08x & %08x\n", machine().describe_context(), Set, m_intc_regs.intstat[Set], mem_mask);
+ return m_intc_regs.intstat[Set];
+}
+
+template <unsigned Set>
+uint32_t sa1111_device::wake_en_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: wake_en_r: Interrupt Wake-Up Enable Register %d: %08x & %08x\n", machine().describe_context(), Set, m_intc_regs.wake_en[Set], mem_mask);
+ return m_intc_regs.wake_en[Set];
+}
+
+template <unsigned Set>
+uint32_t sa1111_device::wake_pol_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: wake_pol_r: Interrupt Wake-Up Polarity Register %d: %08x & %08x\n", machine().describe_context(), Set, m_intc_regs.wake_pol[Set], mem_mask);
+ return m_intc_regs.wake_pol[Set];
+}
+
+template <unsigned Set>
+void sa1111_device::inttest_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: inttest_w: Interrupt Test Register %d = %08x & %08x\n", machine().describe_context(), Set, data, mem_mask);
+ COMBINE_DATA(&m_intc_regs.inttest[Set]);
+}
+
+template <unsigned Set>
+void sa1111_device::inten_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: inten_w: Interrupt Enable Register %d = %08x & %08x\n", machine().describe_context(), Set, data, mem_mask);
+ COMBINE_DATA(&m_intc_regs.inten[Set]);
+}
+
+template <unsigned Set>
+void sa1111_device::intpol_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: intc_w: Interrupt Polarity Register %d = %08x & %08x\n", machine().describe_context(), Set, data, mem_mask);
+ COMBINE_DATA(&m_intc_regs.intpol[Set]);
+}
+
+void sa1111_device::inttstsel_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: inttestsel_w: Interrupt Test Mode Select Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_intc_regs.inttstsel);
+}
+
+template <unsigned Set>
+void sa1111_device::intclr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: intc_w: Interrupt Clear Register %d = %08x & %08x\n", machine().describe_context(), Set, data, mem_mask);
+ m_intc_regs.intstat[Set] &= ~(data & mem_mask);
+}
+
+template <unsigned Set>
+void sa1111_device::intset_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: intset_w: Interrupt Set Register %d = %08x & %08x\n", machine().describe_context(), Set, data, mem_mask);
+ m_intc_regs.intstat[Set] |= (data & mem_mask);
+}
+
+template <unsigned Set>
+void sa1111_device::wake_en_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: wake_en_w: Interrupt Wake-Up Enable Register %d = %08x & %08x\n", machine().describe_context(), Set, data, mem_mask);
+ COMBINE_DATA(&m_intc_regs.wake_en[Set]);
+}
+
+template <unsigned Set>
+void sa1111_device::wake_pol_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_INTC, "%s: wake_pol_w: Interrupt Wake-Up Polarity Register %d = %08x & %08x\n", machine().describe_context(), Set, data, mem_mask);
+ COMBINE_DATA(&m_intc_regs.wake_pol[Set]);
+}
+
+/*
+
+ Intel SA-1111 PCMCIA Interface
+
+ pg. 147 to 160 Intel StrongARM SA-1111 Microprocessor Companion Chip Developer's Manual
+
+*/
+
+uint32_t sa1111_device::pccr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_CARD, "%s: pccr_r: PCMCIA Control Register: %08x & %08x\n", machine().describe_context(), m_card_regs.pccr, mem_mask);
+ return m_card_regs.pccr;
+}
+
+uint32_t sa1111_device::pcssr_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_CARD, "%s: pcssr_r: PCMCIA Sleep State Register: %08x & %08x\n", machine().describe_context(), m_card_regs.pcssr, mem_mask);
+ return m_card_regs.pcssr;
+}
+
+uint32_t sa1111_device::pcsr_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint32_t data = m_card_regs.pcsr;
+ LOGMASKED(LOG_CARD, "%s: pcsr_r: PCMCIA Status Register: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_CARD, "%s: Socket 0 Ready: %d\n", machine().describe_context(), BIT(data, PCSR_S0R_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 Ready: %d\n", machine().describe_context(), BIT(data, PCSR_S1R_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 0 Card Detect: %d\n", machine().describe_context(), BIT(data, PCSR_S0CD_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 Card Detect: %d\n", machine().describe_context(), BIT(data, PCSR_S1CD_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 0 Voltage Sense 1: %d\n", machine().describe_context(), BIT(data, PCSR_S0VS1_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 0 Voltage Sense 2: %d\n", machine().describe_context(), BIT(data, PCSR_S0VS2_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 Voltage Sense 1: %d\n", machine().describe_context(), BIT(data, PCSR_S1VS1_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 Voltage Sense 2: %d\n", machine().describe_context(), BIT(data, PCSR_S1VS2_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 0 Write Protect: %d\n", machine().describe_context(), BIT(data, PCSR_S0WP_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 Write Protect: %d\n", machine().describe_context(), BIT(data, PCSR_S1WP_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 0 BVD1: %d\n", machine().describe_context(), BIT(data, PCSR_S0BVD1_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 0 BVD2: %d\n", machine().describe_context(), BIT(data, PCSR_S0BVD2_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 BVD1: %d\n", machine().describe_context(), BIT(data, PCSR_S1BVD1_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 BVD2: %d\n", machine().describe_context(), BIT(data, PCSR_S1BVD2_BIT));
+ return data;
+}
+
+void sa1111_device::pccr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_CARD, "%s: pccr_w: PCMCIA Control Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_CARD, "%s: Socket 0 Reset: %d\n", machine().describe_context(), BIT(data, PCCR_S0RST_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 Reset: %d\n", machine().describe_context(), BIT(data, PCCR_S1RST_BIT));
+ LOGMASKED(LOG_CARD, "%s: Set Socket 0 Floating: %d\n", machine().describe_context(), BIT(data, PCCR_S0FLT_BIT));
+ LOGMASKED(LOG_CARD, "%s: Set Socket 1 Floating: %d\n", machine().describe_context(), BIT(data, PCCR_S1FLT_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 0 PWAIT Enable: %d\n", machine().describe_context(), BIT(data, PCCR_S0PWEN_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 PWAIT Enable: %d\n", machine().describe_context(), BIT(data, PCCR_S1PWEN_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 0 Power Mode: %s\n", machine().describe_context(), BIT(data, PCCR_S0PSE_BIT) ? "5V" : "3V");
+ LOGMASKED(LOG_CARD, "%s: Socket 1 Power Mode: %s\n", machine().describe_context(), BIT(data, PCCR_S1PSE_BIT) ? "5V" : "3V");
+ COMBINE_DATA(&m_card_regs.pccr);
+}
+
+void sa1111_device::pcssr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_CARD, "%s: pcssr_w: PCMCIA Sleep State Register = %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_CARD, "%s: Socket 0 Sleep Mode: %d\n", machine().describe_context(), BIT(data, PCSSR_S0SLP_BIT));
+ LOGMASKED(LOG_CARD, "%s: Socket 1 Sleep Mode: %d\n", machine().describe_context(), BIT(data, PCSSR_S1SLP_BIT));
+ COMBINE_DATA(&m_card_regs.pcssr);
+}
+
+void sa1111_device::device_start()
+{
+ save_item(NAME(m_sbi_regs.skcr));
+ save_item(NAME(m_sbi_regs.smcr));
+ save_item(NAME(m_sbi_regs.skid));
+
+ save_item(NAME(m_sk_regs.skpcr));
+ save_item(NAME(m_sk_regs.skcdr));
+ save_item(NAME(m_sk_regs.skaud));
+ save_item(NAME(m_sk_regs.skpmc));
+ save_item(NAME(m_sk_regs.skptc));
+ save_item(NAME(m_sk_regs.skpen0));
+ save_item(NAME(m_sk_regs.skpwm0));
+ save_item(NAME(m_sk_regs.skpen1));
+ save_item(NAME(m_sk_regs.skpwm1));
+
+ save_item(NAME(m_usb_regs.ohci));
+ save_item(NAME(m_usb_regs.status));
+ save_item(NAME(m_usb_regs.reset));
+ save_item(NAME(m_usb_regs.int_test));
+ save_item(NAME(m_usb_regs.fifo));
+
+ save_item(NAME(m_audio_regs.sacr0));
+ save_item(NAME(m_audio_regs.sacr1));
+ save_item(NAME(m_audio_regs.sacr2));
+ save_item(NAME(m_audio_regs.sasr0));
+ save_item(NAME(m_audio_regs.sasr1));
+ save_item(NAME(m_audio_regs.l3car));
+ save_item(NAME(m_audio_regs.l3cdr));
+ save_item(NAME(m_audio_regs.accar));
+ save_item(NAME(m_audio_regs.accdr));
+ save_item(NAME(m_audio_regs.acsar));
+ save_item(NAME(m_audio_regs.acsdr));
+ save_item(NAME(m_audio_regs.sadtcs));
+ save_item(NAME(m_audio_regs.sadtsa));
+ save_item(NAME(m_audio_regs.sadtca));
+ save_item(NAME(m_audio_regs.sadtsb));
+ save_item(NAME(m_audio_regs.sadtcb));
+ save_item(NAME(m_audio_regs.sadrcs));
+ save_item(NAME(m_audio_regs.sadrsa));
+ save_item(NAME(m_audio_regs.sadrca));
+ save_item(NAME(m_audio_regs.sadrsb));
+ save_item(NAME(m_audio_regs.sadrcb));
+ save_item(NAME(m_audio_regs.saitr));
+ save_item(NAME(m_audio_regs.rx_fifo));
+ save_item(NAME(m_audio_regs.rx_fifo_read_idx));
+ save_item(NAME(m_audio_regs.rx_fifo_write_idx));
+ save_item(NAME(m_audio_regs.rx_fifo_count));
+ save_item(NAME(m_audio_regs.tx_fifo));
+ save_item(NAME(m_audio_regs.tx_fifo_read_idx));
+ save_item(NAME(m_audio_regs.tx_fifo_write_idx));
+ save_item(NAME(m_audio_regs.tx_fifo_count));
+
+ save_item(NAME(m_ssp_regs.sspcr0));
+ save_item(NAME(m_ssp_regs.sspcr1));
+ save_item(NAME(m_ssp_regs.sspsr));
+ save_item(NAME(m_ssp_regs.sspitr));
+ save_item(NAME(m_ssp_regs.rx_fifo));
+ save_item(NAME(m_ssp_regs.rx_fifo_read_idx));
+ save_item(NAME(m_ssp_regs.rx_fifo_write_idx));
+ save_item(NAME(m_ssp_regs.rx_fifo_count));
+ save_item(NAME(m_ssp_regs.tx_fifo));
+ save_item(NAME(m_ssp_regs.tx_fifo_read_idx));
+ save_item(NAME(m_ssp_regs.tx_fifo_write_idx));
+ save_item(NAME(m_ssp_regs.tx_fifo_count));
+
+ save_item(NAME(m_track_regs.kbdcr));
+ save_item(NAME(m_track_regs.kbdstat));
+ save_item(NAME(m_track_regs.kbddata_tx));
+ save_item(NAME(m_track_regs.kbddata_rx));
+ save_item(NAME(m_track_regs.kbdclkdiv));
+ save_item(NAME(m_track_regs.kbdprecnt));
+ save_item(NAME(m_track_regs.kbditr));
+
+ save_item(NAME(m_mouse_regs.kbdcr));
+ save_item(NAME(m_mouse_regs.kbdstat));
+ save_item(NAME(m_mouse_regs.kbddata_tx));
+ save_item(NAME(m_mouse_regs.kbddata_rx));
+ save_item(NAME(m_mouse_regs.kbdclkdiv));
+ save_item(NAME(m_mouse_regs.kbdprecnt));
+ save_item(NAME(m_mouse_regs.kbditr));
+
+ save_item(NAME(m_gpio_regs.ddr));
+ save_item(NAME(m_gpio_regs.level));
+ save_item(NAME(m_gpio_regs.sdr));
+ save_item(NAME(m_gpio_regs.ssr));
+ save_item(NAME(m_gpio_regs.out_latch));
+ save_item(NAME(m_gpio_regs.in_latch));
+
+ save_item(NAME(m_intc_regs.inttest));
+ save_item(NAME(m_intc_regs.inten));
+ save_item(NAME(m_intc_regs.intpol));
+ save_item(NAME(m_intc_regs.inttstsel));
+ save_item(NAME(m_intc_regs.intstat));
+ save_item(NAME(m_intc_regs.wake_en));
+ save_item(NAME(m_intc_regs.wake_pol));
+
+ save_item(NAME(m_card_regs.pccr));
+ save_item(NAME(m_card_regs.pcssr));
+ save_item(NAME(m_card_regs.pcsr));
+
+ m_audio_regs.rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1111_device::audio_rx_callback), this));
+ m_audio_regs.tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1111_device::audio_tx_callback), this));
+
+ m_ssp_regs.rx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1111_device::ssp_rx_callback), this));
+ m_ssp_regs.tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sa1111_device::ssp_tx_callback), this));
+
+ m_gpio_out.resolve_all_safe();
+ m_ssp_out.resolve_safe();
+}
+
+void sa1111_device::device_reset()
+{
+ m_sbi_regs.skcr = (1 << SKCR_RDY_BIT);
+ m_sbi_regs.smcr = (1 << SMCR_CLAT_BIT) | (5 << SMCR_DRAC_BIT) | (1 << SMCR_DTIM_BIT);
+ m_sbi_regs.skid = 0x690cc211;
+
+ m_sk_regs.skpcr = 0;
+ m_sk_regs.skcdr = (0x4c << SKCDR_FBD_BIT);
+ m_sk_regs.skaud = (0x18 << SKAUD_ACD_BIT);
+ m_sk_regs.skpmc = (0x11 << SKPMC_PMCD_BIT);
+ m_sk_regs.skptc = (0x11 << SKPTC_PTCD_BIT);
+ m_sk_regs.skpen0 = 0;
+ m_sk_regs.skpwm0 = 0;
+ m_sk_regs.skpen1 = 0;
+ m_sk_regs.skpwm1 = 0;
+
+ memset(m_usb_regs.ohci, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_usb_regs.ohci));
+ m_usb_regs.status = 0;
+ m_usb_regs.reset = (1 << USBRST_FHR_BIT) | (1 << USBRST_FIR_BIT);
+ m_usb_regs.int_test = 0;
+ memset(m_usb_regs.fifo, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_usb_regs.fifo));
+
+ m_audio_regs.sacr0 = (0x7 << SACR0_RFTH_BIT) | (0x7 << SACR0_TFTH_BIT);
+ m_audio_regs.sacr1 = 0;
+ m_audio_regs.sacr2 = 0;
+ m_audio_regs.sasr0 = 0;
+ m_audio_regs.sasr1 = 0;
+ m_audio_regs.l3car = 0;
+ m_audio_regs.l3cdr = 0;
+ m_audio_regs.accar = 0;
+ m_audio_regs.accdr = 0;
+ m_audio_regs.acsar = 0;
+ m_audio_regs.acsdr = 0;
+ m_audio_regs.sadtcs = 0;
+ m_audio_regs.sadtsa = 0;
+ m_audio_regs.sadtca = 0;
+ m_audio_regs.sadtsb = 0;
+ m_audio_regs.sadtcb = 0;
+ m_audio_regs.sadrcs = 0;
+ m_audio_regs.sadrsa = 0;
+ m_audio_regs.sadrca = 0;
+ m_audio_regs.sadrsb = 0;
+ m_audio_regs.sadrcb = 0;
+ m_audio_regs.saitr = 0;
+ memset(m_audio_regs.rx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_audio_regs.rx_fifo));
+ m_audio_regs.rx_fifo_read_idx = 0;
+ m_audio_regs.rx_fifo_write_idx = 0;
+ m_audio_regs.rx_fifo_count = 0;
+ m_audio_regs.rx_timer->adjust(attotime::never);
+ memset(m_audio_regs.tx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_audio_regs.tx_fifo));
+ m_audio_regs.tx_fifo_read_idx = 0;
+ m_audio_regs.tx_fifo_write_idx = 0;
+ m_audio_regs.tx_fifo_count = 0;
+ m_audio_regs.tx_timer->adjust(attotime::never);
+
+ m_ssp_regs.sspcr0 = 0;
+ m_ssp_regs.sspcr1 = (0x7 << SSPCR1_RFT_BIT) | (0x7 << SSPCR1_TFT_BIT);
+ m_ssp_regs.sspsr = 0;
+ m_ssp_regs.sspitr = 0;
+ memset(m_ssp_regs.rx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_ssp_regs.rx_fifo));
+ m_ssp_regs.rx_fifo_read_idx = 0;
+ m_ssp_regs.rx_fifo_write_idx = 0;
+ m_ssp_regs.rx_fifo_count = 0;
+ m_ssp_regs.rx_timer->adjust(attotime::never);
+ memset(m_ssp_regs.tx_fifo, 0, sizeof(uint16_t) * ARRAY_LENGTH(m_ssp_regs.tx_fifo));
+ m_ssp_regs.tx_fifo_read_idx = 0;
+ m_ssp_regs.tx_fifo_write_idx = 0;
+ m_ssp_regs.tx_fifo_count = 0;
+ m_ssp_regs.tx_timer->adjust(attotime::never);
+
+ memset(&m_track_regs, 0, sizeof(ps2_regs));
+ memset(&m_mouse_regs, 0, sizeof(ps2_regs));
+
+ memset(m_gpio_regs.ddr, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_gpio_regs.ddr));
+ memset(m_gpio_regs.level, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_gpio_regs.level));
+ memset(m_gpio_regs.sdr, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_gpio_regs.sdr));
+ memset(m_gpio_regs.ssr, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_gpio_regs.ssr));
+ memset(m_gpio_regs.out_latch, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_gpio_regs.out_latch));
+ memset(m_gpio_regs.in_latch, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_gpio_regs.in_latch));
+
+ memset(m_intc_regs.inttest, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_intc_regs.inttest));
+ memset(m_intc_regs.inten, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_intc_regs.inten));
+ memset(m_intc_regs.intpol, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_intc_regs.intpol));
+ m_intc_regs.inttstsel = 0;
+ memset(m_intc_regs.intstat, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_intc_regs.intstat));
+ memset(m_intc_regs.wake_en, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_intc_regs.wake_en));
+ memset(m_intc_regs.wake_pol, 0, sizeof(uint32_t) * ARRAY_LENGTH(m_intc_regs.wake_pol));
+
+ m_card_regs.pccr = 0;
+ m_card_regs.pcssr = 0;
+ m_card_regs.pcsr = 0x0000000f;
+}
+
+void sa1111_device::device_add_mconfig(machine_config &config)
+{
+}
diff --git a/src/devices/machine/sa1111.h b/src/devices/machine/sa1111.h
new file mode 100644
index 00000000000..dc3d04d760a
--- /dev/null
+++ b/src/devices/machine/sa1111.h
@@ -0,0 +1,591 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/***************************************************************************
+
+ Intel SA1111 Microprocessor Companion Chip skeleton
+
+***************************************************************************/
+
+#ifndef MAME_MACHINE_SA1111
+#define MAME_MACHINE_SA1111
+
+#pragma once
+
+#include "machine/input_merger.h"
+
+class sa1111_device : public device_t
+{
+public:
+ sa1111_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ template <unsigned Line> void pa_in(int state) { gpio_in(0 + Line, state); }
+ template <unsigned Line> void pb_in(int state) { gpio_in(8 + Line, state); }
+ template <unsigned Line> void pc_in(int state) { gpio_in(16 + Line, state); }
+ template <unsigned Line> auto pa_out() { return m_gpio_out[0 + Line].bind(); }
+ template <unsigned Line> auto pb_out() { return m_gpio_out[8 + Line].bind(); }
+ template <unsigned Line> auto pc_out() { return m_gpio_out[16 + Line].bind(); }
+
+ void ssp_in(uint16_t data) { ssp_rx_fifo_push(data); }
+ auto ssp_out() { return m_ssp_out.bind(); }
+
+ void map(address_map &map);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ TIMER_CALLBACK_MEMBER(ssp_rx_callback);
+ TIMER_CALLBACK_MEMBER(ssp_tx_callback);
+
+ TIMER_CALLBACK_MEMBER(audio_rx_callback);
+ TIMER_CALLBACK_MEMBER(audio_tx_callback);
+
+ uint32_t unknown_r(offs_t offset, uint32_t mem_mask);
+ void unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t skcr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t smcr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skid_r(offs_t offset, uint32_t mem_mask);
+ void skcr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void smcr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t skpcr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skcdr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skaud_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skpmc_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skptc_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skpen0_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skpwm0_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skpen1_r(offs_t offset, uint32_t mem_mask);
+ uint32_t skpwm1_r(offs_t offset, uint32_t mem_mask);
+ void skpcr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void skcdr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void skaud_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void skpmc_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void skptc_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void skpen0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void skpwm0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void skpen1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void skpwm1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t ohci_r(offs_t offset, uint32_t mem_mask);
+ uint32_t usb_status_r(offs_t offset, uint32_t mem_mask);
+ uint32_t usb_reset_r(offs_t offset, uint32_t mem_mask);
+ uint32_t usb_fifo_r(offs_t offset, uint32_t mem_mask);
+ void ohci_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void usb_reset_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void usb_int_test_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t sacr0_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sacr1_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sacr2_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sasr0_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sasr1_r(offs_t offset, uint32_t mem_mask);
+ uint32_t l3car_r(offs_t offset, uint32_t mem_mask);
+ uint32_t l3cdr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t accar_r(offs_t offset, uint32_t mem_mask);
+ uint32_t accdr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t acsar_r(offs_t offset, uint32_t mem_mask);
+ uint32_t acsdr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadtcs_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadtsa_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadtca_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadtsb_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadtcb_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadrcs_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadrsa_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadrca_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadrsb_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadrcb_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sadr_r(offs_t offset, uint32_t mem_mask);
+ void sacr0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sacr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sacr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sascr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void l3car_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void l3cdr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void accar_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void accdr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void acsar_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void acsdr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadtcs_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadtsa_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadtca_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadtsb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadtcb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadrcs_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadrsa_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadrca_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadrsb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadrcb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void saitr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sadr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t sspcr0_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sspcr1_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sspsr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t sspdr_r(offs_t offset, uint32_t mem_mask);
+ void sspcr0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sspcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sspsr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sspitr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void sspdr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t track_kbdcr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t track_kbdstat_r(offs_t offset, uint32_t mem_mask);
+ uint32_t track_kbddata_r(offs_t offset, uint32_t mem_mask);
+ uint32_t track_kbdclkdiv_r(offs_t offset, uint32_t mem_mask);
+ uint32_t track_kbdprecnt_r(offs_t offset, uint32_t mem_mask);
+ void track_kbdcr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void track_kbdstat_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void track_kbddata_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void track_kbdclkdiv_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void track_kbdprecnt_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void track_kbditr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t mouse_kbdcr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t mouse_kbdstat_r(offs_t offset, uint32_t mem_mask);
+ uint32_t mouse_kbddata_r(offs_t offset, uint32_t mem_mask);
+ uint32_t mouse_kbdclkdiv_r(offs_t offset, uint32_t mem_mask);
+ uint32_t mouse_kbdprecnt_r(offs_t offset, uint32_t mem_mask);
+ void mouse_kbdcr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void mouse_kbdstat_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void mouse_kbddata_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void mouse_kbdclkdiv_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void mouse_kbdprecnt_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void mouse_kbditr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ template <unsigned Block> uint32_t ddr_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Block> uint32_t drr_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Block> uint32_t sdr_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Block> uint32_t ssr_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Block> void ddr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Block> void dwr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Block> void sdr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Block> void ssr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ template <unsigned Set> uint32_t inttest_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Set> uint32_t inten_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Set> uint32_t intpol_r(offs_t offset, uint32_t mem_mask);
+ uint32_t inttstsel_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Set> uint32_t intstat_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Set> uint32_t wake_en_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Set> uint32_t wake_pol_r(offs_t offset, uint32_t mem_mask);
+ template <unsigned Set> void inttest_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Set> void inten_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Set> void intpol_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void inttstsel_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Set> void intclr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Set> void intset_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Set> void wake_en_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ template <unsigned Set> void wake_pol_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t pccr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pcssr_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pcsr_r(offs_t offset, uint32_t mem_mask);
+ void pccr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void pcssr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ void ssp_update_enable_state();
+ void ssp_update_rx_level();
+ void ssp_update_tx_level();
+ void ssp_rx_fifo_push(const uint16_t data);
+ void ssp_tx_fifo_push(const uint16_t data);
+ uint16_t ssp_rx_fifo_pop();
+
+ void gpio_in(const uint32_t line, const int state);
+ void gpio_update_direction(const uint32_t block, const uint32_t old_dir);
+ void gpio_update_outputs(const uint32_t block, const uint32_t old_latch);
+
+ // register contents
+ enum : uint32_t
+ {
+ SKCR_PLLB_BIT = 0,
+ SKCR_RCLK_BIT = 1,
+ SKCR_SLEEP_BIT = 2,
+ SKCR_DOZE_BIT = 3,
+ SKCR_VCO_BIT = 4,
+ SKCR_SCANTST_BIT = 5,
+ SKCR_CLKTST_BIT = 6,
+ SKCR_RDY_BIT = 7,
+ SKCR_SLAC_BIT = 8,
+ SKCR_OPPC_BIT = 9,
+ SKCR_PII_BIT = 10,
+ SKCR_UIOTEN_BIT = 11,
+ SKCR_OEEN_BIT = 12,
+
+ SMCR_DTIM_BIT = 0,
+ SMCR_MBGE_BIT = 1,
+ SMCR_DRAC_BIT = 2,
+ SMCR_DRAC_MASK = 0x0000001c,
+ SMCR_CLAT_BIT = 5,
+
+ SKPCR_UCLKE_BIT = 0,
+ SKPCR_ACCLKE_BIT = 1,
+ SKPCR_ISCLKE_BIT = 2,
+ SKPCR_L3CLKE_BIT = 3,
+ SKPCR_SCLKE_BIT = 4,
+ SKPCR_PMCLKE_BIT = 5,
+ SKPCR_PTCLKE_BIT = 6,
+ SKPCR_DCLKE_BIT = 7,
+ SKPCR_PWMCLKE_BIT = 8,
+
+ SKCDR_FBD_BIT = 0,
+ SKCDR_FBD_MASK = 0x0000007f,
+ SKCDR_IPD_BIT = 7,
+ SKCDR_IPD_MASK = 0x00000f80,
+ SKCDR_OPD_BIT = 12,
+ SKCDR_OPD_MASK = 0x00003000,
+ SKCDR_OPS_BIT = 14,
+
+ SKAUD_ACD_BIT = 0,
+ SKAUD_ACD_MASK = 0x0000007f,
+
+ SKPMC_PMCD_BIT = 0,
+ SKPMC_PMCD_MASK = 0x000000ff,
+
+ SKPTC_PTCD_BIT = 0,
+ SKPTC_PTCD_MASK = 0x000000ff,
+
+ SKPEN0_PWM0EN_BIT = 0,
+
+ SKPWM0_PWM0CK_BIT = 0,
+ SKPWM0_PWM0CK_MASK = 0x000000ff,
+
+ SKPEN1_PWM1EN_BIT = 0,
+
+ SKPWM1_PWM1CK_BIT = 0,
+ SKPWM1_PWM1CK_MASK = 0x000000ff,
+
+ USBSTAT_IHRW_BIT = 7,
+ USBSTAT_IHBA_BIT = 8,
+ USBSTAT_NHT_BIT = 9,
+ USBSTAT_NHFCT_BIT = 10,
+ USBSTAT_UPRT_BIT = 11,
+
+ USBRST_FIR_BIT = 0,
+ USBRST_FHR_BIT = 1,
+ USBRST_CGR_BIT = 2,
+ USBRST_SSDC_BIT = 3,
+ USBRST_UIT_BIT = 4,
+ USBRST_SSE_BIT = 5,
+ USBRST_PSPL_BIT = 6,
+ USBRST_PCPL_BIT = 7,
+
+ USBINT_IHRWT_BIT = 7,
+ USBINT_IHBAT_BIT = 8,
+ USBINT_NHT_BIT = 9,
+ USBINT_NHFCT_BIT = 10,
+ USBINT_UPRT_BIT = 11,
+
+ SACR0_ENB_BIT = 0,
+ SACR0_BCKD_BIT = 2,
+ SACR0_RST_BIT = 3,
+ SACR0_TFTH_BIT = 8,
+ SACR0_TFTH_MASK = 0x00000f00,
+ SACR0_RFTH_BIT = 12,
+ SACR0_RFTH_MASK = 0x0000f000,
+
+ SACR1_AMSL_BIT = 0,
+ SACR1_L3EN_BIT = 1,
+ SACR1_L3MB_BIT = 2,
+ SACR1_DREC_BIT = 3,
+ SACR1_DRPL_BIT = 4,
+ SACR1_ENLBF_BIT = 5,
+
+ SACR2_TS3V_BIT = 0,
+ SACR2_TS4V_BIT = 1,
+ SACR2_WKUP_BIT = 2,
+ SACR2_DREC_BIT = 3,
+ SACR2_DRPL_BIT = 4,
+ SACR2_ENLBF_BIT = 5,
+ SACR2_RESET_BIT = 6,
+
+ SASCR_TUR_BIT = 5,
+ SASCR_ROR_BIT = 6,
+ SASCR_DTS_BIT = 16,
+ SASCR_RDD_BIT = 17,
+ SASCR_STO_BIT = 18,
+
+ SASR0_TNF_BIT = 0,
+ SASR0_RNE_BIT = 1,
+ SASR0_BSY_BIT = 2,
+ SASR0_TFS_BIT = 3,
+ SASR0_RFS_BIT = 4,
+ SASR0_TUR_BIT = 5,
+ SASR0_ROR_BIT = 6,
+ SASR0_TFL_BIT = 7,
+ SASR0_TFL_MASK = 0x00000f00,
+ SASR0_RFL_BIT = 12,
+ SASR0_RFL_MASK = 0x0000f000,
+ SASR0_L3WD_BIT = 16,
+ SASR0_L3RD_BIT = 17,
+
+ SASR1_TNF_BIT = 0,
+ SASR1_RNE_BIT = 1,
+ SASR1_BSY_BIT = 2,
+ SASR1_TFS_BIT = 3,
+ SASR1_RFS_BIT = 4,
+ SASR1_TUR_BIT = 5,
+ SASR1_ROR_BIT = 6,
+ SASR1_TFL_BIT = 8,
+ SASR1_TFL_MASK = 0x00000f00,
+ SASR1_RFL_BIT = 12,
+ SASR1_RFL_MASK = 0x0000f000,
+ SASR1_CADT_BIT = 16,
+ SASR1_SADR_BIT = 17,
+ SASR1_RSTO_BIT = 18,
+ SASR1_CLPM_BIT = 19,
+ SASR1_CRDY_BIT = 20,
+ SASR1_RS3V_BIT = 21,
+ SASR1_RS4V_BIT = 22,
+
+ SADTCS_TDEN_BIT = 0,
+ SADTCS_TDBDA_BIT = 3,
+ SADTCS_TDSTA_BIT = 4,
+ SADTCS_TDBDB_BIT = 5,
+ SADTCS_TDSTB_BIT = 6,
+
+ SADRCS_RDEN_BIT = 0,
+ SADRCS_RDBDA_BIT = 3,
+ SADRCS_RDSTA_BIT = 4,
+ SADRCS_RDBDB_BIT = 5,
+ SADRCS_RDSTB_BIT = 6,
+
+ SAITR_TFS_BIT = 0,
+ SAITR_RFS_BIT = 1,
+ SAITR_TUR_BIT = 2,
+ SAITR_ROR_BIT = 3,
+ SAITR_CADT_BIT = 4,
+ SAITR_SADR_BIT = 5,
+ SAITR_RSTO_BIT = 6,
+ SAITR_TDBDA_BIT = 8,
+ SAITR_TDBDB_BIT = 9,
+ SAITR_RDBDA_BIT = 10,
+ SAITR_RDBDB_BIT = 11,
+
+ SSPCR0_DSS_BIT = 0,
+ SSPCR0_DSS_MASK = 0x0000000f,
+ SSPCR0_FRF_BIT = 4,
+ SSPCR0_FRF_MASK = 0x00000030,
+ SSPCR0_FRF_SPI = 0,
+ SSPCR0_FRF_SSP = 1,
+ SSPCR0_FRF_MWIRE = 2,
+ SSPCR0_FRF_RESV = 3,
+ SSPCR0_SSPEN_BIT = 7,
+ SSPCR0_SCR_BIT = 8,
+ SSPCR0_SCR_MASK = 0x0000ff00,
+
+ SSPCR1_LBM_BIT = 2,
+ SSPCR1_SPO_BIT = 3,
+ SSPCR1_SPH_BIT = 4,
+ SSPCR1_TFT_BIT = 7,
+ SSPCR1_TFT_MASK = 0x00000780,
+ SSPCR1_RFT_BIT = 11,
+ SSPCR1_RFT_MASK = 0x00007800,
+
+ SSPSR_TNF_BIT = 2,
+ SSPSR_RNE_BIT = 3,
+ SSPSR_BSY_BIT = 4,
+ SSPSR_TFS_BIT = 5,
+ SSPSR_RFS_BIT = 6,
+ SSPSR_ROR_BIT = 7,
+ SSPSR_TFL_BIT = 8,
+ SSPSR_TFL_MASK = 0x00000f00,
+ SSPSR_RFL_BIT = 12,
+ SSPSR_RFL_MASK = 0x0000f000,
+
+ SSPITR_TFS_BIT = 2,
+ SSPITR_RFS_BIT = 3,
+ SSPITR_ROR_BIT = 4,
+
+ KBDCR_FKC_BIT = 0,
+ KBDCR_FKD_BIT = 1,
+ KBDCR_ENA_BIT = 3,
+
+ KBDSTAT_KBC_BIT = 0,
+ KBDSTAT_KBD_BIT = 1,
+ KBDSTAT_RXP_BIT = 2,
+ KBDSTAT_ENA_BIT = 3,
+ KBDSTAT_RXB_BIT = 4,
+ KBDSTAT_RXF_BIT = 5,
+ KBDSTAT_TXB_BIT = 6,
+ KBDSTAT_TXE_BIT = 7,
+ KBDSTAT_STP_BIT = 8,
+
+ KBDCLKDIV_DV_BIT = 0,
+ KBDCLKDIV_DV_MASK = 0x00000003,
+
+ PCSR_S0R_BIT = 0,
+ PCSR_S1R_BIT = 1,
+ PCSR_S0CD_BIT = 2,
+ PCSR_S1CD_BIT = 3,
+ PCSR_S0VS1_BIT = 4,
+ PCSR_S0VS2_BIT = 5,
+ PCSR_S1VS1_BIT = 6,
+ PCSR_S1VS2_BIT = 7,
+ PCSR_S0WP_BIT = 8,
+ PCSR_S1WP_BIT = 9,
+ PCSR_S0BVD1_BIT = 10,
+ PCSR_S0BVD2_BIT = 11,
+ PCSR_S1BVD1_BIT = 12,
+ PCSR_S1BVD2_BIT = 13,
+
+ PCCR_S0RST_BIT = 0,
+ PCCR_S1RST_BIT = 1,
+ PCCR_S0FLT_BIT = 2,
+ PCCR_S1FLT_BIT = 3,
+ PCCR_S0PWEN_BIT = 4,
+ PCCR_S1PWEN_BIT = 5,
+ PCCR_S0PSE_BIT = 6,
+ PCCR_S1PSE_BIT = 7,
+
+ PCSSR_S0SLP_BIT = 0,
+ PCSSR_S1SLP_BIT = 1
+ };
+
+ struct sbi_regs
+ {
+ uint32_t skcr;
+ uint32_t smcr;
+ uint32_t skid;
+ };
+
+ struct sysctrl_regs
+ {
+ uint32_t skpcr;
+ uint32_t skcdr;
+ uint32_t skaud;
+ uint32_t skpmc;
+ uint32_t skptc;
+ uint32_t skpen0;
+ uint32_t skpwm0;
+ uint32_t skpen1;
+ uint32_t skpwm1;
+ };
+
+ struct usb_regs
+ {
+ uint32_t ohci[22];
+ uint32_t status;
+ uint32_t reset;
+ uint32_t int_test;
+ uint32_t fifo[12];
+ };
+
+ struct audio_regs
+ {
+ uint32_t sacr0;
+ uint32_t sacr1;
+ uint32_t sacr2;
+ uint32_t sasr0;
+ uint32_t sasr1;
+ uint32_t l3car;
+ uint32_t l3cdr;
+ uint32_t accar;
+ uint32_t accdr;
+ uint32_t acsar;
+ uint32_t acsdr;
+ uint32_t sadtcs;
+ uint32_t sadtsa;
+ uint32_t sadtca;
+ uint32_t sadtsb;
+ uint32_t sadtcb;
+ uint32_t sadrcs;
+ uint32_t sadrsa;
+ uint32_t sadrca;
+ uint32_t sadrsb;
+ uint32_t sadrcb;
+ uint32_t saitr;
+
+ uint32_t rx_fifo[16];
+ int rx_fifo_read_idx;
+ int rx_fifo_write_idx;
+ int rx_fifo_count;
+ emu_timer *rx_timer;
+
+ uint32_t tx_fifo[16];
+ int tx_fifo_read_idx;
+ int tx_fifo_write_idx;
+ int tx_fifo_count;
+ emu_timer *tx_timer;
+ };
+
+ struct ssp_regs
+ {
+ uint32_t sspcr0;
+ uint32_t sspcr1;
+ uint32_t sspsr;
+ uint32_t sspitr;
+
+ uint16_t rx_fifo[16];
+ int rx_fifo_read_idx;
+ int rx_fifo_write_idx;
+ int rx_fifo_count;
+ emu_timer *rx_timer;
+
+ uint16_t tx_fifo[16];
+ int tx_fifo_read_idx;
+ int tx_fifo_write_idx;
+ int tx_fifo_count;
+ emu_timer *tx_timer;
+ };
+
+ struct ps2_regs
+ {
+ uint32_t kbdcr;
+ uint32_t kbdstat;
+ uint32_t kbddata_tx;
+ uint32_t kbddata_rx;
+ uint32_t kbdclkdiv;
+ uint32_t kbdprecnt;
+ uint32_t kbditr;
+ };
+
+ struct gpio_regs
+ {
+ uint32_t ddr[3];
+ uint32_t level[3];
+ uint32_t sdr[3];
+ uint32_t ssr[3];
+ uint32_t out_latch[3];
+ uint32_t in_latch[3];
+ };
+
+ struct intc_regs
+ {
+ uint32_t inttest[2];
+ uint32_t inten[2];
+ uint32_t intpol[2];
+ uint32_t inttstsel;
+ uint32_t intstat[2];
+ uint32_t wake_en[2];
+ uint32_t wake_pol[2];
+ };
+
+ struct card_regs
+ {
+ uint32_t pccr;
+ uint32_t pcssr;
+ uint32_t pcsr;
+ };
+
+ sbi_regs m_sbi_regs;
+ sysctrl_regs m_sk_regs;
+ usb_regs m_usb_regs;
+ audio_regs m_audio_regs;
+ ssp_regs m_ssp_regs;
+ ps2_regs m_track_regs;
+ ps2_regs m_mouse_regs;
+ gpio_regs m_gpio_regs;
+ intc_regs m_intc_regs;
+ card_regs m_card_regs;
+
+ devcb_write_line::array<24> m_gpio_out;
+ devcb_write16 m_ssp_out;
+};
+
+DECLARE_DEVICE_TYPE(SA1111, sa1111_device)
+
+#endif // MAME_MACHINE_SA1111
diff --git a/src/devices/video/sed1356.cpp b/src/devices/video/sed1356.cpp
new file mode 100644
index 00000000000..7562a8d6d04
--- /dev/null
+++ b/src/devices/video/sed1356.cpp
@@ -0,0 +1,1579 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/**********************************************************************
+
+ Epson SED1356 LCD Controller emulation skeleton
+
+ Status:
+ - Currently hard-coded for use with the Jornada 720 driver.
+ - Register contents are correctly stored, logged and masked, but
+ register handling is otherwise non-present.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "sed1356.h"
+#include "screen.h"
+
+#define LOG_MISC_RD (1 << 1)
+#define LOG_MISC_WR (1 << 2)
+#define LOG_LCD_RD (1 << 3)
+#define LOG_LCD_WR (1 << 4)
+#define LOG_CRT_RD (1 << 5)
+#define LOG_CRT_WR (1 << 6)
+#define LOG_BITBLT_RD (1 << 7)
+#define LOG_BITBLT_WR (1 << 8)
+#define LOG_LUT_RD (1 << 9)
+#define LOG_LUT_WR (1 << 10)
+#define LOG_MPLUG_RD (1 << 11)
+#define LOG_MPLUG_WR (1 << 12)
+#define LOG_ALL (LOG_MISC_RD | LOG_MISC_WR | LOG_LCD_RD | LOG_LCD_WR | LOG_CRT_RD | LOG_CRT_WR | LOG_BITBLT_RD | LOG_BITBLT_WR | LOG_LUT_RD | LOG_LUT_WR | LOG_MPLUG_RD | LOG_MPLUG_WR)
+
+#define VERBOSE (LOG_ALL)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(SED1356, sed1356_device, "sed1356", "Epson SED1356")
+
+sed1356_device::sed1356_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SED1356, tag, owner, clock)
+ , device_video_interface(mconfig, *this)
+ , m_vram(*this, "vram")
+{
+}
+
+void sed1356_device::map(address_map &map)
+{
+ map(0x000000, 0x000000).r(FUNC(sed1356_device::revision_r));
+ map(0x000001, 0x000001).rw(FUNC(sed1356_device::misc_r), FUNC(sed1356_device::misc_w));
+ map(0x000004, 0x000004).rw(FUNC(sed1356_device::gpio_config_r), FUNC(sed1356_device::gpio_config_w));
+ map(0x000008, 0x000008).rw(FUNC(sed1356_device::gpio_ctrl_r), FUNC(sed1356_device::gpio_ctrl_w));
+ map(0x00000c, 0x00000d).rw(FUNC(sed1356_device::md_config_readback_r), FUNC(sed1356_device::md_config_readback_w));
+ map(0x000010, 0x000010).rw(FUNC(sed1356_device::mem_clk_config_r), FUNC(sed1356_device::mem_clk_config_w));
+ map(0x000014, 0x000014).rw(FUNC(sed1356_device::lcd_pclk_config_r), FUNC(sed1356_device::lcd_pclk_config_w));
+ map(0x000018, 0x000018).rw(FUNC(sed1356_device::crt_pclk_config_r), FUNC(sed1356_device::crt_pclk_config_w));
+ map(0x00001c, 0x00001c).rw(FUNC(sed1356_device::mplug_clk_config_r), FUNC(sed1356_device::mplug_clk_config_w));
+ map(0x00001e, 0x00001e).rw(FUNC(sed1356_device::mem_wait_select_r), FUNC(sed1356_device::mem_wait_select_w));
+ map(0x000020, 0x000020).rw(FUNC(sed1356_device::mem_config_r), FUNC(sed1356_device::mem_config_w));
+ map(0x000021, 0x000021).rw(FUNC(sed1356_device::dram_refresh_select_r), FUNC(sed1356_device::dram_refresh_select_w));
+ map(0x00002a, 0x00002b).r(FUNC(sed1356_device::dram_timing_ctrl_r));
+ map(0x00002a, 0x00002a).w(FUNC(sed1356_device::dram_timing_ctrl0_w));
+ map(0x00002b, 0x00002b).w(FUNC(sed1356_device::dram_timing_ctrl1_w));
+ map(0x000030, 0x000030).rw(FUNC(sed1356_device::panel_type_r), FUNC(sed1356_device::panel_type_w));
+ map(0x000031, 0x000031).rw(FUNC(sed1356_device::mod_rate_r), FUNC(sed1356_device::mod_rate_w));
+ map(0x000032, 0x000032).rw(FUNC(sed1356_device::lcd_display_width_r), FUNC(sed1356_device::lcd_display_width_w));
+ map(0x000034, 0x000034).rw(FUNC(sed1356_device::lcd_hblank_period_r), FUNC(sed1356_device::lcd_hblank_period_w));
+ map(0x000035, 0x000035).rw(FUNC(sed1356_device::tft_fpline_start_pos_r), FUNC(sed1356_device::tft_fpline_start_pos_w));
+ map(0x000036, 0x000036).rw(FUNC(sed1356_device::tft_fpline_pulse_width_r), FUNC(sed1356_device::tft_fpline_pulse_width_w));
+ map(0x000038, 0x000039).rw(FUNC(sed1356_device::lcd_display_height_r), FUNC(sed1356_device::lcd_display_height_w));
+ map(0x00003a, 0x00003a).rw(FUNC(sed1356_device::lcd_vblank_period_r), FUNC(sed1356_device::lcd_vblank_period_w));
+ map(0x00003b, 0x00003b).rw(FUNC(sed1356_device::tft_fpframe_start_pos_r), FUNC(sed1356_device::tft_fpframe_start_pos_w));
+ map(0x00003c, 0x00003c).rw(FUNC(sed1356_device::tft_fpframe_pulse_width_r), FUNC(sed1356_device::tft_fpframe_pulse_width_w));
+ map(0x000040, 0x000040).rw(FUNC(sed1356_device::lcd_display_mode_r), FUNC(sed1356_device::lcd_display_mode_w));
+ map(0x000041, 0x000041).rw(FUNC(sed1356_device::lcd_misc_r), FUNC(sed1356_device::lcd_misc_w));
+ map(0x000042, 0x000044).rw(FUNC(sed1356_device::lcd_display_start_addr_r), FUNC(sed1356_device::lcd_display_start_addr_w));
+ map(0x000046, 0x000047).rw(FUNC(sed1356_device::lcd_mem_addr_offset_r), FUNC(sed1356_device::lcd_mem_addr_offset_w));
+ map(0x000048, 0x000048).rw(FUNC(sed1356_device::lcd_pixel_pan_r), FUNC(sed1356_device::lcd_pixel_pan_w));
+ map(0x00004a, 0x00004a).rw(FUNC(sed1356_device::lcd_display_fifo_hi_thresh_r), FUNC(sed1356_device::lcd_display_fifo_hi_thresh_w));
+ map(0x00004b, 0x00004b).rw(FUNC(sed1356_device::lcd_display_fifo_lo_thresh_r), FUNC(sed1356_device::lcd_display_fifo_lo_thresh_w));
+ map(0x000050, 0x000050).rw(FUNC(sed1356_device::crt_display_width_r), FUNC(sed1356_device::crt_display_width_w));
+ map(0x000052, 0x000052).rw(FUNC(sed1356_device::crt_hblank_period_r), FUNC(sed1356_device::crt_hblank_period_w));
+ map(0x000053, 0x000053).rw(FUNC(sed1356_device::crt_hrtc_start_pos_r), FUNC(sed1356_device::crt_hrtc_start_pos_w));
+ map(0x000054, 0x000054).rw(FUNC(sed1356_device::crt_hrtc_pulse_width_r), FUNC(sed1356_device::crt_hrtc_pulse_width_w));
+ map(0x000056, 0x000057).rw(FUNC(sed1356_device::crt_display_height_r), FUNC(sed1356_device::crt_display_height_w));
+ map(0x000058, 0x000058).rw(FUNC(sed1356_device::crt_vblank_period_r), FUNC(sed1356_device::crt_vblank_period_w));
+ map(0x000059, 0x000059).rw(FUNC(sed1356_device::crt_vrtc_start_pos_r), FUNC(sed1356_device::crt_vrtc_start_pos_w));
+ map(0x00005a, 0x00005a).rw(FUNC(sed1356_device::crt_vrtc_pulse_width_r), FUNC(sed1356_device::crt_vrtc_pulse_width_w));
+ map(0x00005b, 0x00005b).rw(FUNC(sed1356_device::crt_output_ctrl_r), FUNC(sed1356_device::crt_output_ctrl_w));
+ map(0x000060, 0x000060).rw(FUNC(sed1356_device::crt_display_mode_r), FUNC(sed1356_device::crt_display_mode_w));
+ map(0x000062, 0x000064).rw(FUNC(sed1356_device::crt_display_start_addr_r), FUNC(sed1356_device::crt_display_start_addr_w));
+ map(0x000066, 0x000067).rw(FUNC(sed1356_device::crt_mem_addr_offset_r), FUNC(sed1356_device::crt_mem_addr_offset_w));
+ map(0x000068, 0x000068).rw(FUNC(sed1356_device::crt_pixel_pan_r), FUNC(sed1356_device::crt_pixel_pan_w));
+ map(0x00006a, 0x00006a).rw(FUNC(sed1356_device::crt_display_fifo_hi_thresh_r), FUNC(sed1356_device::crt_display_fifo_hi_thresh_w));
+ map(0x00006b, 0x00006b).rw(FUNC(sed1356_device::crt_display_fifo_lo_thresh_r), FUNC(sed1356_device::crt_display_fifo_lo_thresh_w));
+ map(0x000070, 0x000070).rw(FUNC(sed1356_device::lcd_cursor_ctrl_r), FUNC(sed1356_device::lcd_cursor_ctrl_w));
+ map(0x000071, 0x000071).rw(FUNC(sed1356_device::lcd_cursor_start_addr_r), FUNC(sed1356_device::lcd_cursor_start_addr_w));
+ map(0x000072, 0x000073).rw(FUNC(sed1356_device::lcd_cursor_x_r), FUNC(sed1356_device::lcd_cursor_x_w));
+ map(0x000074, 0x000075).rw(FUNC(sed1356_device::lcd_cursor_y_r), FUNC(sed1356_device::lcd_cursor_y_w));
+ map(0x000076, 0x000078).r(FUNC(sed1356_device::lcd_cursor_color0_r));
+ map(0x000076, 0x000076).w(FUNC(sed1356_device::lcd_cursor_color0_blu_w));
+ map(0x000077, 0x000077).w(FUNC(sed1356_device::lcd_cursor_color0_grn_w));
+ map(0x000078, 0x000078).w(FUNC(sed1356_device::lcd_cursor_color0_red_w));
+ map(0x00007a, 0x00007b).r(FUNC(sed1356_device::lcd_cursor_color1_r));
+ map(0x00007a, 0x00007a).w(FUNC(sed1356_device::lcd_cursor_color1_blu_w));
+ map(0x00007b, 0x00007b).w(FUNC(sed1356_device::lcd_cursor_color1_grn_w));
+ map(0x00007c, 0x00007c).w(FUNC(sed1356_device::lcd_cursor_color1_red_w));
+ map(0x00007e, 0x00007e).rw(FUNC(sed1356_device::lcd_cursor_fifo_thresh_r), FUNC(sed1356_device::lcd_cursor_fifo_thresh_w));
+ map(0x000080, 0x000080).rw(FUNC(sed1356_device::crt_cursor_ctrl_r), FUNC(sed1356_device::crt_cursor_ctrl_w));
+ map(0x000081, 0x000081).rw(FUNC(sed1356_device::crt_cursor_start_addr_r), FUNC(sed1356_device::crt_cursor_start_addr_w));
+ map(0x000082, 0x000083).rw(FUNC(sed1356_device::crt_cursor_x_r), FUNC(sed1356_device::crt_cursor_x_w));
+ map(0x000084, 0x000085).rw(FUNC(sed1356_device::crt_cursor_y_r), FUNC(sed1356_device::crt_cursor_y_w));
+ map(0x000086, 0x000088).r(FUNC(sed1356_device::crt_cursor_color0_r));
+ map(0x000086, 0x000086).w(FUNC(sed1356_device::crt_cursor_color0_blu_w));
+ map(0x000087, 0x000087).w(FUNC(sed1356_device::crt_cursor_color0_grn_w));
+ map(0x000088, 0x000088).w(FUNC(sed1356_device::crt_cursor_color0_red_w));
+ map(0x00008a, 0x00008b).r(FUNC(sed1356_device::crt_cursor_color1_r));
+ map(0x00008a, 0x00008a).w(FUNC(sed1356_device::crt_cursor_color1_blu_w));
+ map(0x00008b, 0x00008b).w(FUNC(sed1356_device::crt_cursor_color1_grn_w));
+ map(0x00008c, 0x00008c).w(FUNC(sed1356_device::crt_cursor_color1_red_w));
+ map(0x00008e, 0x00008e).rw(FUNC(sed1356_device::crt_cursor_fifo_thresh_r), FUNC(sed1356_device::crt_cursor_fifo_thresh_w));
+ map(0x000100, 0x000100).rw(FUNC(sed1356_device::bitblt_ctrl0_r), FUNC(sed1356_device::bitblt_ctrl0_w));
+ map(0x000101, 0x000101).rw(FUNC(sed1356_device::bitblt_ctrl1_r), FUNC(sed1356_device::bitblt_ctrl1_w));
+ map(0x000102, 0x000102).rw(FUNC(sed1356_device::bitblt_rop_code_r), FUNC(sed1356_device::bitblt_rop_code_w));
+ map(0x000103, 0x000103).rw(FUNC(sed1356_device::bitblt_operation_r), FUNC(sed1356_device::bitblt_operation_w));
+ map(0x000104, 0x000106).rw(FUNC(sed1356_device::bitblt_src_start_addr_r), FUNC(sed1356_device::bitblt_src_start_addr_w));
+ map(0x000108, 0x00010a).rw(FUNC(sed1356_device::bitblt_dst_start_addr_r), FUNC(sed1356_device::bitblt_dst_start_addr_w));
+ map(0x00010c, 0x00010d).rw(FUNC(sed1356_device::bitblt_mem_addr_offset_r), FUNC(sed1356_device::bitblt_mem_addr_offset_w));
+ map(0x000110, 0x000111).rw(FUNC(sed1356_device::bitblt_width_r), FUNC(sed1356_device::bitblt_width_w));
+ map(0x000112, 0x000113).rw(FUNC(sed1356_device::bitblt_height_r), FUNC(sed1356_device::bitblt_height_w));
+ map(0x000114, 0x000115).rw(FUNC(sed1356_device::bitblt_bgcolor_r), FUNC(sed1356_device::bitblt_bgcolor_w));
+ map(0x000118, 0x000119).rw(FUNC(sed1356_device::bitblt_fgcolor_r), FUNC(sed1356_device::bitblt_fgcolor_w));
+ map(0x0001e0, 0x0001e0).rw(FUNC(sed1356_device::lut_mode_r), FUNC(sed1356_device::lut_mode_w));
+ map(0x0001e2, 0x0001e2).rw(FUNC(sed1356_device::lut_addr_r), FUNC(sed1356_device::lut_addr_w));
+ map(0x0001e4, 0x0001e4).rw(FUNC(sed1356_device::lut_data_r), FUNC(sed1356_device::lut_data_w));
+ map(0x0001f0, 0x0001f0).rw(FUNC(sed1356_device::power_config_r), FUNC(sed1356_device::power_config_w));
+ map(0x0001f1, 0x0001f1).r(FUNC(sed1356_device::power_status_r));
+ map(0x0001f4, 0x0001f4).rw(FUNC(sed1356_device::cpu_mem_watchdog_r), FUNC(sed1356_device::cpu_mem_watchdog_w));
+ map(0x0001fc, 0x0001fc).rw(FUNC(sed1356_device::display_mode_r), FUNC(sed1356_device::display_mode_w));
+ map(0x001000, 0x001001).rw(FUNC(sed1356_device::mplug_lcmd_r), FUNC(sed1356_device::mplug_lcmd_w));
+ map(0x001002, 0x001003).rw(FUNC(sed1356_device::mplug_resv_lcmd_r), FUNC(sed1356_device::mplug_resv_lcmd_w));
+ map(0x001004, 0x001005).rw(FUNC(sed1356_device::mplug_cmd_r), FUNC(sed1356_device::mplug_cmd_w));
+ map(0x001006, 0x001007).rw(FUNC(sed1356_device::mplug_resv_cmd_r), FUNC(sed1356_device::mplug_resv_cmd_w));
+ map(0x001008, 0x001fff).rw(FUNC(sed1356_device::mplug_data_r), FUNC(sed1356_device::mplug_data_w));
+ map(0x100000, 0x1fffff).rw(FUNC(sed1356_device::bitblt_data_r), FUNC(sed1356_device::bitblt_data_w));
+}
+
+void sed1356_device::vram_map(address_map &map)
+{
+ map(0x00000, 0x80000).ram().share(m_vram);
+}
+
+uint8_t sed1356_device::revision_r(offs_t offset)
+{
+ const uint8_t data = 0x11;
+ LOGMASKED(LOG_MISC_RD, "%s: revision_r: %02x\n", machine().describe_context(), data);
+ return data;
+}
+
+
+uint8_t sed1356_device::misc_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: misc_r: %02x\n", machine().describe_context(), m_misc);
+ return m_misc;
+}
+
+void sed1356_device::misc_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: misc_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: Register/Memory Select: %d\n", machine().describe_context(), BIT(data, MISC_RMS_BIT));
+ m_misc = data & MISC_MASK;
+}
+
+
+uint8_t sed1356_device::gpio_config_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: gpio_config_r: %02x\n", machine().describe_context(), m_gpio_config);
+ return m_gpio_config;
+}
+
+void sed1356_device::gpio_config_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: gpio_config_w = %02x\n", machine().describe_context(), data);
+ m_gpio_config = data & GPCFG_MASK;
+}
+
+uint8_t sed1356_device::gpio_ctrl_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: gpio_ctrl_r: %02x\n", machine().describe_context(), m_gpio_ctrl);
+ return m_gpio_ctrl;
+}
+
+void sed1356_device::gpio_ctrl_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: gpio_ctrl_w = %02x\n", machine().describe_context(), data);
+ m_gpio_ctrl = data & GPCTRL_MASK;
+}
+
+
+uint8_t sed1356_device::md_config_readback_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: md_config_readback_r[%d]: %02x\n", machine().describe_context(), offset, m_md_config[offset]);
+ return m_md_config[offset];
+}
+
+void sed1356_device::md_config_readback_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: md_config_readback_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ m_md_config[offset] = data;
+}
+
+
+uint8_t sed1356_device::mem_clk_config_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: mem_clk_config_r: %02x\n", machine().describe_context(), m_memclk_config);
+ return m_memclk_config;
+}
+
+uint8_t sed1356_device::lcd_pclk_config_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: lcd_pclk_config_r: %02x\n", machine().describe_context(), m_lcd_pclk_config);
+ return m_lcd_pclk_config;
+}
+
+uint8_t sed1356_device::crt_pclk_config_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: crt_pclk_config_r: %02x\n", machine().describe_context(), m_crt_pclk_config);
+ return m_crt_pclk_config;
+}
+
+uint8_t sed1356_device::mplug_clk_config_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: mplug_clk_config_r: %02x\n", machine().describe_context(), m_mplug_clk_config);
+ return m_mplug_clk_config;
+}
+
+void sed1356_device::mem_clk_config_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: mem_clk_config_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: MCLK Source: %s\n", machine().describe_context(), BIT(data, MEMCLK_SRC_BIT) ? "BUSCLK" : "CLKI");
+ LOGMASKED(LOG_MISC_WR, "%s: MCLK Divider: %d:1\n", machine().describe_context(), BIT(data, MEMCLK_DIV_BIT) + 1);
+ m_memclk_config = data & MEMCLK_MASK;
+}
+
+void sed1356_device::lcd_pclk_config_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_source_names[4] = { "CLKI", "BUSCLK", "CLKI2", "MCLK" };
+ LOGMASKED(LOG_MISC_WR, "%s: lcd_pclk_config_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: LCD PCLK Source: %s\n", machine().describe_context(), s_source_names[(data & LCDCLK_SRC_MASK) >> LCDCLK_SRC_BIT]);
+ LOGMASKED(LOG_MISC_WR, "%s: LCD PCLK Divider: %d:1\n", machine().describe_context(), ((data & LCDCLK_DIV_MASK) >> LCDCLK_DIV_BIT) + 1);
+ m_lcd_pclk_config = data & LCDCLK_MASK;
+}
+
+void sed1356_device::crt_pclk_config_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_source_names[4] = { "CLKI", "BUSCLK", "CLKI2", "MCLK" };
+ LOGMASKED(LOG_MISC_WR, "%s: crt_pclk_config_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: CRT PCLK Source: %s\n", machine().describe_context(), s_source_names[(data & CRTCLK_SRC_MASK) >> CRTCLK_SRC_BIT]);
+ LOGMASKED(LOG_MISC_WR, "%s: CRT PCLK Divider: %d:1\n", machine().describe_context(), ((data & CRTCLK_DIV_MASK) >> CRTCLK_DIV_BIT) + 1);
+ LOGMASKED(LOG_MISC_WR, "%s: CRT PCLK 2x Enable: %d\n", machine().describe_context(), BIT(data, CRTCLK_2X_BIT));
+ m_crt_pclk_config = data & CRTCLK_MASK;
+}
+
+void sed1356_device::mplug_clk_config_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_source_names[4] = { "CLKI", "BUSCLK", "CLKI2", "MCLK" };
+ LOGMASKED(LOG_MISC_WR, "%s: mplug_clk_config_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: MediaPlug CLK Source: %s\n", machine().describe_context(), s_source_names[(data & PLUGCLK_SRC_MASK) >> PLUGCLK_SRC_BIT]);
+ LOGMASKED(LOG_MISC_WR, "%s: MediaPlug CLK Divider: %d:1\n", machine().describe_context(), ((data & PLUGCLK_DIV_MASK) >> PLUGCLK_DIV_BIT) + 1);
+ m_mplug_clk_config = data & PLUGCLK_MASK;
+}
+
+
+uint8_t sed1356_device::mem_wait_select_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: mem_wait_select_r: %02x\n", machine().describe_context(), m_wait_state_sel);
+ return m_wait_state_sel;
+}
+
+uint8_t sed1356_device::mem_config_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: mem_config_r: %02x\n", machine().describe_context(), m_mem_config);
+ return m_mem_config;
+}
+
+uint8_t sed1356_device::dram_refresh_select_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: dram_refresh_select_r: %02x\n", machine().describe_context(), m_dram_refresh);
+ return m_dram_refresh;
+}
+
+uint8_t sed1356_device::dram_timing_ctrl_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: dram_timing_ctrl_r[%d]: %02x\n", machine().describe_context(), offset, m_dram_timing);
+ return m_dram_timing[offset];
+}
+
+void sed1356_device::mem_wait_select_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_sel_names[4] = { "no restrictions", "2 * MCLK - 4ns", "MCLK - 4ns", "Reserved" };
+ LOGMASKED(LOG_MISC_WR, "%s: mem_wait_select_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: Mode: %s\n", machine().describe_context(), s_sel_names[(data & CPUWAIT_SEL_MASK) >> CPUWAIT_SEL_BIT]);
+ m_wait_state_sel = data & CPUWAIT_MASK;
+}
+
+void sed1356_device::mem_config_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_type_names[4] = { "EDO-DRAM w/ 2-CAS#", "FPM-DRAM w/ 2-CAS#", "EDO-DRAM w/ 2-WE#", "FPM-DRAM w/ 2-WE#" };
+ LOGMASKED(LOG_MISC_WR, "%s: mem_config_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: Type: %s\n", machine().describe_context(), s_type_names[(data & MEMCFG_TYPE_MASK) >> MEMCFG_TYPE_BIT]);
+ m_mem_config = data & MEMCFG_MASK;
+}
+
+void sed1356_device::dram_refresh_select_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_sel_names[4] = { "CBR Refresh", "Self-Refresh", "No Refresh [2]", "No Refresh [3]" };
+ LOGMASKED(LOG_MISC_WR, "%s: dram_refresh_select_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: Rate: MCLK/%d\n", machine().describe_context(), 64 << ((data & MEMRFSH_RATE_MASK) >> MEMRFSH_RATE_BIT));
+ LOGMASKED(LOG_MISC_WR, "%s: Type: %s\n", machine().describe_context(), s_sel_names[(data & MEMRFSH_SEL_MASK) >> MEMRFSH_SEL_BIT]);
+ m_dram_refresh = data & MEMRFSH_MASK;
+}
+
+void sed1356_device::dram_timing_ctrl0_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: dram_timing_ctrl_w[0] = %02x\n", machine().describe_context(), data);
+ m_dram_timing[0] = data;
+}
+
+void sed1356_device::dram_timing_ctrl1_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: dram_timing_ctrl_w[1] = %02x\n", machine().describe_context(), data);
+ m_dram_timing[1] = data & DRAMTIME1_MASK;
+}
+
+uint8_t sed1356_device::panel_type_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: panel_type_r: %02x\n", machine().describe_context(), m_panel_type);
+ return m_panel_type;
+}
+
+uint8_t sed1356_device::mod_rate_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: mod_rate_r: %02x\n", machine().describe_context(), m_mod_rate);
+ return m_mod_rate;
+}
+
+void sed1356_device::panel_type_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_data_names[2][4] =
+ {
+ { "4-bit", "8-bit", "16-bit", "Reserved" },
+ { "9-bit", "12-bit", "18-bit", "Reserved" }
+ };
+ LOGMASKED(LOG_MISC_WR, "%s: panel_type_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: Panel Type: %s\n", machine().describe_context(), BIT(data, PTYPE_TFT_PASS_BIT) ? "TFT" : "Passive");
+ LOGMASKED(LOG_MISC_WR, "%s: Panel Count: %d\n", machine().describe_context(), 1 + BIT(data, PTYPE_COUNT_BIT));
+ LOGMASKED(LOG_MISC_WR, "%s: Color Panel: %s\n", machine().describe_context(), BIT(data, PTYPE_COLOR_BIT) ? "Yes" : "No");
+ LOGMASKED(LOG_MISC_WR, "%s: Format Select: %d\n", machine().describe_context(), BIT(data, PTYPE_FORMAT_BIT));
+ LOGMASKED(LOG_MISC_WR, "%s: Data Width: %s\n", machine().describe_context(), s_data_names[BIT(data, PTYPE_TFT_PASS_BIT)][(data & PTYPE_WIDTH_MASK) >> PTYPE_WIDTH_BIT]);
+ LOGMASKED(LOG_MISC_WR, "%s: EL Mode Enable: %d\n", machine().describe_context(), BIT(data, PTYPE_EL_BIT));
+ m_panel_type = data & PTYPE_MASK;
+}
+
+void sed1356_device::mod_rate_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: mod_rate_w = %02x\n", machine().describe_context(), data);
+ m_mod_rate = data & MODRATE_MASK;
+}
+
+
+uint8_t sed1356_device::lcd_display_width_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_display_width_r: %02x\n", machine().describe_context(), m_lcd_width);
+ return m_lcd_width;
+}
+
+uint8_t sed1356_device::lcd_hblank_period_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_hblank_period_r: %02x\n", machine().describe_context(), m_lcd_hblank_period);
+ return m_lcd_hblank_period;
+}
+
+uint8_t sed1356_device::tft_fpline_start_pos_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: tft_fpline_start_pos_r: %02x\n", machine().describe_context(), m_tft_fpline_start);
+ return m_tft_fpline_start;
+}
+
+uint8_t sed1356_device::tft_fpline_pulse_width_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: tft_fpline_pulse_width_r: %02x\n", machine().describe_context(), m_tft_fpline_width);
+ return m_tft_fpline_width;
+}
+
+uint8_t sed1356_device::lcd_display_height_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_lcd_height >> (8 * offset));
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_display_height_r[%d]: %02x\n", machine().describe_context(), data);
+ return data;
+}
+
+uint8_t sed1356_device::lcd_vblank_period_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_vblank_period_r: %02x\n", machine().describe_context(), m_lcd_vblank_period);
+ return m_lcd_vblank_period;
+}
+
+uint8_t sed1356_device::tft_fpframe_start_pos_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: tft_fpframe_start_pos_r: %02x\n", machine().describe_context(), m_tft_fpframe_start);
+ return m_tft_fpframe_start;
+}
+
+uint8_t sed1356_device::tft_fpframe_pulse_width_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: tft_fpframe_pulse_width_r: %02x\n", machine().describe_context(), m_tft_fpframe_width);
+ return m_tft_fpframe_width;
+}
+
+uint8_t sed1356_device::lcd_display_mode_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_display_mode_r: %02x\n", machine().describe_context(), m_lcd_mode);
+ return m_lcd_mode;
+}
+
+uint8_t sed1356_device::lcd_misc_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_misc_r: %02x\n", machine().describe_context(), m_lcd_misc);
+ return m_lcd_misc;
+}
+
+uint8_t sed1356_device::lcd_display_start_addr_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_lcd_addr >> (8 * offset));
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_display_start_addr_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::lcd_mem_addr_offset_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_lcd_mem_offset >> (8 * offset));
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_mem_addr_offset_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::lcd_pixel_pan_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_pixel_pan_r: %02x\n", machine().describe_context(), m_lcd_pan);
+ return m_lcd_pan;
+}
+
+uint8_t sed1356_device::lcd_display_fifo_hi_thresh_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_display_fifo_hi_thresh_r: %02x\n", machine().describe_context(), m_lcd_fifo_hi_thresh);
+ return m_lcd_fifo_hi_thresh;
+}
+
+uint8_t sed1356_device::lcd_display_fifo_lo_thresh_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_display_fifo_lo_thresh_r: %02x\n", machine().describe_context(), m_lcd_fifo_lo_thresh);
+ return m_lcd_fifo_lo_thresh;
+}
+
+void sed1356_device::lcd_display_width_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_display_width_w = %02x\n", machine().describe_context(), data);
+ m_lcd_width = data & LCDW_MASK;
+}
+
+void sed1356_device::lcd_hblank_period_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_hblank_period_w = %02x\n", machine().describe_context(), data);
+ m_lcd_hblank_period = data & LCDHBL_MASK;
+}
+
+void sed1356_device::tft_fpline_start_pos_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: tft_fpline_start_pos_w = %02x\n", machine().describe_context(), data);
+ m_tft_fpline_start = data & TFTFPLS_MASK;
+}
+
+void sed1356_device::tft_fpline_pulse_width_w(offs_t offset, uint8_t data)
+{
+ const int tft = BIT(data, PTYPE_TFT_PASS_BIT);
+ static const char *const s_polarity_names[2][2] =
+ {
+ { "active-high", "active-low" },
+ { "active-low", "active-high" }
+ };
+ LOGMASKED(LOG_LCD_WR, "%s: tft_fpline_pulse_width_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_LCD_WR, "%s: Pulse Width: %d\n", machine().describe_context(), (data & TFTFPLW_WIDTH_MASK) >> TFTFPLW_WIDTH_BIT);
+ LOGMASKED(LOG_LCD_WR, "%s: Polarity: %s\n", machine().describe_context(), s_polarity_names[tft][BIT(data, TFTFPLW_POL_BIT)]);
+ m_tft_fpline_width = data & TFTFPLW_MASK;
+}
+
+void sed1356_device::lcd_display_height_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_display_height_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_lcd_height &= ~(0x00ff << shift);
+ m_lcd_height = (m_lcd_height | (data << shift)) & LCDH_MASK;
+}
+
+void sed1356_device::lcd_vblank_period_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_vblank_period_w = %02x\n", machine().describe_context(), data);
+ m_lcd_vblank_period &= ~LCDVBL_VALUE_MASK;
+ m_lcd_vblank_period |= (data & LCDVBL_VALUE_MASK) << LCDVBL_VALUE_BIT;
+}
+
+void sed1356_device::tft_fpframe_start_pos_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: tft_fpframe_start_pos_w = %02x\n", machine().describe_context(), data);
+ m_tft_fpframe_start = data & TFTFPLS_MASK;
+}
+
+void sed1356_device::tft_fpframe_pulse_width_w(offs_t offset, uint8_t data)
+{
+ const int tft = BIT(data, PTYPE_TFT_PASS_BIT);
+ static const char *const s_polarity_names[2][2] =
+ {
+ { "active-high", "active-low" },
+ { "active-low", "active-high" }
+ };
+ LOGMASKED(LOG_LCD_WR, "%s: tft_fpframe_pulse_width_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_LCD_WR, "%s: Pulse Width: %d\n", machine().describe_context(), (data & TFTFPFW_WIDTH_MASK) >> TFTFPFW_WIDTH_BIT);
+ LOGMASKED(LOG_LCD_WR, "%s: Polarity: %s\n", machine().describe_context(), s_polarity_names[tft][BIT(data, TFTFPFW_POL_BIT)]);
+ m_tft_fpframe_width = data & TFTFPFW_MASK;
+}
+
+void sed1356_device::lcd_display_mode_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_bpp_names[8] = { "Reserved", "Reserved", "4bpp", "8bpp", "15bpp", "16bpp", "Reserved", "Reserved" };
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_display_mode_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_LCD_WR, "%s: Bit Depth: %s\n", machine().describe_context(), s_bpp_names[(data & LCDMODE_BPP_MASK) >> LCDMODE_BPP_BIT]);
+ LOGMASKED(LOG_LCD_WR, "%s: SwivelView Enable Bit 1: %d\n", machine().describe_context(), BIT(data, LCDMODE_SWIVEN1_BIT));
+ LOGMASKED(LOG_LCD_WR, "%s: LCD Display Blank: %d\n", machine().describe_context(), BIT(data, LCDMODE_BLANK_BIT));
+ m_lcd_mode = data & LCDMODE_MASK;
+}
+
+void sed1356_device::lcd_misc_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_misc_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_LCD_WR, "%s: Dual-Panel Buffer Disable: %d\n", machine().describe_context(), BIT(data, LCDMISC_DPDIS_BIT));
+ LOGMASKED(LOG_LCD_WR, "%s: Dithering Disable: %d\n", machine().describe_context(), BIT(data, LCDMISC_DITHDIS_BIT));
+ m_lcd_misc = data & LCDMISC_MASK;
+}
+
+void sed1356_device::lcd_display_start_addr_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_display_start_addr_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint32_t shift = 8 * offset;
+ m_lcd_addr &= ~(0x00ff << shift);
+ m_lcd_addr = (m_lcd_addr | (data << shift)) & LCDDS_MASK;
+}
+
+void sed1356_device::lcd_mem_addr_offset_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_mem_addr_offset_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_lcd_mem_offset &= ~(0x00ff << shift);
+ m_lcd_mem_offset = (m_lcd_mem_offset | (data << shift)) & LCDMOFS_MASK;
+}
+
+void sed1356_device::lcd_pixel_pan_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_pixel_pan_w = %02x\n", machine().describe_context(), data);
+ m_lcd_pan = data & LCDPAN_MASK;
+}
+
+void sed1356_device::lcd_display_fifo_hi_thresh_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_display_fifo_hi_thresh_w = %02x\n", machine().describe_context(), data);
+ m_lcd_fifo_hi_thresh = data & LCDFIFO_MASK;
+}
+
+void sed1356_device::lcd_display_fifo_lo_thresh_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_display_fifo_lo_thresh_w = %02x\n", machine().describe_context(), data);
+ m_lcd_fifo_lo_thresh = data & LCDFIFO_MASK;
+}
+
+
+uint8_t sed1356_device::crt_display_width_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_display_width_r: %02x\n", machine().describe_context(), m_crt_width);
+ return m_crt_width;
+}
+
+uint8_t sed1356_device::crt_hblank_period_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_hblank_period_r: %02x\n", machine().describe_context(), m_crt_hblank_period);
+ return m_crt_hblank_period;
+}
+
+uint8_t sed1356_device::crt_hrtc_start_pos_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_hrtc_start_pos_r: %02x\n", machine().describe_context(), m_crt_hrtc_start);
+ return m_crt_hrtc_start;
+}
+
+uint8_t sed1356_device::crt_hrtc_pulse_width_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_hrtc_pulse_width_r: %02x\n", machine().describe_context(), m_crt_hrtc_width);
+ return m_crt_hrtc_width;
+}
+
+uint8_t sed1356_device::crt_display_height_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_crt_height >> (8 * offset));
+ LOGMASKED(LOG_CRT_RD, "%s: crt_display_height_r[%d]: %02x\n", machine().describe_context(), data);
+ return data;
+}
+
+uint8_t sed1356_device::crt_vblank_period_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_vblank_period_r: %02x\n", machine().describe_context(), m_crt_vblank_period);
+ LOGMASKED(LOG_CRT_RD, "%s: VBlank Active: %d\n", machine().describe_context(), BIT(m_crt_vblank_period, CRTVBL_STATUS_BIT));
+ return m_crt_vblank_period;
+}
+
+uint8_t sed1356_device::crt_vrtc_start_pos_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_vrtc_start_pos_r: %02x\n", machine().describe_context(), m_crt_vrtc_start);
+ return m_crt_vrtc_start;
+}
+
+uint8_t sed1356_device::crt_vrtc_pulse_width_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_vrtc_pulse_width_r: %02x\n", machine().describe_context(), m_crt_vrtc_width);
+ return m_crt_vrtc_width;
+}
+
+uint8_t sed1356_device::crt_output_ctrl_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_output_ctrl_r: %02x\n", machine().describe_context(), m_crt_output_ctrl);
+ return m_crt_output_ctrl;
+}
+
+uint8_t sed1356_device::crt_display_mode_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_display_mode_r: %02x\n", machine().describe_context(), m_crt_mode);
+ return m_crt_mode;
+}
+
+uint8_t sed1356_device::crt_display_start_addr_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_crt_addr >> (8 * offset));
+ LOGMASKED(LOG_CRT_RD, "%s: crt_display_start_addr_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::crt_mem_addr_offset_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_crt_mem_offset >> (8 * offset));
+ LOGMASKED(LOG_CRT_RD, "%s: crt_mem_addr_offset_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::crt_pixel_pan_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: crt_pixel_pan_r: %02x\n", machine().describe_context(), m_crt_pan);
+ return m_crt_pan;
+}
+
+uint8_t sed1356_device::crt_display_fifo_hi_thresh_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_display_fifo_hi_thresh_r: %02x\n", machine().describe_context(), m_crt_fifo_hi_thresh);
+ return m_crt_fifo_hi_thresh;
+}
+
+uint8_t sed1356_device::crt_display_fifo_lo_thresh_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_display_fifo_lo_thresh_r: %02x\n", machine().describe_context(), m_crt_fifo_lo_thresh);
+ return m_crt_fifo_lo_thresh;
+}
+
+void sed1356_device::crt_display_width_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_display_width_w = %02x\n", machine().describe_context(), data);
+ m_crt_width = data & CRTW_MASK;
+}
+
+void sed1356_device::crt_hblank_period_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_hblank_period_w = %02x\n", machine().describe_context(), data);
+ m_crt_hblank_period = data & CRTHBL_MASK;
+}
+
+void sed1356_device::crt_hrtc_start_pos_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_hrtc_start_pos_w = %02x\n", machine().describe_context(), data);
+ m_crt_hrtc_start = data & CRTHRTS_MASK;
+}
+
+void sed1356_device::crt_hrtc_pulse_width_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_hrtc_pulse_width_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_CRT_WR, "%s: Pulse Width: %d\n", machine().describe_context(), (data & CRTHRTW_WIDTH_MASK) >> CRTHRTW_WIDTH_BIT);
+ LOGMASKED(LOG_CRT_WR, "%s: Polarity: %s\n", machine().describe_context(), BIT(data, CRTHRTW_POL_BIT) ? "active-high" : "active-low");
+ m_crt_hrtc_width = data & CRTHRTW_MASK;
+}
+
+void sed1356_device::crt_display_height_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_display_height_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_crt_height &= ~(0x00ff << shift);
+ m_crt_height = (m_crt_height | (data << shift)) & CRTH_MASK;
+}
+
+void sed1356_device::crt_vblank_period_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_vblank_period_w = %02x\n", machine().describe_context(), data);
+ m_crt_vblank_period &= ~CRTVBL_VALUE_MASK;
+ m_crt_vblank_period |= (data & CRTVBL_VALUE_MASK) << CRTVBL_VALUE_BIT;
+}
+
+void sed1356_device::crt_vrtc_start_pos_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_vrtc_start_pos_w = %02x\n", machine().describe_context(), data);
+ m_crt_vrtc_start = data & CRTVRTS_MASK;
+}
+
+void sed1356_device::crt_vrtc_pulse_width_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_vrtc_pulse_width_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_CRT_WR, "%s: Pulse Width: %d\n", machine().describe_context(), (data & CRTVRTW_WIDTH_MASK) >> CRTVRTW_WIDTH_BIT);
+ LOGMASKED(LOG_CRT_WR, "%s: Polarity: %s\n", machine().describe_context(), BIT(data, CRTVRTW_POL_BIT) ? "active-high" : "active-low");
+ m_crt_vrtc_width = data & CRTVRTW_MASK;
+}
+
+void sed1356_device::crt_output_ctrl_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_output_ctrl_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_CRT_WR, "%s: Output Format: %s\n", machine().describe_context(), BIT(data, CRTCTRL_PAL_BIT) ? "PAL" : "NTSC");
+ LOGMASKED(LOG_CRT_WR, "%s: Output Signal: %s\n", machine().describe_context(), BIT(data, CRTCTRL_SVID_BIT) ? "S-Video" : "Composite");
+ LOGMASKED(LOG_CRT_WR, "%s: DAC Output Level Select: %d\n", machine().describe_context(), BIT(data, CRTCTRL_DACLVL_BIT));
+ LOGMASKED(LOG_CRT_WR, "%s: Luma Filter Enable: %d\n", machine().describe_context(), BIT(data, CRTCTRL_LUMF_BIT));
+ LOGMASKED(LOG_CRT_WR, "%s: Chroma Filter Enable: %d\n", machine().describe_context(), BIT(data, CRTCTRL_CHRF_BIT));
+ m_crt_output_ctrl = data & CRTCTRL_MASK;
+}
+
+void sed1356_device::crt_display_mode_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_bpp_names[8] = { "Reserved", "Reserved", "4bpp", "8bpp", "15bpp", "16bpp", "Reserved", "Reserved" };
+ LOGMASKED(LOG_CRT_WR, "%s: crt_display_mode_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_CRT_WR, "%s: Bit Depth: %s\n", machine().describe_context(), s_bpp_names[(data & CRTMODE_BPP_MASK) >> CRTMODE_BPP_BIT]);
+ LOGMASKED(LOG_CRT_WR, "%s: CRT Display Blank: %d\n", machine().describe_context(), BIT(data, CRTMODE_BLANK_BIT));
+ m_crt_mode = data & CRTMODE_MASK;
+}
+
+void sed1356_device::crt_display_start_addr_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_display_start_addr_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint32_t shift = 8 * offset;
+ m_crt_addr &= ~(0x00ff << shift);
+ m_crt_addr = (m_crt_addr | (data << shift)) & CRTDS_MASK;
+}
+
+void sed1356_device::crt_mem_addr_offset_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_mem_addr_offset_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_crt_mem_offset &= ~(0x00ff << shift);
+ m_crt_mem_offset = (m_crt_mem_offset | (data << shift)) & CRTMOFS_MASK;
+}
+
+void sed1356_device::crt_pixel_pan_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_pixel_pan_w = %02x\n", machine().describe_context(), data);
+ m_crt_pan = data & CRTPAN_MASK;
+}
+
+void sed1356_device::crt_display_fifo_hi_thresh_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_display_fifo_hi_thresh_w = %02x\n", machine().describe_context(), data);
+ m_crt_fifo_hi_thresh = data & CRTFIFO_MASK;
+}
+
+void sed1356_device::crt_display_fifo_lo_thresh_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_display_fifo_lo_thresh_w = %02x\n", machine().describe_context(), data);
+ m_crt_fifo_lo_thresh = data & CRTFIFO_MASK;
+}
+
+
+uint8_t sed1356_device::lcd_cursor_ctrl_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_cursor_ctrl_r: %02x\n", machine().describe_context(), m_lcd_cursor_ctrl);
+ return m_lcd_cursor_ctrl;
+}
+
+uint8_t sed1356_device::lcd_cursor_start_addr_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_cursor_start_addr_r: %02x\n", machine().describe_context(), m_lcd_cursor_addr);
+ return m_lcd_cursor_addr;
+}
+
+uint8_t sed1356_device::lcd_cursor_x_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_lcd_cursor_x >> (8 * offset));
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_cursor_x_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::lcd_cursor_y_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_lcd_cursor_y >> (8 * offset));
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_cursor_y_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::lcd_cursor_color0_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_cursor_color0_r[%d]: %02x\n", machine().describe_context(), offset, m_lcd_cursor_color0[offset]);
+ return m_lcd_cursor_color0[offset];
+}
+
+uint8_t sed1356_device::lcd_cursor_color1_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_cursor_color1_r[%d]: %02x\n", machine().describe_context(), offset, m_lcd_cursor_color1[offset]);
+ return m_lcd_cursor_color1[offset];
+}
+
+uint8_t sed1356_device::lcd_cursor_fifo_thresh_r(offs_t offset)
+{
+ LOGMASKED(LOG_LCD_RD, "%s: lcd_cursor_fifo_thresh_r: %02x\n", machine().describe_context(), offset, m_lcd_cursor_fifo_thresh);
+ return m_lcd_cursor_fifo_thresh;
+}
+
+void sed1356_device::lcd_cursor_ctrl_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_mode_names[4] = { "Inactive", "Cursor", "Ink", "Reserved" };
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_ctrl_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_LCD_WR, "%s: Cursor Mode: %s\n", machine().describe_context(), s_mode_names[(data & CURCTRL_MODE_MASK) >> CURCTRL_MODE_BIT]);
+ m_lcd_cursor_ctrl = data & CURCTRL_MASK;
+}
+
+void sed1356_device::lcd_cursor_start_addr_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_start_addr_w = %02x\n", machine().describe_context(), data);
+ m_lcd_cursor_addr = data;
+}
+
+void sed1356_device::lcd_cursor_x_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_x_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_lcd_cursor_x &= ~(0x00ff << shift);
+ m_lcd_cursor_x = (m_lcd_cursor_x | (data << shift)) & CURX_MASK;
+}
+
+void sed1356_device::lcd_cursor_y_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_y_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_lcd_cursor_y &= ~(0x00ff << shift);
+ m_lcd_cursor_y = (m_lcd_cursor_y | (data << shift)) & CURY_MASK;
+}
+
+void sed1356_device::lcd_cursor_color0_blu_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_color0_blu_w = %02x\n", machine().describe_context(), data);
+ m_lcd_cursor_color0[0] = data & CURB_MASK;
+}
+
+void sed1356_device::lcd_cursor_color0_grn_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_color0_grn_w = %02x\n", machine().describe_context(), data);
+ m_lcd_cursor_color0[1] = data & CURG_MASK;
+}
+
+void sed1356_device::lcd_cursor_color0_red_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_color0_red_w = %02x\n", machine().describe_context(), data);
+ m_lcd_cursor_color0[2] = data & CURR_MASK;
+}
+
+void sed1356_device::lcd_cursor_color1_blu_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_color1_blu_w = %02x\n", machine().describe_context(), data);
+ m_lcd_cursor_color1[0] = data & CURB_MASK;
+}
+
+void sed1356_device::lcd_cursor_color1_grn_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_color1_grn_w = %02x\n", machine().describe_context(), data);
+ m_lcd_cursor_color1[1] = data & CURG_MASK;
+}
+
+void sed1356_device::lcd_cursor_color1_red_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_color1_red_w = %02x\n", machine().describe_context(), data);
+ m_lcd_cursor_color1[2] = data & CURR_MASK;
+}
+
+void sed1356_device::lcd_cursor_fifo_thresh_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: lcd_cursor_fifo_thresh_w = %02x\n", machine().describe_context(), data);
+ m_lcd_cursor_fifo_thresh = data & CUR_FIFO_MASK;
+}
+
+
+uint8_t sed1356_device::crt_cursor_ctrl_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_cursor_ctrl_r: %02x\n", machine().describe_context(), m_crt_cursor_ctrl);
+ return m_crt_cursor_ctrl;
+}
+
+uint8_t sed1356_device::crt_cursor_start_addr_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_cursor_start_addr_r: %02x\n", machine().describe_context(), m_crt_cursor_addr);
+ return m_crt_cursor_addr;
+}
+
+uint8_t sed1356_device::crt_cursor_x_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_crt_cursor_x >> (8 * offset));
+ LOGMASKED(LOG_CRT_RD, "%s: crt_cursor_x_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::crt_cursor_y_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_crt_cursor_y >> (8 * offset));
+ LOGMASKED(LOG_CRT_RD, "%s: crt_cursor_y_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::crt_cursor_color0_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_cursor_color0_r[%d]: %02x\n", machine().describe_context(), offset, m_crt_cursor_color0[offset]);
+ return m_crt_cursor_color0[offset];
+}
+
+uint8_t sed1356_device::crt_cursor_color1_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_cursor_color1_r[%d]: %02x\n", machine().describe_context(), offset, m_crt_cursor_color1[offset]);
+ return m_crt_cursor_color1[offset];
+}
+
+uint8_t sed1356_device::crt_cursor_fifo_thresh_r(offs_t offset)
+{
+ LOGMASKED(LOG_CRT_RD, "%s: crt_cursor_fifo_thresh_r: %02x\n", machine().describe_context(), offset, m_crt_cursor_fifo_thresh);
+ return m_crt_cursor_fifo_thresh;
+}
+
+void sed1356_device::crt_cursor_ctrl_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_mode_names[4] = { "Inactive", "Cursor", "Ink", "Reserved" };
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_ctrl_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_CRT_WR, "%s: Cursor Mode: %s\n", machine().describe_context(), s_mode_names[(data & CURCTRL_MODE_MASK) >> CURCTRL_MODE_BIT]);
+ m_crt_cursor_ctrl = data & CURCTRL_MASK;
+}
+
+void sed1356_device::crt_cursor_start_addr_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_start_addr_w = %02x\n", machine().describe_context(), data);
+ m_crt_cursor_addr = data;
+}
+
+void sed1356_device::crt_cursor_x_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_x_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_crt_cursor_x &= ~(0x00ff << shift);
+ m_crt_cursor_x = (m_crt_cursor_x | (data << shift)) & CURX_MASK;
+}
+
+void sed1356_device::crt_cursor_y_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_y_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_crt_cursor_y &= ~(0x00ff << shift);
+ m_crt_cursor_y = (m_crt_cursor_y | (data << shift)) & CURY_MASK;
+}
+
+void sed1356_device::crt_cursor_color0_blu_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_color0_blu_w = %02x\n", machine().describe_context(), data);
+ m_crt_cursor_color0[0] = data & CURB_MASK;
+}
+
+void sed1356_device::crt_cursor_color0_grn_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_color0_grn_w = %02x\n", machine().describe_context(), data);
+ m_crt_cursor_color0[1] = data & CURG_MASK;
+}
+
+void sed1356_device::crt_cursor_color0_red_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LCD_WR, "%s: crt_cursor_color0_red_w = %02x\n", machine().describe_context(), data);
+ m_crt_cursor_color0[2] = data & CURR_MASK;
+}
+
+void sed1356_device::crt_cursor_color1_blu_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_color1_blu_w = %02x\n", machine().describe_context(), data);
+ m_crt_cursor_color1[0] = data & CURB_MASK;
+}
+
+void sed1356_device::crt_cursor_color1_grn_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_color1_grn_w = %02x\n", machine().describe_context(), data);
+ m_crt_cursor_color1[1] = data & CURG_MASK;
+}
+
+void sed1356_device::crt_cursor_color1_red_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_color1_red_w = %02x\n", machine().describe_context(), data);
+ m_crt_cursor_color1[2] = data & CURR_MASK;
+}
+
+void sed1356_device::crt_cursor_fifo_thresh_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_CRT_WR, "%s: crt_cursor_fifo_thresh_w = %02x\n", machine().describe_context(), data);
+ m_crt_cursor_fifo_thresh = data & CUR_FIFO_MASK;
+}
+
+
+uint8_t sed1356_device::bitblt_ctrl0_r(offs_t offset)
+{
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_ctrl0_r: %02x\n", machine().describe_context(), m_bitblt_ctrl[0]);
+ LOGMASKED(LOG_BITBLT_RD, "%s: FIFO Full: %d\n", machine().describe_context(), BIT(m_bitblt_ctrl[0], BBCTRL0_FULL_BIT));
+ LOGMASKED(LOG_BITBLT_RD, "%s: FIFO Half-Full: %d\n", machine().describe_context(), BIT(m_bitblt_ctrl[0], BBCTRL0_HALF_BIT));
+ LOGMASKED(LOG_BITBLT_RD, "%s: FIFO Not Empty: %d\n", machine().describe_context(), BIT(m_bitblt_ctrl[0], BBCTRL0_ANY_BIT));
+ LOGMASKED(LOG_BITBLT_RD, "%s: Active: %d\n", machine().describe_context(), BIT(m_bitblt_ctrl[0], BBCTRL0_ACTIVE_BIT));
+ return m_bitblt_ctrl[0];
+}
+
+uint8_t sed1356_device::bitblt_ctrl1_r(offs_t offset)
+{
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_ctrl1_r: %02x\n", machine().describe_context(), m_bitblt_ctrl[1]);
+ return m_bitblt_ctrl[1];
+}
+
+uint8_t sed1356_device::bitblt_rop_code_r(offs_t offset)
+{
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_rop_code_r: %02x\n", machine().describe_context(), m_bitblt_rop);
+ return m_bitblt_rop;
+}
+
+uint8_t sed1356_device::bitblt_operation_r(offs_t offset)
+{
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_operation_r: %02x\n", machine().describe_context(), m_bitblt_op);
+ return m_bitblt_op;
+}
+
+uint8_t sed1356_device::bitblt_src_start_addr_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_bitblt_src_addr >> (8 * offset));
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_src_start_addr_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::bitblt_dst_start_addr_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_bitblt_dst_addr >> (8 * offset));
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_dst_start_addr_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::bitblt_mem_addr_offset_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_bitblt_mem_offset >> (8 * offset));
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_mem_addr_offset_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::bitblt_width_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_bitblt_width >> (8 * offset));
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_width_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::bitblt_height_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_bitblt_height >> (8 * offset));
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_height_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::bitblt_bgcolor_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_bitblt_bgcolor >> (8 * offset));
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_bgcolor_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::bitblt_fgcolor_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_bitblt_fgcolor >> (8 * offset));
+ LOGMASKED(LOG_BITBLT_RD, "%s: bitblt_fgcolor_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+void sed1356_device::bitblt_ctrl0_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_ctrl0_w = %02x\n", machine().describe_context(), data);
+ m_bitblt_ctrl[0] &= ~BBCTRL0_WR_MASK;
+ m_bitblt_ctrl[0] |= data & BBCTRL0_WR_MASK;
+}
+
+void sed1356_device::bitblt_ctrl1_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_ctrl1_w = %02x\n", machine().describe_context(), data);
+ m_bitblt_ctrl[1] &= ~BBCTRL1_WR_MASK;
+ m_bitblt_ctrl[1] |= data & BBCTRL1_WR_MASK;
+}
+
+void sed1356_device::bitblt_rop_code_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_rop_code_w = %02x\n", machine().describe_context(), data);
+ m_bitblt_rop = data & BBCODE_MASK;
+}
+
+void sed1356_device::bitblt_operation_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_operation_w = %02x\n", machine().describe_context(), data);
+ m_bitblt_op = data & BBOP_MASK;
+}
+
+void sed1356_device::bitblt_src_start_addr_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_src_start_addr_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_bitblt_src_addr &= ~(0x00ff << shift);
+ m_bitblt_src_addr = (m_bitblt_src_addr | (data << shift)) & BBSRC_MASK;
+}
+
+void sed1356_device::bitblt_dst_start_addr_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_dst_start_addr_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_bitblt_dst_addr &= ~(0x00ff << shift);
+ m_bitblt_dst_addr = (m_bitblt_dst_addr | (data << shift)) & BBDST_MASK;
+}
+
+void sed1356_device::bitblt_mem_addr_offset_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_mem_addr_offset_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_bitblt_mem_offset &= ~(0x00ff << shift);
+ m_bitblt_mem_offset = (m_bitblt_mem_offset | (data << shift)) & BBMADR_MASK;
+}
+
+void sed1356_device::bitblt_width_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_width_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_bitblt_width &= ~(0x00ff << shift);
+ m_bitblt_width = (m_bitblt_width | (data << shift)) & BBWIDTH_MASK;
+}
+
+void sed1356_device::bitblt_height_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_height_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_bitblt_height &= ~(0x00ff << shift);
+ m_bitblt_height = (m_bitblt_height | (data << shift)) & BBHEIGHT_MASK;
+}
+
+void sed1356_device::bitblt_bgcolor_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_bgcolor_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_bitblt_bgcolor &= ~(0x00ff << shift);
+ m_bitblt_bgcolor |= (data << shift);
+}
+
+void sed1356_device::bitblt_fgcolor_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: bitblt_fgcolor_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_bitblt_fgcolor &= ~(0x00ff << shift);
+ m_bitblt_fgcolor |= (data << shift);
+}
+
+
+uint8_t sed1356_device::lut_mode_r(offs_t offset)
+{
+ LOGMASKED(LOG_LUT_RD, "%s: lut_mode_r: %02x\n", machine().describe_context(), m_lut_mode);
+ return m_lut_mode;
+}
+
+uint8_t sed1356_device::lut_addr_r(offs_t offset)
+{
+ LOGMASKED(LOG_LUT_RD, "%s: lut_addr_r: %02x\n", machine().describe_context(), m_lut_addr);
+ return m_lut_addr;
+}
+
+uint8_t sed1356_device::lut_data_r(offs_t offset)
+{
+ LOGMASKED(LOG_LUT_RD, "%s: lut_data_r: %02x\n", machine().describe_context(), m_lut_data);
+ return m_lut_data;
+}
+
+void sed1356_device::lut_mode_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LUT_WR, "%s: lut_mode_w = %02x\n", machine().describe_context(), data);
+ m_lut_mode = data & LUTMODE_MASK;
+}
+
+void sed1356_device::lut_addr_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LUT_WR, "%s: lut_addr_w = %02x\n", machine().describe_context(), data);
+ m_lut_addr = data;
+}
+
+void sed1356_device::lut_data_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_LUT_WR, "%s: lut_data_w = %02x\n", machine().describe_context(), data);
+ m_lut_data = data & LUTDATA_MASK;
+}
+
+
+uint8_t sed1356_device::power_config_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: power_config_r: %02x\n", machine().describe_context(), m_power_config);
+ return m_power_config;
+}
+
+uint8_t sed1356_device::power_status_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: power_status_r: %02x\n", machine().describe_context(), m_power_status);
+ return m_power_status;
+}
+
+void sed1356_device::power_config_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: power_config_w = %02x\n", machine().describe_context(), data);
+ m_power_config = data & PWRCFG_MASK;
+}
+
+
+uint8_t sed1356_device::cpu_mem_watchdog_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: cpu_mem_watchdog_r: %02x\n", machine().describe_context(), m_watchdog);
+ return m_watchdog;
+}
+
+void sed1356_device::cpu_mem_watchdog_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MISC_WR, "%s: cpu_mem_watchdog_w = %02x\n", machine().describe_context(), data);
+ m_watchdog = data & WATCHDOG_MASK;
+}
+
+
+uint8_t sed1356_device::display_mode_r(offs_t offset)
+{
+ LOGMASKED(LOG_MISC_RD, "%s: display_mode_r: %02x\n", machine().describe_context(), m_display_mode);
+ return m_display_mode;
+}
+
+void sed1356_device::display_mode_w(offs_t offset, uint8_t data)
+{
+ static const char *const s_mode_names[8] =
+ {
+ "No Display",
+ "LCD only",
+ "CRT only",
+ "Double, CRT and LCD",
+ "TV w/ no flicker filter",
+ "Double, TV w/ no flicker filter and LCD",
+ "TV w/ flicker filter",
+ "Double, TV w/ flicker filter and LCD"
+ };
+ LOGMASKED(LOG_MISC_WR, "%s: display_mode_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_MISC_WR, "%s: Display Mode: %s\n", machine().describe_context(), s_mode_names[(data & DISPMODE_MODE_MASK) >> DISPMODE_MODE_BIT]);
+ LOGMASKED(LOG_MISC_WR, "%s: SwivelView Enable Bit 0: %d\n", machine().describe_context(), BIT(data, DISPMODE_SWIVEN0_BIT));
+ m_display_mode = data & DISPMODE_MASK;
+}
+
+
+uint8_t sed1356_device::mplug_lcmd_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_mplug_lcmd >> (8 * offset));
+ LOGMASKED(LOG_MPLUG_RD, "%s: mplug_lcmd_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::mplug_resv_lcmd_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_mplug_resv_lcmd >> (8 * offset));
+ LOGMASKED(LOG_MPLUG_RD, "%s: mplug_resv_lcmd_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::mplug_cmd_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_mplug_cmd >> (8 * offset));
+ LOGMASKED(LOG_MPLUG_RD, "%s: mplug_cmd_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::mplug_resv_cmd_r(offs_t offset)
+{
+ const uint8_t data = (uint8_t)(m_mplug_resv_cmd >> (8 * offset));
+ LOGMASKED(LOG_MPLUG_RD, "%s: mplug_resv_cmd_r[%d]: %02x\n", machine().describe_context(), offset, data);
+ return data;
+}
+
+uint8_t sed1356_device::mplug_data_r(offs_t offset)
+{
+ LOGMASKED(LOG_MPLUG_RD, "%s: (not implemented) mplug_data_r[%04x]: %02x\n", machine().describe_context(), 0x1008 + offset, 0);
+ return 0;
+}
+
+void sed1356_device::mplug_lcmd_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MPLUG_WR, "%s: mplug_lcmd_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_mplug_lcmd &= ~(0x00ff << shift);
+ m_mplug_lcmd |= (data << shift);
+}
+
+void sed1356_device::mplug_resv_lcmd_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MPLUG_WR, "%s: mplug_resv_lcmd_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_mplug_resv_lcmd &= ~(0x00ff << shift);
+ m_mplug_resv_lcmd |= (data << shift);
+}
+
+void sed1356_device::mplug_cmd_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MPLUG_WR, "%s: mplug_cmd_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_mplug_cmd &= ~(0x00ff << shift);
+ m_mplug_cmd |= (data << shift);
+}
+
+void sed1356_device::mplug_resv_cmd_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MPLUG_WR, "%s: mplug_resv_cmd_w[%d] = %02x\n", machine().describe_context(), offset, data);
+ const uint16_t shift = 8 * offset;
+ m_mplug_resv_cmd &= ~(0x00ff << shift);
+ m_mplug_resv_cmd |= (data << shift);
+}
+
+void sed1356_device::mplug_data_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_MPLUG_WR, "%s: (not implemented) mplug_data_w[%04x]: %02x\n", machine().describe_context(), 0x1008 + offset, data);
+}
+
+
+uint8_t sed1356_device::bitblt_data_r(offs_t offset)
+{
+ LOGMASKED(LOG_BITBLT_RD, "%s: (not implemented) bitblt_data_r[%06x]: %02x\n", machine().describe_context(), 0x100000 + offset, 0);
+ return 0;
+}
+
+void sed1356_device::bitblt_data_w(offs_t offset, uint8_t data)
+{
+ LOGMASKED(LOG_BITBLT_WR, "%s: (not implemented) bitblt_data_w[%06x]: %02x\n", machine().describe_context(), 0x100000 + offset, data);
+}
+
+void sed1356_device::device_start()
+{
+ save_item(NAME(m_misc));
+ save_item(NAME(m_gpio_config));
+ save_item(NAME(m_gpio_ctrl));
+ save_item(NAME(m_md_config));
+
+ save_item(NAME(m_memclk_config));
+ save_item(NAME(m_lcd_pclk_config));
+ save_item(NAME(m_crt_pclk_config));
+ save_item(NAME(m_mplug_clk_config));
+
+ save_item(NAME(m_wait_state_sel));
+ save_item(NAME(m_mem_config));
+ save_item(NAME(m_dram_refresh));
+ save_item(NAME(m_dram_timing));
+
+ save_item(NAME(m_panel_type));
+ save_item(NAME(m_mod_rate));
+
+ save_item(NAME(m_lcd_width));
+ save_item(NAME(m_lcd_hblank_period));
+ save_item(NAME(m_tft_fpline_start));
+ save_item(NAME(m_tft_fpline_width));
+ save_item(NAME(m_lcd_height));
+ save_item(NAME(m_lcd_vblank_period));
+ save_item(NAME(m_tft_fpframe_start));
+ save_item(NAME(m_tft_fpframe_width));
+ save_item(NAME(m_lcd_mode));
+ save_item(NAME(m_lcd_misc));
+ save_item(NAME(m_lcd_addr));
+ save_item(NAME(m_lcd_mem_offset));
+ save_item(NAME(m_lcd_pan));
+ save_item(NAME(m_lcd_fifo_hi_thresh));
+ save_item(NAME(m_lcd_fifo_lo_thresh));
+
+ save_item(NAME(m_crt_width));
+ save_item(NAME(m_crt_hblank_period));
+ save_item(NAME(m_crt_hrtc_start));
+ save_item(NAME(m_crt_hrtc_width));
+ save_item(NAME(m_crt_height));
+ save_item(NAME(m_crt_vblank_period));
+ save_item(NAME(m_crt_vrtc_start));
+ save_item(NAME(m_crt_vrtc_width));
+ save_item(NAME(m_crt_output_ctrl));
+ save_item(NAME(m_crt_mode));
+ save_item(NAME(m_crt_addr));
+ save_item(NAME(m_crt_mem_offset));
+ save_item(NAME(m_crt_pan));
+ save_item(NAME(m_crt_fifo_hi_thresh));
+ save_item(NAME(m_crt_fifo_lo_thresh));
+
+ save_item(NAME(m_lcd_cursor_ctrl));
+ save_item(NAME(m_lcd_cursor_addr));
+ save_item(NAME(m_lcd_cursor_x));
+ save_item(NAME(m_lcd_cursor_y));
+ save_item(NAME(m_lcd_cursor_color0));
+ save_item(NAME(m_lcd_cursor_color1));
+ save_item(NAME(m_lcd_cursor_fifo_thresh));
+
+ save_item(NAME(m_crt_cursor_ctrl));
+ save_item(NAME(m_crt_cursor_addr));
+ save_item(NAME(m_crt_cursor_x));
+ save_item(NAME(m_crt_cursor_y));
+ save_item(NAME(m_crt_cursor_color0));
+ save_item(NAME(m_crt_cursor_color1));
+ save_item(NAME(m_crt_cursor_fifo_thresh));
+
+ save_item(NAME(m_bitblt_ctrl));
+ save_item(NAME(m_bitblt_rop));
+ save_item(NAME(m_bitblt_op));
+ save_item(NAME(m_bitblt_src_addr));
+ save_item(NAME(m_bitblt_dst_addr));
+ save_item(NAME(m_bitblt_mem_offset));
+ save_item(NAME(m_bitblt_width));
+ save_item(NAME(m_bitblt_height));
+ save_item(NAME(m_bitblt_bgcolor));
+ save_item(NAME(m_bitblt_fgcolor));
+
+ save_item(NAME(m_lut_mode));
+ save_item(NAME(m_lut_addr));
+ save_item(NAME(m_lut_data));
+
+ save_item(NAME(m_power_config));
+ save_item(NAME(m_power_status));
+
+ save_item(NAME(m_watchdog));
+
+ save_item(NAME(m_display_mode));
+
+ save_item(NAME(m_mplug_lcmd));
+ save_item(NAME(m_mplug_resv_lcmd));
+ save_item(NAME(m_mplug_cmd));
+ save_item(NAME(m_mplug_resv_cmd));
+}
+
+void sed1356_device::device_reset()
+{
+ m_misc = 0;
+ m_gpio_config = 0;
+ m_gpio_ctrl = 0;
+ m_md_config[0] = 0;
+ m_md_config[1] = 0;
+
+ m_memclk_config = 0;
+ m_lcd_pclk_config = 0;
+ m_crt_pclk_config = 0;
+ m_mplug_clk_config = 0;
+
+ m_wait_state_sel = 0;
+ m_mem_config = 0;
+ m_dram_refresh = 0;
+ m_dram_timing[0] = 0;
+ m_dram_timing[1] = 0;
+
+ m_panel_type = 0;
+ m_mod_rate = 0;
+
+ m_lcd_width = 0;
+ m_lcd_hblank_period = 0;
+ m_tft_fpline_start = 0;
+ m_tft_fpline_width = 0;
+ m_lcd_height = 0;
+ m_lcd_vblank_period = 0;
+ m_tft_fpframe_start = 0;
+ m_tft_fpframe_width = 0;
+ m_lcd_mode = 0;
+ m_lcd_misc = 0;
+ m_lcd_addr = 0;
+ m_lcd_mem_offset = 0;
+ m_lcd_pan = 0;
+ m_lcd_fifo_hi_thresh = 0;
+ m_lcd_fifo_lo_thresh = 0;
+
+ m_crt_width = 0;
+ m_crt_hblank_period = 0;
+ m_crt_hrtc_start = 0;
+ m_crt_hrtc_width = 0;
+ m_crt_height = 0;
+ m_crt_vblank_period = 0;
+ m_crt_vrtc_start = 0;
+ m_crt_vrtc_width = 0;
+ m_crt_output_ctrl = 0;
+ m_crt_mode = 0;
+ m_crt_addr = 0;
+ m_crt_mem_offset = 0;
+ m_crt_pan = 0;
+ m_crt_fifo_hi_thresh = 0;
+ m_crt_fifo_lo_thresh = 0;
+
+ m_lcd_cursor_ctrl = 0;
+ m_lcd_cursor_addr = 0;
+ m_lcd_cursor_x = 0;
+ m_lcd_cursor_y = 0;
+ m_lcd_cursor_color0[0] = 0;
+ m_lcd_cursor_color0[1] = 0;
+ m_lcd_cursor_color0[2] = 0;
+ m_lcd_cursor_color1[0] = 0;
+ m_lcd_cursor_color1[1] = 0;
+ m_lcd_cursor_color1[2] = 0;
+ m_lcd_cursor_fifo_thresh = 0;
+
+ m_crt_cursor_ctrl = 0;
+ m_crt_cursor_addr = 0;
+ m_crt_cursor_x = 0;
+ m_crt_cursor_y = 0;
+ m_crt_cursor_color0[0] = 0;
+ m_crt_cursor_color0[1] = 0;
+ m_crt_cursor_color0[2] = 0;
+ m_crt_cursor_color1[0] = 0;
+ m_crt_cursor_color1[1] = 0;
+ m_crt_cursor_color1[2] = 0;
+ m_crt_cursor_fifo_thresh = 0;
+
+ m_bitblt_ctrl[0] = 0;
+ m_bitblt_ctrl[1] = 0;
+ m_bitblt_rop = 0;
+ m_bitblt_op = 0;
+ m_bitblt_src_addr = 0;
+ m_bitblt_dst_addr = 0;
+ m_bitblt_mem_offset = 0;
+ m_bitblt_width = 0;
+ m_bitblt_height = 0;
+ m_bitblt_bgcolor = 0;
+ m_bitblt_fgcolor = 0;
+
+ m_lut_mode = 0;
+ m_lut_addr = 0;
+ m_lut_data = 0;
+
+ m_power_config = 0;
+ m_power_status = 0;
+
+ m_watchdog = 0;
+
+ m_display_mode = 0;
+
+ m_mplug_lcmd = 0;
+ m_mplug_resv_lcmd = 0;
+ m_mplug_cmd = 0;
+ m_mplug_resv_cmd = 0;
+}
+
+uint32_t sed1356_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
+ {
+ const uint16_t *src = (uint16_t*)&m_vram[y * (0x500 >> 2)];
+ uint32_t *dst = &bitmap.pix(y);
+ for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
+ {
+ const uint16_t pix = src[x];
+ const uint8_t src_red = (uint8_t)((pix >> 11) & 0x1f);
+ const uint8_t src_grn = (uint8_t)((pix >> 5) & 0x3f);
+ const uint8_t src_blu = (uint8_t)(pix & 0x1f);
+ const uint32_t dst_red = ((src_red << 3) | (src_red >> 2)) & 0x000000ff;
+ const uint32_t dst_grn = ((src_grn << 2) | (src_grn >> 4)) & 0x000000ff;
+ const uint32_t dst_blu = ((src_blu << 3) | (src_blu >> 2)) & 0x000000ff;
+ dst[x] = 0xff000000 | (dst_red << 16) | (dst_grn << 8) | dst_blu;
+ }
+ }
+ return 0;
+}
diff --git a/src/devices/video/sed1356.h b/src/devices/video/sed1356.h
new file mode 100644
index 00000000000..4bd06b94fca
--- /dev/null
+++ b/src/devices/video/sed1356.h
@@ -0,0 +1,547 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/**********************************************************************
+
+ Epson SED1356 LCD Controller emulation skeleton
+
+ Status:
+ - Currently hard-coded for use with the Jornada 720 driver.
+ - Register contents are correctly stored, logged and masked, but
+ register handling is otherwise non-present.
+
+**********************************************************************/
+
+#ifndef MAME_VIDEO_SED1356_H
+#define MAME_VIDEO_SED1356_H
+
+#pragma once
+
+class sed1356_device : public device_t,
+ public device_video_interface
+{
+public:
+ // construction/destruction
+ sed1356_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ void map(address_map &map);
+ void vram_map(address_map &map);
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ uint8_t revision_r(offs_t offset);
+
+ uint8_t misc_r(offs_t offset);
+ void misc_w(offs_t offset, uint8_t data);
+
+ uint8_t gpio_config_r(offs_t offset);
+ void gpio_config_w(offs_t offset, uint8_t data);
+ uint8_t gpio_ctrl_r(offs_t offset);
+ void gpio_ctrl_w(offs_t offset, uint8_t data);
+
+ uint8_t md_config_readback_r(offs_t offset);
+ void md_config_readback_w(offs_t offset, uint8_t data);
+
+ uint8_t mem_clk_config_r(offs_t offset);
+ uint8_t lcd_pclk_config_r(offs_t offset);
+ uint8_t crt_pclk_config_r(offs_t offset);
+ uint8_t mplug_clk_config_r(offs_t offset);
+ void mem_clk_config_w(offs_t offset, uint8_t data);
+ void lcd_pclk_config_w(offs_t offset, uint8_t data);
+ void crt_pclk_config_w(offs_t offset, uint8_t data);
+ void mplug_clk_config_w(offs_t offset, uint8_t data);
+
+ uint8_t mem_wait_select_r(offs_t offset);
+ uint8_t mem_config_r(offs_t offset);
+ uint8_t dram_refresh_select_r(offs_t offset);
+ uint8_t dram_timing_ctrl_r(offs_t offset);
+ void mem_wait_select_w(offs_t offset, uint8_t data);
+ void mem_config_w(offs_t offset, uint8_t data);
+ void dram_refresh_select_w(offs_t offset, uint8_t data);
+ void dram_timing_ctrl0_w(offs_t offset, uint8_t data);
+ void dram_timing_ctrl1_w(offs_t offset, uint8_t data);
+
+ uint8_t panel_type_r(offs_t offset);
+ uint8_t mod_rate_r(offs_t offset);
+ void panel_type_w(offs_t offset, uint8_t data);
+ void mod_rate_w(offs_t offset, uint8_t data);
+
+ uint8_t lcd_display_width_r(offs_t offset);
+ uint8_t lcd_hblank_period_r(offs_t offset);
+ uint8_t tft_fpline_start_pos_r(offs_t offset);
+ uint8_t tft_fpline_pulse_width_r(offs_t offset);
+ uint8_t lcd_display_height_r(offs_t offset);
+ uint8_t lcd_vblank_period_r(offs_t offset);
+ uint8_t tft_fpframe_start_pos_r(offs_t offset);
+ uint8_t tft_fpframe_pulse_width_r(offs_t offset);
+ uint8_t lcd_display_mode_r(offs_t offset);
+ uint8_t lcd_misc_r(offs_t offset);
+ uint8_t lcd_display_start_addr_r(offs_t offset);
+ uint8_t lcd_mem_addr_offset_r(offs_t offset);
+ uint8_t lcd_pixel_pan_r(offs_t offset);
+ uint8_t lcd_display_fifo_hi_thresh_r(offs_t offset);
+ uint8_t lcd_display_fifo_lo_thresh_r(offs_t offset);
+ void lcd_display_width_w(offs_t offset, uint8_t data);
+ void lcd_hblank_period_w(offs_t offset, uint8_t data);
+ void tft_fpline_start_pos_w(offs_t offset, uint8_t data);
+ void tft_fpline_pulse_width_w(offs_t offset, uint8_t data);
+ void lcd_display_height_w(offs_t offset, uint8_t data);
+ void lcd_vblank_period_w(offs_t offset, uint8_t data);
+ void tft_fpframe_start_pos_w(offs_t offset, uint8_t data);
+ void tft_fpframe_pulse_width_w(offs_t offset, uint8_t data);
+ void lcd_display_mode_w(offs_t offset, uint8_t data);
+ void lcd_misc_w(offs_t offset, uint8_t data);
+ void lcd_display_start_addr_w(offs_t offset, uint8_t data);
+ void lcd_mem_addr_offset_w(offs_t offset, uint8_t data);
+ void lcd_pixel_pan_w(offs_t offset, uint8_t data);
+ void lcd_display_fifo_hi_thresh_w(offs_t offset, uint8_t data);
+ void lcd_display_fifo_lo_thresh_w(offs_t offset, uint8_t data);
+
+ uint8_t crt_display_width_r(offs_t offset);
+ uint8_t crt_hblank_period_r(offs_t offset);
+ uint8_t crt_hrtc_start_pos_r(offs_t offset);
+ uint8_t crt_hrtc_pulse_width_r(offs_t offset);
+ uint8_t crt_display_height_r(offs_t offset);
+ uint8_t crt_vblank_period_r(offs_t offset);
+ uint8_t crt_vrtc_start_pos_r(offs_t offset);
+ uint8_t crt_vrtc_pulse_width_r(offs_t offset);
+ uint8_t crt_output_ctrl_r(offs_t offset);
+ uint8_t crt_display_mode_r(offs_t offset);
+ uint8_t crt_display_start_addr_r(offs_t offset);
+ uint8_t crt_mem_addr_offset_r(offs_t offset);
+ uint8_t crt_pixel_pan_r(offs_t offset);
+ uint8_t crt_display_fifo_hi_thresh_r(offs_t offset);
+ uint8_t crt_display_fifo_lo_thresh_r(offs_t offset);
+ void crt_display_width_w(offs_t offset, uint8_t data);
+ void crt_hblank_period_w(offs_t offset, uint8_t data);
+ void crt_hrtc_start_pos_w(offs_t offset, uint8_t data);
+ void crt_hrtc_pulse_width_w(offs_t offset, uint8_t data);
+ void crt_display_height_w(offs_t offset, uint8_t data);
+ void crt_vblank_period_w(offs_t offset, uint8_t data);
+ void crt_vrtc_start_pos_w(offs_t offset, uint8_t data);
+ void crt_vrtc_pulse_width_w(offs_t offset, uint8_t data);
+ void crt_output_ctrl_w(offs_t offset, uint8_t data);
+ void crt_display_mode_w(offs_t offset, uint8_t data);
+ void crt_display_start_addr_w(offs_t offset, uint8_t data);
+ void crt_mem_addr_offset_w(offs_t offset, uint8_t data);
+ void crt_pixel_pan_w(offs_t offset, uint8_t data);
+ void crt_display_fifo_hi_thresh_w(offs_t offset, uint8_t data);
+ void crt_display_fifo_lo_thresh_w(offs_t offset, uint8_t data);
+
+ uint8_t lcd_cursor_ctrl_r(offs_t offset);
+ uint8_t lcd_cursor_start_addr_r(offs_t offset);
+ uint8_t lcd_cursor_x_r(offs_t offset);
+ uint8_t lcd_cursor_y_r(offs_t offset);
+ uint8_t lcd_cursor_color0_r(offs_t offset);
+ uint8_t lcd_cursor_color1_r(offs_t offset);
+ uint8_t lcd_cursor_fifo_thresh_r(offs_t offset);
+ void lcd_cursor_ctrl_w(offs_t offset, uint8_t data);
+ void lcd_cursor_start_addr_w(offs_t offset, uint8_t data);
+ void lcd_cursor_x_w(offs_t offset, uint8_t data);
+ void lcd_cursor_y_w(offs_t offset, uint8_t data);
+ void lcd_cursor_color0_blu_w(offs_t offset, uint8_t data);
+ void lcd_cursor_color0_grn_w(offs_t offset, uint8_t data);
+ void lcd_cursor_color0_red_w(offs_t offset, uint8_t data);
+ void lcd_cursor_color1_blu_w(offs_t offset, uint8_t data);
+ void lcd_cursor_color1_grn_w(offs_t offset, uint8_t data);
+ void lcd_cursor_color1_red_w(offs_t offset, uint8_t data);
+ void lcd_cursor_fifo_thresh_w(offs_t offset, uint8_t data);
+
+ uint8_t crt_cursor_ctrl_r(offs_t offset);
+ uint8_t crt_cursor_start_addr_r(offs_t offset);
+ uint8_t crt_cursor_x_r(offs_t offset);
+ uint8_t crt_cursor_y_r(offs_t offset);
+ uint8_t crt_cursor_color0_r(offs_t offset);
+ uint8_t crt_cursor_color1_r(offs_t offset);
+ uint8_t crt_cursor_fifo_thresh_r(offs_t offset);
+ void crt_cursor_ctrl_w(offs_t offset, uint8_t data);
+ void crt_cursor_start_addr_w(offs_t offset, uint8_t data);
+ void crt_cursor_x_w(offs_t offset, uint8_t data);
+ void crt_cursor_y_w(offs_t offset, uint8_t data);
+ void crt_cursor_color0_blu_w(offs_t offset, uint8_t data);
+ void crt_cursor_color0_grn_w(offs_t offset, uint8_t data);
+ void crt_cursor_color0_red_w(offs_t offset, uint8_t data);
+ void crt_cursor_color1_blu_w(offs_t offset, uint8_t data);
+ void crt_cursor_color1_grn_w(offs_t offset, uint8_t data);
+ void crt_cursor_color1_red_w(offs_t offset, uint8_t data);
+ void crt_cursor_fifo_thresh_w(offs_t offset, uint8_t data);
+
+ uint8_t bitblt_ctrl0_r(offs_t offset);
+ uint8_t bitblt_ctrl1_r(offs_t offset);
+ uint8_t bitblt_rop_code_r(offs_t offset);
+ uint8_t bitblt_operation_r(offs_t offset);
+ uint8_t bitblt_src_start_addr_r(offs_t offset);
+ uint8_t bitblt_dst_start_addr_r(offs_t offset);
+ uint8_t bitblt_mem_addr_offset_r(offs_t offset);
+ uint8_t bitblt_width_r(offs_t offset);
+ uint8_t bitblt_height_r(offs_t offset);
+ uint8_t bitblt_bgcolor_r(offs_t offset);
+ uint8_t bitblt_fgcolor_r(offs_t offset);
+ void bitblt_ctrl0_w(offs_t offset, uint8_t data);
+ void bitblt_ctrl1_w(offs_t offset, uint8_t data);
+ void bitblt_rop_code_w(offs_t offset, uint8_t data);
+ void bitblt_operation_w(offs_t offset, uint8_t data);
+ void bitblt_src_start_addr_w(offs_t offset, uint8_t data);
+ void bitblt_dst_start_addr_w(offs_t offset, uint8_t data);
+ void bitblt_mem_addr_offset_w(offs_t offset, uint8_t data);
+ void bitblt_width_w(offs_t offset, uint8_t data);
+ void bitblt_height_w(offs_t offset, uint8_t data);
+ void bitblt_bgcolor_w(offs_t offset, uint8_t data);
+ void bitblt_fgcolor_w(offs_t offset, uint8_t data);
+
+ uint8_t lut_mode_r(offs_t offset);
+ uint8_t lut_addr_r(offs_t offset);
+ uint8_t lut_data_r(offs_t offset);
+ void lut_mode_w(offs_t offset, uint8_t data);
+ void lut_addr_w(offs_t offset, uint8_t data);
+ void lut_data_w(offs_t offset, uint8_t data);
+
+ uint8_t power_config_r(offs_t offset);
+ uint8_t power_status_r(offs_t offset);
+ void power_config_w(offs_t offset, uint8_t data);
+
+ uint8_t cpu_mem_watchdog_r(offs_t offset);
+ void cpu_mem_watchdog_w(offs_t offset, uint8_t data);
+
+ uint8_t display_mode_r(offs_t offset);
+ void display_mode_w(offs_t offset, uint8_t data);
+
+ uint8_t mplug_lcmd_r(offs_t offset);
+ uint8_t mplug_resv_lcmd_r(offs_t offset);
+ uint8_t mplug_cmd_r(offs_t offset);
+ uint8_t mplug_resv_cmd_r(offs_t offset);
+ uint8_t mplug_data_r(offs_t offset);
+ void mplug_lcmd_w(offs_t offset, uint8_t data);
+ void mplug_resv_lcmd_w(offs_t offset, uint8_t data);
+ void mplug_cmd_w(offs_t offset, uint8_t data);
+ void mplug_resv_cmd_w(offs_t offset, uint8_t data);
+ void mplug_data_w(offs_t offset, uint8_t data);
+
+ uint8_t bitblt_data_r(offs_t offset);
+ void bitblt_data_w(offs_t offset, uint8_t data);
+
+ enum
+ {
+ MISC_RMS_BIT = 7,
+ MISC_MASK = 0x80,
+
+ GPCFG_GPIO1_BIT = 1,
+ GPCFG_GPIO2_BIT = 2,
+ GPCFG_GPIO3_BIT = 3,
+ GPCFG_MASK = 0x0e,
+
+ GPCTRL_GPIO1_BIT = 1,
+ GPCTRL_GPIO2_BIT = 2,
+ GPCTRL_GPIO3_BIT = 3,
+ GPCTRL_MASK = 0x0e,
+
+ MEMCLK_SRC_BIT = 0,
+ MEMCLK_DIV_BIT = 4,
+ MEMCLK_MASK = 0x11,
+
+ LCDCLK_SRC_BIT = 0,
+ LCDCLK_SRC_MASK = 0x03,
+ LCDCLK_DIV_BIT = 4,
+ LCDCLK_DIV_MASK = 0x30,
+ LCDCLK_MASK = 0x33,
+
+ CRTCLK_SRC_BIT = 0,
+ CRTCLK_SRC_MASK = 0x03,
+ CRTCLK_DIV_BIT = 4,
+ CRTCLK_DIV_MASK = 0x30,
+ CRTCLK_2X_BIT = 7,
+ CRTCLK_MASK = 0xb3,
+
+ PLUGCLK_SRC_BIT = 0,
+ PLUGCLK_SRC_MASK = 0x03,
+ PLUGCLK_DIV_BIT = 4,
+ PLUGCLK_DIV_MASK = 0x30,
+ PLUGCLK_MASK = 0x33,
+
+ CPUWAIT_SEL_BIT = 0,
+ CPUWAIT_SEL_MASK = 0x03,
+ CPUWAIT_MASK = 0x03,
+
+ MEMCFG_TYPE_BIT = 0,
+ MEMCFG_TYPE_MASK = 0x03,
+ MEMCFG_MASK = 0x03,
+
+ MEMRFSH_RATE_BIT = 0,
+ MEMRFSH_RATE_MASK = 0x07,
+ MEMRFSH_SEL_BIT = 6,
+ MEMRFSH_SEL_MASK = 0xc0,
+ MEMRFSH_MASK = 0xc7,
+
+ DRAMTIME1_MASK = 0x03,
+
+ PTYPE_TFT_PASS_BIT = 0,
+ PTYPE_COUNT_BIT = 1,
+ PTYPE_COLOR_BIT = 2,
+ PTYPE_FORMAT_BIT = 3,
+ PTYPE_WIDTH_BIT = 4,
+ PTYPE_WIDTH_MASK = 0x30,
+ PTYPE_EL_BIT = 7,
+ PTYPE_MASK = 0xbf,
+
+ MODRATE_MASK = 0x3f,
+
+ LCDW_MASK = 0x7f,
+
+ LCDHBL_MASK = 0x1f,
+
+ TFTFPLS_MASK = 0x1f,
+
+ TFTFPLW_WIDTH_BIT = 0,
+ TFTFPLW_WIDTH_MASK = 0x0f,
+ TFTFPLW_POL_BIT = 7,
+ TFTFPLW_MASK = 0x8f,
+
+ LCDH_MASK = 0x03ff,
+
+ LCDVBL_VALUE_BIT = 0,
+ LCDVBL_VALUE_MASK = 0x3f,
+ LCDVBL_STATUS_BIT = 7,
+ LCDVBL_MASK = 0x3f,
+
+ TFTFPFS_MASK = 0x3f,
+
+ TFTFPFW_WIDTH_BIT = 0,
+ TFTFPFW_WIDTH_MASK = 0x07,
+ TFTFPFW_POL_BIT = 7,
+ TFTFPFW_MASK = 0x87,
+
+ LCDMODE_BPP_BIT = 0,
+ LCDMODE_BPP_MASK = 0x07,
+ LCDMODE_SWIVEN1_BIT = 4,
+ LCDMODE_BLANK_BIT = 7,
+ LCDMODE_MASK = 0x97,
+
+ LCDMISC_DPDIS_BIT = 0,
+ LCDMISC_DITHDIS_BIT = 1,
+ LCDMISC_MASK = 0x03,
+
+ LCDDS_MASK = 0x000fffff,
+
+ LCDMOFS_MASK = 0x07ff,
+
+ LCDPAN_PAN_BIT = 0,
+ LCDPAN_PAN_MASK = 0x03,
+ LCDPAN_MASK = 0x03,
+
+ LCDFIFO_MASK = 0x3f,
+
+ CRTW_MASK = 0x7f,
+
+ CRTHBL_MASK = 0x3f,
+
+ CRTHRTS_MASK = 0x3f,
+
+ CRTHRTW_WIDTH_BIT = 0,
+ CRTHRTW_WIDTH_MASK = 0x0f,
+ CRTHRTW_POL_BIT = 7,
+ CRTHRTW_MASK = 0x8f,
+
+ CRTH_MASK = 0x03ff,
+
+ CRTVBL_VALUE_BIT = 0,
+ CRTVBL_VALUE_MASK = 0x7f,
+ CRTVBL_STATUS_BIT = 7,
+ CRTVBL_MASK = 0xff,
+
+ CRTVRTS_MASK = 0x7f,
+
+ CRTVRTW_WIDTH_BIT = 0,
+ CRTVRTW_WIDTH_MASK = 0x07,
+ CRTVRTW_POL_BIT = 7,
+ CRTVRTW_MASK = 0x87,
+
+ CRTCTRL_PAL_BIT = 0,
+ CRTCTRL_SVID_BIT = 1,
+ CRTCTRL_DACLVL_BIT = 3,
+ CRTCTRL_LUMF_BIT = 4,
+ CRTCTRL_CHRF_BIT = 5,
+ CRTCTRL_MASK = 0x3b,
+
+ CRTMODE_BPP_BIT = 0,
+ CRTMODE_BPP_MASK = 0x07,
+ CRTMODE_BLANK_BIT = 7,
+ CRTMODE_MASK = 0x87,
+
+ CRTDS_MASK = 0x000fffff,
+
+ CRTMOFS_MASK = 0x07ff,
+
+ CRTPAN_PAN_BIT = 0,
+ CRTPAN_PAN_MASK = 0x03,
+ CRTPAN_MASK = 0x03,
+
+ CRTFIFO_MASK = 0x3f,
+
+ CURCTRL_MODE_BIT = 0,
+ CURCTRL_MODE_MASK = 0x03,
+ CURCTRL_MASK = 0x03,
+
+ CURX_SIGN_BIT = 15,
+ CURX_MASK = 0x83ff,
+
+ CURY_SIGN_BIT = 15,
+ CURY_MASK = 0x83ff,
+
+ CURB_MASK = 0x1f,
+ CURG_MASK = 0x3f,
+ CURR_MASK = 0x1f,
+
+ CUR_FIFO_MASK = 0x0f,
+
+ BBCTRL0_SRCLIN_BIT = 0,
+ BBCTRL0_DSTLIN_BIT = 1,
+ BBCTRL0_FULL_BIT = 4,
+ BBCTRL0_HALF_BIT = 5,
+ BBCTRL0_ANY_BIT = 6,
+ BBCTRL0_ACTIVE_BIT = 7,
+ BBCTRL0_WR_MASK = 0x03,
+
+ BBCTRL1_COLFMT_BIT = 0,
+ BBCTRL1_FIFO_DEPTH_BIT = 4,
+ BBCTRL1_WR_MASK = 0x11,
+
+ BBCODE_MASK = 0x0f,
+
+ BBOP_MASK = 0x0f,
+
+ BBSRC_MASK = 0x001fffff,
+ BBDST_MASK = 0x001fffff,
+
+ BBMADR_MASK = 0x07ff,
+
+ BBWIDTH_MASK = 0x03ff,
+
+ BBHEIGHT_MASK = 0x03ff,
+
+ LUTMODE_MODE_BIT = 0,
+ LUTMODE_MODE_MASK = 0x03,
+ LUTMODE_MASK = 0x03,
+
+ LUTDATA_BIT = 4,
+ LUTDATA_MASK = 0xf0,
+
+ PWRCFG_ENABLE_BIT = 0,
+ PWRCFG_MASK = 0x01,
+
+ PWRSTAT_MCPSS_BIT = 0,
+ PWRSTAT_LCDPSS_BIT = 1,
+ PWRSTAT_MASK = 0x03,
+
+ WATCHDOG_MASK = 0x3f,
+
+ DISPMODE_MODE_BIT = 0,
+ DISPMODE_MODE_MASK = 0x07,
+ DISPMODE_SWIVEN0_BIT = 6,
+ DISPMODE_MASK = 0x47
+ };
+
+ uint8_t m_misc;
+ uint8_t m_gpio_config;
+ uint8_t m_gpio_ctrl;
+ uint8_t m_md_config[2];
+
+ uint8_t m_memclk_config;
+ uint8_t m_lcd_pclk_config;
+ uint8_t m_crt_pclk_config;
+ uint8_t m_mplug_clk_config;
+
+ uint8_t m_wait_state_sel;
+ uint8_t m_mem_config;
+ uint8_t m_dram_refresh;
+ uint8_t m_dram_timing[2];
+
+ uint8_t m_panel_type;
+ uint8_t m_mod_rate;
+
+ uint8_t m_lcd_width;
+ uint8_t m_lcd_hblank_period;
+ uint8_t m_tft_fpline_start;
+ uint8_t m_tft_fpline_width;
+ uint16_t m_lcd_height;
+ uint8_t m_lcd_vblank_period;
+ uint8_t m_tft_fpframe_start;
+ uint8_t m_tft_fpframe_width;
+ uint8_t m_lcd_mode;
+ uint8_t m_lcd_misc;
+ uint32_t m_lcd_addr;
+ uint16_t m_lcd_mem_offset;
+ uint8_t m_lcd_pan;
+ uint8_t m_lcd_fifo_hi_thresh;
+ uint8_t m_lcd_fifo_lo_thresh;
+
+ uint8_t m_crt_width;
+ uint8_t m_crt_hblank_period;
+ uint8_t m_crt_hrtc_start;
+ uint8_t m_crt_hrtc_width;
+ uint16_t m_crt_height;
+ uint8_t m_crt_vblank_period;
+ uint8_t m_crt_vrtc_start;
+ uint8_t m_crt_vrtc_width;
+ uint8_t m_crt_output_ctrl;
+ uint8_t m_crt_mode;
+ uint32_t m_crt_addr;
+ uint16_t m_crt_mem_offset;
+ uint8_t m_crt_pan;
+ uint8_t m_crt_fifo_hi_thresh;
+ uint8_t m_crt_fifo_lo_thresh;
+
+ uint8_t m_lcd_cursor_ctrl;
+ uint8_t m_lcd_cursor_addr;
+ uint16_t m_lcd_cursor_x;
+ uint16_t m_lcd_cursor_y;
+ uint8_t m_lcd_cursor_color0[3];
+ uint8_t m_lcd_cursor_color1[3];
+ uint8_t m_lcd_cursor_fifo_thresh;
+
+ uint8_t m_crt_cursor_ctrl;
+ uint8_t m_crt_cursor_addr;
+ uint16_t m_crt_cursor_x;
+ uint16_t m_crt_cursor_y;
+ uint8_t m_crt_cursor_color0[3];
+ uint8_t m_crt_cursor_color1[3];
+ uint8_t m_crt_cursor_fifo_thresh;
+
+ uint8_t m_bitblt_ctrl[2];
+ uint8_t m_bitblt_rop;
+ uint8_t m_bitblt_op;
+ uint32_t m_bitblt_src_addr;
+ uint32_t m_bitblt_dst_addr;
+ uint16_t m_bitblt_mem_offset;
+ uint16_t m_bitblt_width;
+ uint16_t m_bitblt_height;
+ uint16_t m_bitblt_bgcolor;
+ uint16_t m_bitblt_fgcolor;
+
+ uint8_t m_lut_mode;
+ uint8_t m_lut_addr;
+ uint8_t m_lut_data;
+
+ uint8_t m_power_config;
+ uint8_t m_power_status;
+
+ uint8_t m_watchdog;
+
+ uint8_t m_display_mode;
+
+ uint16_t m_mplug_lcmd;
+ uint16_t m_mplug_resv_lcmd;
+ uint16_t m_mplug_cmd;
+ uint16_t m_mplug_resv_cmd;
+
+ required_shared_ptr<uint32_t> m_vram;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(SED1356, sed1356_device)
+
+#endif // MAME_VIDEO_SED1356_H
diff --git a/src/mame/drivers/jornada.cpp b/src/mame/drivers/jornada.cpp
new file mode 100644
index 00000000000..2a64e59bdaa
--- /dev/null
+++ b/src/mame/drivers/jornada.cpp
@@ -0,0 +1,301 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/***************************************************************************
+
+ HP Jornada PDA skeleton driver
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+#include "machine/sa1110.h"
+#include "machine/sa1111.h"
+#include "video/sed1356.h"
+#include "screen.h"
+#include "emupal.h"
+
+#define LOG_MCU (1 << 1)
+#define LOG_ALL (LOG_MCU)
+
+#define VERBOSE (LOG_ALL)
+#include "logmacro.h"
+
+#define SA1110_CLOCK 206000000
+
+namespace
+{
+
+class jornada_state : public driver_device
+{
+public:
+ jornada_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
+ , m_ram(*this, "ram")
+ , m_sa_periphs(*this, "onboard")
+ , m_companion(*this, "companion")
+ , m_eeprom_data(*this, "eeprom")
+ , m_epson(*this, "epson")
+ , m_kbd_port(*this, "KBD0")
+ { }
+
+ void jornada720(machine_config &config);
+
+ DECLARE_INPUT_CHANGED_MEMBER(key_changed);
+
+ enum
+ {
+ KEY_ON_OFF
+ };
+
+protected:
+ // driver_device overrides
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+ virtual void device_reset_after_children() override;
+
+ void main_map(address_map &map);
+
+ void mcu_byte_received(uint16_t data);
+ void eeprom_cmd_received(uint16_t data);
+
+ enum mcu_state : int
+ {
+ MCU_IDLE,
+
+ MCU_KBD_SEND_COUNT,
+ MCU_KBD_SEND_CODES
+ };
+
+ // devices
+ required_device<cpu_device> m_maincpu;
+ required_shared_ptr<uint32_t> m_ram;
+ required_device<sa1110_periphs_device> m_sa_periphs;
+ required_device<sa1111_device> m_companion;
+ required_region_ptr<uint8_t> m_eeprom_data;
+ required_device<sed1356_device> m_epson;
+
+ required_ioport m_kbd_port;
+
+ // MCU-related members
+ int m_mcu_state;
+ uint8_t m_mcu_key_send_idx;
+ uint8_t m_mcu_key_codes[2][8];
+ uint8_t m_mcu_key_count[2];
+
+ // EEPROM-related members
+ uint8_t m_eeprom_cmd;
+ uint8_t m_eeprom_count;
+ uint8_t m_eeprom_read_idx;
+};
+
+void jornada_state::main_map(address_map &map)
+{
+ map(0x00000000, 0x01ffffff).rom().region("firmware", 0);
+ map(0x1a000000, 0x1a000fff).noprw();
+ map(0x40000000, 0x40001fff).m(m_companion, FUNC(sa1111_device::map));
+ map(0x48000000, 0x481fffff).m(m_epson, FUNC(sed1356_device::map));
+ map(0x48200000, 0x4827ffff).m(m_epson, FUNC(sed1356_device::vram_map));
+ 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(0x80070000, 0x80070077).rw(m_sa_periphs, FUNC(sa1110_periphs_device::ssp_r), FUNC(sa1110_periphs_device::ssp_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));
+ map(0x90030000, 0x90030007).rw(m_sa_periphs, FUNC(sa1110_periphs_device::reset_r), FUNC(sa1110_periphs_device::reset_w));
+ map(0x90040000, 0x90040023).rw(m_sa_periphs, FUNC(sa1110_periphs_device::gpio_r), FUNC(sa1110_periphs_device::gpio_w));
+ map(0x90050000, 0x90050023).rw(m_sa_periphs, FUNC(sa1110_periphs_device::intc_r), FUNC(sa1110_periphs_device::intc_w));
+ map(0xc0000000, 0xc1ffffff).ram().share("ram");
+}
+
+void jornada_state::device_reset_after_children()
+{
+}
+
+void jornada_state::mcu_byte_received(uint16_t data)
+{
+ const uint8_t raw_value = (uint8_t)(data >> 8);
+ const uint8_t value = bitswap<8>(raw_value, 0, 1, 2, 3, 4, 5, 6, 7);
+
+ uint8_t response = 0x11;
+ switch (m_mcu_state)
+ {
+ case MCU_IDLE:
+ switch (value)
+ {
+ case 0x90:
+ LOGMASKED(LOG_MCU, "mcu_byte_received in MCU_IDLE: GetScanKeyCode, entering KBD_SEND_COUNT state\n");
+ m_mcu_state = MCU_KBD_SEND_COUNT;
+ m_mcu_key_send_idx = 1 - m_mcu_key_send_idx;
+ break;
+ default:
+ LOGMASKED(LOG_MCU, "mcu_byte_received in MCU_IDLE: Unknown (%02x), ignoring and sending TxDummy response\n", value);
+ break;
+ }
+ break;
+
+ case MCU_KBD_SEND_COUNT:
+ if (value == 0x11)
+ {
+ LOGMASKED(LOG_MCU, "mcu_byte_received in MCU_KBD_SEND_COUNT: TxDummy, entering KBD_SEND_CODES state\n");
+ response = m_mcu_key_count[m_mcu_key_send_idx];
+ m_mcu_state = MCU_KBD_SEND_CODES;
+ }
+ else
+ {
+ LOGMASKED(LOG_MCU, "mcu_byte_received in MCU_KBD_SEND_COUNT: Unknown (%02x), sending ErrorCode response and returning to IDLE state\n");
+ response = 0;
+ }
+ break;
+
+ case MCU_KBD_SEND_CODES:
+ if (value == 0x11)
+ {
+ m_mcu_key_count[m_mcu_key_send_idx]--;
+ response = m_mcu_key_codes[m_mcu_key_send_idx][m_mcu_key_count[m_mcu_key_send_idx]];
+ if (m_mcu_key_send_idx)
+ {
+ LOGMASKED(LOG_MCU, "mcu_byte_received in MCU_KBD_SEND_CODES: TxDummy, sending scan code %02x with %d remaining\n", response, m_mcu_key_count[m_mcu_key_send_idx]);
+ }
+ else
+ {
+ LOGMASKED(LOG_MCU, "mcu_byte_received in MCU_KBD_SEND_CODES: TxDummy, sending scan code %02x and returning to IDLE state\n", response);
+ m_mcu_state = MCU_IDLE;
+ }
+ }
+ else
+ {
+ LOGMASKED(LOG_MCU, "mcu_byte_received in MCU_KBD_SEND_CODES: Unknown (%02x), sending ErrorCode response and returning to IDLE state\n");
+ response = 0;
+ }
+ }
+
+ response = bitswap<8>(response, 0, 1, 2, 3, 4, 5, 6, 7);
+ m_sa_periphs->ssp_in((uint16_t)response);
+}
+
+void jornada_state::eeprom_cmd_received(uint16_t data)
+{
+ bool reset_state = true;
+ uint8_t response = 0;
+
+ if (m_eeprom_cmd == 0)
+ {
+ m_eeprom_cmd = (uint8_t)data;
+ if (m_eeprom_cmd == 3)
+ reset_state = false;
+ }
+ else if (m_eeprom_count == 0)
+ {
+ if (m_eeprom_cmd == 3)
+ {
+ m_eeprom_count = (uint8_t)data;
+ m_eeprom_read_idx = 0;
+ reset_state = false;
+ }
+ }
+ else if (m_eeprom_read_idx < m_eeprom_count)
+ {
+ response = m_eeprom_data[m_eeprom_read_idx];
+ m_eeprom_read_idx++;
+ if (m_eeprom_read_idx < m_eeprom_count)
+ reset_state = false;
+ }
+
+ m_companion->ssp_in((uint16_t)response);
+
+ if (reset_state)
+ {
+ m_eeprom_cmd = 0;
+ m_eeprom_count = 0;
+ m_eeprom_read_idx = 0;
+ }
+}
+
+INPUT_CHANGED_MEMBER(jornada_state::key_changed)
+{
+ const uint8_t state = m_kbd_port->read();
+ if (BIT(state, 0))
+ {
+ m_sa_periphs->gpio_in<0>(1);
+ m_sa_periphs->gpio_in<0>(0);
+
+ const uint8_t key_recv_idx = 1 - m_mcu_key_send_idx;
+ if (m_mcu_key_count[key_recv_idx] < 8)
+ {
+ m_mcu_key_codes[key_recv_idx][m_mcu_key_count[key_recv_idx]] = 0x7f;
+ m_mcu_key_count[key_recv_idx]++;
+ }
+ }
+}
+
+static INPUT_PORTS_START( jornada720 )
+ PORT_START("KBD0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("On/Off") PORT_CODE(KEYCODE_HOME) PORT_CHANGED_MEMBER(DEVICE_SELF, jornada_state, key_changed, jornada_state::KEY_ON_OFF)
+ PORT_BIT(0xfe, IP_ACTIVE_HIGH, IPT_UNUSED)
+INPUT_PORTS_END
+
+void jornada_state::machine_start()
+{
+ save_item(NAME(m_mcu_state));
+ save_item(NAME(m_mcu_key_send_idx));
+ save_item(NAME(m_mcu_key_codes[0]));
+ save_item(NAME(m_mcu_key_codes[1]));
+ save_item(NAME(m_mcu_key_count));
+
+ save_item(NAME(m_eeprom_cmd));
+ save_item(NAME(m_eeprom_count));
+ save_item(NAME(m_eeprom_read_idx));
+}
+
+void jornada_state::machine_reset()
+{
+ m_mcu_state = MCU_IDLE;
+ m_mcu_key_send_idx = 0;
+ memset(m_mcu_key_codes[0], 0, 8);
+ memset(m_mcu_key_codes[1], 0, 8);
+ memset(m_mcu_key_count, 0, 2);
+
+ m_eeprom_cmd = 0;
+ m_eeprom_count = 0;
+ m_eeprom_read_idx = 0;
+}
+
+void jornada_state::jornada720(machine_config &config)
+{
+ SA1110(config, m_maincpu, SA1110_CLOCK);
+ m_maincpu->set_addrmap(AS_PROGRAM, &jornada_state::main_map);
+
+ SA1110_PERIPHERALS(config, m_sa_periphs, SA1110_CLOCK, m_maincpu);
+ m_sa_periphs->ssp_out().set(FUNC(jornada_state::mcu_byte_received));
+
+ SA1111(config, m_companion);
+ m_companion->ssp_out().set(FUNC(jornada_state::eeprom_cmd_received));
+
+ SED1356(config, m_epson);
+
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
+ screen.set_refresh_hz(60);
+ screen.set_size(640, 240);
+ screen.set_visarea(0, 640-1, 0, 240-1);
+ screen.set_screen_update(m_epson, FUNC(sed1356_device::screen_update));
+}
+
+/***************************************************************************
+
+ System driver(s)
+
+***************************************************************************/
+
+ROM_START( jorn720 )
+ ROM_REGION32_LE( 0x2000000, "firmware", ROMREGION_ERASE00 )
+ ROM_LOAD( "jornada720.bin", 0x0000000, 0x2000000, CRC(cb47d854) SHA1(d3664b748387026987ddc71f9840ee21e5753afd) )
+
+ ROM_REGION( 0x80, "eeprom", ROMREGION_ERASE00 )
+ ROM_LOAD( "jorn720_eeprom.bin", 0x00, 0x80, CRC(12345678) SHA1(1234567812345678123456781234567812345678) )
+ROM_END
+
+} // anonymous namespace
+
+COMP( 2000, jorn720, 0, 0, jornada720, jornada720, jornada_state, empty_init, "Hewlett Packard", "Jornada 720", MACHINE_IS_SKELETON )
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index cba4143071e..4f913b81a0a 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -17299,6 +17299,9 @@ jongkyo // (c) 1985 Kiwako
@source:jonos.cpp
jonos //
+@source:jornada.cpp
+jorn720 // (c) 2000 Hewlett Packard
+
@source:joystand.cpp
joystand // 1997 Yuvo
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 71028f9cbeb..a8af9b7e3ac 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -463,6 +463,7 @@ jade.cpp
jazz.cpp
jensen.cpp
jonos.cpp
+jornada.cpp
jr100.cpp
jr200.cpp
jtc.cpp