diff options
-rw-r--r-- | scripts/src/machine.lua | 12 | ||||
-rw-r--r-- | scripts/src/video.lua | 11 | ||||
-rw-r--r-- | scripts/target/mame/arcade.lua | 2 | ||||
-rw-r--r-- | scripts/target/mame/mess.lua | 3 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7.cpp | 206 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7.h | 8 | ||||
-rw-r--r-- | src/devices/cpu/arm7/arm7dasm.cpp | 3 | ||||
-rw-r--r-- | src/devices/machine/sa1110.cpp | 286 | ||||
-rw-r--r-- | src/devices/machine/sa1110.h | 63 | ||||
-rw-r--r-- | src/devices/machine/sa1111.cpp | 1733 | ||||
-rw-r--r-- | src/devices/machine/sa1111.h | 591 | ||||
-rw-r--r-- | src/devices/video/sed1356.cpp | 1579 | ||||
-rw-r--r-- | src/devices/video/sed1356.h | 547 | ||||
-rw-r--r-- | src/mame/drivers/jornada.cpp | 301 | ||||
-rw-r--r-- | src/mame/mame.lst | 3 | ||||
-rw-r--r-- | src/mame/mess.flt | 1 |
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 |