From 16e265185ead968484e6d1614bb63549a0fcda39 Mon Sep 17 00:00:00 2001 From: MooglyGuy Date: Fri, 16 Dec 2022 13:44:37 +0100 Subject: [PATCH] palm/palm.cpp: Improved Palm IIIc support. (#10684) [Ryan Holtz] * machine/mc68328.cpp: Split MC68328 device into a base class with shared functionality, and derived MC68328 and MC68EZ328 models. * video/sed1375.cpp: Added roughly-functional implementation of the Epson SED1375 LCD controller. Machines promoted to working ------------------------ 3Com Palm IIIc [Ryan Holtz] --- scripts/src/video.lua | 11 + src/devices/machine/mc68328.cpp | 3533 ++++++++++++++++++++----------- src/devices/machine/mc68328.h | 1314 +++++++----- src/devices/video/sed1375.cpp | 549 +++++ src/devices/video/sed1375.h | 196 ++ src/mame/palm/palm.cpp | 802 +++++-- src/mame/palm/palm_dbg.ipp | 2 +- 7 files changed, 4452 insertions(+), 1955 deletions(-) create mode 100644 src/devices/video/sed1375.cpp create mode 100644 src/devices/video/sed1375.h diff --git a/scripts/src/video.lua b/scripts/src/video.lua index 538cf859a32..23e502444af 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -917,6 +917,17 @@ if (VIDEOS["SED1356"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/video/sed1375.h,VIDEOS["SED1375"] = true +-------------------------------------------------- +if (VIDEOS["SED1375"]~=null) then + files { + MAME_DIR .. "src/devices/video/sed1375.cpp", + MAME_DIR .. "src/devices/video/sed1375.h", + } +end + -------------------------------------------------- -- --@src/devices/video/sed1500.h,VIDEOS["SED1500"] = true diff --git a/src/devices/machine/mc68328.cpp b/src/devices/machine/mc68328.cpp index 9de8ed969d5..8f43307bcd8 100644 --- a/src/devices/machine/mc68328.cpp +++ b/src/devices/machine/mc68328.cpp @@ -35,24 +35,161 @@ #define LOG_UART (1U << 22) #define LOG_LCD (1U << 23) #define LOG_RTC (1U << 24) -#define LOG_ALL (LOG_SCR | LOG_CS_GRP | LOG_CS_SEL | LOG_PLL | LOG_INTS | LOG_GPIO_A | LOG_GPIO_B | LOG_GPIO_C | LOG_GPIO_D | LOG_GPIO_E \ +#define LOG_ALL (LOG_SCR | LOG_PLL | LOG_INTS | LOG_GPIO_A | LOG_GPIO_B | LOG_GPIO_C | LOG_GPIO_D | LOG_GPIO_E \ | LOG_GPIO_F | LOG_GPIO_G | LOG_GPIO_J | LOG_GPIO_K | LOG_GPIO_M | LOG_PWM | LOG_TIMERS | LOG_TSTAT | LOG_WATCHDOG | LOG_SPIS \ | LOG_SPIM | LOG_UART | LOG_LCD | LOG_RTC) #define VERBOSE (0) #include "logmacro.h" -DEFINE_DEVICE_TYPE(MC68328, mc68328_device, "mc68328", "MC68328 DragonBall Integrated Processor") +DEFINE_DEVICE_TYPE(MC68328, mc68328_device, "mc68328", "MC68328 DragonBall Processor") +DEFINE_DEVICE_TYPE(MC68EZ328, mc68ez328_device, "mc68ez328", "MC68EZ328 DragonBall-EZ Processor") -const uint32_t mc68328_device::VCO_DIVISORS[8] = { 2, 4, 8, 16, 1, 1, 1, 1 }; +const u32 mc68328_base_device::VCO_DIVISORS[8] = { 2, 4, 8, 16, 1, 1, 1, 1 }; + +mc68328_base_device::mc68328_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 addr_bits, address_map_constructor internal_map_ctor) + : m68000_device(mconfig, tag, owner, clock, type, 16, addr_bits, internal_map_ctor) + , m_pwm(nullptr) + , m_rtc(nullptr) + , m_spim(nullptr) + , m_out_port_a_cb(*this) + , m_out_port_b_cb(*this) + , m_out_port_c_cb(*this) + , m_out_port_d_cb(*this) + , m_out_port_e_cb(*this) + , m_out_port_f_cb(*this) + , m_out_port_g_cb(*this) + , m_in_port_a_cb(*this) + , m_in_port_b_cb(*this) + , m_in_port_c_cb(*this) + , m_in_port_d_cb(*this) + , m_in_port_e_cb(*this) + , m_in_port_f_cb(*this) + , m_in_port_g_cb(*this) + , m_out_pwm_cb(*this) + , m_out_spim_cb(*this) + , m_in_spim_cb(*this) + , m_out_flm_cb(*this) + , m_out_llp_cb(*this) + , m_out_lsclk_cb(*this) + , m_out_ld_cb(*this) + , m_lcd_info_changed_cb(*this) +{ +} + +mc68328_device::mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : mc68328_base_device(mconfig, MC68328, tag, owner, clock, 24, address_map_constructor(FUNC(mc68328_device::internal_map), this)) + , m_out_port_j_cb(*this) + , m_out_port_k_cb(*this) + , m_out_port_m_cb(*this) + , m_in_port_j_cb(*this) + , m_in_port_k_cb(*this) + , m_in_port_m_cb(*this) +{ + m_cpu_space_config.m_internal_map = address_map_constructor(FUNC(mc68328_device::cpu_space_map), this); +} + +mc68ez328_device::mc68ez328_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : mc68328_base_device(mconfig, MC68EZ328, tag, owner, clock, 32, address_map_constructor(FUNC(mc68ez328_device::internal_map), this)) +{ + m_cpu_space_config.m_internal_map = address_map_constructor(FUNC(mc68ez328_device::cpu_space_map), this); +} + +void mc68328_base_device::base_internal_map(u32 addr_bits, address_map &map) +{ + map(addr_bits | 0x000, addr_bits | 0x000).rw(FUNC(mc68328_base_device::scr_r), FUNC(mc68328_base_device::scr_w)); + map(addr_bits | 0x100, addr_bits | 0x101).rw(FUNC(mc68328_base_device::grpbasea_r), FUNC(mc68328_base_device::grpbasea_w)); + map(addr_bits | 0x102, addr_bits | 0x103).rw(FUNC(mc68328_base_device::grpbaseb_r), FUNC(mc68328_base_device::grpbaseb_w)); + map(addr_bits | 0x104, addr_bits | 0x105).rw(FUNC(mc68328_base_device::grpbasec_r), FUNC(mc68328_base_device::grpbasec_w)); + map(addr_bits | 0x106, addr_bits | 0x107).rw(FUNC(mc68328_base_device::grpbased_r), FUNC(mc68328_base_device::grpbased_w)); + + map(addr_bits | 0x200, addr_bits | 0x201).rw(FUNC(mc68328_base_device::pllcr_r), FUNC(mc68328_base_device::pllcr_w)); + map(addr_bits | 0x202, addr_bits | 0x203).rw(FUNC(mc68328_base_device::pllfsr_r), FUNC(mc68328_base_device::pllfsr_w)); + map(addr_bits | 0x207, addr_bits | 0x207).rw(FUNC(mc68328_base_device::pctlr_r), FUNC(mc68328_base_device::pctlr_w)); + + map(addr_bits | 0x300, addr_bits | 0x300).rw(FUNC(mc68328_base_device::ivr_r), FUNC(mc68328_base_device::ivr_w)); + map(addr_bits | 0x302, addr_bits | 0x303).rw(FUNC(mc68328_base_device::icr_r), FUNC(mc68328_base_device::icr_w)); + map(addr_bits | 0x304, addr_bits | 0x305).rw(FUNC(mc68328_base_device::imr_msw_r), FUNC(mc68328_base_device::imr_msw_w)); + map(addr_bits | 0x306, addr_bits | 0x307).rw(FUNC(mc68328_base_device::imr_lsw_r), FUNC(mc68328_base_device::imr_lsw_w)); + map(addr_bits | 0x30c, addr_bits | 0x30d).rw(FUNC(mc68328_base_device::isr_msw_r), FUNC(mc68328_base_device::isr_msw_w)); + map(addr_bits | 0x30e, addr_bits | 0x30f).rw(FUNC(mc68328_base_device::isr_lsw_r), FUNC(mc68328_base_device::isr_lsw_w)); + map(addr_bits | 0x310, addr_bits | 0x311).rw(FUNC(mc68328_base_device::ipr_msw_r), FUNC(mc68328_base_device::ipr_msw_w)); + map(addr_bits | 0x312, addr_bits | 0x313).rw(FUNC(mc68328_base_device::ipr_lsw_r), FUNC(mc68328_base_device::ipr_lsw_w)); + + map(addr_bits | 0x400, addr_bits | 0x400).rw(FUNC(mc68328_base_device::padir_r), FUNC(mc68328_base_device::padir_w)); + map(addr_bits | 0x401, addr_bits | 0x401).rw(FUNC(mc68328_base_device::padata_r), FUNC(mc68328_base_device::padata_w)); + map(addr_bits | 0x408, addr_bits | 0x408).rw(FUNC(mc68328_base_device::pbdir_r), FUNC(mc68328_base_device::pbdir_w)); + map(addr_bits | 0x409, addr_bits | 0x409).rw(FUNC(mc68328_base_device::pbdata_r), FUNC(mc68328_base_device::pbdata_w)); + map(addr_bits | 0x40b, addr_bits | 0x40b).rw(FUNC(mc68328_base_device::pbsel_r), FUNC(mc68328_base_device::pbsel_w)); + map(addr_bits | 0x410, addr_bits | 0x410).rw(FUNC(mc68328_base_device::pcdir_r), FUNC(mc68328_base_device::pcdir_w)); + map(addr_bits | 0x411, addr_bits | 0x411).rw(FUNC(mc68328_base_device::pcdata_r), FUNC(mc68328_base_device::pcdata_w)); + map(addr_bits | 0x413, addr_bits | 0x413).rw(FUNC(mc68328_base_device::pcsel_r), FUNC(mc68328_base_device::pcsel_w)); + map(addr_bits | 0x418, addr_bits | 0x418).rw(FUNC(mc68328_base_device::pddir_r), FUNC(mc68328_base_device::pddir_w)); + map(addr_bits | 0x419, addr_bits | 0x419).rw(FUNC(mc68328_base_device::pddata_r), FUNC(mc68328_base_device::pddata_w)); + map(addr_bits | 0x41a, addr_bits | 0x41a).rw(FUNC(mc68328_base_device::pdpuen_r), FUNC(mc68328_base_device::pdpuen_w)); + map(addr_bits | 0x41c, addr_bits | 0x41c).rw(FUNC(mc68328_base_device::pdpol_r), FUNC(mc68328_base_device::pdpol_w)); + map(addr_bits | 0x41d, addr_bits | 0x41d).rw(FUNC(mc68328_base_device::pdirqen_r), FUNC(mc68328_base_device::pdirqen_w)); + map(addr_bits | 0x41f, addr_bits | 0x41f).rw(FUNC(mc68328_base_device::pdirqedge_r), FUNC(mc68328_base_device::pdirqedge_w)); + map(addr_bits | 0x420, addr_bits | 0x420).rw(FUNC(mc68328_base_device::pedir_r), FUNC(mc68328_base_device::pedir_w)); + map(addr_bits | 0x421, addr_bits | 0x421).rw(FUNC(mc68328_base_device::pedata_r), FUNC(mc68328_base_device::pedata_w)); + map(addr_bits | 0x422, addr_bits | 0x422).rw(FUNC(mc68328_base_device::pepuen_r), FUNC(mc68328_base_device::pepuen_w)); + map(addr_bits | 0x423, addr_bits | 0x423).rw(FUNC(mc68328_base_device::pesel_r), FUNC(mc68328_base_device::pesel_w)); + map(addr_bits | 0x428, addr_bits | 0x428).rw(FUNC(mc68328_base_device::pfdir_r), FUNC(mc68328_base_device::pfdir_w)); + map(addr_bits | 0x429, addr_bits | 0x429).rw(FUNC(mc68328_base_device::pfdata_r), FUNC(mc68328_base_device::pfdata_w)); + map(addr_bits | 0x42a, addr_bits | 0x42a).rw(FUNC(mc68328_base_device::pfpuen_r), FUNC(mc68328_base_device::pfpuen_w)); + map(addr_bits | 0x42b, addr_bits | 0x42b).rw(FUNC(mc68328_base_device::pfsel_r), FUNC(mc68328_base_device::pfsel_w)); + map(addr_bits | 0x430, addr_bits | 0x430).rw(FUNC(mc68328_base_device::pgdir_r), FUNC(mc68328_base_device::pgdir_w)); + map(addr_bits | 0x431, addr_bits | 0x431).rw(FUNC(mc68328_base_device::pgdata_r), FUNC(mc68328_base_device::pgdata_w)); + map(addr_bits | 0x432, addr_bits | 0x432).rw(FUNC(mc68328_base_device::pgpuen_r), FUNC(mc68328_base_device::pgpuen_w)); + map(addr_bits | 0x433, addr_bits | 0x433).rw(FUNC(mc68328_base_device::pgsel_r), FUNC(mc68328_base_device::pgsel_w)); + + map(addr_bits | 0x500, addr_bits | 0x501).rw(FUNC(mc68328_base_device::pwmc_r), FUNC(mc68328_base_device::pwmc_w)); + + map(addr_bits | 0x600, addr_bits | 0x601).rw(FUNC(mc68328_base_device::tctl_r<0>), FUNC(mc68328_base_device::tctl_w<0>)); + map(addr_bits | 0x602, addr_bits | 0x603).rw(FUNC(mc68328_base_device::tprer_r<0>), FUNC(mc68328_base_device::tprer_w<0>)); + map(addr_bits | 0x604, addr_bits | 0x605).rw(FUNC(mc68328_base_device::tcmp_r<0>), FUNC(mc68328_base_device::tcmp_w<0>)); + map(addr_bits | 0x606, addr_bits | 0x607).rw(FUNC(mc68328_base_device::tcr_r<0>), FUNC(mc68328_base_device::tcr_w<0>)); + map(addr_bits | 0x608, addr_bits | 0x609).rw(FUNC(mc68328_base_device::tcn_r<0>), FUNC(mc68328_base_device::tcn_w<0>)); + map(addr_bits | 0x60a, addr_bits | 0x60b).rw(FUNC(mc68328_base_device::tstat_r<0>), FUNC(mc68328_base_device::tstat_w<0>)); + + map(addr_bits | 0x800, addr_bits | 0x801).rw(FUNC(mc68328_base_device::spimdata_r), FUNC(mc68328_base_device::spimdata_w)); + map(addr_bits | 0x802, addr_bits | 0x803).rw(FUNC(mc68328_base_device::spimcont_r), FUNC(mc68328_base_device::spimcont_w)); + + map(addr_bits | 0x900, addr_bits | 0x901).rw(FUNC(mc68328_base_device::ustcnt_r), FUNC(mc68328_base_device::ustcnt_w)); + map(addr_bits | 0x902, addr_bits | 0x903).rw(FUNC(mc68328_base_device::ubaud_r), FUNC(mc68328_base_device::ubaud_w)); + map(addr_bits | 0x904, addr_bits | 0x905).rw(FUNC(mc68328_base_device::urx_r), FUNC(mc68328_base_device::urx_w)); + map(addr_bits | 0x906, addr_bits | 0x907).rw(FUNC(mc68328_base_device::utx_r), FUNC(mc68328_base_device::utx_w)); + map(addr_bits | 0x908, addr_bits | 0x909).rw(FUNC(mc68328_base_device::umisc_r), FUNC(mc68328_base_device::umisc_w)); + + map(addr_bits | 0xa00, addr_bits | 0xa01).rw(FUNC(mc68328_base_device::lssa_msw_r), FUNC(mc68328_base_device::lssa_msw_w)); + map(addr_bits | 0xa02, addr_bits | 0xa03).rw(FUNC(mc68328_base_device::lssa_lsw_r), FUNC(mc68328_base_device::lssa_lsw_w)); + map(addr_bits | 0xa05, addr_bits | 0xa05).rw(FUNC(mc68328_base_device::lvpw_r), FUNC(mc68328_base_device::lvpw_w)); + map(addr_bits | 0xa08, addr_bits | 0xa09).rw(FUNC(mc68328_base_device::lxmax_r), FUNC(mc68328_base_device::lxmax_w)); + map(addr_bits | 0xa0a, addr_bits | 0xa0b).rw(FUNC(mc68328_base_device::lymax_r), FUNC(mc68328_base_device::lymax_w)); + map(addr_bits | 0xa18, addr_bits | 0xa19).rw(FUNC(mc68328_base_device::lcxp_r), FUNC(mc68328_base_device::lcxp_w)); + map(addr_bits | 0xa1a, addr_bits | 0xa1b).rw(FUNC(mc68328_base_device::lcyp_r), FUNC(mc68328_base_device::lcyp_w)); + map(addr_bits | 0xa1c, addr_bits | 0xa1d).rw(FUNC(mc68328_base_device::lcwch_r), FUNC(mc68328_base_device::lcwch_w)); + map(addr_bits | 0xa1f, addr_bits | 0xa1f).rw(FUNC(mc68328_base_device::lblkc_r), FUNC(mc68328_base_device::lblkc_w)); + map(addr_bits | 0xa20, addr_bits | 0xa20).rw(FUNC(mc68328_base_device::lpicf_r), FUNC(mc68328_base_device::lpicf_w)); + map(addr_bits | 0xa21, addr_bits | 0xa21).rw(FUNC(mc68328_base_device::lpolcf_r), FUNC(mc68328_base_device::lpolcf_w)); + map(addr_bits | 0xa23, addr_bits | 0xa23).rw(FUNC(mc68328_base_device::lacdrc_r), FUNC(mc68328_base_device::lacdrc_w)); + map(addr_bits | 0xa25, addr_bits | 0xa25).rw(FUNC(mc68328_base_device::lpxcd_r), FUNC(mc68328_base_device::lpxcd_w)); + map(addr_bits | 0xa27, addr_bits | 0xa27).rw(FUNC(mc68328_base_device::lckcon_r), FUNC(mc68328_base_device::lckcon_w)); + map(addr_bits | 0xa2d, addr_bits | 0xa2d).rw(FUNC(mc68328_base_device::lposr_r), FUNC(mc68328_base_device::lposr_w)); + map(addr_bits | 0xa31, addr_bits | 0xa31).rw(FUNC(mc68328_base_device::lfrcm_r), FUNC(mc68328_base_device::lfrcm_w)); + + map(addr_bits | 0xb00, addr_bits | 0xb01).rw(FUNC(mc68328_base_device::hmsr_msw_r), FUNC(mc68328_base_device::hmsr_msw_w)); + map(addr_bits | 0xb02, addr_bits | 0xb03).rw(FUNC(mc68328_base_device::hmsr_lsw_r), FUNC(mc68328_base_device::hmsr_lsw_w)); + map(addr_bits | 0xb04, addr_bits | 0xb05).rw(FUNC(mc68328_base_device::alarm_msw_r), FUNC(mc68328_base_device::alarm_msw_w)); + map(addr_bits | 0xb06, addr_bits | 0xb07).rw(FUNC(mc68328_base_device::alarm_lsw_r), FUNC(mc68328_base_device::alarm_lsw_w)); + map(addr_bits | 0xb0e, addr_bits | 0xb0f).rw(FUNC(mc68328_base_device::rtcisr_r), FUNC(mc68328_base_device::rtcisr_w)); + map(addr_bits | 0xb10, addr_bits | 0xb11).rw(FUNC(mc68328_base_device::rtcienr_r), FUNC(mc68328_base_device::rtcienr_w)); + map(addr_bits | 0xb12, addr_bits | 0xb13).rw(FUNC(mc68328_base_device::stpwtch_r), FUNC(mc68328_base_device::stpwtch_w)); +} void mc68328_device::internal_map(address_map &map) { - map(0xfff000, 0xfff000).rw(FUNC(mc68328_device::scr_r), FUNC(mc68328_device::scr_w)); - map(0xfff100, 0xfff101).rw(FUNC(mc68328_device::grpbasea_r), FUNC(mc68328_device::grpbasea_w)); - map(0xfff102, 0xfff103).rw(FUNC(mc68328_device::grpbaseb_r), FUNC(mc68328_device::grpbaseb_w)); - map(0xfff104, 0xfff105).rw(FUNC(mc68328_device::grpbasec_r), FUNC(mc68328_device::grpbasec_w)); - map(0xfff106, 0xfff107).rw(FUNC(mc68328_device::grpbased_r), FUNC(mc68328_device::grpbased_w)); + base_internal_map(0xfff000, map); map(0xfff108, 0xfff109).rw(FUNC(mc68328_device::grpmaska_r), FUNC(mc68328_device::grpmaska_w)); map(0xfff10a, 0xfff10b).rw(FUNC(mc68328_device::grpmaskb_r), FUNC(mc68328_device::grpmaskb_w)); map(0xfff10c, 0xfff10d).rw(FUNC(mc68328_device::grpmaskc_r), FUNC(mc68328_device::grpmaskc_w)); @@ -90,48 +227,11 @@ void mc68328_device::internal_map(address_map &map) map(0xfff14c, 0xfff14d).rw(FUNC(mc68328_device::csd_msw_r<3>), FUNC(mc68328_device::csd_msw_w<3>)); map(0xfff14e, 0xfff14f).rw(FUNC(mc68328_device::csd_lsw_r<3>), FUNC(mc68328_device::csd_lsw_w<3>)); - map(0xfff200, 0xfff201).rw(FUNC(mc68328_device::pllcr_r), FUNC(mc68328_device::pllcr_w)); - map(0xfff202, 0xfff203).rw(FUNC(mc68328_device::pllfsr_r), FUNC(mc68328_device::pllfsr_w)); - map(0xfff207, 0xfff207).rw(FUNC(mc68328_device::pctlr_r), FUNC(mc68328_device::pctlr_w)); - - map(0xfff300, 0xfff300).rw(FUNC(mc68328_device::ivr_r), FUNC(mc68328_device::ivr_w)); - map(0xfff302, 0xfff303).rw(FUNC(mc68328_device::icr_r), FUNC(mc68328_device::icr_w)); - map(0xfff304, 0xfff305).rw(FUNC(mc68328_device::imr_msw_r), FUNC(mc68328_device::imr_msw_w)); - map(0xfff306, 0xfff307).rw(FUNC(mc68328_device::imr_lsw_r), FUNC(mc68328_device::imr_lsw_w)); map(0xfff308, 0xfff309).rw(FUNC(mc68328_device::iwr_msw_r), FUNC(mc68328_device::iwr_msw_w)); map(0xfff30a, 0xfff30b).rw(FUNC(mc68328_device::iwr_lsw_r), FUNC(mc68328_device::iwr_lsw_w)); - map(0xfff30c, 0xfff30d).rw(FUNC(mc68328_device::isr_msw_r), FUNC(mc68328_device::isr_msw_w)); - map(0xfff30e, 0xfff30f).rw(FUNC(mc68328_device::isr_lsw_r), FUNC(mc68328_device::isr_lsw_w)); - map(0xfff310, 0xfff311).rw(FUNC(mc68328_device::ipr_msw_r), FUNC(mc68328_device::ipr_msw_w)); - map(0xfff312, 0xfff313).rw(FUNC(mc68328_device::ipr_lsw_r), FUNC(mc68328_device::ipr_lsw_w)); - map(0xfff400, 0xfff400).rw(FUNC(mc68328_device::padir_r), FUNC(mc68328_device::padir_w)); - map(0xfff401, 0xfff401).rw(FUNC(mc68328_device::padata_r), FUNC(mc68328_device::padata_w)); map(0xfff403, 0xfff403).rw(FUNC(mc68328_device::pasel_r), FUNC(mc68328_device::pasel_w)); - map(0xfff408, 0xfff408).rw(FUNC(mc68328_device::pbdir_r), FUNC(mc68328_device::pbdir_w)); - map(0xfff409, 0xfff409).rw(FUNC(mc68328_device::pbdata_r), FUNC(mc68328_device::pbdata_w)); - map(0xfff40b, 0xfff40b).rw(FUNC(mc68328_device::pbsel_r), FUNC(mc68328_device::pbsel_w)); - map(0xfff410, 0xfff410).rw(FUNC(mc68328_device::pcdir_r), FUNC(mc68328_device::pcdir_w)); - map(0xfff411, 0xfff411).rw(FUNC(mc68328_device::pcdata_r), FUNC(mc68328_device::pcdata_w)); - map(0xfff413, 0xfff413).rw(FUNC(mc68328_device::pcsel_r), FUNC(mc68328_device::pcsel_w)); - map(0xfff418, 0xfff418).rw(FUNC(mc68328_device::pddir_r), FUNC(mc68328_device::pddir_w)); - map(0xfff419, 0xfff419).rw(FUNC(mc68328_device::pddata_r), FUNC(mc68328_device::pddata_w)); - map(0xfff41a, 0xfff41a).rw(FUNC(mc68328_device::pdpuen_r), FUNC(mc68328_device::pdpuen_w)); - map(0xfff41c, 0xfff41c).rw(FUNC(mc68328_device::pdpol_r), FUNC(mc68328_device::pdpol_w)); - map(0xfff41d, 0xfff41d).rw(FUNC(mc68328_device::pdirqen_r), FUNC(mc68328_device::pdirqen_w)); - map(0xfff41f, 0xfff41f).rw(FUNC(mc68328_device::pdirqedge_r), FUNC(mc68328_device::pdirqedge_w)); - map(0xfff420, 0xfff420).rw(FUNC(mc68328_device::pedir_r), FUNC(mc68328_device::pedir_w)); - map(0xfff421, 0xfff421).rw(FUNC(mc68328_device::pedata_r), FUNC(mc68328_device::pedata_w)); - map(0xfff422, 0xfff422).rw(FUNC(mc68328_device::pepuen_r), FUNC(mc68328_device::pepuen_w)); - map(0xfff423, 0xfff423).rw(FUNC(mc68328_device::pesel_r), FUNC(mc68328_device::pesel_w)); - map(0xfff428, 0xfff428).rw(FUNC(mc68328_device::pfdir_r), FUNC(mc68328_device::pfdir_w)); - map(0xfff429, 0xfff429).rw(FUNC(mc68328_device::pfdata_r), FUNC(mc68328_device::pfdata_w)); - map(0xfff42a, 0xfff42a).rw(FUNC(mc68328_device::pfpuen_r), FUNC(mc68328_device::pfpuen_w)); - map(0xfff42b, 0xfff42b).rw(FUNC(mc68328_device::pfsel_r), FUNC(mc68328_device::pfsel_w)); - map(0xfff430, 0xfff430).rw(FUNC(mc68328_device::pgdir_r), FUNC(mc68328_device::pgdir_w)); - map(0xfff431, 0xfff431).rw(FUNC(mc68328_device::pgdata_r), FUNC(mc68328_device::pgdata_w)); - map(0xfff432, 0xfff432).rw(FUNC(mc68328_device::pgpuen_r), FUNC(mc68328_device::pgpuen_w)); - map(0xfff433, 0xfff433).rw(FUNC(mc68328_device::pgsel_r), FUNC(mc68328_device::pgsel_w)); + map(0xfff438, 0xfff438).rw(FUNC(mc68328_device::pjdir_r), FUNC(mc68328_device::pjdir_w)); map(0xfff439, 0xfff439).rw(FUNC(mc68328_device::pjdata_r), FUNC(mc68328_device::pjdata_w)); map(0xfff43b, 0xfff43b).rw(FUNC(mc68328_device::pjsel_r), FUNC(mc68328_device::pjsel_w)); @@ -144,17 +244,10 @@ void mc68328_device::internal_map(address_map &map) map(0xfff44a, 0xfff44a).rw(FUNC(mc68328_device::pmpuen_r), FUNC(mc68328_device::pmpuen_w)); map(0xfff44b, 0xfff44b).rw(FUNC(mc68328_device::pmsel_r), FUNC(mc68328_device::pmsel_w)); - map(0xfff500, 0xfff501).rw(FUNC(mc68328_device::pwmc_r), FUNC(mc68328_device::pwmc_w)); map(0xfff502, 0xfff503).rw(FUNC(mc68328_device::pwmp_r), FUNC(mc68328_device::pwmp_w)); map(0xfff504, 0xfff505).rw(FUNC(mc68328_device::pwmw_r), FUNC(mc68328_device::pwmw_w)); map(0xfff506, 0xfff507).rw(FUNC(mc68328_device::pwmcnt_r), FUNC(mc68328_device::pwmcnt_w)); - map(0xfff600, 0xfff601).rw(FUNC(mc68328_device::tctl_r<0>), FUNC(mc68328_device::tctl_w<0>)); - map(0xfff602, 0xfff603).rw(FUNC(mc68328_device::tprer_r<0>), FUNC(mc68328_device::tprer_w<0>)); - map(0xfff604, 0xfff605).rw(FUNC(mc68328_device::tcmp_r<0>), FUNC(mc68328_device::tcmp_w<0>)); - map(0xfff606, 0xfff607).rw(FUNC(mc68328_device::tcr_r<0>), FUNC(mc68328_device::tcr_w<0>)); - map(0xfff608, 0xfff609).rw(FUNC(mc68328_device::tcn_r<0>), FUNC(mc68328_device::tcn_w<0>)); - map(0xfff60a, 0xfff60b).rw(FUNC(mc68328_device::tstat_r<0>), FUNC(mc68328_device::tstat_w<0>)); map(0xfff60c, 0xfff60d).rw(FUNC(mc68328_device::tctl_r<1>), FUNC(mc68328_device::tctl_w<1>)); map(0xfff60e, 0xfff60f).rw(FUNC(mc68328_device::tprer_r<1>), FUNC(mc68328_device::tprer_w<1>)); map(0xfff610, 0xfff611).rw(FUNC(mc68328_device::tcmp_r<1>), FUNC(mc68328_device::tcmp_w<1>)); @@ -167,43 +260,36 @@ void mc68328_device::internal_map(address_map &map) map(0xfff700, 0xfff701).rw(FUNC(mc68328_device::spisr_r), FUNC(mc68328_device::spisr_w)); - map(0xfff800, 0xfff801).rw(FUNC(mc68328_device::spimdata_r), FUNC(mc68328_device::spimdata_w)); - map(0xfff802, 0xfff803).rw(FUNC(mc68328_device::spimcont_r), FUNC(mc68328_device::spimcont_w)); - - map(0xfff900, 0xfff901).rw(FUNC(mc68328_device::ustcnt_r), FUNC(mc68328_device::ustcnt_w)); - map(0xfff902, 0xfff903).rw(FUNC(mc68328_device::ubaud_r), FUNC(mc68328_device::ubaud_w)); - map(0xfff904, 0xfff905).rw(FUNC(mc68328_device::urx_r), FUNC(mc68328_device::urx_w)); - map(0xfff906, 0xfff907).rw(FUNC(mc68328_device::utx_r), FUNC(mc68328_device::utx_w)); - map(0xfff908, 0xfff909).rw(FUNC(mc68328_device::umisc_r), FUNC(mc68328_device::umisc_w)); - - map(0xfffa00, 0xfffa01).rw(FUNC(mc68328_device::lssa_msw_r), FUNC(mc68328_device::lssa_msw_w)); - map(0xfffa02, 0xfffa03).rw(FUNC(mc68328_device::lssa_lsw_r), FUNC(mc68328_device::lssa_lsw_w)); - map(0xfffa05, 0xfffa05).rw(FUNC(mc68328_device::lvpw_r), FUNC(mc68328_device::lvpw_w)); - map(0xfffa08, 0xfffa09).rw(FUNC(mc68328_device::lxmax_r), FUNC(mc68328_device::lxmax_w)); - map(0xfffa0a, 0xfffa0b).rw(FUNC(mc68328_device::lymax_r), FUNC(mc68328_device::lymax_w)); - map(0xfffa18, 0xfffa19).rw(FUNC(mc68328_device::lcxp_r), FUNC(mc68328_device::lcxp_w)); - map(0xfffa1a, 0xfffa1b).rw(FUNC(mc68328_device::lcyp_r), FUNC(mc68328_device::lcyp_w)); - map(0xfffa1c, 0xfffa1d).rw(FUNC(mc68328_device::lcwch_r), FUNC(mc68328_device::lcwch_w)); - map(0xfffa1f, 0xfffa1f).rw(FUNC(mc68328_device::lblkc_r), FUNC(mc68328_device::lblkc_w)); - map(0xfffa20, 0xfffa20).rw(FUNC(mc68328_device::lpicf_r), FUNC(mc68328_device::lpicf_w)); - map(0xfffa21, 0xfffa21).rw(FUNC(mc68328_device::lpolcf_r), FUNC(mc68328_device::lpolcf_w)); - map(0xfffa23, 0xfffa23).rw(FUNC(mc68328_device::lacdrc_r), FUNC(mc68328_device::lacdrc_w)); - map(0xfffa25, 0xfffa25).rw(FUNC(mc68328_device::lpxcd_r), FUNC(mc68328_device::lpxcd_w)); - map(0xfffa27, 0xfffa27).rw(FUNC(mc68328_device::lckcon_r), FUNC(mc68328_device::lckcon_w)); map(0xfffa29, 0xfffa29).rw(FUNC(mc68328_device::llbar_r), FUNC(mc68328_device::llbar_w)); map(0xfffa2b, 0xfffa2b).rw(FUNC(mc68328_device::lotcr_r), FUNC(mc68328_device::lotcr_w)); - map(0xfffa2d, 0xfffa2d).rw(FUNC(mc68328_device::lposr_r), FUNC(mc68328_device::lposr_w)); - map(0xfffa31, 0xfffa31).rw(FUNC(mc68328_device::lfrcm_r), FUNC(mc68328_device::lfrcm_w)); map(0xfffa32, 0xfffa33).rw(FUNC(mc68328_device::lgpmr_r), FUNC(mc68328_device::lgpmr_w)); - map(0xfffb00, 0xfffb01).rw(FUNC(mc68328_device::hmsr_msw_r), FUNC(mc68328_device::hmsr_msw_w)); - map(0xfffb02, 0xfffb03).rw(FUNC(mc68328_device::hmsr_lsw_r), FUNC(mc68328_device::hmsr_lsw_w)); - map(0xfffb04, 0xfffb05).rw(FUNC(mc68328_device::alarm_msw_r), FUNC(mc68328_device::alarm_msw_w)); - map(0xfffb06, 0xfffb07).rw(FUNC(mc68328_device::alarm_lsw_r), FUNC(mc68328_device::alarm_lsw_w)); map(0xfffb0c, 0xfffb0d).rw(FUNC(mc68328_device::rtcctl_r), FUNC(mc68328_device::rtcctl_w)); - map(0xfffb0e, 0xfffb0f).rw(FUNC(mc68328_device::rtcisr_r), FUNC(mc68328_device::rtcisr_w)); - map(0xfffb10, 0xfffb11).rw(FUNC(mc68328_device::rtcienr_r), FUNC(mc68328_device::rtcienr_w)); - map(0xfffb12, 0xfffb13).rw(FUNC(mc68328_device::stpwtch_r), FUNC(mc68328_device::stpwtch_w)); +} + +void mc68ez328_device::internal_map(address_map &map) +{ + base_internal_map(0xfffff000, map); + + map(0xfffff004, 0xfffff007).r(FUNC(mc68ez328_device::revision_r)); + + map(0xfffff110, 0xfffff111).rw(FUNC(mc68ez328_device::csa_r), FUNC(mc68ez328_device::csa_w)); + map(0xfffff112, 0xfffff113).rw(FUNC(mc68ez328_device::csb_r), FUNC(mc68ez328_device::csb_w)); + map(0xfffff114, 0xfffff115).rw(FUNC(mc68ez328_device::csc_r), FUNC(mc68ez328_device::csc_w)); + map(0xfffff116, 0xfffff117).rw(FUNC(mc68ez328_device::csd_r), FUNC(mc68ez328_device::csd_w)); + map(0xfffff118, 0xfffff119).rw(FUNC(mc68ez328_device::emucs_r), FUNC(mc68ez328_device::emucs_w)); + + map(0xfffff502, 0xfffff503).rw(FUNC(mc68ez328_device::pwms_r), FUNC(mc68ez328_device::pwms_w)); + map(0xfffff504, 0xfffff504).rw(FUNC(mc68ez328_device::pwmp_r), FUNC(mc68ez328_device::pwmp_w)); + map(0xfffff505, 0xfffff505).rw(FUNC(mc68ez328_device::pwmcnt_r), FUNC(mc68ez328_device::pwmcnt_w)); + + map(0xfffffa29, 0xfffffa29).rw(FUNC(mc68ez328_device::lrra_r), FUNC(mc68ez328_device::lrra_w)); + map(0xfffffa36, 0xfffffa37).rw(FUNC(mc68ez328_device::pwmr_r), FUNC(mc68ez328_device::pwmr_w)); + + map(0xfffffb0a, 0xfffffb0b).rw(FUNC(mc68ez328_device::watchdog_r), FUNC(mc68ez328_device::watchdog_w)); + map(0xfffffb0c, 0xfffffb0d).rw(FUNC(mc68ez328_device::rtcctl_r), FUNC(mc68ez328_device::rtcctl_w)); + map(0xfffffb1a, 0xfffffb1b).rw(FUNC(mc68ez328_device::dayr_r), FUNC(mc68ez328_device::dayr_w)); + map(0xfffffb1c, 0xfffffb1d).rw(FUNC(mc68ez328_device::dayalarm_r), FUNC(mc68ez328_device::dayalarm_w)); } void mc68328_device::cpu_space_map(address_map &map) @@ -211,42 +297,9 @@ void mc68328_device::cpu_space_map(address_map &map) map(0xfffff0, 0xffffff).r(FUNC(mc68328_device::irq_callback)).umask16(0x00ff); } - -mc68328_device::mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : m68000_device(mconfig, tag, owner, clock, MC68328, 16, 24, address_map_constructor(FUNC(mc68328_device::internal_map), this)) - , m_rtc(nullptr) - , m_pwm(nullptr) - , m_spim(nullptr) - , m_out_port_a_cb(*this) - , m_out_port_b_cb(*this) - , m_out_port_c_cb(*this) - , m_out_port_d_cb(*this) - , m_out_port_e_cb(*this) - , m_out_port_f_cb(*this) - , m_out_port_g_cb(*this) - , m_out_port_j_cb(*this) - , m_out_port_k_cb(*this) - , m_out_port_m_cb(*this) - , m_in_port_a_cb(*this) - , m_in_port_b_cb(*this) - , m_in_port_c_cb(*this) - , m_in_port_d_cb(*this) - , m_in_port_e_cb(*this) - , m_in_port_f_cb(*this) - , m_in_port_g_cb(*this) - , m_in_port_j_cb(*this) - , m_in_port_k_cb(*this) - , m_in_port_m_cb(*this) - , m_out_pwm_cb(*this) - , m_out_spim_cb(*this) - , m_in_spim_cb(*this) - , m_out_flm_cb(*this) - , m_out_llp_cb(*this) - , m_out_lsclk_cb(*this) - , m_out_ld_cb(*this) - , m_lcd_info_changed_cb(*this) +void mc68ez328_device::cpu_space_map(address_map &map) { - m_cpu_space_config.m_internal_map = address_map_constructor(FUNC(mc68328_device::cpu_space_map), this); + map(0xfffffff0, 0xffffffff).r(FUNC(mc68ez328_device::irq_callback)).umask16(0x00ff); } //------------------------------------------------- @@ -255,31 +308,25 @@ mc68328_device::mc68328_device(const machine_config &mconfig, const char *tag, d // initial conditions at start time //------------------------------------------------- -void mc68328_device::device_resolve_objects() +void mc68328_base_device::device_resolve_objects() { m68000_device::device_resolve_objects(); - m_out_port_a_cb.resolve_safe(); - m_out_port_b_cb.resolve_safe(); - m_out_port_c_cb.resolve_safe(); - m_out_port_d_cb.resolve_safe(); - m_out_port_e_cb.resolve_safe(); - m_out_port_f_cb.resolve_safe(); - m_out_port_g_cb.resolve_safe(); - m_out_port_j_cb.resolve_safe(); - m_out_port_k_cb.resolve_safe(); - m_out_port_m_cb.resolve_safe(); + m_out_port_a_cb.resolve_all_safe(); + m_out_port_b_cb.resolve_all_safe(); + m_out_port_c_cb.resolve_all_safe(); + m_out_port_d_cb.resolve_all_safe(); + m_out_port_e_cb.resolve_all_safe(); + m_out_port_f_cb.resolve_all_safe(); + m_out_port_g_cb.resolve_all_safe(); - m_in_port_a_cb.resolve(); - m_in_port_b_cb.resolve(); - m_in_port_c_cb.resolve(); - m_in_port_d_cb.resolve(); - m_in_port_e_cb.resolve(); - m_in_port_f_cb.resolve(); - m_in_port_g_cb.resolve(); - m_in_port_j_cb.resolve(); - m_in_port_k_cb.resolve(); - m_in_port_m_cb.resolve(); + m_in_port_a_cb.resolve_all(); + m_in_port_b_cb.resolve_all(); + m_in_port_c_cb.resolve_all(); + m_in_port_d_cb.resolve_all(); + m_in_port_e_cb.resolve_all(); + m_in_port_f_cb.resolve_all(); + m_in_port_g_cb.resolve_all(); m_out_pwm_cb.resolve_safe(); @@ -294,31 +341,68 @@ void mc68328_device::device_resolve_objects() m_lcd_info_changed_cb.resolve(); } +void mc68328_device::device_resolve_objects() +{ + mc68328_base_device::device_resolve_objects(); + + m_out_port_j_cb.resolve_all_safe(); + m_out_port_k_cb.resolve_all_safe(); + m_out_port_m_cb.resolve_all_safe(); + + m_in_port_j_cb.resolve_all(); + m_in_port_k_cb.resolve_all(); + m_in_port_m_cb.resolve_all(); +} + +void mc68ez328_device::device_resolve_objects() +{ + mc68328_base_device::device_resolve_objects(); +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- -void mc68328_device::device_start() +void mc68328_base_device::device_start() { m68000_device::device_start(); - m_gptimer[0] = timer_alloc(FUNC(mc68328_device::timer_tick<0>),this); - m_gptimer[1] = timer_alloc(FUNC(mc68328_device::timer_tick<1>),this); - m_rtc = timer_alloc(FUNC(mc68328_device::rtc_tick),this); - m_pwm = timer_alloc(FUNC(mc68328_device::pwm_tick),this); - m_spim = timer_alloc(FUNC(mc68328_device::spim_tick),this); - m_lcd_scan = timer_alloc(FUNC(mc68328_device::lcd_scan_tick),this); + m_refclk = timer_alloc(FUNC(mc68328_base_device::refclk_tick), this); + m_pwm = timer_alloc(FUNC(mc68328_base_device::pwm_tick), this); + m_rtc = timer_alloc(FUNC(mc68328_base_device::rtc_tick), this); + m_spim = timer_alloc(FUNC(mc68328_base_device::spim_tick), this); + m_lcd_scan = timer_alloc(FUNC(mc68328_base_device::lcd_scan_tick), this); - m_lcd_line_buffer = std::make_unique(1024 / 8); // 1024px wide, up to 8 pixels per word + m_lcd_line_buffer = std::make_unique(1024 / 8); // 1024px wide, up to 8 pixels per word register_state_save(); } +void mc68328_device::device_start() +{ + mc68328_base_device::device_start(); + + m_gptimer[0] = timer_alloc(FUNC(mc68328_device::timer_tick<0>), this); + m_gptimer[1] = timer_alloc(FUNC(mc68328_device::timer_tick<1>), this); +} + +void mc68ez328_device::device_start() +{ + mc68328_base_device::device_start(); + + m_gptimer = timer_alloc(FUNC(mc68ez328_device::timer_tick<0>), this); + m_rtc_sample_timer = timer_alloc(FUNC(mc68ez328_device::sample_timer_tick), this); + + m_dayr = 0; + m_dayalarm = 0; + m_sam_cnt = 0; +} + //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- -void mc68328_device::device_reset() +void mc68328_base_device::device_reset() { m68000_device::device_reset(); @@ -327,15 +411,8 @@ void mc68328_device::device_reset() m_grpbaseb = 0x0000; m_grpbasec = 0x0000; m_grpbased = 0x0000; - m_grpmaska = 0x0000; - m_grpmaskb = 0x0000; - m_grpmaskc = 0x0000; - m_grpmaskd = 0x0000; - std::fill(std::begin(m_csa), std::end(m_csa), 0x00010006); - std::fill(std::begin(m_csb), std::end(m_csb), 0x00010006); - std::fill(std::begin(m_csc), std::end(m_csc), 0x00010006); - std::fill(std::begin(m_csd), std::end(m_csd), 0x00010006); + m_refclk->adjust(attotime::from_hz(32768), 0, attotime::from_hz(32768)); m_pllcr = 0x2400; m_pllfsr = 0x0123; m_pctlr = 0x1f; @@ -343,13 +420,12 @@ void mc68328_device::device_reset() m_ivr = 0x00; m_icr = 0x0000; m_imr = 0x00ffffff; - m_iwr = 0x00ffffff; m_isr = 0x00000000; m_ipr = 0x00000000; + m_pasel = 0x00; m_padir = 0x00; m_padata = 0x00; - m_pasel = 0x00; m_pbdir = 0x00; m_pbdata = 0x00; m_pbsel = 0x00; @@ -361,8 +437,8 @@ void mc68328_device::device_reset() m_pdpuen = 0xff; m_pdpol = 0x00; m_pdirqen = 0x00; - m_pddataedge = 0x00; m_pdirqedge = 0x00; + m_pdindata = 0x00; m_pedir = 0x00; m_pedata = 0x00; m_pepuen = 0x80; @@ -375,40 +451,13 @@ void mc68328_device::device_reset() m_pgdata = 0x00; m_pgpuen = 0xff; m_pgsel = 0xff; - m_pjdir = 0x00; - m_pjdata = 0x00; - m_pjsel = 0x00; - m_pkdir = 0x00; - m_pkdata = 0x00; - m_pkpuen = 0xff; - m_pksel = 0xff; - m_pmdir = 0x00; - m_pmdata = 0x00; - m_pmpuen = 0xff; - m_pmsel = 0xff; - - m_pwmc = 0x0000; - m_pwmp = 0x0000; - m_pwmw = 0x0000; - m_pwmcnt = 0x0000; - - m_tctl[0] = m_tctl[1] = 0x0000; - m_tprer[0] = m_tprer[1] = 0x0000; - m_tcmp[0] = m_tcmp[1] = 0xffff; - m_tcr[0] = m_tcr[1] = 0x0000; - m_tcn[0] = m_tcn[1] = 0x0000; - m_tstat[0] = m_tstat[1] = 0x0000; - m_wctlr = 0x0000; - m_wcmpr = 0xffff; - m_wcn = 0x0000; - - m_spisr = 0x0000; m_spimdata = 0x0000; m_spimcont = 0x0000; m_spmtxd = false; m_spmrxd = false; m_spmclk = false; + m_spim_bit_read_idx = 15; m_ustcnt = 0x0000; m_ubaud = 0x003f; @@ -429,23 +478,21 @@ void mc68328_device::device_reset() m_lacdrc = 0x00; m_lpxcd = 0x00; m_lckcon = 0x40; - m_llbar = 0x3e; - m_lotcr = 0x3f; m_lposr = 0x00; m_lfrcm = 0xb9; - m_lgpmr = 0x1073; m_hmsr = 0x00000000; m_alarm = 0x00000000; m_rtcctl = 0x00; - m_rtcisr = 0x00; - m_rtcienr = 0x00; - m_stpwtch = 0x00; - m_gptimer[0]->adjust(attotime::never); - m_gptimer[1]->adjust(attotime::never); - m_rtc->adjust(attotime::from_hz(1), 0, attotime::from_hz(1)); + m_rtcisr = 0x0000; + m_rtcienr = 0x0000; + m_stpwtch = 0x0000; + m_pwm->adjust(attotime::never); + m_pwmo = false; + + m_rtc->adjust(attotime::from_hz(1), 0, attotime::from_hz(1)); m_spim->adjust(attotime::never); m_lcd_scan->adjust(attotime::never); m_lcd_sysmem_ptr = 0; @@ -454,21 +501,96 @@ void mc68328_device::device_reset() m_lsclk = false; } -void mc68328_device::register_state_save() +void mc68328_device::device_reset() +{ + mc68328_base_device::device_reset(); + + m_grpmaska = 0x0000; + m_grpmaskb = 0x0000; + m_grpmaskc = 0x0000; + m_grpmaskd = 0x0000; + std::fill(std::begin(m_csa), std::end(m_csa), 0x00010006); + std::fill(std::begin(m_csb), std::end(m_csb), 0x00010006); + std::fill(std::begin(m_csc), std::end(m_csc), 0x00010006); + std::fill(std::begin(m_csd), std::end(m_csd), 0x00010006); + + m_iwr = 0x00ffffff; + + m_pasel = 0xff; + m_pjdir = 0x00; + m_pjdata = 0x00; + m_pjsel = 0x00; + m_pkdir = 0x00; + m_pkdata = 0x00; + m_pkpuen = 0xff; + m_pksel = 0xff; + m_pmdir = 0x00; + m_pmdata = 0x00; + m_pmpuen = 0xff; + m_pmsel = 0xff; + + m_pwmc = 0x0000; + m_pwmp = 0x0000; + m_pwmw = 0x0000; + m_pwmcnt = 0x0000; + + m_timer_regs[0].tctl = m_timer_regs[1].tctl = 0x0000; + m_timer_regs[0].tprer = m_timer_regs[1].tprer = 0x0000; + m_timer_regs[0].tcmp = m_timer_regs[1].tcmp = 0xffff; + m_timer_regs[0].tcr = m_timer_regs[1].tcr = 0x0000; + m_timer_regs[0].tcn = m_timer_regs[1].tcn = 0x0000; + m_timer_regs[0].tstat = m_timer_regs[1].tstat = 0x0000; + m_wctlr = 0x0000; + m_wcmpr = 0xffff; + m_wcn = 0x0000; + m_timer_regs[0].tclear = m_timer_regs[1].tclear = 0; + + m_spisr = 0x0000; + + m_llbar = 0x3e; + m_lotcr = 0x3f; + m_lgpmr = 0x1073; + + m_gptimer[0]->adjust(attotime::never); + m_gptimer[1]->adjust(attotime::never); +} + +void mc68ez328_device::device_reset() +{ + mc68328_base_device::device_reset(); + + m_csa = 0x00e0; + m_csb = 0x0000; + m_csc = 0x0000; + m_csd = 0x0020; + m_emucs = 0x0060; + + m_pwmc = 0x0020; + m_pwmp = 0xfe; + m_pwmcnt = 0x00; + std::fill(std::begin(m_pwmfifo), std::end(m_pwmfifo), 0x0000); + m_pwmfifo_wr = 0; + m_pwmfifo_rd = 0; + m_pwmfifo_cnt = 0; + m_pwm_rep_cnt = 1; + + m_gptimer->adjust(attotime::never); + + m_lrra = 0xff; + m_pwmr = 0x0000; + + m_rtc_sample_timer->adjust(attotime::from_ticks(64, 32768), 0, attotime::from_ticks(64, 32768)); + m_watchdog = 0x0001; + m_sam_cnt = 0; +} + +void mc68328_base_device::register_state_save() { save_item(NAME(m_scr)); save_item(NAME(m_grpbasea)); save_item(NAME(m_grpbaseb)); save_item(NAME(m_grpbasec)); save_item(NAME(m_grpbased)); - save_item(NAME(m_grpmaska)); - save_item(NAME(m_grpmaskb)); - save_item(NAME(m_grpmaskc)); - save_item(NAME(m_grpmaskd)); - save_item(NAME(m_csa)); - save_item(NAME(m_csb)); - save_item(NAME(m_csc)); - save_item(NAME(m_csd)); save_item(NAME(m_pllcr)); save_item(NAME(m_pllfsr)); @@ -477,13 +599,11 @@ void mc68328_device::register_state_save() save_item(NAME(m_ivr)); save_item(NAME(m_icr)); save_item(NAME(m_imr)); - save_item(NAME(m_iwr)); save_item(NAME(m_isr)); save_item(NAME(m_ipr)); save_item(NAME(m_padir)); save_item(NAME(m_padata)); - save_item(NAME(m_pasel)); save_item(NAME(m_pbdir)); save_item(NAME(m_pbdata)); save_item(NAME(m_pbsel)); @@ -495,8 +615,8 @@ void mc68328_device::register_state_save() save_item(NAME(m_pdpuen)); save_item(NAME(m_pdpol)); save_item(NAME(m_pdirqen)); - save_item(NAME(m_pddataedge)); save_item(NAME(m_pdirqedge)); + save_item(NAME(m_pdindata)); save_item(NAME(m_pedir)); save_item(NAME(m_pedata)); save_item(NAME(m_pepuen)); @@ -509,40 +629,16 @@ void mc68328_device::register_state_save() save_item(NAME(m_pgdata)); save_item(NAME(m_pgpuen)); save_item(NAME(m_pgsel)); - save_item(NAME(m_pjdir)); - save_item(NAME(m_pjdata)); - save_item(NAME(m_pjsel)); - save_item(NAME(m_pkdir)); - save_item(NAME(m_pkdata)); - save_item(NAME(m_pkpuen)); - save_item(NAME(m_pksel)); - save_item(NAME(m_pmdir)); - save_item(NAME(m_pmdata)); - save_item(NAME(m_pmpuen)); - save_item(NAME(m_pmsel)); save_item(NAME(m_pwmc)); - save_item(NAME(m_pwmp)); - save_item(NAME(m_pwmw)); - save_item(NAME(m_pwmcnt)); - - save_item(NAME(m_tctl)); - save_item(NAME(m_tprer)); - save_item(NAME(m_tcmp)); - save_item(NAME(m_tcr)); - save_item(NAME(m_tcn)); - save_item(NAME(m_tstat)); - save_item(NAME(m_wctlr)); - save_item(NAME(m_wcmpr)); - save_item(NAME(m_wcn)); - - save_item(NAME(m_spisr)); + save_item(NAME(m_pwmo)); save_item(NAME(m_spimdata)); save_item(NAME(m_spimcont)); save_item(NAME(m_spmtxd)); save_item(NAME(m_spmrxd)); save_item(NAME(m_spmclk)); + save_item(NAME(m_spim_bit_read_idx)); save_item(NAME(m_ustcnt)); save_item(NAME(m_ubaud)); @@ -583,241 +679,431 @@ void mc68328_device::register_state_save() save_item(NAME(m_lsclk)); } +void mc68328_device::register_state_save() +{ + mc68328_base_device::register_state_save(); + + save_item(NAME(m_grpmaska)); + save_item(NAME(m_grpmaskb)); + save_item(NAME(m_grpmaskc)); + save_item(NAME(m_grpmaskd)); + save_item(NAME(m_csa)); + save_item(NAME(m_csb)); + save_item(NAME(m_csc)); + save_item(NAME(m_csd)); + + save_item(NAME(m_iwr)); + + save_item(NAME(m_pasel)); + save_item(NAME(m_pjdir)); + save_item(NAME(m_pjdata)); + save_item(NAME(m_pjsel)); + save_item(NAME(m_pkdir)); + save_item(NAME(m_pkdata)); + save_item(NAME(m_pkpuen)); + save_item(NAME(m_pksel)); + save_item(NAME(m_pmdir)); + save_item(NAME(m_pmdata)); + save_item(NAME(m_pmpuen)); + save_item(NAME(m_pmsel)); + + save_item(NAME(m_pwmp)); + save_item(NAME(m_pwmw)); + save_item(NAME(m_pwmcnt)); + + save_item(STRUCT_MEMBER(m_timer_regs, tctl)); + save_item(STRUCT_MEMBER(m_timer_regs, tprer)); + save_item(STRUCT_MEMBER(m_timer_regs, tcmp)); + save_item(STRUCT_MEMBER(m_timer_regs, tcr)); + save_item(STRUCT_MEMBER(m_timer_regs, tcn)); + save_item(STRUCT_MEMBER(m_timer_regs, tstat)); + save_item(STRUCT_MEMBER(m_timer_regs, tclear)); + save_item(NAME(m_wctlr)); + save_item(NAME(m_wcmpr)); + save_item(NAME(m_wcn)); + + save_item(NAME(m_spisr)); +} + +void mc68ez328_device::register_state_save() +{ + mc68328_base_device::register_state_save(); + + save_item(NAME(m_pwmp)); + save_item(NAME(m_pwmcnt)); + save_item(NAME(m_pwmfifo)); + save_item(NAME(m_pwmfifo_wr)); + save_item(NAME(m_pwmfifo_rd)); + save_item(NAME(m_pwmfifo_cnt)); + save_item(NAME(m_pwm_rep_cnt)); + + save_item(STRUCT_MEMBER(m_timer_regs, tctl)); + save_item(STRUCT_MEMBER(m_timer_regs, tprer)); + save_item(STRUCT_MEMBER(m_timer_regs, tcmp)); + save_item(STRUCT_MEMBER(m_timer_regs, tcr)); + save_item(STRUCT_MEMBER(m_timer_regs, tcn)); + save_item(STRUCT_MEMBER(m_timer_regs, tstat)); + save_item(STRUCT_MEMBER(m_timer_regs, tclear)); + + save_item(NAME(m_lrra)); + save_item(NAME(m_pwmr)); + + save_item(NAME(m_watchdog)); + save_item(NAME(m_dayr)); + save_item(NAME(m_dayalarm)); + save_item(NAME(m_sam_cnt)); +} //------------------------------------------------- // System control hardware //------------------------------------------------- -void mc68328_device::scr_w(uint8_t data) // 0x000 +void mc68328_base_device::scr_w(u8 data) // 0x000 { - LOGMASKED(LOG_SCR, "scr_w: SCR = %02x\n", data); + LOGMASKED(LOG_SCR, "%s: scr_w: SCR = %02x\n", machine().describe_context(), data); } -uint8_t mc68328_device::scr_r() // 0x000 +u8 mc68328_base_device::scr_r() // 0x000 { - LOGMASKED(LOG_SCR, "scr_r: SCR: %02x\n", m_scr); + LOGMASKED(LOG_SCR, "%s: scr_r: SCR: %02x\n", machine().describe_context(), m_scr); return m_scr; } //------------------------------------------------- -// Memory-mapping/chip-select hardware +// MMU/chip-select hardware - Standard MC68328 //------------------------------------------------- -void mc68328_device::grpbasea_w(uint16_t data) // 0x100 +void mc68328_base_device::grpbasea_w(u16 data) // 0x100 { - LOGMASKED(LOG_CS_GRP, "grpbasea_w: GRPBASEA = %04x\n", data); + LOGMASKED(LOG_CS_GRP, "%s: grpbasea_w: GRPBASEA = %04x\n", machine().describe_context(), data); m_grpbasea = data; } -uint16_t mc68328_device::grpbasea_r() // 0x100 +u16 mc68328_base_device::grpbasea_r() // 0x100 { - LOGMASKED(LOG_CS_GRP, "grpbasea_r: GRPBASEA: %04x\n", m_grpbasea); + LOGMASKED(LOG_CS_GRP, "%s: grpbasea_r: GRPBASEA: %04x\n", machine().describe_context(), m_grpbasea); return m_grpbasea; } -void mc68328_device::grpbaseb_w(uint16_t data) // 0x102 +void mc68328_base_device::grpbaseb_w(u16 data) // 0x102 { - LOGMASKED(LOG_CS_GRP, "grpbaseb_w: GRPBASEB = %04x\n", data); + LOGMASKED(LOG_CS_GRP, "%s: grpbaseb_w: GRPBASEB = %04x\n", machine().describe_context(), data); m_grpbaseb = data; } -uint16_t mc68328_device::grpbaseb_r() // 0x102 +u16 mc68328_base_device::grpbaseb_r() // 0x102 { - LOGMASKED(LOG_CS_GRP, "grpbaseb_r: GRPBASEB: %04x\n", m_grpbaseb); + LOGMASKED(LOG_CS_GRP, "%s: grpbaseb_r: GRPBASEB: %04x\n", machine().describe_context(), m_grpbaseb); return m_grpbaseb; } -void mc68328_device::grpbasec_w(uint16_t data) // 0x104 +void mc68328_base_device::grpbasec_w(u16 data) // 0x104 { - LOGMASKED(LOG_CS_GRP, "grpbasec_w: GRPBASEC = %04x\n", data); + LOGMASKED(LOG_CS_GRP, "%s: grpbasec_w: GRPBASEC = %04x\n", machine().describe_context(), data); m_grpbasec = data; } -uint16_t mc68328_device::grpbasec_r() // 0x104 +u16 mc68328_base_device::grpbasec_r() // 0x104 { - LOGMASKED(LOG_CS_GRP, "grpbasec_r: GRPBASEC: %04x\n", m_grpbasec); + LOGMASKED(LOG_CS_GRP, "%s: grpbasec_r: GRPBASEC: %04x\n", machine().describe_context(), m_grpbasec); return m_grpbasec; } -void mc68328_device::grpbased_w(uint16_t data) // 0x106 +void mc68328_base_device::grpbased_w(u16 data) // 0x106 { - LOGMASKED(LOG_CS_GRP, "grpbased_w: GRPBASED = %04x\n", data); + LOGMASKED(LOG_CS_GRP, "%s: grpbased_w: GRPBASED = %04x\n", machine().describe_context(), data); m_grpbased = data; } -uint16_t mc68328_device::grpbased_r() // 0x106 +u16 mc68328_base_device::grpbased_r() // 0x106 { - LOGMASKED(LOG_CS_GRP, "grpbased_r: GRPBASED: %04x\n", m_grpbased); + LOGMASKED(LOG_CS_GRP, "%s: grpbased_r: GRPBASED: %04x\n", machine().describe_context(), m_grpbased); return m_grpbased; } -void mc68328_device::grpmaska_w(uint16_t data) // 0x108 +void mc68328_device::grpmaska_w(u16 data) // 0x108 { - LOGMASKED(LOG_CS_GRP, "grpmaska_w: GRPMASKA = %04x\n", data); + LOGMASKED(LOG_CS_GRP, "%s: grpmaska_w: GRPMASKA = %04x\n", machine().describe_context(), data); m_grpmaska = data; } -uint16_t mc68328_device::grpmaska_r() // 0x108 +u16 mc68328_device::grpmaska_r() // 0x108 { - LOGMASKED(LOG_CS_GRP, "grpmaska_r: GRPMASKA: %04x\n", m_grpmaska); + LOGMASKED(LOG_CS_GRP, "%s: grpmaska_r: GRPMASKA: %04x\n", machine().describe_context(), m_grpmaska); return m_grpmaska; } -void mc68328_device::grpmaskb_w(uint16_t data) // 0x10a +void mc68328_device::grpmaskb_w(u16 data) // 0x10a { - LOGMASKED(LOG_CS_GRP, "grpmaskb_w: GRPMASKB = %04x\n", data); + LOGMASKED(LOG_CS_GRP, "%s: grpmaskb_w: GRPMASKB = %04x\n", machine().describe_context(), data); m_grpmaskb = data; } -uint16_t mc68328_device::grpmaskb_r() // 0x10a +u16 mc68328_device::grpmaskb_r() // 0x10a { - LOGMASKED(LOG_CS_GRP, "grpmaskb_r: GRPMASKB: %04x\n", m_grpmaskb); + LOGMASKED(LOG_CS_GRP, "%s: grpmaskb_r: GRPMASKB: %04x\n", machine().describe_context(), m_grpmaskb); return m_grpmaskb; } -void mc68328_device::grpmaskc_w(uint16_t data) // 0x10c +void mc68328_device::grpmaskc_w(u16 data) // 0x10c { - LOGMASKED(LOG_CS_GRP, "grpmaskc_w: GRPMASKC = %04x\n", data); + LOGMASKED(LOG_CS_GRP, "%s: grpmaskc_w: GRPMASKC = %04x\n", machine().describe_context(), data); m_grpmaskc = data; } -uint16_t mc68328_device::grpmaskc_r() // 0x10c +u16 mc68328_device::grpmaskc_r() // 0x10c { - LOGMASKED(LOG_CS_GRP, "grpmaskc_r: GRPMASKC: %04x\n", m_grpmaskc); + LOGMASKED(LOG_CS_GRP, "%s: grpmaskc_r: GRPMASKC: %04x\n", machine().describe_context(), m_grpmaskc); return m_grpmaskc; } -void mc68328_device::grpmaskd_w(uint16_t data) // 0x10e +void mc68328_device::grpmaskd_w(u16 data) // 0x10e { - LOGMASKED(LOG_CS_GRP, "grpmaskd_w: GRPMASKD = %04x\n", data); + LOGMASKED(LOG_CS_GRP, "%s: grpmaskd_w: GRPMASKD = %04x\n", machine().describe_context(), data); m_grpmaskd = data; } -uint16_t mc68328_device::grpmaskd_r() // 0x10e +u16 mc68328_device::grpmaskd_r() // 0x10e { - LOGMASKED(LOG_CS_GRP, "grpmaskd_r: GRPMASKD: %04x\n", m_grpmaskd); + LOGMASKED(LOG_CS_GRP, "%s: grpmaskd_r: GRPMASKD: %04x\n", machine().describe_context(), m_grpmaskd); return m_grpmaskd; } template -void mc68328_device::csa_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x110, 0x114, 0x118, 0x11c +void mc68328_device::csa_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x110, 0x114, 0x118, 0x11c { - LOGMASKED(LOG_CS_SEL, "csa_msw_w<%d>: CSA%d(16) = %04x\n", ChipSelect, ChipSelect, data); + LOGMASKED(LOG_CS_SEL, "%s: csa_msw_w<%d>: CSA%d(16) = %04x\n", machine().describe_context(), ChipSelect, ChipSelect, data); m_csa[ChipSelect] &= 0xffff0000 | (~mem_mask); m_csa[ChipSelect] |= data & mem_mask; } template -uint16_t mc68328_device::csa_msw_r() // 0x110, 0x120, 0x130, 0x140 +u16 mc68328_device::csa_msw_r() // 0x110, 0x120, 0x130, 0x140 { - LOGMASKED(LOG_CS_SEL, "csa_msw_r: CSA%d(MSW): %04x\n", ChipSelect, (uint16_t)(m_csa[ChipSelect] >> 16)); - return (uint16_t)(m_csa[ChipSelect] >> 16); + LOGMASKED(LOG_CS_SEL, "%s: csa_msw_r: CSA%d(MSW): %04x\n", machine().describe_context(), ChipSelect, (u16)(m_csa[ChipSelect] >> 16)); + return (u16)(m_csa[ChipSelect] >> 16); } template -void mc68328_device::csa_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x112, 0x116, 0x11a, 0x11e +void mc68328_device::csa_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0x112, 0x116, 0x11a, 0x11e { - LOGMASKED(LOG_CS_SEL, "csa_lsw_w<%d>: CSA%d(0) = %04x\n", ChipSelect, ChipSelect, data); + LOGMASKED(LOG_CS_SEL, "%s: csa_lsw_w<%d>: CSA%d(0) = %04x\n", machine().describe_context(), ChipSelect, ChipSelect, data); m_csa[ChipSelect] &= ~(mem_mask << 16); m_csa[ChipSelect] |= (data & mem_mask) << 16; } template -uint16_t mc68328_device::csa_lsw_r() // 0x112, 0x122, 0x132, 0x142 +u16 mc68328_device::csa_lsw_r() // 0x112, 0x122, 0x132, 0x142 { - LOGMASKED(LOG_CS_SEL, "csa_lsw_r: CSA%d(LSW): %04x\n", ChipSelect, (uint16_t)m_csa[ChipSelect]); - return (uint16_t)m_csa[ChipSelect]; + LOGMASKED(LOG_CS_SEL, "%s: csa_lsw_r: CSA%d(LSW): %04x\n", machine().describe_context(), ChipSelect, (u16)m_csa[ChipSelect]); + return (u16)m_csa[ChipSelect]; } template -void mc68328_device::csb_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x120, 0x124, 0x128, 0x12c +void mc68328_device::csb_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x120, 0x124, 0x128, 0x12c { - LOGMASKED(LOG_CS_SEL, "csb_msw_w<%d>: CSB%d(MSW) = %04x\n", ChipSelect, ChipSelect, data); + LOGMASKED(LOG_CS_SEL, "%s: csb_msw_w<%d>: CSB%d(MSW) = %04x\n", machine().describe_context(), ChipSelect, ChipSelect, data); m_csb[ChipSelect] &= 0xffff0000 | (~mem_mask); m_csb[ChipSelect] |= data & mem_mask; } template -uint16_t mc68328_device::csb_msw_r() // 0x114, 0x124, 0x134, 0x144 +u16 mc68328_device::csb_msw_r() // 0x114, 0x124, 0x134, 0x144 { - LOGMASKED(LOG_CS_SEL, "csb_msw_r: CSB%d(MSW): %04x\n", ChipSelect, (uint16_t)(m_csb[ChipSelect] >> 16)); - return (uint16_t)(m_csb[ChipSelect] >> 16); + LOGMASKED(LOG_CS_SEL, "%s: csb_msw_r: CSB%d(MSW): %04x\n", machine().describe_context(), ChipSelect, (u16)(m_csb[ChipSelect] >> 16)); + return (u16)(m_csb[ChipSelect] >> 16); } template -void mc68328_device::csb_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x122, 0x126, 0x12a, 0x12e +void mc68328_device::csb_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0x122, 0x126, 0x12a, 0x12e { - LOGMASKED(LOG_CS_SEL, "csb_lsw_w<%d>: CSB%d(LSW) = %04x\n", ChipSelect, ChipSelect, data); + LOGMASKED(LOG_CS_SEL, "%s: csb_lsw_w<%d>: CSB%d(LSW) = %04x\n", machine().describe_context(), ChipSelect, ChipSelect, data); m_csb[ChipSelect] &= ~(mem_mask << 16); m_csb[ChipSelect] |= (data & mem_mask) << 16; } template -uint16_t mc68328_device::csb_lsw_r() // 0x116, 0x126, 0x136, 0x146 +u16 mc68328_device::csb_lsw_r() // 0x116, 0x126, 0x136, 0x146 { - LOGMASKED(LOG_CS_SEL, "csb_lsw_r: CSB%d(LSW): %04x\n", ChipSelect, (uint16_t)m_csb[ChipSelect]); - return (uint16_t)m_csb[ChipSelect]; + LOGMASKED(LOG_CS_SEL, "%s: csb_lsw_r: CSB%d(LSW): %04x\n", machine().describe_context(), ChipSelect, (u16)m_csb[ChipSelect]); + return (u16)m_csb[ChipSelect]; } template -void mc68328_device::csc_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x130, 0x134, 0x138, 0x13c +void mc68328_device::csc_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x130, 0x134, 0x138, 0x13c { - LOGMASKED(LOG_CS_SEL, "csc_msw_w<%d>: CSC%d(MSW) = %04x\n", ChipSelect, ChipSelect, data); + LOGMASKED(LOG_CS_SEL, "%s: csc_msw_w<%d>: CSC%d(MSW) = %04x\n", machine().describe_context(), ChipSelect, ChipSelect, data); m_csc[ChipSelect] &= 0xffff0000 | (~mem_mask); m_csc[ChipSelect] |= data & mem_mask; } template -uint16_t mc68328_device::csc_msw_r() // 0x118, 0x128, 0x138, 0x148 +u16 mc68328_device::csc_msw_r() // 0x118, 0x128, 0x138, 0x148 { - LOGMASKED(LOG_CS_SEL, "csc_msw_r: CSC%d(MSW): %04x\n", ChipSelect, (uint16_t)(m_csc[ChipSelect] >> 16)); - return (uint16_t)(m_csc[ChipSelect] >> 16); + LOGMASKED(LOG_CS_SEL, "%s: csc_msw_r: CSC%d(MSW): %04x\n", machine().describe_context(), ChipSelect, (u16)(m_csc[ChipSelect] >> 16)); + return (u16)(m_csc[ChipSelect] >> 16); } template -void mc68328_device::csc_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x132, 0x136, 0x13a, 0x13e +void mc68328_device::csc_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0x132, 0x136, 0x13a, 0x13e { - LOGMASKED(LOG_CS_SEL, "csc_lsw_w<%d>: CSC%d(LSW) = %04x\n", ChipSelect, ChipSelect, data); + LOGMASKED(LOG_CS_SEL, "%s: csc_lsw_w<%d>: CSC%d(LSW) = %04x\n", machine().describe_context(), ChipSelect, ChipSelect, data); m_csc[ChipSelect] &= ~(mem_mask << 16); m_csc[ChipSelect] |= (data & mem_mask) << 16; } template -uint16_t mc68328_device::csc_lsw_r() // 0x11a, 0x12a, 0x13a, 0x14a +u16 mc68328_device::csc_lsw_r() // 0x11a, 0x12a, 0x13a, 0x14a { - LOGMASKED(LOG_CS_SEL, "csc_lsw_r: CSC%d(LSW): %04x\n", ChipSelect, (uint16_t)m_csc[ChipSelect]); - return (uint16_t)m_csc[ChipSelect]; + LOGMASKED(LOG_CS_SEL, "%s: csc_lsw_r: CSC%d(LSW): %04x\n", machine().describe_context(), ChipSelect, (u16)m_csc[ChipSelect]); + return (u16)m_csc[ChipSelect]; } template -void mc68328_device::csd_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x140, 0x144, 0x148, 0x14c +void mc68328_device::csd_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x140, 0x144, 0x148, 0x14c { - LOGMASKED(LOG_CS_SEL, "csd_msw_w<%d>: CSD%d(MSW) = %04x\n", ChipSelect, ChipSelect, data); + LOGMASKED(LOG_CS_SEL, "%s: csd_msw_w<%d>: CSD%d(MSW) = %04x\n", machine().describe_context(), ChipSelect, ChipSelect, data); m_csd[ChipSelect] &= 0xffff0000 | (~mem_mask); m_csd[ChipSelect] |= data & mem_mask; } template -uint16_t mc68328_device::csd_msw_r() // 0x11c, 0x12c, 0x13c, 0x14c +u16 mc68328_device::csd_msw_r() // 0x11c, 0x12c, 0x13c, 0x14c { - LOGMASKED(LOG_CS_SEL, "csd_msw_r: CSD%d(MSW): %04x\n", ChipSelect, (uint16_t)(m_csd[ChipSelect] >> 16)); - return (uint16_t)(m_csd[ChipSelect] >> 16); + LOGMASKED(LOG_CS_SEL, "%s: csd_msw_r: CSD%d(MSW): %04x\n", machine().describe_context(), ChipSelect, (u16)(m_csd[ChipSelect] >> 16)); + return (u16)(m_csd[ChipSelect] >> 16); } template -void mc68328_device::csd_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x142, 0x146, 0x14a, 0x14e +void mc68328_device::csd_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0x142, 0x146, 0x14a, 0x14e { - LOGMASKED(LOG_CS_SEL, "csd_lsw_w<%d>: CSD%d(LSW) = %04x\n", ChipSelect, ChipSelect, data); + LOGMASKED(LOG_CS_SEL, "%s: csd_lsw_w<%d>: CSD%d(LSW) = %04x\n", machine().describe_context(), ChipSelect, ChipSelect, data); m_csd[ChipSelect] &= ~(mem_mask << 16); m_csd[ChipSelect] |= (data & mem_mask) << 16; } template -uint16_t mc68328_device::csd_lsw_r() // 0x11e, 0x12e, 0x13e, 0x14e +u16 mc68328_device::csd_lsw_r() // 0x11e, 0x12e, 0x13e, 0x14e { - LOGMASKED(LOG_CS_SEL, "csd_lsw_r: CSD%d(LSW): %04x\n", ChipSelect, (uint16_t)m_csd[ChipSelect]); - return (uint16_t)m_csd[ChipSelect]; + LOGMASKED(LOG_CS_SEL, "%s: csd_lsw_r: CSD%d(LSW): %04x\n", machine().describe_context(), ChipSelect, (u16)m_csd[ChipSelect]); + return (u16)m_csd[ChipSelect]; +} + + +//------------------------------------------------- +// MMU/chip-select hardware - EZ variant +//------------------------------------------------- + +u8 mc68ez328_device::revision_r(offs_t offset) +{ + LOGMASKED(LOG_PLL, "%s: revision_r: Silicon Revision[%d] = %02x\n", machine().describe_context(), offset, 0x01); + return 0x01; +} + +void mc68ez328_device::csa_w(offs_t offset, u16 data, u16 mem_mask) +{ + static const char *const SIZ_NAMES[8] = { "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M" }; + static const char *const WS_NAMES[8] = { "None", "1", "2", "3", "4", "5", "6", "External /DTACK" }; + LOGMASKED(LOG_CS_SEL, "%s: csa_w: CSA = %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_CS_SEL, "%s: Enable: %d\n", machine().describe_context(), BIT(data, CS_EN_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Chip-Select Size: %s\n", machine().describe_context(), SIZ_NAMES[(data & CS_SIZ_MASK) >> CS_SIZ_SHIFT]); + LOGMASKED(LOG_CS_SEL, "%s: Wait States: %s\n", machine().describe_context(), WS_NAMES[(data & CS_WS_MASK) >> CS_WS_SHIFT]); + LOGMASKED(LOG_CS_SEL, "%s: Bus Width: %d Bits\n", machine().describe_context(), BIT(data, CS_BSW_BIT) ? 16 : 8); + LOGMASKED(LOG_CS_SEL, "%s: Delay /LWE and /UWE for Flash: %s\n", machine().describe_context(), BIT(data, CS_FLASH_BIT) ? "Yes" : "No"); + LOGMASKED(LOG_CS_SEL, "%s: Read-Only: %d\n", machine().describe_context(), BIT(data, CS_RO_BIT)); + m_csa = data; +} + +u16 mc68ez328_device::csa_r() +{ + LOGMASKED(LOG_CS_SEL, "%s: csa_r: CSA: %04x\n", machine().describe_context(), m_csa); + return m_csa; +} + +void mc68ez328_device::csb_w(offs_t offset, u16 data, u16 mem_mask) +{ + static const char *const SIZ_NAMES[8] = { "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M" }; + static const char *const WS_NAMES[8] = { "None", "1", "2", "3", "4", "5", "6", "External /DTACK" }; + LOGMASKED(LOG_CS_SEL, "%s: csb_w: CSB = %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_CS_SEL, "%s: Enable: %d\n", machine().describe_context(), BIT(data, CS_EN_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Chip-Select Size: %s\n", machine().describe_context(), SIZ_NAMES[(data & CS_SIZ_MASK) >> CS_SIZ_SHIFT]); + LOGMASKED(LOG_CS_SEL, "%s: Wait States: %s\n", machine().describe_context(), WS_NAMES[(data & CS_WS_MASK) >> CS_WS_SHIFT]); + LOGMASKED(LOG_CS_SEL, "%s: Bus Width: %d Bits\n", machine().describe_context(), BIT(data, CS_BSW_BIT) ? 16 : 8); + LOGMASKED(LOG_CS_SEL, "%s: Delay /LWE and /UWE for Flash: %s\n", machine().describe_context(), BIT(data, CS_FLASH_BIT) ? "Yes" : "No"); + LOGMASKED(LOG_CS_SEL, "%s: Unprotected Block Size: %dK\n", machine().describe_context(), 32 << ((data & CS_UPSIZ_MASK) >> CS_UPSIZ_SHIFT)); + LOGMASKED(LOG_CS_SEL, "%s: Read-Only for Protected Block: %d\n", machine().describe_context(), BIT(data, CS_ROP_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Supervisor-Only for Protected Block: %d\n", machine().describe_context(), BIT(data, CS_SOP_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Read-Only: %d\n", machine().describe_context(), BIT(data, CS_RO_BIT)); + m_csb = data; +} + +u16 mc68ez328_device::csb_r() +{ + LOGMASKED(LOG_CS_SEL, "%s: csb_r: CSB: %04x\n", machine().describe_context(), m_csb); + return m_csb; +} + +void mc68ez328_device::csc_w(offs_t offset, u16 data, u16 mem_mask) +{ + static const char *const SIZ_NAMES[8] = { "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M" }; + static const char *const WS_NAMES[8] = { "None", "1", "2", "3", "4", "5", "6", "External /DTACK" }; + LOGMASKED(LOG_CS_SEL, "%s: csc_w: CSC = %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_CS_SEL, "%s: Enable: %d\n", machine().describe_context(), BIT(data, CS_EN_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Chip-Select Size: %s\n", machine().describe_context(), SIZ_NAMES[(data & CS_SIZ_MASK) >> CS_SIZ_SHIFT]); + LOGMASKED(LOG_CS_SEL, "%s: Wait States: %s\n", machine().describe_context(), WS_NAMES[(data & CS_WS_MASK) >> CS_WS_SHIFT]); + LOGMASKED(LOG_CS_SEL, "%s: Bus Width: %d Bits\n", machine().describe_context(), BIT(data, CS_BSW_BIT) ? 16 : 8); + LOGMASKED(LOG_CS_SEL, "%s: Delay /LWE and /UWE for Flash: %s\n", machine().describe_context(), BIT(data, CS_FLASH_BIT) ? "Yes" : "No"); + LOGMASKED(LOG_CS_SEL, "%s: Unprotected Block Size: %dK\n", machine().describe_context(), 32 << ((data & CS_UPSIZ_MASK) >> CS_UPSIZ_SHIFT)); + LOGMASKED(LOG_CS_SEL, "%s: Read-Only for Protected Block: %d\n", machine().describe_context(), BIT(data, CS_ROP_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Supervisor-Only for Protected Block: %d\n", machine().describe_context(), BIT(data, CS_SOP_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Read-Only: %d\n", machine().describe_context(), BIT(data, CS_RO_BIT)); + m_csc = data; +} + +u16 mc68ez328_device::csc_r() +{ + LOGMASKED(LOG_CS_SEL, "%s: csc_r: CSC: %04x\n", machine().describe_context(), m_csc); + return m_csc; +} + +void mc68ez328_device::csd_w(offs_t offset, u16 data, u16 mem_mask) +{ + static const char *const SIZ_NAMES[8] = { "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M" }; + static const char *const WS_NAMES[8] = { "None", "1", "2", "3", "4", "5", "6", "External /DTACK" }; + LOGMASKED(LOG_CS_SEL, "%s: csd_w: CSD = %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_CS_SEL, "%s: Enable: %d\n", machine().describe_context(), BIT(data, CS_EN_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Chip-Select Size: %s\n", machine().describe_context(), SIZ_NAMES[(data & CS_SIZ_MASK) >> CS_SIZ_SHIFT]); + LOGMASKED(LOG_CS_SEL, "%s: Wait States: %s\n", machine().describe_context(), WS_NAMES[(data & CS_WS_MASK) >> CS_WS_SHIFT]); + LOGMASKED(LOG_CS_SEL, "%s: Bus Width: %d Bits\n", machine().describe_context(), BIT(data, CS_BSW_BIT) ? 16 : 8); + LOGMASKED(LOG_CS_SEL, "%s: Delay /LWE and /UWE for Flash: %s\n", machine().describe_context(), BIT(data, CS_FLASH_BIT) ? "Yes" : "No"); + LOGMASKED(LOG_CS_SEL, "%s: DRAM Selection: %s\n", machine().describe_context(), BIT(data, CS_DRAM_BIT) ? "Select /CAS and /RAS" : "Select /CSC[1:0] and /CSD[1:0]"); + LOGMASKED(LOG_CS_SEL, "%s: Use /RAS0 for /RAS1: %s\n", machine().describe_context(), BIT(data, CS_COMB_BIT) ? "Yes" : "No"); + LOGMASKED(LOG_CS_SEL, "%s: Unprotected Block Size: %dK\n", machine().describe_context(), 32 << ((data & CS_UPSIZ_MASK) >> CS_UPSIZ_SHIFT)); + LOGMASKED(LOG_CS_SEL, "%s: Read-Only for Protected Block: %d\n", machine().describe_context(), BIT(data, CS_ROP_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Supervisor-Only for Protected Block: %d\n", machine().describe_context(), BIT(data, CS_SOP_BIT)); + LOGMASKED(LOG_CS_SEL, "%s: Read-Only: %d\n", machine().describe_context(), BIT(data, CS_RO_BIT)); + m_csd = data; +} + +u16 mc68ez328_device::csd_r() +{ + LOGMASKED(LOG_CS_SEL, "%s: csd_r: CSD: %04x\n", machine().describe_context(), m_csd); + return m_csd; +} + +void mc68ez328_device::emucs_w(offs_t offset, u16 data, u16 mem_mask) +{ + static const char *const WS_NAMES[8] = { "None", "1", "2", "3", "4", "5", "6", "External /DTACK" }; + LOGMASKED(LOG_CS_SEL, "%s: emucs_w: EMUCS = %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_CS_SEL, "%s: Wait States: %s\n", machine().describe_context(), WS_NAMES[(data & CS_WS_MASK) >> CS_WS_SHIFT]); + m_emucs = data; +} + +u16 mc68ez328_device::emucs_r() +{ + LOGMASKED(LOG_CS_SEL, "%s: emucs_r: EMUCS: %04x\n", machine().describe_context(), m_emucs); + return m_emucs; } @@ -825,298 +1111,387 @@ uint16_t mc68328_device::csd_lsw_r() // 0x11e, 0x12e, 0x13e, 0x14e // PLL/power hardware //------------------------------------------------- -void mc68328_device::pllcr_w(uint16_t data) // 0x200 +TIMER_CALLBACK_MEMBER(mc68328_base_device::refclk_tick) { - LOGMASKED(LOG_PLL, "pllcr_w: PLLCR = %04x\n", data); + m_pllfsr ^= 0x8000; +} + +void mc68328_base_device::pllcr_w(u16 data) // 0x200 +{ + LOGMASKED(LOG_PLL, "%s: pllcr_w: PLLCR = %04x\n", machine().describe_context(), data); m_pllcr = data; } -uint16_t mc68328_device::pllcr_r() // 0x200 +u16 mc68328_base_device::pllcr_r() // 0x200 { - LOGMASKED(LOG_PLL, "pllcr_r: PLLCR: %04x\n", m_pllcr); + LOGMASKED(LOG_PLL, "%s: pllcr_r: PLLCR: %04x\n", machine().describe_context(), m_pllcr); return m_pllcr; } -void mc68328_device::pllfsr_w(uint16_t data) // 0x202 +void mc68328_base_device::pllfsr_w(u16 data) // 0x202 { - LOGMASKED(LOG_PLL, "pllfsr_w: PLLFSR = %04x\n", data); + LOGMASKED(LOG_PLL, "%s: pllfsr_w: PLLFSR = %04x\n", machine().describe_context(), data); m_pllfsr = data; } -uint16_t mc68328_device::pllfsr_r() // 0x202 +u16 mc68328_base_device::pllfsr_r() // 0x202 { - LOGMASKED(LOG_PLL, "pllfsr_r: PLLFSR: %04x\n", m_pllfsr); - m_pllfsr ^= 0x8000; + LOGMASKED(LOG_PLL, "%s: pllfsr_r: PLLFSR: %04x\n", machine().describe_context(), m_pllfsr); return m_pllfsr; } -void mc68328_device::pctlr_w(uint8_t data) // 0x207 +void mc68328_base_device::pctlr_w(u8 data) // 0x207 { - LOGMASKED(LOG_PLL, "pctlr_w: PCTLR = %02x\n", data); + LOGMASKED(LOG_PLL, "%s: pctlr_w: PCTLR = %02x\n", machine().describe_context(), data); m_pctlr = data; } -uint8_t mc68328_device::pctlr_r() // 0x207 +u8 mc68328_base_device::pctlr_r() // 0x207 { - LOGMASKED(LOG_PLL, "pctlr_r: PCTLR: %02x\n", m_pctlr); + LOGMASKED(LOG_PLL, "%s: pctlr_r: PCTLR: %02x\n", machine().describe_context(), m_pctlr); return m_pctlr; } //------------------------------------------------- -// Interrupt-related hardware +// Interrupt-related hardware - standard MC68328 //------------------------------------------------- -void mc68328_device::set_interrupt_line(uint32_t line, uint32_t active) +void mc68328_base_device::update_ipr_state(u32 changed_mask) { + const int irq_level = get_irq_level_for_mask(changed_mask); + const u32 irq_mask = get_irq_mask_for_level(irq_level); + + if (!irq_level || !irq_mask) + { + return; + } + + if (m_ipr & changed_mask) + { + // If a pending interrupt has changed, it's not masked, and it's not currently in service, raise the corresponding 68k IRQ line and mark it as + // in-service. + if ((~m_imr & irq_mask) && !(m_isr & changed_mask)) + { + m_isr |= changed_mask; + set_input_line(irq_level, ASSERT_LINE); + } + } + else + { + m_isr &= ~changed_mask; + + // If there are no other pending, unmasked interrupts at this level, lower the corresponding 68k IRQ line. + if (!(m_ipr & ~m_imr & irq_mask)) + { + set_input_line(irq_level, CLEAR_LINE); + } + } +} + +void mc68328_base_device::update_imr_state(u32 changed_mask) +{ + int irq_level = get_irq_level_for_mask(changed_mask); + u32 irq_mask = get_irq_mask_for_level(irq_level); + u32 level_mask = irq_mask & changed_mask; + + while (irq_level && irq_mask) + { + if (m_ipr & ~m_isr & ~m_imr & level_mask) + { + // If a newly-unmasked interrupt is pending and not currently in-service, raise the relevant line. + m_isr |= level_mask; + set_input_line(irq_level, ASSERT_LINE); + } + else if (m_isr & m_imr & level_mask) + { + // If a newly-masked interrupt is in-service, lower the relevant line. + set_input_line(irq_level, CLEAR_LINE); + } + + changed_mask &= ~irq_mask; + irq_level = get_irq_level_for_mask(changed_mask); + irq_mask = get_irq_mask_for_level(irq_level); + level_mask = irq_mask & changed_mask; + } +} + +void mc68328_base_device::set_interrupt_line(u32 line, u32 active) +{ + const u32 mask = 1 << line; + if (active) { - m_ipr |= line; - - if (!(m_imr & line) && !(m_isr & line)) - { - m_isr |= line; - - if (m_isr & INT_M68K_LINE7) - { - set_input_line(M68K_IRQ_7, ASSERT_LINE); - } - else if (m_isr & INT_M68K_LINE6) - { - set_input_line(M68K_IRQ_6, ASSERT_LINE); - } - else if (m_isr & INT_M68K_LINE5) - { - set_input_line(M68K_IRQ_5, ASSERT_LINE); - } - else if (m_isr & INT_M68K_LINE4) - { - set_input_line(M68K_IRQ_4, ASSERT_LINE); - } - else if (m_isr & INT_M68K_LINE3) - { - set_input_line(M68K_IRQ_3, ASSERT_LINE); - } - else if (m_isr & INT_M68K_LINE2) - { - set_input_line(M68K_IRQ_2, ASSERT_LINE); - } - else if (m_isr & INT_M68K_LINE1) - { - set_input_line(M68K_IRQ_1, ASSERT_LINE); - } - } + m_ipr |= mask; } else { - m_isr &= ~line; - - if ((line & INT_M68K_LINE7) && !(m_isr & INT_M68K_LINE7)) - { - set_input_line(M68K_IRQ_7, CLEAR_LINE); - } - if ((line & INT_M68K_LINE6) && !(m_isr & INT_M68K_LINE6)) - { - set_input_line(M68K_IRQ_6, CLEAR_LINE); - } - if ((line & INT_M68K_LINE5) && !(m_isr & INT_M68K_LINE5)) - { - set_input_line(M68K_IRQ_5, CLEAR_LINE); - } - if ((line & INT_M68K_LINE4) && !(m_isr & INT_M68K_LINE4)) - { - set_input_line(M68K_IRQ_4, CLEAR_LINE); - } - if ((line & INT_M68K_LINE3) && !(m_isr & INT_M68K_LINE3)) - { - set_input_line(M68K_IRQ_3, CLEAR_LINE); - } - if ((line & INT_M68K_LINE2) && !(m_isr & INT_M68K_LINE2)) - { - set_input_line(M68K_IRQ_2, CLEAR_LINE); - } - if ((line & INT_M68K_LINE1) && !(m_isr & INT_M68K_LINE1)) - { - set_input_line(M68K_IRQ_1, CLEAR_LINE); - } + m_ipr &= ~mask; } + + update_ipr_state(mask); } -WRITE_LINE_MEMBER( mc68328_device::set_penirq_line ) +int mc68328_device::get_irq_level_for_mask(u32 mask) { - if (state) + constexpr u32 IRQ_MASKS[8] = { - set_interrupt_line(INT_PEN, 1); - } - else + 0, + INT_IRQ1_MASK, + INT_IRQ2_MASK, + INT_IRQ3_MASK, + INT_INT0_MASK | INT_INT1_MASK | INT_INT2_MASK | INT_INT3_MASK | INT_INT4_MASK | INT_INT5_MASK | INT_INT6_MASK | INT_INT7_MASK + | INT_PWM_MASK | INT_KB_MASK | INT_RTC_MASK | INT_WDT_MASK | INT_UART_MASK | INT_TIMER2_MASK | INT_SPIM_MASK, + INT_IRQ5_MASK, + INT_IRQ6_MASK | INT_TIMER1_MASK | INT_SPIS_MASK, + INT_IRQ7_MASK + }; + + for (int level = 7; level >= 1; level--) { - m_ipr &= ~INT_PEN; - set_interrupt_line(INT_PEN, 0); + if (IRQ_MASKS[level] & mask) + { + return level; + } } + return 0; } -uint8_t mc68328_device::irq_callback(offs_t offset) +u32 mc68328_device::get_irq_mask_for_level(int level) +{ + constexpr u32 IRQ_MASKS[8] = + { + 0, + INT_IRQ1_MASK, + INT_IRQ2_MASK, + INT_IRQ3_MASK, + INT_INT0_MASK | INT_INT1_MASK | INT_INT2_MASK | INT_INT3_MASK | INT_INT4_MASK | INT_INT5_MASK | INT_INT6_MASK | INT_INT7_MASK + | INT_PWM_MASK | INT_KB_MASK | INT_RTC_MASK | INT_WDT_MASK | INT_UART_MASK | INT_TIMER2_MASK | INT_SPIM_MASK, + INT_IRQ5_MASK, + INT_IRQ6_MASK | INT_TIMER1_MASK | INT_SPIS_MASK, + INT_IRQ7_MASK + }; + if (level >= 0 && level <= 7) + { + return IRQ_MASKS[level]; + } + return 0; +} + +WRITE_LINE_MEMBER(mc68328_base_device::irq5_w) +{ + set_interrupt_line(INT_IRQ5, state); +} + +u8 mc68328_base_device::irq_callback(offs_t offset) { return m_ivr | offset; } -void mc68328_device::ivr_w(uint8_t data) // 0x300 +void mc68328_base_device::ivr_w(u8 data) // 0x300 { - LOGMASKED(LOG_INTS, "ivr_w: IVR = %02x\n", data); + LOGMASKED(LOG_INTS, "%s: ivr_w: IVR = %02x\n", machine().describe_context(), data); m_ivr = data; } -uint8_t mc68328_device::ivr_r() // 0x300 +u8 mc68328_base_device::ivr_r() // 0x300 { - LOGMASKED(LOG_INTS, "ivr_r: IVR: %02x\n", m_ivr); + LOGMASKED(LOG_INTS, "%s: ivr_r: IVR: %02x\n", machine().describe_context(), m_ivr); return m_ivr; } -void mc68328_device::icr_w(uint8_t data) // 0x302 +void mc68328_base_device::icr_w(u8 data) // 0x302 { - LOGMASKED(LOG_INTS, "icr_w: ICR = %02x\n", data); + LOGMASKED(LOG_INTS, "%s: icr_w: ICR = %02x\n", machine().describe_context(), data); m_icr = data; } -uint16_t mc68328_device::icr_r() // 0x302 +u16 mc68328_base_device::icr_r() // 0x302 { - LOGMASKED(LOG_INTS, "icr_r: ICR: %04x\n", m_icr); + LOGMASKED(LOG_INTS, "%s: icr_r: ICR: %04x\n", machine().describe_context(), m_icr); return m_icr; } -void mc68328_device::imr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x304 +void mc68328_base_device::imr_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x304 { - const uint32_t imr_old = m_imr; - LOGMASKED(LOG_INTS, "imr_msw_w: IMR(MSW) = %04x\n", data); + const u32 imr_old = m_imr; + LOGMASKED(LOG_INTS, "%s: imr_msw_w: IMR(MSW) = %04x\n", machine().describe_context(), data); m_imr &= ~(mem_mask << 16); m_imr |= (data & mem_mask) << 16; - m_isr &= ~((data & mem_mask) << 16); - const uint32_t imr_diff = imr_old ^ m_imr; - set_interrupt_line(imr_diff, 0); + update_imr_state(imr_old ^ m_imr); } -uint16_t mc68328_device::imr_msw_r() // 0x304 +u16 mc68328_base_device::imr_msw_r() // 0x304 { - LOGMASKED(LOG_INTS, "imr_msw_r: IMR(MSW): %04x\n", (uint16_t)(m_imr >> 16)); - return (uint16_t)(m_imr >> 16); + LOGMASKED(LOG_INTS, "%s: imr_msw_r: IMR(MSW): %04x\n", machine().describe_context(), (u16)(m_imr >> 16)); + return (u16)(m_imr >> 16); } -void mc68328_device::imr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x306 +void mc68328_base_device::imr_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0x306 { - const uint32_t imr_old = m_imr; - LOGMASKED(LOG_INTS, "imr_lsw_w: IMR(LSW) = %04x\n", data); + const u32 imr_old = m_imr; + LOGMASKED(LOG_INTS, "%s: imr_lsw_w: IMR(LSW) = %04x\n", machine().describe_context(), data); m_imr &= 0xffff0000 | (~mem_mask); m_imr |= data & mem_mask; - m_isr &= ~(data & mem_mask); - const uint32_t imr_diff = imr_old ^ m_imr; - set_interrupt_line(imr_diff, 0); + update_imr_state(imr_old ^ m_imr); } -uint16_t mc68328_device::imr_lsw_r() // 0x306 +u16 mc68328_base_device::imr_lsw_r() // 0x306 { - LOGMASKED(LOG_INTS, "imr_lsw_r: IMR(LSW): %04x\n", (uint16_t)m_imr); - return (uint16_t)m_imr; + LOGMASKED(LOG_INTS, "%s: imr_lsw_r: IMR(LSW): %04x\n", machine().describe_context(), (u16)m_imr); + return (u16)m_imr; } -void mc68328_device::iwr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x308 +void mc68328_device::iwr_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x308 { - LOGMASKED(LOG_INTS, "iwr_msw_w: IWR(MSW) = %04x\n", data); + LOGMASKED(LOG_INTS, "%s: iwr_msw_w: IWR(MSW) = %04x\n", machine().describe_context(), data); m_iwr &= ~(mem_mask << 16); m_iwr |= (data & mem_mask) << 16; } -uint16_t mc68328_device::iwr_msw_r() // 0x308 +u16 mc68328_device::iwr_msw_r() // 0x308 { - LOGMASKED(LOG_INTS, "iwr_msw_r: IWR(MSW): %04x\n", (uint16_t)(m_iwr >> 16)); - return (uint16_t)(m_iwr >> 16); + LOGMASKED(LOG_INTS, "%s: iwr_msw_r: IWR(MSW): %04x\n", machine().describe_context(), (u16)(m_iwr >> 16)); + return (u16)(m_iwr >> 16); } -void mc68328_device::iwr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x30a +void mc68328_device::iwr_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0x30a { - LOGMASKED(LOG_INTS, "iwr_lsw_w: IWR(LSW) = %04x\n", data); + LOGMASKED(LOG_INTS, "%s: iwr_lsw_w: IWR(LSW) = %04x\n", machine().describe_context(), data); m_iwr &= 0xffff0000 | (~mem_mask); m_iwr |= data & mem_mask; } -uint16_t mc68328_device::iwr_lsw_r() // 0x30a +u16 mc68328_device::iwr_lsw_r() // 0x30a { - LOGMASKED(LOG_INTS, "iwr_lsw_r: IWR(LSW): %04x\n", (uint16_t)m_iwr); - return (uint16_t)m_iwr; + LOGMASKED(LOG_INTS, "%s: iwr_lsw_r: IWR(LSW): %04x\n", machine().describe_context(), (u16)m_iwr); + return (u16)m_iwr; } -void mc68328_device::isr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x30c +void mc68328_base_device::isr_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x30c { - LOGMASKED(LOG_INTS, "isr_msw_w: ISR(MSW) = %04x\n", data); + LOGMASKED(LOG_INTS, "%s: isr_msw_w: ISR(MSW) = %04x\n", machine().describe_context(), data); // Clear edge-triggered IRQ1 - if ((m_icr & ICR_ET1) == ICR_ET1 && (data & INT_IRQ1_SHIFT) == INT_IRQ1_SHIFT) + if ((m_icr & ICR_ET1) == ICR_ET1 && (data & INT_IRQ1_MASK) == INT_IRQ1_MASK) { - m_isr &= ~INT_IRQ1; + m_isr &= ~INT_IRQ1_MASK; } // Clear edge-triggered IRQ2 - if ((m_icr & ICR_ET2) == ICR_ET2 && (data & INT_IRQ2_SHIFT) == INT_IRQ2_SHIFT) + if ((m_icr & ICR_ET2) == ICR_ET2 && (data & INT_IRQ2_MASK) == INT_IRQ2_MASK) { - m_isr &= ~INT_IRQ2; + m_isr &= ~INT_IRQ2_MASK; } // Clear edge-triggered IRQ3 - if ((m_icr & ICR_ET3) == ICR_ET3 && (data & INT_IRQ3_SHIFT) == INT_IRQ3_SHIFT) + if ((m_icr & ICR_ET3) == ICR_ET3 && (data & INT_IRQ3_MASK) == INT_IRQ3_MASK) { - m_isr &= ~INT_IRQ3; + m_isr &= ~INT_IRQ3_MASK; } // Clear edge-triggered IRQ6 - if ((m_icr & ICR_ET6) == ICR_ET6 && (data & INT_IRQ6_SHIFT) == INT_IRQ6_SHIFT) + if ((m_icr & ICR_ET6) == ICR_ET6 && (data & INT_IRQ6_MASK) == INT_IRQ6_MASK) { - m_isr &= ~INT_IRQ6; + m_isr &= ~INT_IRQ6_MASK; } // Clear edge-triggered IRQ7 - if ((data & INT_IRQ7_SHIFT) == INT_IRQ7_SHIFT) + if ((data & INT_IRQ7_MASK) == INT_IRQ7_MASK) { - m_isr &= ~INT_IRQ7; + m_isr &= ~INT_IRQ7_MASK; } } -uint16_t mc68328_device::isr_msw_r() // 0x30c +u16 mc68328_base_device::isr_msw_r() // 0x30c { - LOGMASKED(LOG_INTS, "isr_msw_r: ISR(MSW): %04x\n", (uint16_t)(m_isr >> 16)); - return (uint16_t)(m_isr >> 16); + LOGMASKED(LOG_INTS, "%s: isr_msw_r: ISR(MSW): %04x\n", machine().describe_context(), (u16)(m_isr >> 16)); + return (u16)(m_isr >> 16); } -void mc68328_device::isr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x30e +void mc68328_base_device::isr_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0x30e { - LOGMASKED(LOG_INTS, "isr_lsw_w: ISR(LSW) = %04x (Ignored)\n", data); + LOGMASKED(LOG_INTS, "%s: isr_lsw_w: ISR(LSW) = %04x (Ignored)\n", machine().describe_context(), data); } -uint16_t mc68328_device::isr_lsw_r() // 0x30e +u16 mc68328_base_device::isr_lsw_r() // 0x30e { - LOGMASKED(LOG_INTS, "isr_lsw_r: ISR(LSW): %04x\n", (uint16_t)m_isr); - return (uint16_t)m_isr; + LOGMASKED(LOG_INTS, "%s: isr_lsw_r: ISR(LSW): %04x\n", machine().describe_context(), (u16)m_isr); + return (u16)m_isr; } -void mc68328_device::ipr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x310 +void mc68328_base_device::ipr_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0x310 { - LOGMASKED(LOG_INTS, "ipr_msw_w: IPR(MSW) = %04x (Ignored)\n", data); + LOGMASKED(LOG_INTS, "%s: ipr_msw_w: IPR(MSW) = %04x (Ignored)\n", machine().describe_context(), data); } -uint16_t mc68328_device::ipr_msw_r() // 0x310 +u16 mc68328_base_device::ipr_msw_r() // 0x310 { - LOGMASKED(LOG_INTS, "ipr_msw_r: IPR(MSW): %04x\n", (uint16_t)(m_ipr >> 16)); - return (uint16_t)(m_ipr >> 16); + LOGMASKED(LOG_INTS, "%s: ipr_msw_r: IPR(MSW): %04x\n", machine().describe_context(), (u16)(m_ipr >> 16)); + return (u16)(m_ipr >> 16); } -void mc68328_device::ipr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0x312 +void mc68328_base_device::ipr_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0x312 { - LOGMASKED(LOG_INTS, "ipr_lsw_w: IPR(LSW) = %04x (Ignored)\n", data); + LOGMASKED(LOG_INTS, "%s: ipr_lsw_w: IPR(LSW) = %04x (Ignored)\n", machine().describe_context(), data); } -uint16_t mc68328_device::ipr_lsw_r() // 0x312 +u16 mc68328_base_device::ipr_lsw_r() // 0x312 { - LOGMASKED(LOG_INTS, "ipr_lsw_r: IPR(LSW): %04x\n", (uint16_t)m_ipr); - return (uint16_t)m_ipr; + LOGMASKED(LOG_INTS, "%s: ipr_lsw_r: IPR(LSW): %04x\n", machine().describe_context(), (u16)m_ipr); + return (u16)m_ipr; +} + + +//------------------------------------------------- +// Interrupt-related hardware - EZ variant +//------------------------------------------------- + +int mc68ez328_device::get_irq_level_for_mask(u32 mask) +{ + constexpr u32 IRQ_MASKS[8] = + { + 0, + INT_IRQ1_MASK, + INT_IRQ2_MASK, + INT_IRQ3_MASK, + INT_INT0_MASK | INT_INT1_MASK | INT_INT2_MASK | INT_INT3_MASK | INT_INT4_MASK | INT_INT5_MASK | INT_INT6_MASK | INT_INT7_MASK + | INT_KB_MASK | INT_RTC_MASK | INT_WDT_MASK | INT_UART_MASK | INT_SPIM_MASK, + INT_IRQ5_MASK, + INT_PWM_MASK | INT_TIMER2_MASK | INT_SPIS_MASK, + INT_MEMIQ_MASK, + }; + + for (int level = 1; level <= 7; level++) + { + if (IRQ_MASKS[level] & mask) + { + return level; + } + } + return 0; +} + +u32 mc68ez328_device::get_irq_mask_for_level(int level) +{ + constexpr u32 IRQ_MASKS[8] = + { + 0, + INT_IRQ1_MASK, + INT_IRQ2_MASK, + INT_IRQ3_MASK, + INT_INT0_MASK | INT_INT1_MASK | INT_INT2_MASK | INT_INT3_MASK | INT_INT4_MASK | INT_INT5_MASK | INT_INT6_MASK | INT_INT7_MASK + | INT_KB_MASK | INT_RTC_MASK | INT_WDT_MASK | INT_UART_MASK | INT_SPIM_MASK, + INT_IRQ5_MASK, + INT_PWM_MASK | INT_TIMER2_MASK | INT_SPIS_MASK, + INT_MEMIQ_MASK, + }; + if (level >= 0 && level <= 7) + { + return IRQ_MASKS[level]; + } + return 0; } @@ -1124,47 +1499,61 @@ uint16_t mc68328_device::ipr_lsw_r() // 0x312 // GPIO hardware - Port A //------------------------------------------------- -void mc68328_device::padir_w(uint8_t data) // 0x400 +void mc68328_base_device::padir_w(u8 data) // 0x400 { - LOGMASKED(LOG_GPIO_A, "padir_w: PADIR = %02x\n", data); + LOGMASKED(LOG_GPIO_A, "%s: padir_w: PADIR = %02x\n", machine().describe_context(), data); m_padir = data; } -uint8_t mc68328_device::padir_r() // 0x400 +u8 mc68328_base_device::padir_r() // 0x400 { - LOGMASKED(LOG_GPIO_A, "mc68328_r: PADIR: %02x\n", m_padir); + LOGMASKED(LOG_GPIO_A, "%s: mc68328_r: PADIR: %02x\n", machine().describe_context(), m_padir); return m_padir; } -void mc68328_device::padata_w(uint8_t data) // 0x401 +void mc68328_base_device::padata_w(u8 data) // 0x401 { - LOGMASKED(LOG_GPIO_A, "padata_w: PADATA = %02x\n", data); + LOGMASKED(LOG_GPIO_A, "%s: padata_w: PADATA = %02x\n", machine().describe_context(), data); m_padata = data; - m_out_port_a_cb(m_padata); -} - -uint8_t mc68328_device::padata_r() // 0x401 -{ - LOGMASKED(LOG_GPIO_A, "padata_r: PADATA: %02x\n", m_padata); - if (!m_in_port_a_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_a_cb(0); - } - else - { - return m_padata; + if (BIT(m_padir & m_pasel, i)) + { + m_out_port_a_cb[i](BIT(m_padata, i)); + } } } -void mc68328_device::pasel_w(uint8_t data) // 0x403 +u8 mc68328_base_device::padata_r() // 0x401 { - LOGMASKED(LOG_GPIO_A, "pasel_w: PASEL = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pasel, i)) + { + if (BIT(m_padir, i)) + { + data |= m_padata & (1 << i); + } + else if (!m_in_port_a_cb[i].isnull()) + { + data |= m_in_port_a_cb[i]() << i; + } + } + } + LOGMASKED(LOG_GPIO_A, "%s: padata_r: PADATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_device::pasel_w(u8 data) // 0x403 +{ + LOGMASKED(LOG_GPIO_A, "%s: pasel_w: PASEL = %02x\n", machine().describe_context(), data); m_pasel = data; } -uint8_t mc68328_device::pasel_r() // 0x403 +u8 mc68328_device::pasel_r() // 0x403 { - LOGMASKED(LOG_GPIO_A, "mc68328_r: PASEL: %02x\n", m_pasel); + LOGMASKED(LOG_GPIO_A, "%s: mc68328_r: PASEL: %02x\n", machine().describe_context(), m_pasel); return m_pasel; } @@ -1173,44 +1562,61 @@ uint8_t mc68328_device::pasel_r() // 0x403 // GPIO hardware - Port B //------------------------------------------------- -void mc68328_device::pbdir_w(uint8_t data) // 0x408 +void mc68328_base_device::pbdir_w(u8 data) // 0x408 { - LOGMASKED(LOG_GPIO_B, "pbdir_w: PBDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_B, "%s: pbdir_w: PBDIR = %02x\n", machine().describe_context(), data); m_pbdir = data; } -uint8_t mc68328_device::pbdir_r() // 0x408 +u8 mc68328_base_device::pbdir_r() // 0x408 { - LOGMASKED(LOG_GPIO_B, "pbdir_r: PBDIR: %02x\n", m_pbdir); + LOGMASKED(LOG_GPIO_B, "%s: pbdir_r: PBDIR: %02x\n", machine().describe_context(), m_pbdir); return m_pbdir; } -void mc68328_device::pbdata_w(uint8_t data) // 0x409 +void mc68328_base_device::pbdata_w(u8 data) // 0x409 { - LOGMASKED(LOG_GPIO_B, "pbdata_w: PBDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_B, "%s: pbdata_w: PBDATA = %02x (outputing %02x)\n", machine().describe_context(), data, data & m_pbdir & m_pbsel); m_pbdata = data; - m_out_port_b_cb(m_pbdata); -} - -uint8_t mc68328_device::pbdata_r() // 0x409 -{ - LOGMASKED(LOG_GPIO_B, "pbdata_r: PBDATA: %02x\n", m_pbdata); - if (!m_in_port_b_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_b_cb(0); + if (BIT(m_pbdir & m_pbsel, i)) + { + m_out_port_b_cb[i](BIT(m_pbdata, i)); + } } - return m_pbdata; } -void mc68328_device::pbsel_w(uint8_t data) // 0x40b +u8 mc68328_base_device::pbdata_r() // 0x409 { - LOGMASKED(LOG_GPIO_B, "pbsel_w: PBSEL = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pbsel, i)) + { + if (BIT(m_pbdir, i)) + { + data |= m_pbdata & (1 << i); + } + else if (!m_in_port_b_cb[i].isnull()) + { + data |= m_in_port_b_cb[i]() << i; + } + } + } + LOGMASKED(LOG_GPIO_B, "%s: pbdata_r: PBDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_base_device::pbsel_w(u8 data) // 0x40b +{ + LOGMASKED(LOG_GPIO_B, "%s: pbsel_w: PBSEL = %02x\n", machine().describe_context(), data); m_pbsel = data; } -uint8_t mc68328_device::pbsel_r() // 0x40b +u8 mc68328_base_device::pbsel_r() // 0x40b { - LOGMASKED(LOG_GPIO_B, "pbsel_r: PBSEL: %02x\n", m_pbsel); + LOGMASKED(LOG_GPIO_B, "%s: pbsel_r: PBSEL: %02x\n", machine().describe_context(), m_pbsel); return m_pbsel; } @@ -1219,44 +1625,65 @@ uint8_t mc68328_device::pbsel_r() // 0x40b // GPIO hardware - Port C //------------------------------------------------- -void mc68328_device::pcdir_w(uint8_t data) // 0x410 +void mc68328_base_device::pcdir_w(u8 data) // 0x410 { - LOGMASKED(LOG_GPIO_C, "pcdir_w: PCDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_C, "%s: pcdir_w: PCDIR = %02x\n", machine().describe_context(), data); m_pcdir = data; } -uint8_t mc68328_device::pcdir_r() // 0x410 +u8 mc68328_base_device::pcdir_r() // 0x410 { - LOGMASKED(LOG_GPIO_C, "pcdir_r: PCDIR: %02x\n", m_pcdir); + LOGMASKED(LOG_GPIO_C, "%s: pcdir_r: PCDIR: %02x\n", machine().describe_context(), m_pcdir); return m_pcdir; } -void mc68328_device::pcdata_w(uint8_t data) // 0x411 +void mc68328_base_device::pcdata_w(u8 data) // 0x411 { - LOGMASKED(LOG_GPIO_C, "pcdata_w: PCDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_C, "%s: pcdata_w: PCDATA = %02x (outputing %02x)\n", machine().describe_context(), data, data & m_pcdir & m_pcsel); m_pcdata = data; - m_out_port_c_cb(m_pcdata); -} - -uint8_t mc68328_device::pcdata_r() // 0x411 -{ - LOGMASKED(LOG_GPIO_C, "pcdata_r: PCDATA: %02x\n", m_pcdata); - if (!m_in_port_c_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_c_cb(0); + if (BIT(m_pcdir & m_pcsel, i)) + { + m_out_port_c_cb[i](BIT(m_pcdata, i)); + } + else if (BIT(~m_pcdir & m_pcsel, i)) + { + m_out_port_c_cb[i](1); + } } - return m_pcdata; } -void mc68328_device::pcsel_w(uint8_t data) // 0x413 +u8 mc68328_base_device::pcdata_r() // 0x411 { - LOGMASKED(LOG_GPIO_C, "pcsel_w: PCSEL = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pcsel, i)) + { + if (BIT(m_pcdir, i)) + { + data |= m_pcdata & (1 << i); + } + else if (!m_in_port_c_cb[i].isnull()) + { + data |= m_in_port_c_cb[i]() << i; + } + } + } + LOGMASKED(LOG_GPIO_C, "%s: pcdata_r: PCDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_base_device::pcsel_w(u8 data) // 0x413 +{ + LOGMASKED(LOG_GPIO_C, "%s: pcsel_w: PCSEL = %02x\n", machine().describe_context(), data); m_pcsel = data; } -uint8_t mc68328_device::pcsel_r() // 0x413 +u8 mc68328_base_device::pcsel_r() // 0x413 { - LOGMASKED(LOG_GPIO_C, "pcsel_r: PCSEL: %02x\n", m_pcsel); + LOGMASKED(LOG_GPIO_C, "%s: pcsel_r: PCSEL: %02x\n", machine().describe_context(), m_pcsel); return m_pcsel; } @@ -1265,115 +1692,131 @@ uint8_t mc68328_device::pcsel_r() // 0x413 // GPIO hardware - Port D //------------------------------------------------- -void mc68328_device::set_port_d_lines(uint8_t state, int bit) +void mc68328_base_device::port_d_in_w(int state, int bit) { - uint8_t old_button_state = m_pddata; + const u8 old_state = m_pdindata; + m_pdindata &= ~(1 << bit); + m_pdindata |= state << bit; - if (state & (1 << bit)) + // If no bit has changed state, there's nothing to do. + if (old_state == m_pdindata) { - m_pddata |= (1 << bit); - } - else - { - m_pddata &= ~(1 << bit); + return; } - m_pddataedge |= ~old_button_state & m_pddata; + // If we're not edge-triggered, handle potential level-sensitive interrupts. + if (!BIT(m_pdirqedge, bit)) + { + // If the new state is low while PDPOL is active-low (0) or vice-versa, assert the interrupt for this bit. + // Otherwise, clear it. + set_interrupt_line(INT_KBDINTS + bit, (int)(state == BIT(m_pdpol, bit))); + return; + } - poll_port_d_interrupts(); + set_interrupt_line(INT_KBDINTS + bit, 1); } -void mc68328_device::poll_port_d_interrupts() +void mc68328_base_device::pddir_w(u8 data) // 0x418 { - uint8_t line_transitions = m_pddataedge & m_pdirqedge; - uint8_t line_holds = m_pddata &~ m_pdirqedge; - uint8_t line_interrupts = (line_transitions | line_holds) & m_pdirqen; - - if (line_interrupts) - { - set_interrupt_line(line_interrupts << 8, 1); - } - else - { - set_interrupt_line(INT_KBDINTS, 0); - } -} - -void mc68328_device::pddir_w(uint8_t data) // 0x418 -{ - LOGMASKED(LOG_GPIO_D, "pddir_w: PDDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_D, "%s: pddir_w: PDDIR = %02x\n", machine().describe_context(), data); m_pddir = data; } -uint8_t mc68328_device::pddir_r() // 0x418 +u8 mc68328_base_device::pddir_r() // 0x418 { - LOGMASKED(LOG_GPIO_D, "pddir_r: PDDIR: %02x\n", m_pddir); + LOGMASKED(LOG_GPIO_D, "%s: pddir_r: PDDIR: %02x\n", machine().describe_context(), m_pddir); return m_pddir; } -void mc68328_device::pddata_w(uint8_t data) // 0x419 +void mc68328_base_device::pddata_w(u8 data) // 0x419 { - LOGMASKED(LOG_GPIO_D, "pddata_w: PDDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_D, "%s: pddata_w: PDDATA = %02x (outputing %02x)\n", machine().describe_context(), data, data & m_pddir); m_pddata = data; - m_out_port_d_cb(m_pddata); -} -uint8_t mc68328_device::pddata_r() // 0x419 -{ - LOGMASKED(LOG_GPIO_D, "pddata_r: PDDATA: %02x\n", m_pddata); - if (!m_in_port_d_cb.isnull()) + for (int bit = 0; bit < 4; bit++) { - return m_in_port_d_cb(0); + if (BIT(m_pdirqedge & data, bit)) + { + set_interrupt_line(INT_KBDINTS + bit, 0); + } + } + + for (int i = 0; i < 8; i++) + { + if (BIT(m_pddir, i)) + { + m_out_port_d_cb[i](BIT(m_pddata, i)); + } } - return m_pddata; } -void mc68328_device::pdpuen_w(uint8_t data) // 0x41a +u8 mc68328_base_device::pddata_r() // 0x419 { - LOGMASKED(LOG_GPIO_D, "pdpuen_w: PDPUEN = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pddir, i)) + { + data |= m_pddata & (1 << i); + } + else if (!m_in_port_d_cb[i].isnull()) + { + data |= m_in_port_d_cb[i]() << i; + } + else + { + data |= m_pdpuen & (1 << i); + } + } + LOGMASKED(LOG_GPIO_D, "%s: pddata_r: PDDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_base_device::pdpuen_w(u8 data) // 0x41a +{ + LOGMASKED(LOG_GPIO_D, "%s: pdpuen_w: PDPUEN = %02x\n", machine().describe_context(), data); m_pdpuen = data; } -uint8_t mc68328_device::pdpuen_r() // 0x41a +u8 mc68328_base_device::pdpuen_r() // 0x41a { - LOGMASKED(LOG_GPIO_D, "pdpuen_r: PDPUEN: %02x\n", m_pdpuen); + LOGMASKED(LOG_GPIO_D, "%s: pdpuen_r: PDPUEN: %02x\n", machine().describe_context(), m_pdpuen); return m_pdpuen; } -void mc68328_device::pdpol_w(uint8_t data) // 0x41c +void mc68328_base_device::pdpol_w(u8 data) // 0x41c { - LOGMASKED(LOG_GPIO_D, "pdpol_w: PDPOL = %02x\n", data); + LOGMASKED(LOG_GPIO_D, "%s: pdpol_w: PDPOL = %02x\n", machine().describe_context(), data); m_pdpol = data; } -uint8_t mc68328_device::pdpol_r() // 0x41c +u8 mc68328_base_device::pdpol_r() // 0x41c { - LOGMASKED(LOG_GPIO_D, "pdpol_r: PDPOL: %02x\n", m_pdpol); + LOGMASKED(LOG_GPIO_D, "%s: pdpol_r: PDPOL: %02x\n", machine().describe_context(), m_pdpol); return m_pdpol; } -void mc68328_device::pdirqen_w(uint8_t data) // 0x41d +void mc68328_base_device::pdirqen_w(u8 data) // 0x41d { - LOGMASKED(LOG_GPIO_D, "pdirqen_w: PDIRQEN = %02x\n", data); + LOGMASKED(LOG_GPIO_D, "%s: pdirqen_w: PDIRQEN = %02x\n", machine().describe_context(), data); m_pdirqen = data & 0x00ff; - poll_port_d_interrupts(); } -uint8_t mc68328_device::pdirqen_r() // 0x41d +u8 mc68328_base_device::pdirqen_r() // 0x41d { - LOGMASKED(LOG_GPIO_D, "pdirqen_r: PDIRQEN: %02x\n", m_pdirqen); + LOGMASKED(LOG_GPIO_D, "%s: pdirqen_r: PDIRQEN: %02x\n", machine().describe_context(), m_pdirqen); return m_pdirqen; } -void mc68328_device::pdirqedge_w(uint8_t data) // 0x41f +void mc68328_base_device::pdirqedge_w(u8 data) // 0x41f { - LOGMASKED(LOG_GPIO_D, "pdirqedge_w: PDIRQEDGE = %02x\n", data); + LOGMASKED(LOG_GPIO_D, "%s: pdirqedge_w: PDIRQEDGE = %02x\n", machine().describe_context(), data); m_pdirqedge = data; } -uint8_t mc68328_device::pdirqedge_r() // 0x41f +u8 mc68328_base_device::pdirqedge_r() // 0x41f { - LOGMASKED(LOG_GPIO_D, "pdirqedge_r: PDIRQEDGE: %02x\n", m_pdirqedge); + LOGMASKED(LOG_GPIO_D, "%s: pdirqedge_r: PDIRQEDGE: %02x\n", machine().describe_context(), m_pdirqedge); return m_pdirqedge; } @@ -1382,56 +1825,77 @@ uint8_t mc68328_device::pdirqedge_r() // 0x41f // GPIO hardware - Port E //------------------------------------------------- -void mc68328_device::pedir_w(uint8_t data) // 0x420 +void mc68328_base_device::pedir_w(u8 data) // 0x420 { - LOGMASKED(LOG_GPIO_E, "pedir_w: PEDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_E, "%s: pedir_w: PEDIR = %02x\n", machine().describe_context(), data); m_pedir = data; } -uint8_t mc68328_device::pedir_r() // 0x420 +u8 mc68328_base_device::pedir_r() // 0x420 { - LOGMASKED(LOG_GPIO_E, "pedir_r: PEDIR: %02x\n", m_pedir); + LOGMASKED(LOG_GPIO_E, "%s: pedir_r: PEDIR: %02x\n", machine().describe_context(), m_pedir); return m_pedir; } -void mc68328_device::pedata_w(uint8_t data) // 0x421 +void mc68328_base_device::pedata_w(u8 data) // 0x421 { - LOGMASKED(LOG_GPIO_E, "pedata_w: PEDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_E, "%s: pedata_w: PEDATA = %02x (outputing %02x)\n", machine().describe_context(), data, data & m_pedir & m_pesel); m_pedata = data; - m_out_port_e_cb(m_pedata); -} - -uint8_t mc68328_device::pedata_r() // 0x421 -{ - LOGMASKED(LOG_GPIO_E, "pedata_r: PEDATA: %02x\n", m_pedata); - if (!m_in_port_e_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_e_cb(0); + if (BIT(m_pedir & m_pesel, i)) + { + m_out_port_e_cb[i](BIT(m_pedata, i)); + } } - return m_pedata; } -void mc68328_device::pepuen_w(uint8_t data) // 0x422 +u8 mc68328_base_device::pedata_r() // 0x421 { - LOGMASKED(LOG_GPIO_E, "pepuen_w: PEPUEN = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pesel, i)) + { + if (BIT(m_pedir, i)) + { + data |= m_pedata & (1 << i); + } + else if (!m_in_port_e_cb[i].isnull()) + { + data |= m_in_port_e_cb[i]() << i; + } + else + { + data |= m_pepuen & (1 << i); + } + } + } + LOGMASKED(LOG_GPIO_E, "%s: pedata_r: PEDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_base_device::pepuen_w(u8 data) // 0x422 +{ + LOGMASKED(LOG_GPIO_E, "%s: pepuen_w: PEPUEN = %02x\n", machine().describe_context(), data); m_pepuen = data; } -uint8_t mc68328_device::pepuen_r() // 0x422 +u8 mc68328_base_device::pepuen_r() // 0x422 { - LOGMASKED(LOG_GPIO_E, "pepuen_r: PEPUEN: %02x\n", m_pepuen); + LOGMASKED(LOG_GPIO_E, "%s: pepuen_r: PEPUEN: %02x\n", machine().describe_context(), m_pepuen); return m_pepuen; } -void mc68328_device::pesel_w(uint8_t data) // 0x423 +void mc68328_base_device::pesel_w(u8 data) // 0x423 { - LOGMASKED(LOG_GPIO_E, "pesel_w: PESEL = %02x\n", data); + LOGMASKED(LOG_GPIO_E, "%s: pesel_w: PESEL = %02x\n", machine().describe_context(), data); m_pesel = data; } -uint8_t mc68328_device::pesel_r() // 0x423 +u8 mc68328_base_device::pesel_r() // 0x423 { - LOGMASKED(LOG_GPIO_E, "pesel_r: PESEL: %02x\n", m_pesel); + LOGMASKED(LOG_GPIO_E, "%s: pesel_r: PESEL: %02x\n", machine().describe_context(), m_pesel); return m_pesel; } @@ -1440,56 +1904,77 @@ uint8_t mc68328_device::pesel_r() // 0x423 // GPIO hardware - Port F //------------------------------------------------- -void mc68328_device::pfdir_w(uint8_t data) // 0x428 +void mc68328_base_device::pfdir_w(u8 data) // 0x428 { - LOGMASKED(LOG_GPIO_F, "pfdir_w: PFDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_F, "%s: pfdir_w: PFDIR = %02x\n", machine().describe_context(), data); m_pfdir = data; } -uint8_t mc68328_device::pfdir_r() // 0x428 +u8 mc68328_base_device::pfdir_r() // 0x428 { - LOGMASKED(LOG_GPIO_F, "pfdir_r: PFDIR: %02x\n", m_pfdir); + LOGMASKED(LOG_GPIO_F, "%s: pfdir_r: PFDIR: %02x\n", machine().describe_context(), m_pfdir); return m_pfdir; } -void mc68328_device::pfdata_w(uint8_t data) // 0x429 +void mc68328_base_device::pfdata_w(u8 data) // 0x429 { - LOGMASKED(LOG_GPIO_F, "pfdata_w: PFDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_F, "%s: pfdata_w: PFDATA = %02x (outputing %02x)\n", machine().describe_context(), data, data & m_pfdir & m_pfsel); m_pfdata = data; - m_out_port_f_cb(m_pfdata); -} - -uint8_t mc68328_device::pfdata_r() // 0x429 -{ - LOGMASKED(LOG_GPIO_F, "pfdata_r: PFDATA: %02x\n", m_pfdata); - if (!m_in_port_f_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_f_cb(0); + if (BIT(m_pfdir & m_pfsel, i)) + { + m_out_port_f_cb[i](BIT(m_pfdata, i)); + } } - return m_pfdata; } -void mc68328_device::pfpuen_w(uint8_t data) // 0x42a +u8 mc68328_base_device::pfdata_r() // 0x429 { - LOGMASKED(LOG_GPIO_F, "pfpuen_w: PFPUEN = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pfsel, i)) + { + if (BIT(m_pfdir, i)) + { + data |= m_pfdata & (1 << i); + } + else if (!m_in_port_f_cb[i].isnull()) + { + data |= m_in_port_f_cb[i]() << i; + } + else + { + data |= m_pfpuen & (1 << i); + } + } + } + LOGMASKED(LOG_GPIO_F, "%s: pfdata_r: PFDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_base_device::pfpuen_w(u8 data) // 0x42a +{ + LOGMASKED(LOG_GPIO_F, "%s: pfpuen_w: PFPUEN = %02x\n", machine().describe_context(), data); m_pfpuen = data; } -uint8_t mc68328_device::pfpuen_r() // 0x42a +u8 mc68328_base_device::pfpuen_r() // 0x42a { - LOGMASKED(LOG_GPIO_F, "pfpuen_r: PFPUEN: %02x\n", m_pfpuen); + LOGMASKED(LOG_GPIO_F, "%s: pfpuen_r: PFPUEN: %02x\n", machine().describe_context(), m_pfpuen); return m_pfpuen; } -void mc68328_device::pfsel_w(uint8_t data) // 0x42b +void mc68328_base_device::pfsel_w(u8 data) // 0x42b { - LOGMASKED(LOG_GPIO_F, "pfsel_w: PFSEL = %02x\n", data); + LOGMASKED(LOG_GPIO_F, "%s: pfsel_w: PFSEL = %02x\n", machine().describe_context(), data); m_pfsel = data; } -uint8_t mc68328_device::pfsel_r() // 0x42b +u8 mc68328_base_device::pfsel_r() // 0x42b { - LOGMASKED(LOG_GPIO_F, "pfsel_r: PFSEL: %02x\n", m_pfsel); + LOGMASKED(LOG_GPIO_F, "%s: pfsel_r: PFSEL: %02x\n", machine().describe_context(), m_pfsel); return m_pfsel; } @@ -1498,56 +1983,77 @@ uint8_t mc68328_device::pfsel_r() // 0x42b // GPIO hardware - Port G //------------------------------------------------- -void mc68328_device::pgdir_w(uint8_t data) // 0x430 +void mc68328_base_device::pgdir_w(u8 data) // 0x430 { - LOGMASKED(LOG_GPIO_G, "pgdir_w: PGDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_G, "%s: pgdir_w: PGDIR = %02x\n", machine().describe_context(), data); m_pgdir = data; } -uint8_t mc68328_device::pgdir_r() // 0x430 +u8 mc68328_base_device::pgdir_r() // 0x430 { - LOGMASKED(LOG_GPIO_G, "pgdir_r: PGDIR: %02x\n", m_pgdir); + LOGMASKED(LOG_GPIO_G, "%s: pgdir_r: PGDIR: %02x\n", machine().describe_context(), m_pgdir); return m_pgdir; } -void mc68328_device::pgdata_w(uint8_t data) // 0x431 +void mc68328_base_device::pgdata_w(u8 data) // 0x431 { - LOGMASKED(LOG_GPIO_G, "pgdata_w: PGDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_G, "%s: pgdata_w: PGDATA = %02x (outputing %02x)\n", machine().describe_context(), data, data & m_pgdir & m_pgsel); m_pgdata = data; - m_out_port_g_cb(m_pgdata); -} - -uint8_t mc68328_device::pgdata_r() // 0x431 -{ - LOGMASKED(LOG_GPIO_G, "pgdata_r: PGDATA: %02x\n", m_pgdata); - if (!m_in_port_g_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_g_cb(0); + if (BIT(m_pgdir & m_pgsel, i)) + { + m_out_port_g_cb[i](BIT(m_pgdata, i)); + } } - return m_pgdata; } -void mc68328_device::pgpuen_w(uint8_t data) // 0x432 +u8 mc68328_base_device::pgdata_r() // 0x431 { - LOGMASKED(LOG_GPIO_G, "pgpuen_w: PGPUEN = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pgsel, i)) + { + if (BIT(m_pgdir, i)) + { + data |= m_pgdata & (1 << i); + } + else if (!m_in_port_g_cb[i].isnull()) + { + data |= m_in_port_g_cb[i]() << i; + } + else + { + data |= m_pgpuen & (1 << i); + } + } + } + LOGMASKED(LOG_GPIO_G, "%s: pgdata_r: PGDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_base_device::pgpuen_w(u8 data) // 0x432 +{ + LOGMASKED(LOG_GPIO_G, "%s: pgpuen_w: PGPUEN = %02x\n", machine().describe_context(), data); m_pgpuen = data; } -uint8_t mc68328_device::pgpuen_r() // 0x432 +u8 mc68328_base_device::pgpuen_r() // 0x432 { - LOGMASKED(LOG_GPIO_G, "pgpuen_r: PGPUEN: %02x\n", m_pgpuen); + LOGMASKED(LOG_GPIO_G, "%s: pgpuen_r: PGPUEN: %02x\n", machine().describe_context(), m_pgpuen); return m_pgpuen; } -void mc68328_device::pgsel_w(uint8_t data) // 0x433 +void mc68328_base_device::pgsel_w(u8 data) // 0x433 { - LOGMASKED(LOG_GPIO_G, "pgsel_w: PGSEL = %02x\n", data); + LOGMASKED(LOG_GPIO_G, "%s: pgsel_w: PGSEL = %02x\n", machine().describe_context(), data); m_pgsel = data; } -uint8_t mc68328_device::pgsel_r() // 0x433 +u8 mc68328_base_device::pgsel_r() // 0x433 { - LOGMASKED(LOG_GPIO_G, "pgsel_r: PGSEL: %02x\n", m_pgsel); + LOGMASKED(LOG_GPIO_G, "%s: pgsel_r: PGSEL: %02x\n", machine().describe_context(), m_pgsel); return m_pgsel; } @@ -1556,44 +2062,61 @@ uint8_t mc68328_device::pgsel_r() // 0x433 // GPIO hardware - Port J //------------------------------------------------- -void mc68328_device::pjdir_w(uint8_t data) // 0x438 +void mc68328_device::pjdir_w(u8 data) // 0x438 { - LOGMASKED(LOG_GPIO_J, "pjdir_w: PJDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_J, "%s: pjdir_w: PJDIR = %02x\n", machine().describe_context(), data); m_pjdir = data; } -uint8_t mc68328_device::pjdir_r() // 0x438 +u8 mc68328_device::pjdir_r() // 0x438 { - LOGMASKED(LOG_GPIO_J, "pjdir_r: PJDIR: %02x\n", m_pjdir); + LOGMASKED(LOG_GPIO_J, "%s: pjdir_r: PJDIR: %02x\n", machine().describe_context(), m_pjdir); return m_pjdir; } -void mc68328_device::pjdata_w(uint8_t data) // 0x439 +void mc68328_device::pjdata_w(u8 data) // 0x439 { - LOGMASKED(LOG_GPIO_J, "pjdata_w: PJDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_J, "%s: pjdata_w: PJDATA = %02x\n", machine().describe_context(), data); m_pjdata = data; - m_out_port_j_cb(m_pjdata); -} - -uint8_t mc68328_device::pjdata_r() // 0x439 -{ - LOGMASKED(LOG_GPIO_J, "pjdata_r: PJDATA: %02x\n", m_pjdata); - if (!m_in_port_j_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_j_cb(0); + if (BIT(m_pjdir & m_pjsel, i)) + { + m_out_port_j_cb[i](BIT(m_pjdata, i)); + } } - return m_pjdata; } -void mc68328_device::pjsel_w(uint8_t data) // 0x43b +u8 mc68328_device::pjdata_r() // 0x439 { - LOGMASKED(LOG_GPIO_J, "pjsel_w: PJSEL = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pjsel, i)) + { + if (BIT(m_pjdir, i)) + { + data |= m_pjdata & (1 << i); + } + else if (!m_in_port_j_cb[i].isnull()) + { + data |= m_in_port_j_cb[i]() << i; + } + } + } + LOGMASKED(LOG_GPIO_J, "%s: pjdata_r: PJDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_device::pjsel_w(u8 data) // 0x43b +{ + LOGMASKED(LOG_GPIO_J, "%s: pjsel_w: PJSEL = %02x\n", machine().describe_context(), data); m_pjsel = data; } -uint8_t mc68328_device::pjsel_r() // 0x43b +u8 mc68328_device::pjsel_r() // 0x43b { - LOGMASKED(LOG_GPIO_J, "pjsel_r: PJSEL: %02x\n", m_pjsel); + LOGMASKED(LOG_GPIO_J, "%s: pjsel_r: PJSEL: %02x\n", machine().describe_context(), m_pjsel); return m_pjsel; } @@ -1602,56 +2125,77 @@ uint8_t mc68328_device::pjsel_r() // 0x43b // GPIO hardware - Port K //------------------------------------------------- -void mc68328_device::pkdir_w(uint8_t data) // 0x440 +void mc68328_device::pkdir_w(u8 data) // 0x440 { - LOGMASKED(LOG_GPIO_K, "pkdir_w: PKDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_K, "%s: pkdir_w: PKDIR = %02x\n", machine().describe_context(), data); m_pkdir = data; } -uint8_t mc68328_device::pkdir_r() // 0x440 +u8 mc68328_device::pkdir_r() // 0x440 { - LOGMASKED(LOG_GPIO_K, "pkdir_r: PKDIR: %02x\n", m_pkdir); + LOGMASKED(LOG_GPIO_K, "%s: pkdir_r: PKDIR: %02x\n", machine().describe_context(), m_pkdir); return m_pkdir; } -void mc68328_device::pkdata_w(uint8_t data) // 0x441 +void mc68328_device::pkdata_w(u8 data) // 0x441 { - LOGMASKED(LOG_GPIO_K, "pkdata_w: PKDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_K, "%s: pkdata_w: PKDATA = %02x\n", machine().describe_context(), data); m_pkdata = data; - m_out_port_k_cb(m_pkdata); -} - -uint8_t mc68328_device::pkdata_r() // 0x441 -{ - LOGMASKED(LOG_GPIO_K, "pkdata_r: PKDATA: %02x\n", m_pkdata); - if (!m_in_port_k_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_k_cb(0); + if (BIT(m_pkdir & m_pksel, i)) + { + m_out_port_k_cb[i](BIT(m_pkdata, i)); + } } - return m_pkdata; } -void mc68328_device::pkpuen_w(uint8_t data) // 0x442 +u8 mc68328_device::pkdata_r() // 0x441 { - LOGMASKED(LOG_GPIO_K, "pkpuen_w: PKPUEN = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pksel, i)) + { + if (BIT(m_pkdir, i)) + { + data |= m_pkdata & (1 << i); + } + else if (!m_in_port_k_cb[i].isnull()) + { + data |= m_in_port_k_cb[i]() << i; + } + else + { + data |= m_pkpuen & (1 << i); + } + } + } + LOGMASKED(LOG_GPIO_K, "%s: pkdata_r: PKDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_device::pkpuen_w(u8 data) // 0x442 +{ + LOGMASKED(LOG_GPIO_K, "%s: pkpuen_w: PKPUEN = %02x\n", machine().describe_context(), data); m_pkpuen = data; } -uint8_t mc68328_device::pkpuen_r() // 0x442 +u8 mc68328_device::pkpuen_r() // 0x442 { - LOGMASKED(LOG_GPIO_K, "pkpuen_r: PKPUEN: %02x\n", m_pkpuen); + LOGMASKED(LOG_GPIO_K, "%s: pkpuen_r: PKPUEN: %02x\n", machine().describe_context(), m_pkpuen); return m_pkpuen; } -void mc68328_device::pksel_w(uint8_t data) // 0x443 +void mc68328_device::pksel_w(u8 data) // 0x443 { - LOGMASKED(LOG_GPIO_K, "pksel_w: PKSEL = %02x\n", data); + LOGMASKED(LOG_GPIO_K, "%s: pksel_w: PKSEL = %02x\n", machine().describe_context(), data); m_pksel = data; } -uint8_t mc68328_device::pksel_r() // 0x443 +u8 mc68328_device::pksel_r() // 0x443 { - LOGMASKED(LOG_GPIO_K, "pksel_r: PKSEL: %02x\n", m_pksel); + LOGMASKED(LOG_GPIO_K, "%s: pksel_r: PKSEL: %02x\n", machine().describe_context(), m_pksel); return m_pksel; } @@ -1660,98 +2204,109 @@ uint8_t mc68328_device::pksel_r() // 0x443 // GPIO hardware - Port M //------------------------------------------------- -void mc68328_device::pmdir_w(uint8_t data) // 0x448 +void mc68328_device::pmdir_w(u8 data) // 0x448 { - LOGMASKED(LOG_GPIO_M, "pmdir_w: PMDIR = %02x\n", data); + LOGMASKED(LOG_GPIO_M, "%s: pmdir_w: PMDIR = %02x\n", machine().describe_context(), data); m_pmdir = data; } -uint8_t mc68328_device::pmdir_r() // 0x448 +u8 mc68328_device::pmdir_r() // 0x448 { - LOGMASKED(LOG_GPIO_M, "pmdir_r: PMDIR: %02x\n", m_pmdir); + LOGMASKED(LOG_GPIO_M, "%s: pmdir_r: PMDIR: %02x\n", machine().describe_context(), m_pmdir); return m_pmdir; } -void mc68328_device::pmdata_w(uint8_t data) // 0x449 +void mc68328_device::pmdata_w(u8 data) // 0x449 { - LOGMASKED(LOG_GPIO_M, "pmdata_w: PMDATA = %02x\n", data); + LOGMASKED(LOG_GPIO_M, "%s: pmdata_w: PMDATA = %02x\n", machine().describe_context(), data); m_pmdata = data; - m_out_port_m_cb(m_pmdata); -} - -uint8_t mc68328_device::pmdata_r() // 0x449 -{ - LOGMASKED(LOG_GPIO_M, "pmdata_r: PMDATA: %02x\n", m_pmdata); - if (!m_in_port_m_cb.isnull()) + for (int i = 0; i < 8; i++) { - return m_in_port_m_cb(0); + if (BIT(m_pmdir & m_pmsel, i)) + { + m_out_port_m_cb[i](BIT(m_pmdata, i)); + } } - return m_pmdata; } -void mc68328_device::pmpuen_w(uint8_t data) // 0x44a +u8 mc68328_device::pmdata_r() // 0x449 { - LOGMASKED(LOG_GPIO_M, "pmpuen_w: PMPUEN = %02x\n", data); + u8 data = 0; + for (int i = 0; i < 8; i++) + { + if (BIT(m_pmsel, i)) + { + if (BIT(m_pmdir, i)) + { + data |= m_pmdata & (1 << i); + } + else if (!m_in_port_m_cb[i].isnull()) + { + data |= m_in_port_m_cb[i]() << i; + } + else + { + data |= m_pmpuen & (1 << i); + } + } + } + LOGMASKED(LOG_GPIO_M, "%s: pmdata_r: PMDATA: %02x\n", machine().describe_context(), data); + return data; +} + +void mc68328_device::pmpuen_w(u8 data) // 0x44a +{ + LOGMASKED(LOG_GPIO_M, "%s: pmpuen_w: PMPUEN = %02x\n", machine().describe_context(), data); m_pmpuen = data; } -uint8_t mc68328_device::pmpuen_r() // 0x44a +u8 mc68328_device::pmpuen_r() // 0x44a { - LOGMASKED(LOG_GPIO_M, "pmpuen_r: PMPUEN: %02x\n", m_pmpuen); + LOGMASKED(LOG_GPIO_M, "%s: pmpuen_r: PMPUEN: %02x\n", machine().describe_context(), m_pmpuen); return m_pmpuen; } -void mc68328_device::pmsel_w(uint8_t data) // 0x44b +void mc68328_device::pmsel_w(u8 data) // 0x44b { - LOGMASKED(LOG_GPIO_M, "pmsel_w: PMSEL = %02x\n", data); + LOGMASKED(LOG_GPIO_M, "%s: pmsel_w: PMSEL = %02x\n", machine().describe_context(), data); m_pmsel = data; } -uint8_t mc68328_device::pmsel_r() // 0x44b +u8 mc68328_device::pmsel_r() // 0x44b { - LOGMASKED(LOG_GPIO_M, "pmsel_r: PMSEL: %02x\n", m_pmsel); + LOGMASKED(LOG_GPIO_M, "%s: pmsel_r: PMSEL: %02x\n", machine().describe_context(), m_pmsel); return m_pmsel; } //------------------------------------------------- -// PWM hardware +// PWM hardware - Standard MC68328 //------------------------------------------------- -TIMER_CALLBACK_MEMBER( mc68328_device::pwm_tick ) +TIMER_CALLBACK_MEMBER(mc68328_device::pwm_tick) { - if (m_pwmw >= m_pwmp || m_pwmw == 0 || m_pwmp == 0) + if (m_pwmw >= m_pwmp || !m_pwmw || !m_pwmp) { m_pwm->adjust(attotime::never); return; } + const u32 divisor = 4 << (m_pwmc & PWMC_CLKSEL); + if (((m_pwmc & PWMC_POL) == 0 && (m_pwmc & PWMC_PIN) != 0) || ((m_pwmc & PWMC_POL) != 0 && (m_pwmc & PWMC_PIN) == 0)) { - uint32_t frequency = 32768 * 506; - uint32_t divisor = 4 << (m_pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot. - attotime period; - - frequency /= divisor; - period = attotime::from_hz(frequency) * (m_pwmp - m_pwmw); - + attotime period = attotime::from_ticks((m_pwmp - m_pwmw) * divisor, clock()); m_pwm->adjust(period); - if (m_pwmc & PWMC_IRQEN) + if (m_pwmc & PWMC_IRQ_EN) { set_interrupt_line(INT_PWM, 1); } } else { - uint32_t frequency = 32768 * 506; - uint32_t divisor = 4 << (m_pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot. - attotime period; - - frequency /= divisor; - period = attotime::from_hz(frequency) * m_pwmw; - + attotime period = attotime::from_ticks(m_pwmw * divisor, clock()); m_pwm->adjust(period); } @@ -1760,85 +2315,303 @@ TIMER_CALLBACK_MEMBER( mc68328_device::pwm_tick ) m_out_pwm_cb((m_pwmc & PWMC_PIN) ? 1 : 0); } -void mc68328_device::pwmc_w(uint16_t data) // 0x500 +void mc68328_device::pwmc_w(u16 data) // 0x500 { - LOGMASKED(LOG_PWM, "pwmc_w: PWMC = %04x\n", data); + LOGMASKED(LOG_PWM, "%s: pwmc_w: PWMC = %04x\n", machine().describe_context(), data); + const u16 old_pwmc = m_pwmc; m_pwmc = data; + const u16 changed = m_pwmc ^ old_pwmc; - if (m_pwmc & PWMC_PWMIRQ) + if (m_pwmc & PWMC_IRQ) { set_interrupt_line(INT_PWM, 1); } - m_pwmc &= ~PWMC_LOAD; - - if ((m_pwmc & PWMC_PWMEN) != 0 && m_pwmw != 0 && m_pwmp != 0) + if (changed & (PWMC_EN | PWMC_CLKSEL | PWMC_LOAD)) { - uint32_t frequency = 32768 * 506; - uint32_t divisor = 4 << (m_pwmc & PWMC_CLKSEL); // ?? Datasheet says 2 <<, but then we're an octave higher than CoPilot. - attotime period; - frequency /= divisor; - period = attotime::from_hz(frequency) * m_pwmw; - m_pwm->adjust(period); - if (m_pwmc & PWMC_IRQEN) + const bool enable_or_update = (changed & m_pwmc & PWMC_EN) || (m_pwmc & PWMC_LOAD); + if (enable_or_update && m_pwmw && m_pwmp) { - set_interrupt_line(INT_PWM, 1); + const u32 divisor = 4 << (m_pwmc & PWMC_CLKSEL); + attotime period = attotime::from_ticks(m_pwmw * divisor, clock()); + m_pwm->adjust(period); + if (m_pwmc & PWMC_IRQ_EN) + { + set_interrupt_line(INT_PWM, 1); + } + m_pwmc |= PWMC_PIN; + } + else + { + m_pwm->adjust(attotime::never); } - m_pwmc ^= PWMC_PIN; } - else + + m_pwmc &= ~PWMC_LOAD; +} + +u16 mc68328_device::pwmc_r() // 0x500 +{ + const u16 data = m_pwmc; + LOGMASKED(LOG_PWM, "%s: pwmc_r: PWMC: %04x\n", machine().describe_context(), data); + if (m_pwmc & PWMC_IRQ) { - m_pwm->adjust(attotime::never); + m_pwmc &= ~PWMC_IRQ; + if (m_pwmc & PWMC_IRQ_EN) + { + set_interrupt_line(INT_PWM, 0); + } + } + return data; +} + +void mc68328_device::pwmp_w(u16 data) // 0x502 +{ + LOGMASKED(LOG_PWM, "%s: pwmp_w: PWMP = %04x\n", machine().describe_context(), data); + m_pwmp = data; +} + +u16 mc68328_device::pwmp_r() // 0x502 +{ + LOGMASKED(LOG_PWM, "%s: pwmp_r: PWMP: %04x\n", machine().describe_context(), m_pwmp); + return m_pwmp; +} + +void mc68328_device::pwmw_w(u16 data) // 0x504 +{ + LOGMASKED(LOG_PWM, "%s: pwmw_w: PWMW = %04x\n", machine().describe_context(), data); + m_pwmw = data; +} + +u16 mc68328_device::pwmw_r() // 0x504 +{ + LOGMASKED(LOG_PWM, "%s: pwmw_r: PWMW: %04x\n", machine().describe_context(), m_pwmw); + return m_pwmw; +} + +void mc68328_device::pwmcnt_w(u16 data) // 0x506 +{ + LOGMASKED(LOG_PWM, "%s: pwmcnt_w: PWMCNT = %04x\n", machine().describe_context(), data); + m_pwmcnt = 0; +} + +u16 mc68328_device::pwmcnt_r() // 0x506 +{ + LOGMASKED(LOG_PWM, "%s: pwmcnt_r: PWMCNT: %04x\n", machine().describe_context(), m_pwmcnt); + return m_pwmcnt; +} + + +//------------------------------------------------- +// PWM hardware - EZ variant +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(mc68ez328_device::pwm_tick) +{ + if (!(m_pwmc & PWMC_EN)) + { + return; + } + + if (!param) + { + m_pwm_rep_cnt--; + if (!m_pwm_rep_cnt) + { + m_pwm_rep_cnt = 1 << ((m_pwmc & PWMC_REPEAT) >> PWMC_REPEAT_SHIFT); + pwm_fifo_pop(); + } + } + + m_pwmo = param; + update_pwm_period(!m_pwmo); + m_out_pwm_cb((int)m_pwmo); +} + +void mc68ez328_device::update_pwm_period(bool high_cycle) +{ + const u32 frequency = (m_pwmc & PWMC_CLK_SRC) ? 32768 : clock(); + const u32 prescale = ((m_pwmc & PWMC_PRESCALE) >> PWMC_PRESCALE_SHIFT) + 1; + const u32 divisor = 2 << (m_pwmc & PWMC_CLKSEL); + const u32 period_reg = (u32)std::min(m_pwmp + 1u, 0xffu); + u32 sample_period = period_reg; + if (m_pwmfifo[m_pwmfifo_rd] <= period_reg) + { + sample_period = high_cycle ? (period_reg - m_pwmfifo[m_pwmfifo_rd]) : m_pwmfifo[m_pwmfifo_rd]; + sample_period++; + } + attotime period = attotime::from_ticks(prescale * divisor * sample_period, frequency); + m_pwm->adjust(period, (int)high_cycle); +} + +void mc68ez328_device::pwm_fifo_push(u8 data) +{ + if (m_pwmfifo_cnt >= std::size(m_pwmfifo)) + { + return; + } + m_pwmfifo[m_pwmfifo_wr] = data; + m_pwmfifo_wr = (m_pwmfifo_wr + 1) % std::size(m_pwmfifo); + const u8 old_cnt = m_pwmfifo_cnt; + m_pwmfifo_cnt++; + if (m_pwmfifo_cnt == std::size(m_pwmfifo)) + { + m_pwmc &= ~PWMC_FIFO_AV; + } + else if (old_cnt <= 1 && m_pwmfifo_cnt > 1) + { + if (m_pwmc & PWMC_IRQ) + { + m_pwmc &= ~PWMC_IRQ; + set_interrupt_line(INT_PWM, 0); + } } } -uint16_t mc68328_device::pwmc_r() // 0x500 +void mc68ez328_device::pwm_fifo_pop() { - const uint16_t data = m_pwmc; - LOGMASKED(LOG_PWM, "pwmc_r: PWMC: %04x\n", data); - if (m_pwmc & PWMC_PWMIRQ) + if (m_pwmfifo_cnt > 0) { - m_pwmc &= ~PWMC_PWMIRQ; + m_pwmfifo_rd = (m_pwmfifo_rd + 1) % std::size(m_pwmfifo); + m_pwmfifo_cnt--; + + m_pwmc |= PWMC_FIFO_AV; + } + + if (m_pwmfifo_cnt <= 1) + { + if (!(m_pwmc & PWMC_IRQ)) + { + m_pwmc |= PWMC_IRQ; + set_interrupt_line(INT_PWM, 1); + } + } +} + +void mc68ez328_device::pwmc_w(u16 data) // 0x500 +{ + LOGMASKED(LOG_PWM, "%s: pwmc_w: PWMC = %04x\n", machine().describe_context(), data); + + const u16 old = m_pwmc; + m_pwmc = (m_pwmc & PWMC_FIFO_AV) | (data & ~PWMC_FIFO_AV); + const u16 changed = old ^ m_pwmc; + if (!changed) + { + return; + } + + bool set_irq = false; + if (m_pwmc & PWMC_IRQ_EN) + { + if (m_pwmc & PWMC_IRQ) + { + set_irq = true; + } + } + else if (old & PWMC_IRQ_EN) + { + set_interrupt_line(INT_PWM, 0); + } + + const bool recalculate = (changed & PWMC_RECALC_MASK); + if (recalculate) + { + if (m_pwmc & PWMC_EN) + { + if (changed & PWMC_EN) + { + set_irq = true; + m_pwmc |= PWMC_FIFO_AV; + } + m_pwmo = true; + m_out_pwm_cb((int)m_pwmo); + update_pwm_period(false); + m_pwm_rep_cnt = 1 << ((m_pwmc & PWMC_REPEAT) >> PWMC_REPEAT_SHIFT); + } + else + { + m_pwmfifo_cnt = 0; + m_pwmo = false; + m_pwm->adjust(attotime::never); + } + } + + if (set_irq && (m_pwmc & PWMC_IRQ_EN)) + { + m_pwmc |= PWMC_IRQ; + set_interrupt_line(INT_PWM, BIT(m_pwmc, PWMC_IRQ_BIT)); + } +} + +u16 mc68ez328_device::pwmc_r() // 0x500 +{ + const u16 data = m_pwmc; + LOGMASKED(LOG_PWM, "%s: pwmc_r: PWMC: %04x\n", machine().describe_context(), data); + if (m_pwmc & PWMC_IRQ) + { + m_pwmc &= ~PWMC_IRQ; set_interrupt_line(INT_PWM, 0); } return data; } -void mc68328_device::pwmp_w(uint16_t data) // 0x502 +void mc68ez328_device::pwms_w(offs_t offset, u16 data, u16 mem_mask) // 0x502 { - LOGMASKED(LOG_PWM, "pwmp_w: PWMP = %04x\n", data); - m_pwmp = data; + LOGMASKED(LOG_PWM, "%s: pwms_w: PWMS = %04x & %04x\n", machine().describe_context(), data, mem_mask); + if (mem_mask == 0xffff) + { + pwm_fifo_push((u8)(data >> 8)); + pwm_fifo_push((u8)data); + } + else if (mem_mask == 0x00ff) + { + pwm_fifo_push((u8)data); + } } -uint16_t mc68328_device::pwmp_r() // 0x502 +u16 mc68ez328_device::pwms_r() // 0x502 { - LOGMASKED(LOG_PWM, "pwmp_r: PWMP: %04x\n", m_pwmp); + LOGMASKED(LOG_PWM, "%s: pwms_r: PWMS: %04x\n", machine().describe_context(), m_pwmfifo[m_pwmfifo_rd]); + return m_pwmfifo[m_pwmfifo_rd]; +} + +void mc68ez328_device::pwmp_w(u8 data) // 0x504 +{ + LOGMASKED(LOG_PWM, "%s: pwmp_w: PWMP = %02x\n", machine().describe_context(), data); + const bool changed = (data != m_pwmp); + m_pwmp = data; + if (changed && (m_pwmc & PWMC_EN)) + { + update_pwm_period(false); + } +} + +u8 mc68ez328_device::pwmp_r() // 0x504 +{ + LOGMASKED(LOG_PWM, "%s: pwmp_r: PWMP: %02x\n", machine().describe_context(), m_pwmp); return m_pwmp; } -void mc68328_device::pwmw_w(uint16_t data) // 0x504 +void mc68ez328_device::pwmcnt_w(u8 data) // 0x505 { - LOGMASKED(LOG_PWM, "pwmw_w: PWMW = %04x\n", data); - m_pwmw = data; + LOGMASKED(LOG_PWM, "%s: pwmcnt_w: PWMCNT = %04x (Ignored)\n", machine().describe_context(), data); } -uint16_t mc68328_device::pwmw_r() // 0x504 +u8 mc68ez328_device::pwmcnt_r() // 0x505 { - LOGMASKED(LOG_PWM, "pwmw_r: PWMW: %04x\n", m_pwmw); - return m_pwmw; -} + u8 data = 0; + if (m_pwmc & PWMC_EN) + { + const u32 frequency = (m_pwmc & PWMC_CLK_SRC) ? 32768 : clock(); + const u32 prescale = (m_pwmc & PWMC_PRESCALE) >> PWMC_PRESCALE_SHIFT; + const u32 divisor = 2 << (m_pwmc & PWMC_CLKSEL); + const u8 period = std::min(m_pwmp + 1u, 0xffu); + data = period - (u8)m_pwm->remaining().as_ticks(frequency) / (prescale * divisor); + } -void mc68328_device::pwmcnt_w(uint16_t data) // 0x506 -{ - LOGMASKED(LOG_PWM, "pwmcnt_w: PWMCNT = %04x\n", data); - m_pwmcnt = 0; -} - -uint16_t mc68328_device::pwmcnt_r() // 0x506 -{ - LOGMASKED(LOG_PWM, "pwmcnt_r: PWMCNT: %04x\n", m_pwmcnt); - return m_pwmcnt; + LOGMASKED(LOG_PWM, "%s: pwmcnt_r: PWMCNT: %02x\n", machine().describe_context(), data); + return data; } @@ -1846,12 +2619,44 @@ uint16_t mc68328_device::pwmcnt_r() // 0x506 // Timer/Watchdog hardware //------------------------------------------------- -template -uint32_t mc68328_device::get_timer_frequency() +emu_timer *mc68328_device::get_timer(int timer) { - uint32_t frequency = 0; + return m_gptimer[timer]; +} - switch (m_tctl[Timer] & TCTL_CLKSOURCE) +emu_timer *mc68ez328_device::get_timer(int timer) +{ + return m_gptimer; +} + +mc68328_base_device::timer_regs &mc68328_device::get_timer_regs(int timer) +{ + return m_timer_regs[timer]; +} + +mc68328_base_device::timer_regs &mc68ez328_device::get_timer_regs(int timer) +{ + return m_timer_regs; +} + +u32 mc68328_device::get_timer_int(int timer) +{ + constexpr u32 TIMER_INTS[2] = { INT_TIMER1, INT_TIMER2 }; + return TIMER_INTS[timer]; +} + +u32 mc68ez328_device::get_timer_int(int timer) +{ + return INT_TIMER2; +} + +template +u32 mc68328_base_device::get_timer_frequency() +{ + timer_regs ®s = get_timer_regs(Timer); + u32 frequency = 0; + + switch (regs.tctl & TCTL_CLKSOURCE) { case TCTL_CLKSOURCE_SYSCLK: frequency = clock(); @@ -1868,217 +2673,215 @@ uint32_t mc68328_device::get_timer_frequency() frequency = 32768; break; } - frequency /= (m_tprer[Timer] + 1); + frequency /= (regs.tprer + 1); return frequency; } template -void mc68328_device::maybe_start_timer(uint32_t new_enable) +void mc68328_base_device::update_gptimer_state() { - if ((m_tctl[Timer] & TCTL_TEN) == TCTL_TEN_ENABLE && (m_tctl[Timer] & TCTL_CLKSOURCE) > TCTL_CLKSOURCE_STOP) + timer_regs ®s = get_timer_regs(Timer); + emu_timer *timer = get_timer(Timer); + if (BIT(regs.tctl, TCTL_TEN_BIT) && (regs.tctl & TCTL_CLKSOURCE) > TCTL_CLKSOURCE_STOP) { - if ((m_tctl[Timer] & TCTL_CLKSOURCE) == TCTL_CLKSOURCE_TIN) + if ((regs.tctl & TCTL_CLKSOURCE) == TCTL_CLKSOURCE_TIN || regs.tcmp == 0) { - m_gptimer[Timer]->adjust(attotime::never); - } - else if (m_tcmp[Timer] == 0) - { - m_gptimer[Timer]->adjust(attotime::never); + timer->adjust(attotime::never); } else { - uint32_t frequency = get_timer_frequency(); - attotime period = (attotime::from_hz(frequency) * m_tcmp[Timer]); - - if (new_enable) - { - m_tcn[Timer] = 0x0000; - } - - m_gptimer[Timer]->adjust(period); + timer->adjust(attotime::from_ticks(regs.tcmp, get_timer_frequency())); } } else { - m_gptimer[Timer]->adjust(attotime::never); + timer->adjust(attotime::never); } } template -TIMER_CALLBACK_MEMBER( mc68328_device::timer_tick ) +TIMER_CALLBACK_MEMBER(mc68328_base_device::timer_tick) { - m_tcn[Timer] = m_tcmp[Timer]; - m_tstat[Timer] |= TSTAT_COMP; + timer_regs ®s = get_timer_regs(Timer); + emu_timer *timer = get_timer(Timer); - if ((m_tctl[Timer] & TCTL_FRR) == TCTL_FRR_RESTART) + regs.tcn = regs.tcmp; + regs.tstat |= TSTAT_COMP; + + if ((regs.tctl & TCTL_FRR) == TCTL_FRR_RESTART) { - uint32_t frequency = get_timer_frequency(); - + u32 frequency = get_timer_frequency(); if (frequency > 0) { - attotime period = attotime::from_hz(frequency) * m_tcmp[Timer]; - - m_tcn[Timer] = 0x0000; - - m_gptimer[Timer]->adjust(period); + attotime period = attotime::from_hz(frequency) * regs.tcmp; + regs.tcn = 0x0000; + timer->adjust(period); } else { - m_gptimer[Timer]->adjust(attotime::never); + timer->adjust(attotime::never); } } else { - uint32_t frequency = get_timer_frequency(); - + u32 frequency = get_timer_frequency(); if (frequency > 0) { attotime period = attotime::from_hz(frequency) * 0x10000; - - m_gptimer[Timer]->adjust(period); + timer->adjust(period); } else { - m_gptimer[Timer]->adjust(attotime::never); + timer->adjust(attotime::never); } } - if ((m_tctl[Timer] & TCTL_IRQEN) == TCTL_IRQEN_ENABLE) + if ((regs.tctl & TCTL_IRQEN) == TCTL_IRQEN_ENABLE) { - set_interrupt_line(Timer ? INT_TIMER2 : INT_TIMER1, 1); + set_interrupt_line(get_timer_int(Timer), 1); } } template -void mc68328_device::tctl_w(uint16_t data) // 0x600, 0x60c +void mc68328_base_device::tctl_w(u16 data) // 0x600, 0x60c { - LOGMASKED(LOG_TIMERS, "tctl_w<%d>: TCTL%d = %04x\n", Timer, Timer + 1, data); - const uint16_t temp = m_tctl[Timer]; - m_tctl[Timer] = data; - if ((temp & TCTL_TEN) == (m_tctl[Timer] & TCTL_TEN)) + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tctl_w<%d>: TCTL%d = %04x\n", machine().describe_context(), Timer, Timer + 1, data); + const u16 old_tctl = regs.tctl; + regs.tctl = data; + + const bool old_enable = BIT(old_tctl, TCTL_TEN_BIT); + const bool new_enable = BIT(regs.tctl, TCTL_TEN_BIT); + if (!old_enable && new_enable) { - maybe_start_timer(0); + regs.tcn = 0x0000; } - else if ((temp & TCTL_TEN) != TCTL_TEN_ENABLE && (m_tctl[Timer] & TCTL_TEN) == TCTL_TEN_ENABLE) + update_gptimer_state(); +} + +template +u16 mc68328_base_device::tctl_r() // 0x600, 0x60c +{ + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tctl_r: TCTL%d: %04x\n", machine().describe_context(), Timer + 1, regs.tctl); + return regs.tctl; +} + +template +void mc68328_base_device::tprer_w(u16 data) // 0x602, 0x60e +{ + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tprer_w<%d>: TPRER%d = %04x\n", machine().describe_context(), Timer, Timer + 1, data); + regs.tprer = data; + update_gptimer_state(); +} + +template +u16 mc68328_base_device::tprer_r() // 0x602, 0x60e +{ + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tprer_r: TPRER%d: %04x\n", machine().describe_context(), Timer + 1, regs.tprer); + return regs.tprer; +} + +template +void mc68328_base_device::tcmp_w(u16 data) // 0x604, 0x610 +{ + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tcmp_w<%d>: TCMP%d = %04x\n", machine().describe_context(), Timer, Timer + 1, data); + regs.tcmp = data; + update_gptimer_state(); +} + +template +u16 mc68328_base_device::tcmp_r() // 0x604, 0x610 +{ + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tcmp_r: TCMP%d: %04x\n", machine().describe_context(), Timer + 1, regs.tcmp); + return regs.tcmp; +} + +template +void mc68328_base_device::tcr_w(u16 data) // 0x606, 0x612 +{ + LOGMASKED(LOG_TIMERS, "%s: tcr_w<%d>: TCR%d = %04x (Ignored)\n", machine().describe_context(), Timer, Timer + 1, data); +} + +template +u16 mc68328_base_device::tcr_r() // 0x606, 0x612 +{ + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tcr_r: TCR%d: %04x\n", machine().describe_context(), Timer + 1, regs.tcr); + return regs.tcr; +} + +template +void mc68328_base_device::tcn_w(u16 data) // 0x608, 0x614 +{ + LOGMASKED(LOG_TIMERS, "%s: tcn_w<%d>: TCN%d = %04x (Ignored)\n", machine().describe_context(), Timer, Timer + 1, data); +} + +template +u16 mc68328_base_device::tcn_r() // 0x608, 0x614 +{ + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tcn_r: TCN%d: %04x\n", machine().describe_context(), Timer + 1, regs.tcn); + return regs.tcn; +} + +template +void mc68328_base_device::tstat_w(u16 data) // 0x60a, 0x616 +{ + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TSTAT, "%s: tstat_w<%d>: TSTAT%d = %04x\n", machine().describe_context(), Timer, Timer + 1, data); + regs.tstat &= ~regs.tclear; + if (!(regs.tstat & TSTAT_COMP)) { - maybe_start_timer(1); + set_interrupt_line(get_timer_int(Timer), 0); } } template -uint16_t mc68328_device::tctl_r() // 0x600, 0x60c +u16 mc68328_base_device::tstat_r() // 0x60a, 0x616 { - LOGMASKED(LOG_TIMERS, "tctl_r: TCTL%d: %04x\n", Timer + 1, m_tctl[Timer]); - return m_tctl[Timer]; + timer_regs ®s = get_timer_regs(Timer); + LOGMASKED(LOG_TIMERS, "%s: tstat_r: TSTAT%d: %04x\n", machine().describe_context(), Timer + 1, regs.tstat); + regs.tclear |= regs.tstat; + return regs.tstat; } -template -void mc68328_device::tprer_w(uint16_t data) // 0x602, 0x60e +void mc68328_device::wctlr_w(u16 data) // 0x618 { - LOGMASKED(LOG_TIMERS, "tprer_w<%d>: TPRER%d = %04x\n", Timer, Timer + 1, data); - m_tprer[Timer] = data; - maybe_start_timer(0); -} - -template -uint16_t mc68328_device::tprer_r() // 0x602, 0x60e -{ - LOGMASKED(LOG_TIMERS, "tprer_r: TPRER%d: %04x\n", Timer + 1, m_tprer[Timer]); - return m_tprer[Timer]; -} - -template -void mc68328_device::tcmp_w(uint16_t data) // 0x604, 0x610 -{ - LOGMASKED(LOG_TIMERS, "tcmp_w<%d>: TCMP%d = %04x\n", Timer, Timer + 1, data); - m_tcmp[Timer] = data; - maybe_start_timer(0); -} - -template -uint16_t mc68328_device::tcmp_r() // 0x604, 0x610 -{ - LOGMASKED(LOG_TIMERS, "tcmp_r: TCMP%d: %04x\n", Timer + 1, m_tcmp[Timer]); - return m_tcmp[Timer]; -} - -template -void mc68328_device::tcr_w(uint16_t data) // 0x606, 0x612 -{ - LOGMASKED(LOG_TIMERS, "tcr_w<%d>: TCR%d = %04x (Ignored)\n", Timer, Timer + 1, data); -} - -template -uint16_t mc68328_device::tcr_r() // 0x606, 0x612 -{ - LOGMASKED(LOG_TIMERS, "tcr_r: TCR%d: %04x\n", Timer + 1, m_tcr[Timer]); - return m_tcr[Timer]; -} - -template -void mc68328_device::tcn_w(uint16_t data) // 0x608, 0x614 -{ - LOGMASKED(LOG_TIMERS, "tcn_w<%d>: TCN%d = %04x (Ignored)\n", Timer, Timer + 1, data); -} - -template -uint16_t mc68328_device::tcn_r() // 0x608, 0x614 -{ - LOGMASKED(LOG_TIMERS, "tcn_r: TCN%d: %04x\n", Timer + 1, m_tcn[Timer]); - return m_tcn[Timer]; -} - -template -void mc68328_device::tstat_w(uint16_t data) // 0x60a, 0x616 -{ - LOGMASKED(LOG_TSTAT, "tstat_w<%d>: TSTAT%d = %04x\n", Timer, Timer + 1, data); - m_tstat[Timer] &= ~m_tclear[Timer]; - if (!(m_tstat[Timer] & TSTAT_COMP)) - { - set_interrupt_line(Timer ? INT_TIMER2 : INT_TIMER1, 0); - } -} - -template -uint16_t mc68328_device::tstat_r() // 0x60a, 0x616 -{ - LOGMASKED(LOG_TIMERS, "tstat_r: TSTAT%d: %04x\n", Timer + 1, m_tstat[Timer]); - m_tclear[Timer] |= m_tstat[Timer]; - return m_tstat[Timer]; -} - -void mc68328_device::wctlr_w(uint16_t data) // 0x618 -{ - LOGMASKED(LOG_WATCHDOG, "wctlr_w: WCTLR = %04x\n", data); + LOGMASKED(LOG_WATCHDOG, "%s: wctlr_w: WCTLR = %04x\n", machine().describe_context(), data); m_wctlr = data; } -uint16_t mc68328_device::wctlr_r() // 0x618 +u16 mc68328_device::wctlr_r() // 0x618 { - LOGMASKED(LOG_WATCHDOG, "wctlr_r: WCTLR: %04x\n", m_wctlr); + LOGMASKED(LOG_WATCHDOG, "%s: wctlr_r: WCTLR: %04x\n", machine().describe_context(), m_wctlr); return m_wctlr; } -void mc68328_device::wcmpr_w(uint16_t data) // 0x61a +void mc68328_device::wcmpr_w(u16 data) // 0x61a { - LOGMASKED(LOG_WATCHDOG, "wcmpr_w: WCMPR = %04x\n", data); + LOGMASKED(LOG_WATCHDOG, "%s: wcmpr_w: WCMPR = %04x\n", machine().describe_context(), data); m_wcmpr = data; } -uint16_t mc68328_device::wcmpr_r() // 0x61a +u16 mc68328_device::wcmpr_r() // 0x61a { - LOGMASKED(LOG_WATCHDOG, "wcmpr_r: WCMPR: %04x\n", m_wcmpr); + LOGMASKED(LOG_WATCHDOG, "%s: wcmpr_r: WCMPR: %04x\n", machine().describe_context(), m_wcmpr); return m_wcmpr; } -void mc68328_device::wcn_w(uint16_t data) // 0x61c +void mc68328_device::wcn_w(u16 data) // 0x61c { - LOGMASKED(LOG_WATCHDOG, "wcn_w: WCN = %04x (Ignored)\n", data); + LOGMASKED(LOG_WATCHDOG, "%s: wcn_w: WCN = %04x (Ignored)\n", machine().describe_context(), data); } -uint16_t mc68328_device::wcn_r() // 0x61c +u16 mc68328_device::wcn_r() // 0x61c { - LOGMASKED(LOG_WATCHDOG, "wcn_r: WCN: %04x\n", m_wcn); + LOGMASKED(LOG_WATCHDOG, "%s: wcn_r: WCN: %04x\n", machine().describe_context(), m_wcn); return m_wcn; } @@ -2087,15 +2890,15 @@ uint16_t mc68328_device::wcn_r() // 0x61c // SPIS hardware //------------------------------------------------- -void mc68328_device::spisr_w(uint16_t data) // 0x700 +void mc68328_device::spisr_w(u16 data) // 0x700 { - LOGMASKED(LOG_SPIS, "spisr_w: SPISR = %04x\n", data); + LOGMASKED(LOG_SPIS, "%s: spisr_w: SPISR = %04x\n", machine().describe_context(), data); m_spisr = data; } -uint16_t mc68328_device::spisr_r() // 0x700 +u16 mc68328_device::spisr_r() // 0x700 { - LOGMASKED(LOG_SPIS, "spisr_r: SPISR: %04x\n", m_spisr); + LOGMASKED(LOG_SPIS, "%s: spisr_r: SPISR: %04x\n", machine().describe_context(), m_spisr); return m_spisr; } @@ -2104,13 +2907,13 @@ uint16_t mc68328_device::spisr_r() // 0x700 // SPIM hardware //------------------------------------------------- -TIMER_CALLBACK_MEMBER( mc68328_device::spim_tick ) +TIMER_CALLBACK_MEMBER(mc68328_base_device::spim_tick) { m_spmclk = !m_spmclk; const bool idle_state = BIT(m_spimcont, SPIM_POL_BIT); const bool invert_phase = BIT(m_spimcont, SPIM_PHA_BIT); - uint16_t spim_bit_index = m_spimcont & SPIM_BIT_COUNT; + u16 spim_bit_index = m_spimcont & SPIM_BIT_COUNT; LOGMASKED(LOG_SPIM, "SPIM Tick:\n"); LOGMASKED(LOG_SPIM, " CLK state: %d\n", m_spmclk); @@ -2120,7 +2923,7 @@ TIMER_CALLBACK_MEMBER( mc68328_device::spim_tick ) const bool clock_txd = (m_spmclk == idle_state && invert_phase) || (m_spmclk != idle_state && !invert_phase); if (clock_txd) { - m_spmtxd = BIT(m_spimdata, spim_bit_index); + m_spmtxd = BIT(m_spimdata, m_spim_bit_read_idx); LOGMASKED(LOG_SPIM, " Clocking TxD: %d\n", m_spmtxd); m_out_spim_cb(m_spmtxd); } @@ -2156,38 +2959,38 @@ TIMER_CALLBACK_MEMBER( mc68328_device::spim_tick ) } } -void mc68328_device::spimdata_w(uint16_t data) // 0x800 +void mc68328_base_device::spimdata_w(u16 data) // 0x800 { - LOGMASKED(LOG_SPIM, "spimdata_w: SPIMDATA = %04x\n", data); + LOGMASKED(LOG_SPIM, "%s: spimdata_w: SPIMDATA = %04x\n", machine().describe_context(), data); m_spimdata = data; } -uint16_t mc68328_device::spimdata_r() // 0x800 +u16 mc68328_base_device::spimdata_r() // 0x800 { - LOGMASKED(LOG_SPIM, "spimdata_r: SPIMDATA: %04x\n", m_spimdata); + LOGMASKED(LOG_SPIM, "%s: spimdata_r: SPIMDATA: %04x\n", machine().describe_context(), m_spimdata); return m_spimdata; } -void mc68328_device::spimcont_w(uint16_t data) // 0x802 +void mc68328_base_device::spimcont_w(u16 data) // 0x802 { - LOGMASKED(LOG_SPIM, "spimcont_w: SPIMCONT = %04x\n", data); - LOGMASKED(LOG_SPIM, " Count = %d\n", data & SPIM_BIT_COUNT); - LOGMASKED(LOG_SPIM, " Polarity = %s\n", BIT(data, SPIM_POL_BIT) ? "Inverted" : "Active-high"); - LOGMASKED(LOG_SPIM, " Phase = %s\n", BIT(data, SPIM_PHA_BIT) ? "Opposite" : "Normal"); - LOGMASKED(LOG_SPIM, " IRQ Enable = %s\n", BIT(data, SPIM_IRQEN_BIT) ? "Enable" : "Disable"); - LOGMASKED(LOG_SPIM, " IRQ Pending = %s\n", BIT(data, SPIM_SPIMIRQ_BIT) ? "Yes" : "No"); - LOGMASKED(LOG_SPIM, " Exchange = %s\n", BIT(data, SPIM_XCH_BIT) ? "Initiate" : "Idle"); - LOGMASKED(LOG_SPIM, " SPIM Enable = %s\n", BIT(data, SPIM_SPMEN_BIT) ? "Enable" : "Disable"); - LOGMASKED(LOG_SPIM, " Data Rate = Divide By %d\n", 4 << ((data & SPIM_RATE_MASK) >> SPIM_RATE_SHIFT) ); + LOGMASKED(LOG_SPIM, "%s: spimcont_w: SPIMCONT = %04x\n", machine().describe_context(), data); + LOGMASKED(LOG_SPIM, "%s: Count = %d\n", machine().describe_context(), data & SPIM_BIT_COUNT); + LOGMASKED(LOG_SPIM, "%s: Polarity = %s\n", machine().describe_context(), BIT(data, SPIM_POL_BIT) ? "Inverted" : "Active-high"); + LOGMASKED(LOG_SPIM, "%s: Phase = %s\n", machine().describe_context(), BIT(data, SPIM_PHA_BIT) ? "Opposite" : "Normal"); + LOGMASKED(LOG_SPIM, "%s: IRQ Enable = %s\n", machine().describe_context(), BIT(data, SPIM_IRQEN_BIT) ? "Enable" : "Disable"); + LOGMASKED(LOG_SPIM, "%s: IRQ Pending = %s\n", machine().describe_context(), BIT(data, SPIM_SPIMIRQ_BIT) ? "Yes" : "No"); + LOGMASKED(LOG_SPIM, "%s: Exchange = %s\n", machine().describe_context(), BIT(data, SPIM_XCH_BIT) ? "Initiate" : "Idle"); + LOGMASKED(LOG_SPIM, "%s: SPIM Enable = %s\n", machine().describe_context(), BIT(data, SPIM_SPMEN_BIT) ? "Enable" : "Disable"); + LOGMASKED(LOG_SPIM, "%s: Data Rate = Divide By %d\n", machine().describe_context(), 4 << ((data & SPIM_RATE_MASK) >> SPIM_RATE_SHIFT) ); - const uint16_t old = m_spimcont; + const u16 old = m_spimcont; m_spimcont = data; - // HACK: We should probably emulate the ADS7843 A/D device properly. if (BIT(data, SPIM_SPMEN_BIT) && BIT(data, SPIM_XCH_BIT) && !BIT(old, SPIM_XCH_BIT)) { const uint64_t divisor = 2 << ((data & SPIM_RATE_MASK) >> SPIM_RATE_SHIFT); const attotime rate = attotime::from_ticks(divisor, clock()); + m_spim_bit_read_idx = m_spimcont & SPIM_BIT_COUNT; m_spim->adjust(rate, 0, rate); m_spimcont &= ~(1 << SPIM_XCH_BIT); @@ -2203,9 +3006,9 @@ void mc68328_device::spimcont_w(uint16_t data) // 0x802 } } -uint16_t mc68328_device::spimcont_r() // 0x802 +u16 mc68328_base_device::spimcont_r() // 0x802 { - LOGMASKED(LOG_SPIM, "spimcont_r: SPIMCONT: %04x\n", m_spimcont); + LOGMASKED(LOG_SPIM, "%s: spimcont_r: SPIMCONT: %04x\n", machine().describe_context(), m_spimcont); return m_spimcont; } @@ -2214,71 +3017,105 @@ uint16_t mc68328_device::spimcont_r() // 0x802 // UART hardware //------------------------------------------------- -void mc68328_device::ustcnt_w(uint16_t data) // 0x900 +void mc68328_base_device::ustcnt_w(u16 data) // 0x900 { - LOGMASKED(LOG_UART, "ustcnt_w: USTCNT = %04x\n", data); + LOGMASKED(LOG_UART, "%s: ustcnt_w: USTCNT = %04x\n", machine().describe_context(), data); m_ustcnt = data; } -uint16_t mc68328_device::ustcnt_r() // 0x900 +u16 mc68328_base_device::ustcnt_r() // 0x900 { - LOGMASKED(LOG_UART, "ustcnt_r: USTCNT: %04x\n", m_ustcnt); + LOGMASKED(LOG_UART, "%s: ustcnt_r: USTCNT: %04x\n", machine().describe_context(), m_ustcnt); return m_ustcnt; } -void mc68328_device::ubaud_w(uint16_t data) // 0x902 +void mc68328_base_device::ubaud_w(u16 data) // 0x902 { - LOGMASKED(LOG_UART, "ubaud_w: UBAUD = %04x\n", data); + LOGMASKED(LOG_UART, "%s: ubaud_w: UBAUD = %04x\n", machine().describe_context(), data); m_ubaud = data; } -uint16_t mc68328_device::ubaud_r() // 0x902 +u16 mc68328_base_device::ubaud_r() // 0x902 { - LOGMASKED(LOG_UART, "ubaud_r: UBAUD: %04x\n", m_ubaud); + LOGMASKED(LOG_UART, "%s: ubaud_r: UBAUD: %04x\n", machine().describe_context(), m_ubaud); return m_ubaud; } -void mc68328_device::urx_w(uint16_t data) // 0x904 +void mc68328_base_device::urx_w(u16 data) // 0x904 { - LOGMASKED(LOG_UART, "urx_w: URX = %04x (Not Yet Implemented)\n", data); + LOGMASKED(LOG_UART, "%s: urx_w: URX = %04x (Not Yet Implemented)\n", machine().describe_context(), data); } -uint16_t mc68328_device::urx_r() // 0x904 +u16 mc68328_base_device::urx_r() // 0x904 { - LOGMASKED(LOG_UART, "urx_r: URX: %04x\n", m_urx); + LOGMASKED(LOG_UART, "%s: urx_r: URX: %04x\n", machine().describe_context(), m_urx); return m_urx; } -void mc68328_device::utx_w(uint16_t data) // 0x906 +void mc68328_base_device::utx_w(u16 data) // 0x906 { - LOGMASKED(LOG_UART, "utx_w: UTX = %04x (Not Yet Implemented)\n", data); + LOGMASKED(LOG_UART, "%s: utx_w: UTX = %04x (Not Yet Implemented)\n", machine().describe_context(), data); } -uint16_t mc68328_device::utx_r() // 0x906 +u16 mc68328_base_device::utx_r() // 0x906 { - uint16_t data = m_utx | UTX_FIFO_EMPTY | UTX_FIFO_HALF | UTX_TX_AVAIL; - LOGMASKED(LOG_UART, "utx_r: UTX: %04x\n", data); + u16 data = m_utx | UTX_FIFO_EMPTY | UTX_FIFO_HALF | UTX_TX_AVAIL; + LOGMASKED(LOG_UART, "%s: utx_r: UTX: %04x\n", machine().describe_context(), data); return data; } -void mc68328_device::umisc_w(uint16_t data) // 0x908 +void mc68328_base_device::umisc_w(u16 data) // 0x908 { - LOGMASKED(LOG_UART, "umisc_w: UMISC = %04x (Not Yet Implemented)\n", data); + LOGMASKED(LOG_UART, "%s: umisc_w: UMISC = %04x (Not Yet Implemented)\n", machine().describe_context(), data); m_umisc = data; } -uint16_t mc68328_device::umisc_r() // 0x908 +u16 mc68328_base_device::umisc_r() // 0x908 { - LOGMASKED(LOG_UART, "umisc_r: UMISC: %04x\n", m_umisc); + LOGMASKED(LOG_UART, "%s: umisc_r: UMISC: %04x\n", machine().describe_context(), m_umisc); return m_umisc; } //------------------------------------------------- -// LCD hardware +// LCD hardware - Shared and Standard MC68328 //------------------------------------------------- -void mc68328_device::fill_lcd_dma_buffer() +u16 mc68328_device::lcd_get_lxmax_mask() +{ + constexpr u16 LXMAX_MASK = 0x03ff; + return LXMAX_MASK; +} + +u32 mc68328_device::lcd_get_line_word_count() +{ + return m_lvpw != m_llbar ? (m_llbar + 1) : m_llbar; +} + +attotime mc68328_device::lcd_get_line_rate() +{ + const u32 sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT]; + return attotime::from_ticks(m_llbar, clock() / sysclk_divisor); +} + +u8 mc68328_device::lcd_get_panel_bit_size() +{ + constexpr u8 BIT_WIDTHS[4] = { 1, 2, 4, 0xff }; + return BIT_WIDTHS[(m_lpicf & LPICF_PBSIZ) >> LPICF_PBSIZ_SHIFT]; +} + +attotime mc68328_device::get_pixclk_rate() +{ + u32 divisor = 1; + if (BIT(m_lckcon, LCKCON_PCDS_BIT)) // Use PIXCLK from PLL + divisor = VCO_DIVISORS[(m_pllcr & PLLCR_PIXCLK_SEL) >> PLLCR_PIXCLK_SHIFT]; + else // Use SYSCLK from PLL + divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT]; + + return attotime::from_ticks((m_lpxcd & LPXCD_MASK) + 1, clock() / divisor); +} + +void mc68328_base_device::fill_lcd_dma_buffer() { if (m_lcd_sysmem_ptr == m_lssa) { @@ -2290,20 +3127,19 @@ void mc68328_device::fill_lcd_dma_buffer() } m_out_llp_cb(BIT(m_lpolcf, LPOLCF_LPPOL_BIT) ? 0 : 1); - const uint32_t sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT]; - attotime buffer_duration = attotime::from_ticks(m_llbar, clock() / sysclk_divisor); + attotime buffer_duration = lcd_get_line_rate(); m_lcd_scan->adjust(buffer_duration); address_space &prg_space = space(AS_PROGRAM); - const uint16_t last_word = m_lvpw != m_llbar ? (m_llbar + 1) : m_llbar; - for (uint32_t word_index = 0; word_index < last_word; word_index++) + const u32 word_count = lcd_get_line_word_count(); + for (u32 word_index = 0; word_index < word_count; word_index++) { m_lcd_line_buffer[word_index] = prg_space.read_word(m_lcd_sysmem_ptr + (word_index << 1)); } m_lcd_sysmem_ptr += m_lvpw << 1; - const uint32_t screen_max_addr = m_lssa + ((m_lvpw * (m_lymax + 1)) << 1); + const u32 screen_max_addr = m_lssa + ((m_lvpw * (m_lymax + 1)) << 1); if (m_lcd_sysmem_ptr >= screen_max_addr) { m_lcd_sysmem_ptr = m_lssa; @@ -2313,18 +3149,17 @@ void mc68328_device::fill_lcd_dma_buffer() m_lcd_line_word = 0; } -TIMER_CALLBACK_MEMBER( mc68328_device::lcd_scan_tick ) +TIMER_CALLBACK_MEMBER(mc68328_base_device::lcd_scan_tick) { - const uint16_t last_word = m_lvpw != m_llbar ? (m_llbar + 1) : m_llbar; m_out_llp_cb(BIT(m_lpolcf, LPOLCF_LPPOL_BIT) ? 1 : 0); m_lsclk = !m_lsclk; if (m_lsclk) { - uint8_t data = 0; - switch (m_lpicf & LPICF_PBSIZ) + u8 data = 0; + switch (lcd_get_panel_bit_size()) { - case LPICF_PBSIZ_1: + case 1: data = BIT(m_lcd_line_buffer[m_lcd_line_word], m_lcd_line_bit); if (m_lcd_line_bit == 0) { @@ -2336,7 +3171,7 @@ TIMER_CALLBACK_MEMBER( mc68328_device::lcd_scan_tick ) m_lcd_line_bit--; } break; - case LPICF_PBSIZ_2: + case 2: data = (m_lcd_line_buffer[m_lcd_line_word] >> (m_lcd_line_bit - 1)) & 3; if (m_lcd_line_bit <= 1) { @@ -2348,7 +3183,7 @@ TIMER_CALLBACK_MEMBER( mc68328_device::lcd_scan_tick ) m_lcd_line_bit -= 2; } break; - case LPICF_PBSIZ_4: + case 4: data = (m_lcd_line_buffer[m_lcd_line_word] >> (m_lcd_line_bit - 3)) & 15; if (m_lcd_line_bit <= 3) { @@ -2368,7 +3203,7 @@ TIMER_CALLBACK_MEMBER( mc68328_device::lcd_scan_tick ) } m_out_lsclk_cb(m_lsclk); - if (m_lcd_line_word == last_word) + if (m_lcd_line_word == lcd_get_line_word_count()) { fill_lcd_dma_buffer(); } @@ -2378,238 +3213,212 @@ TIMER_CALLBACK_MEMBER( mc68328_device::lcd_scan_tick ) } } -attotime mc68328_device::get_pixclk_rate() +void mc68328_base_device::lssa_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0xa00 { - uint32_t divisor = 1; - if (BIT(m_lckcon, LCKCON_PCDS_BIT)) // Use PIXCLK from PLL - divisor = VCO_DIVISORS[(m_pllcr & PLLCR_PIXCLK_SEL) >> PLLCR_PIXCLK_SHIFT]; - else // Use SYSCLK from PLL - divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT]; - - return attotime::from_ticks((m_lpxcd & LPXCD_MASK) + 1, clock() / divisor); -} - -void mc68328_device::lssa_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xa00 -{ - LOGMASKED(LOG_LCD, "lssa_msw_w: LSSA(MSW) = %04x\n", data); + LOGMASKED(LOG_LCD, "%s: lssa_msw_w: LSSA(MSW) = %04x\n", machine().describe_context(), data); m_lssa &= ~(mem_mask << 16); m_lssa |= (data & mem_mask) << 16; - LOGMASKED(LOG_LCD, " Address: %08x\n", m_lssa); + LOGMASKED(LOG_LCD, "%s: Address: %08x\n", machine().describe_context(), m_lssa); } -uint16_t mc68328_device::lssa_msw_r() // 0xa00 +u16 mc68328_base_device::lssa_msw_r() // 0xa00 { - LOGMASKED(LOG_LCD, "lssa_msw_r: LSSA(MSW): %04x\n", (uint16_t)(m_lssa >> 16)); - return (uint16_t)(m_lssa >> 16); + LOGMASKED(LOG_LCD, "%s: lssa_msw_r: LSSA(MSW): %04x\n", machine().describe_context(), (u16)(m_lssa >> 16)); + return (u16)(m_lssa >> 16); } -void mc68328_device::lssa_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xa02 +void mc68328_base_device::lssa_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0xa02 { - LOGMASKED(LOG_LCD, "lssa_lsw_w: LSSA(LSW) = %04x\n", data); + LOGMASKED(LOG_LCD, "%s: lssa_lsw_w: LSSA(LSW) = %04x\n", machine().describe_context(), data); m_lssa &= 0xffff0000 | (~mem_mask); m_lssa |= data & mem_mask; - LOGMASKED(LOG_LCD, " Address: %08x\n", m_lssa); + LOGMASKED(LOG_LCD, " Address: %08x\n", machine().describe_context(), m_lssa); } -uint16_t mc68328_device::lssa_lsw_r() // 0xa02 +u16 mc68328_base_device::lssa_lsw_r() // 0xa02 { - LOGMASKED(LOG_LCD, "lssa_lsw_r: LSSA(LSW): %04x\n", (uint16_t)m_lssa); - return (uint16_t)m_lssa; + LOGMASKED(LOG_LCD, "%s: lssa_lsw_r: LSSA(LSW): %04x\n", machine().describe_context(), (u16)m_lssa); + return (u16)m_lssa; } -void mc68328_device::lvpw_w(uint8_t data) // 0xa05 +void mc68328_base_device::lvpw_w(u8 data) // 0xa05 { - LOGMASKED(LOG_LCD, "lvpw_w: LVPW = %02x\n", data); + LOGMASKED(LOG_LCD, "%s: lvpw_w: LVPW = %02x\n", machine().describe_context(), data); m_lvpw = data; - LOGMASKED(LOG_LCD, " Page Width: %d\n", (m_lvpw << 1) * (BIT(m_lpicf, LPICF_GRAYSCALE_BIT) ? 8 : 16)); + LOGMASKED(LOG_LCD, "%s: Virtual Page Width: %d words\n", machine().describe_context(), m_lvpw << 1); } -uint8_t mc68328_device::lvpw_r() // 0xa05 +u8 mc68328_base_device::lvpw_r() // 0xa05 { - LOGMASKED(LOG_LCD, "lvpw_r: LVPW: %02x\n", m_lvpw); + LOGMASKED(LOG_LCD, "%s: lvpw_r: LVPW: %02x\n", machine().describe_context(), m_lvpw); return m_lvpw; } -void mc68328_device::lxmax_w(uint16_t data) // 0xa08 +void mc68328_base_device::lxmax_w(u16 data) // 0xa08 { - LOGMASKED(LOG_LCD, "lxmax_w: LXMAX = %04x\n", data); - m_lxmax = data & LXMAX_MASK; - LOGMASKED(LOG_LCD, " Width: %d\n", (data & 0x03ff) + 1); + LOGMASKED(LOG_LCD, "%s: lxmax_w: LXMAX = %04x\n", machine().describe_context(), data); + m_lxmax = data & lcd_get_lxmax_mask(); + LOGMASKED(LOG_LCD, "%s: Width: %d\n", machine().describe_context(), (data & 0x03ff) + 1); } -uint16_t mc68328_device::lxmax_r() // 0xa08 +u16 mc68328_base_device::lxmax_r() // 0xa08 { - LOGMASKED(LOG_LCD, "lxmax_r: LXMAX: %04x\n", m_lxmax); + LOGMASKED(LOG_LCD, "%s: lxmax_r: LXMAX: %04x\n", machine().describe_context(), m_lxmax); return m_lxmax; } -void mc68328_device::lymax_w(uint16_t data) // 0xa0a +void mc68328_base_device::lymax_w(u16 data) // 0xa0a { - LOGMASKED(LOG_LCD, "lymax_w: LYMAX = %04x\n", data); + LOGMASKED(LOG_LCD, "%s: lymax_w: LYMAX = %04x\n", machine().describe_context(), data); m_lymax = data & LYMAX_MASK; - LOGMASKED(LOG_LCD, " Height: %d\n", (data & 0x03ff) + 1); + LOGMASKED(LOG_LCD, "%s: Height: %d\n", machine().describe_context(), (data & 0x03ff) + 1); } -uint16_t mc68328_device::lymax_r() // 0xa0a +u16 mc68328_base_device::lymax_r() // 0xa0a { - LOGMASKED(LOG_LCD, "lymax_r: LYMAX: %04x\n", m_lymax); + LOGMASKED(LOG_LCD, "%s: lymax_r: LYMAX: %04x\n", machine().describe_context(), m_lymax); return m_lymax; } -void mc68328_device::lcxp_w(uint16_t data) // 0xa18 +void mc68328_base_device::lcxp_w(u16 data) // 0xa18 { - LOGMASKED(LOG_LCD, "lcxp_w: LCXP = %04x\n", data); + LOGMASKED(LOG_LCD, "%s: lcxp_w: LCXP = %04x\n", machine().describe_context(), data); m_lcxp = data; - LOGMASKED(LOG_LCD, " X Position: %d\n", data & 0x03ff); + LOGMASKED(LOG_LCD, "%s: X Position: %d\n", machine().describe_context(), data & 0x03ff); switch (m_lcxp >> 14) { case 0: - LOGMASKED(LOG_LCD, " Cursor Control: Transparent\n"); + LOGMASKED(LOG_LCD, "%s: Cursor Control: Transparent\n", machine().describe_context()); break; case 1: - LOGMASKED(LOG_LCD, " Cursor Control: Black\n"); + LOGMASKED(LOG_LCD, "%s: Cursor Control: Black\n", machine().describe_context()); break; case 2: - LOGMASKED(LOG_LCD, " Cursor Control: Reverse\n"); + LOGMASKED(LOG_LCD, "%s: Cursor Control: Reverse\n", machine().describe_context()); break; case 3: - LOGMASKED(LOG_LCD, " Cursor Control: Invalid\n"); + LOGMASKED(LOG_LCD, "%s: Cursor Control: Invalid\n", machine().describe_context()); break; } } -uint16_t mc68328_device::lcxp_r() // 0xa18 +u16 mc68328_base_device::lcxp_r() // 0xa18 { - LOGMASKED(LOG_LCD, "lcxp_r: LCXP: %04x\n", m_lcxp); + LOGMASKED(LOG_LCD, "%s: lcxp_r: LCXP: %04x\n", machine().describe_context(), m_lcxp); return m_lcxp; } -void mc68328_device::lcyp_w(uint16_t data) // 0xa1a +void mc68328_base_device::lcyp_w(u16 data) // 0xa1a { - LOGMASKED(LOG_LCD, "lcyp_w: LCYP = %04x\n", data); + LOGMASKED(LOG_LCD, "%s: lcyp_w: LCYP = %04x\n", machine().describe_context(), data); m_lcyp = data; - LOGMASKED(LOG_LCD, " Y Position: %d\n", data & 0x01ff); + LOGMASKED(LOG_LCD, "%s: Y Position: %d\n", machine().describe_context(), data & 0x01ff); } -uint16_t mc68328_device::lcyp_r() // 0xa1a +u16 mc68328_base_device::lcyp_r() // 0xa1a { - LOGMASKED(LOG_LCD, "lcyp_r: LCYP: %04x\n", m_lcyp); + LOGMASKED(LOG_LCD, "%s: lcyp_r: LCYP: %04x\n", machine().describe_context(), m_lcyp); return m_lcyp; } -void mc68328_device::lcwch_w(uint16_t data) // 0xa1c +void mc68328_base_device::lcwch_w(u16 data) // 0xa1c { - LOGMASKED(LOG_LCD, "lcwch_w: LCWCH = %04x\n", data); + LOGMASKED(LOG_LCD, "%s: lcwch_w: LCWCH = %04x\n", machine().describe_context(), data); m_lcwch = data; - LOGMASKED(LOG_LCD, " Width: %d\n", (data >> 8) & 0x1f); - LOGMASKED(LOG_LCD, " Height: %d\n", data & 0x1f); + LOGMASKED(LOG_LCD, "%s: Width: %d\n", machine().describe_context(), (data >> 8) & 0x1f); + LOGMASKED(LOG_LCD, "%s: Height: %d\n", machine().describe_context(), data & 0x1f); } -uint16_t mc68328_device::lcwch_r() // 0xa1c +u16 mc68328_base_device::lcwch_r() // 0xa1c { - LOGMASKED(LOG_LCD, "lcwch_r: LCWCH: %04x\n", m_lcwch); + LOGMASKED(LOG_LCD, "%s: lcwch_r: LCWCH: %04x\n", machine().describe_context(), m_lcwch); return m_lcwch; } -void mc68328_device::lblkc_w(uint8_t data) // 0xa1f +void mc68328_base_device::lblkc_w(u8 data) // 0xa1f { - LOGMASKED(LOG_LCD, "lblkc_w: LBLKC = %02x\n", data); + LOGMASKED(LOG_LCD, "%s: lblkc_w: LBLKC = %02x\n", machine().describe_context(), data); m_lblkc = data; - LOGMASKED(LOG_LCD, " Blink Enable: %d\n", m_lblkc >> 7); - LOGMASKED(LOG_LCD, " Blink Divisor: %d\n", m_lblkc & 0x7f); + LOGMASKED(LOG_LCD, "%s: Blink Enable: %d\n", machine().describe_context(), m_lblkc >> 7); + LOGMASKED(LOG_LCD, "%s: Blink Divisor: %d\n", machine().describe_context(), m_lblkc & 0x7f); } -uint8_t mc68328_device::lblkc_r() // 0xa1f +u8 mc68328_base_device::lblkc_r() // 0xa1f { - LOGMASKED(LOG_LCD, "lblkc_r: LBLKC: %02x\n", m_lblkc); + LOGMASKED(LOG_LCD, "%s: lblkc_r: LBLKC: %02x\n", machine().describe_context(), m_lblkc); return m_lblkc; } -void mc68328_device::lpicf_w(uint8_t data) // 0xa20 +void mc68328_device::lpicf_w(u8 data) // 0xa20 { - LOGMASKED(LOG_LCD, "lpicf_w: LPICF = %02x\n", data); + static const char *const PBSIZ_NAMES[4] = { "1-bit", "2-bit", "4-bit", "Invalid" }; + LOGMASKED(LOG_LCD, "%s: lpicf_w: LPICF = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_LCD, "%s: Grayscale Mode: %d\n", machine().describe_context(), data & LPICF_GS); + LOGMASKED(LOG_LCD, "%s: Bus Size: %s\n", machine().describe_context(), PBSIZ_NAMES[(data & LPICF_PBSIZ) >> LPICF_PBSIZ_SHIFT]); m_lpicf = data; - switch((m_lpicf >> 1) & 0x03) - { - case 0: - LOGMASKED(LOG_LCD, " Bus Size: 1-bit\n"); - break; - - case 1: - LOGMASKED(LOG_LCD, " Bus Size: 2-bit\n"); - break; - - case 2: - LOGMASKED(LOG_LCD, " Bus Size: 4-bit\n"); - break; - - case 3: - LOGMASKED(LOG_LCD, " Bus Size: unused\n"); - break; - } - LOGMASKED(LOG_LCD, " Gray scale enable: %d\n", m_lpicf & 0x01); } -uint8_t mc68328_device::lpicf_r() // 0xa20 +u8 mc68328_base_device::lpicf_r() // 0xa20 { - LOGMASKED(LOG_LCD, "lpicf_r: LPICF: %02x\n", m_lpicf); + LOGMASKED(LOG_LCD, "%s: lpicf_r: LPICF: %02x\n", machine().describe_context(), m_lpicf); return m_lpicf; } -void mc68328_device::lpolcf_w(uint8_t data) // 0xa21 +void mc68328_base_device::lpolcf_w(u8 data) // 0xa21 { - LOGMASKED(LOG_LCD, "lpolcf_w: LPOLCF = %02x\n", data); + LOGMASKED(LOG_LCD, "%s: lpolcf_w: LPOLCF = %02x\n", machine().describe_context(), data); m_lpolcf = data; - LOGMASKED(LOG_LCD, " LCD Shift Clock Polarity: %s\n", (m_lpicf & 0x08) ? "Active positive edge of LCLK" : "Active negative edge of LCLK"); - LOGMASKED(LOG_LCD, " First-line marker polarity: %s\n", (m_lpicf & 0x04) ? "Active Low" : "Active High"); - LOGMASKED(LOG_LCD, " Line-pulse polarity: %s\n", (m_lpicf & 0x02) ? "Active Low" : "Active High"); - LOGMASKED(LOG_LCD, " Pixel polarity: %s\n", (m_lpicf & 0x01) ? "Active Low" : "Active High"); + LOGMASKED(LOG_LCD, "%s: LCD Shift Clock Polarity: %s\n", machine().describe_context(), (m_lpicf & 0x08) ? "Active positive edge of LCLK" : "Active negative edge of LCLK"); + LOGMASKED(LOG_LCD, "%s: First-line marker polarity: %s\n", machine().describe_context(), (m_lpicf & 0x04) ? "Active Low" : "Active High"); + LOGMASKED(LOG_LCD, "%s: Line-pulse polarity: %s\n", machine().describe_context(), (m_lpicf & 0x02) ? "Active Low" : "Active High"); + LOGMASKED(LOG_LCD, "%s: Pixel polarity: %s\n", machine().describe_context(), (m_lpicf & 0x01) ? "Active Low" : "Active High"); } -uint8_t mc68328_device::lpolcf_r() // 0xa21 +u8 mc68328_base_device::lpolcf_r() // 0xa21 { - LOGMASKED(LOG_LCD, "lpolcf_r: LPOLCF: %02x\n", m_lpolcf); + LOGMASKED(LOG_LCD, "%s: lpolcf_r: LPOLCF: %02x\n", machine().describe_context(), m_lpolcf); return m_lpolcf; } -void mc68328_device::lacdrc_w(uint8_t data) // 0xa23 +void mc68328_base_device::lacdrc_w(u8 data) // 0xa23 { - LOGMASKED(LOG_LCD, "lacdrc_w: LACDRC = %02x\n", data); + LOGMASKED(LOG_LCD, "%s: lacdrc_w: LACDRC = %02x\n", machine().describe_context(), data); m_lacdrc = data; } -uint8_t mc68328_device::lacdrc_r() // 0xa23 +u8 mc68328_base_device::lacdrc_r() // 0xa23 { - LOGMASKED(LOG_LCD, "lacdrc_r: LACDRC: %02x\n", m_lacdrc); + LOGMASKED(LOG_LCD, "%s: lacdrc_r: LACDRC: %02x\n", machine().describe_context(), m_lacdrc); return m_lacdrc; } -void mc68328_device::lpxcd_w(uint8_t data) // 0xa25 +void mc68328_base_device::lpxcd_w(u8 data) // 0xa25 { - LOGMASKED(LOG_LCD, "lpxcd_w: LPXCD = %02x\n", data); + LOGMASKED(LOG_LCD, "%s: lpxcd_w: LPXCD = %02x\n", machine().describe_context(), data); m_lpxcd = data; - LOGMASKED(LOG_LCD, " Clock Divisor: %d\n", m_lpxcd + 1); + LOGMASKED(LOG_LCD, "%s: Clock Divisor: %d\n", machine().describe_context(), m_lpxcd + 1); } -uint8_t mc68328_device::lpxcd_r() // 0xa25 +u8 mc68328_base_device::lpxcd_r() // 0xa25 { - LOGMASKED(LOG_LCD, "lpxcd_r: LPXCD: %02x\n", m_lpxcd); + LOGMASKED(LOG_LCD, "%s: lpxcd_r: LPXCD: %02x\n", machine().describe_context(), m_lpxcd); return m_lpxcd; } -void mc68328_device::lckcon_w(uint8_t data) // 0xa27 +void mc68328_device::lckcon_w(u8 data) // 0xa27 { - LOGMASKED(LOG_LCD, "lckcon_w: LCKCON = %02x\n", data); - const uint16_t old = m_lckcon; + LOGMASKED(LOG_LCD, "%s: lckcon_w: LCKCON = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_LCD, "%s: LCDC Enable: %d\n", machine().describe_context(), BIT(data, LCKCON_LCDON_BIT)); + LOGMASKED(LOG_LCD, "%s: DMA Burst Length: %d\n", machine().describe_context(), BIT(data, LCKCON_DMA16_BIT) ? 16 : 8); + LOGMASKED(LOG_LCD, "%s: DMA Bursting Clock Control: %d\n", machine().describe_context(), ((data & LCKCON_WS) >> LCKCON_WS_SHIFT) + 1); + LOGMASKED(LOG_LCD, "%s: Bus Width: %d\n", machine().describe_context(), BIT(data, LCKCON_DWIDTH_BIT) ? 8 : 16); + LOGMASKED(LOG_LCD, "%s: Pixel Clock Divider Source: %s\n", machine().describe_context(), BIT(data, LCKCON_PCDS_BIT) ? "PIX" : "SYS"); + + const u16 old = m_lckcon; m_lckcon = data; - LOGMASKED(LOG_LCD, " LCDC Enable: %d\n", (m_lckcon >> 7) & 0x01); - LOGMASKED(LOG_LCD, " DMA Burst Length: %d\n", ((m_lckcon >> 6) & 0x01) ? 16 : 8); - LOGMASKED(LOG_LCD, " DMA Bursting Clock Control: %d\n", ((m_lckcon >> 4) & 0x03) + 1); - LOGMASKED(LOG_LCD, " Bus Width: %d\n", ((m_lckcon >> 1) & 0x01) ? 8 : 16); - LOGMASKED(LOG_LCD, " Pixel Clock Divider Source: %s\n", (m_lckcon & 0x01) ? "PIX" : "SYS"); if (BIT(old, LCKCON_LCDON_BIT) && !BIT(m_lckcon, LCKCON_LCDON_BIT)) { @@ -2617,7 +3426,7 @@ void mc68328_device::lckcon_w(uint8_t data) // 0xa27 } else if (!BIT(old, LCKCON_LCDON_BIT) && BIT(m_lckcon, LCKCON_LCDON_BIT)) { - const uint32_t sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT]; + const u32 sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT]; attotime lcd_dma_duration = attotime::from_ticks(m_llbar, clock() / sysclk_divisor); attotime lcd_scan_duration = get_pixclk_rate() * (m_lxmax + 1); attotime lcd_frame_duration = (lcd_scan_duration + lcd_dma_duration) * (m_lymax + 1); @@ -2629,267 +3438,521 @@ void mc68328_device::lckcon_w(uint8_t data) // 0xa27 } } -uint8_t mc68328_device::lckcon_r() // 0xa27 +u8 mc68328_base_device::lckcon_r() // 0xa27 { - LOGMASKED(LOG_LCD, "lckcon_r: LCKCON: %02x\n", m_lckcon); + LOGMASKED(LOG_LCD, "%s: lckcon_r: LCKCON: %02x\n", machine().describe_context(), m_lckcon); return m_lckcon; } -void mc68328_device::llbar_w(uint8_t data) // 0xa29 +void mc68328_device::llbar_w(u8 data) // 0xa29 { - LOGMASKED(LOG_LCD, "llbar_w: LLBAR = %02x\n", data); + LOGMASKED(LOG_LCD, "%s: llbar_w: LLBAR = %02x\n", machine().describe_context(), data); m_llbar = data; - LOGMASKED(LOG_LCD, " Address: %d\n", m_llbar << (BIT(m_lpicf, LPICF_GRAYSCALE_BIT) ? 4 : 5)); + LOGMASKED(LOG_LCD, "%s: Address: %d\n", machine().describe_context(), m_llbar << (BIT(m_lpicf, LPICF_GS_BIT) ? 4 : 5)); } -uint8_t mc68328_device::llbar_r() // 0xa29 +u8 mc68328_device::llbar_r() // 0xa29 { - LOGMASKED(LOG_LCD, "llbar_r: LLBAR: %02x\n", m_llbar); + LOGMASKED(LOG_LCD, "%s: llbar_r: LLBAR: %02x\n", machine().describe_context(), m_llbar); return m_llbar; } -void mc68328_device::lotcr_w(uint8_t data) // 0xa2b +void mc68328_device::lotcr_w(u8 data) // 0xa2b { - LOGMASKED(LOG_LCD, "lotcr_w: LOTCR = %02x (Ignored)\n", data); + LOGMASKED(LOG_LCD, "%s: lotcr_w: LOTCR = %02x (Ignored)\n", machine().describe_context(), data); } -uint8_t mc68328_device::lotcr_r() // 0xa2b +u8 mc68328_device::lotcr_r() // 0xa2b { - LOGMASKED(LOG_LCD, "lotcr_r: LOTCR: %02x\n", m_lotcr); + LOGMASKED(LOG_LCD, "%s: lotcr_r: LOTCR: %02x\n", machine().describe_context(), m_lotcr); return m_lotcr; } -void mc68328_device::lposr_w(uint8_t data) // 0xa2d +void mc68328_base_device::lposr_w(u8 data) // 0xa2d { - LOGMASKED(LOG_LCD, "lposr_w: LPOSR = %02x\n", data); + LOGMASKED(LOG_LCD, "%s: lposr_w: LPOSR = %02x\n", machine().describe_context(), data); m_lposr = data; - LOGMASKED(LOG_LCD, " Byte Offset: %d\n", (m_lposr >> 3) & 0x01); - LOGMASKED(LOG_LCD, " Pixel Offset: %d\n", m_lposr & 0x07); + LOGMASKED(LOG_LCD, "%s: Byte Offset: %d\n", machine().describe_context(), (m_lposr >> 3) & 0x01); + LOGMASKED(LOG_LCD, "%s: Pixel Offset: %d\n", machine().describe_context(), m_lposr & 0x07); } -uint8_t mc68328_device::lposr_r() // 0xa2d +u8 mc68328_base_device::lposr_r() // 0xa2d { - LOGMASKED(LOG_LCD, "lposr_r: LPOSR: %02x\n", m_lposr); + LOGMASKED(LOG_LCD, "%s: lposr_r: LPOSR: %02x\n", machine().describe_context(), m_lposr); return m_lposr; } -void mc68328_device::lfrcm_w(uint8_t data) // 0xa31 +void mc68328_base_device::lfrcm_w(u8 data) // 0xa31 { - LOGMASKED(LOG_LCD, "lfrcm_w: LFRCM = %02x\n", data); + LOGMASKED(LOG_LCD, "%s: lfrcm_w: LFRCM = %02x\n", machine().describe_context(), data); m_lfrcm = data; - LOGMASKED(LOG_LCD, " X Modulation: %d\n", (m_lfrcm >> 4) & 0x0f); - LOGMASKED(LOG_LCD, " Y Modulation: %d\n", m_lfrcm & 0x0f); + LOGMASKED(LOG_LCD, "%s: X Modulation: %d\n", machine().describe_context(), (m_lfrcm >> 4) & 0x0f); + LOGMASKED(LOG_LCD, "%s: Y Modulation: %d\n", machine().describe_context(), m_lfrcm & 0x0f); } -uint8_t mc68328_device::lfrcm_r() // 0xa31 +u8 mc68328_base_device::lfrcm_r() // 0xa31 { - LOGMASKED(LOG_LCD, "lfrcm_r: LFRCM: %02x\n", m_lfrcm); + LOGMASKED(LOG_LCD, "%s: lfrcm_r: LFRCM: %02x\n", machine().describe_context(), m_lfrcm); return m_lfrcm; } -void mc68328_device::lgpmr_w(uint8_t data) // 0xa32 +void mc68328_device::lgpmr_w(u8 data) // 0xa32 { - LOGMASKED(LOG_LCD, "lgpmr_w: LGPMR = %04x\n", data); + LOGMASKED(LOG_LCD, "%s: lgpmr_w: LGPMR = %04x\n", machine().describe_context(), data); m_lgpmr = data; - LOGMASKED(LOG_LCD, " Palette 0: %d\n", (m_lgpmr >> 8) & 0x07); - LOGMASKED(LOG_LCD, " Palette 1: %d\n", (m_lgpmr >> 12) & 0x07); - LOGMASKED(LOG_LCD, " Palette 2: %d\n", (m_lgpmr >> 0) & 0x07); - LOGMASKED(LOG_LCD, " Palette 3: %d\n", (m_lgpmr >> 4) & 0x07); + LOGMASKED(LOG_LCD, "%s: Palette 0: %d\n", machine().describe_context(), (m_lgpmr >> 8) & 0x07); + LOGMASKED(LOG_LCD, "%s: Palette 1: %d\n", machine().describe_context(), (m_lgpmr >> 12) & 0x07); + LOGMASKED(LOG_LCD, "%s: Palette 2: %d\n", machine().describe_context(), (m_lgpmr >> 0) & 0x07); + LOGMASKED(LOG_LCD, "%s: Palette 3: %d\n", machine().describe_context(), (m_lgpmr >> 4) & 0x07); } -uint16_t mc68328_device::lgpmr_r() // 0xa32 +u16 mc68328_device::lgpmr_r() // 0xa32 { - LOGMASKED(LOG_LCD, "lgpmr_r: LGPMR: %04x\n", m_lgpmr); + LOGMASKED(LOG_LCD, "%s: lgpmr_r: LGPMR: %04x\n", machine().describe_context(), m_lgpmr); return m_lgpmr; } //------------------------------------------------- -// RTC/alarm hardware +// LCD hardware - EZ variant //------------------------------------------------- -TIMER_CALLBACK_MEMBER( mc68328_device::rtc_tick ) +u16 mc68ez328_device::lcd_get_lxmax_mask() { - if (m_rtcctl & RTCCTL_ENABLE) + constexpr u16 LXMAX_MASK = 0x03f0; + return LXMAX_MASK; +} + +u32 mc68ez328_device::lcd_get_line_word_count() +{ + const u32 pixels_per_word = 16 / lcd_get_panel_bit_size(); + return ((m_lxmax & lcd_get_lxmax_mask()) + 16) / pixels_per_word; +} + +attotime mc68ez328_device::lcd_get_line_rate() +{ + const u32 pixclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_PIXCLK_SEL) >> PLLCR_PIXCLK_SHIFT]; + const u32 pxcd = (m_lpxcd & LPXCD_MASK) + 1; + const u32 lrra_factor = 6 + m_lrra + (m_lxmax & lcd_get_lxmax_mask()) + 16; + return attotime::from_ticks(lrra_factor * pxcd * pixclk_divisor, clock()); +} + +u8 mc68ez328_device::lcd_get_panel_bit_size() +{ + constexpr u8 BIT_WIDTHS[4] = { 1, 2, 4, 1 }; + return BIT_WIDTHS[(m_lpicf & LPICF_PBSIZ) >> LPICF_PBSIZ_SHIFT]; +} + +attotime mc68ez328_device::get_pixclk_rate() +{ + u32 divisor = VCO_DIVISORS[(m_pllcr & PLLCR_PIXCLK_SEL) >> PLLCR_PIXCLK_SHIFT]; + return attotime::from_ticks((m_lpxcd & LPXCD_MASK) + 1, clock() / divisor); +} + +void mc68ez328_device::lpicf_w(u8 data) // 0xa20 +{ + static const char *const PBSIZ_NAMES[4] = { "1-bit", "2-bit", "4-bit", "Invalid" }; + static const char *const GS_NAMES[4] = { "Monochrome", "4-level Grayscale", "16-level Grayscale", "Invalid" }; + LOGMASKED(LOG_LCD, "%s: lpicf_w: LPICF = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_LCD, "%s: Grayscale Mode: %d\n", machine().describe_context(), GS_NAMES[data & LPICF_GS]); + LOGMASKED(LOG_LCD, "%s: Bus Size: %s\n", machine().describe_context(), PBSIZ_NAMES[(data & LPICF_PBSIZ) >> LPICF_PBSIZ_SHIFT]); + m_lpicf = data; +} + +void mc68ez328_device::lckcon_w(u8 data) // 0xa27 +{ + LOGMASKED(LOG_LCD, "%s: lckcon_w: LCKCON = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_LCD, "%s: LCDC Enable: %d\n", machine().describe_context(), BIT(data, LCKCON_LCDON_BIT)); + LOGMASKED(LOG_LCD, "%s: Display Wait States: %d\n", machine().describe_context(), ((data & LCKCON_DWS) >> LCKCON_DWS_SHIFT) + 1); + LOGMASKED(LOG_LCD, "%s: Bus Width: %d\n", machine().describe_context(), BIT(data, LCKCON_DWIDTH_BIT) ? 8 : 16); + + const u16 old = m_lckcon; + m_lckcon = data; + + if (BIT(old, LCKCON_LCDON_BIT) && !BIT(m_lckcon, LCKCON_LCDON_BIT)) { - uint32_t set_int = 0; + m_lcd_scan->adjust(attotime::never); + } + else if (!BIT(old, LCKCON_LCDON_BIT) && BIT(m_lckcon, LCKCON_LCDON_BIT)) + { + const u32 sysclk_divisor = VCO_DIVISORS[(m_pllcr & PLLCR_SYSCLK_SEL) >> PLLCR_SYSCLK_SHIFT]; + attotime lcd_dma_duration = attotime::from_ticks(m_llbar, clock() / sysclk_divisor); + attotime lcd_scan_duration = get_pixclk_rate() * (m_lxmax + 1); + attotime lcd_frame_duration = (lcd_scan_duration + lcd_dma_duration) * (m_lymax + 1); + m_lcd_info_changed_cb(lcd_frame_duration.as_hz(), m_lxmax + 1, m_lymax + 1); - m_hmsr++; + m_lcd_scan->adjust(attotime::never); + m_lcd_sysmem_ptr = m_lssa; + fill_lcd_dma_buffer(); + } +} - if (m_rtcienr & RTCINT_SECOND) +void mc68ez328_device::lrra_w(u8 data) // 0xa29 +{ + LOGMASKED(LOG_LCD, "%s: lrra_w: LRRA = %02x\n", machine().describe_context(), data); + m_lrra = data; +} + +u8 mc68ez328_device::lrra_r() // 0xa29 +{ + LOGMASKED(LOG_LCD, "%s: lrra_r: LRRA: %02x\n", machine().describe_context(), m_lrra); + return m_lrra; +} + +void mc68ez328_device::pwmr_w(offs_t offset, u16 data, u16 mem_mask) // 0xa36 +{ + LOGMASKED(LOG_LCD, "%s: pwmr_w: PWMR = %04x\n", machine().describe_context(), data); + m_pwmr = data; +} + +u16 mc68ez328_device::pwmr_r() // 0xa36 +{ + LOGMASKED(LOG_LCD, "%s: pwmr_r: PWMR: %04x\n", machine().describe_context(), m_lrra); + return m_pwmr; +} + + +//------------------------------------------------- +// RTC/alarm hardware - Standard MC68328 +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(mc68328_base_device::rtc_tick) +{ + if (BIT(m_rtcctl, RTCCTL_ENABLE_BIT)) + { + const bool rtc_int_was_active = rtc_int_is_active(); + + rtc_advance_seconds(); + + if (rtc_get_alarm_match()) { - set_int = 1; - m_rtcisr |= RTCINT_SECOND; + m_rtcisr |= RTCINT_ALARM; } - if ((m_hmsr & 0x0000003f) == 0x0000003c) - { - m_hmsr &= 0xffffffc0; - m_hmsr += 0x00010000; - - if (m_rtcienr & RTCINT_MINUTE) - { - set_int = 1; - m_rtcisr |= RTCINT_MINUTE; - } - - if ((m_hmsr & 0x003f0000) == 0x003c0000) - { - m_hmsr &= 0xffc0ffff; - m_hmsr += 0x0100000; - - if ((m_hmsr & 0x1f000000) == 0x18000000) - { - m_hmsr &= 0xe0ffffff; - - if (m_rtcienr & RTCINT_DAY) - { - set_int = 1; - m_rtcisr |= RTCINT_DAY; - } - } - } - - if (m_stpwtch != 0x003f) - { - m_stpwtch--; - m_stpwtch &= 0x003f; - - if (m_stpwtch == 0x003f) - { - if (m_rtcienr & RTCINT_STOPWATCH) - { - set_int = 1; - m_rtcisr |= RTCINT_STOPWATCH; - } - } - } - } - - if (m_hmsr == m_alarm) - { - if (m_rtcienr & RTCINT_ALARM) - { - set_int = 1; - m_rtcisr |= RTCINT_STOPWATCH; - } - } - - if (set_int) + if (!rtc_int_was_active && rtc_int_is_active()) { set_interrupt_line(INT_RTC, 1); } - else - { - set_interrupt_line(INT_RTC, 0); - } } } -void mc68328_device::hmsr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xb00 +void mc68328_base_device::rtc_advance_seconds() { - LOGMASKED(LOG_RTC, "hmsr_msw_w: HMSR(MSW) = %04x\n", data); + m_hmsr++; + + if (m_rtcienr & RTCINT_SECOND) + { + m_rtcisr |= RTCINT_SECOND; + } + + if ((m_hmsr & RTCHMSR_SECONDS) == 0x0000003c) + { + m_hmsr &= ~RTCHMSR_SECONDS; + m_hmsr += 1 << RTCHMSR_MINUTES_SHIFT; + + if (m_rtcienr & RTCINT_MINUTE) + { + m_rtcisr |= RTCINT_MINUTE; + } + + if ((m_hmsr & RTCHMSR_MINUTES) == 0x003c0000) + { + m_hmsr &= ~RTCHMSR_MINUTES; + m_hmsr += 1 << RTCHMSR_HOURS_SHIFT; + + if ((m_hmsr & RTCHMSR_HOURS) == 0x18000000) + { + m_hmsr &= ~RTCHMSR_HOURS; + + if (m_rtcienr & RTCINT_DAY) + { + m_rtcisr |= RTCINT_DAY; + } + } + } + + if (m_stpwtch != RTCSTPWTCH_MASK) + { + m_stpwtch--; + m_stpwtch &= RTCSTPWTCH_MASK; + + if (m_stpwtch == RTCSTPWTCH_MASK) + { + m_rtcisr |= RTCINT_STOPWATCH; + } + } + } +} + +bool mc68328_device::rtc_int_is_active() +{ + return m_rtcisr & m_rtcienr; +} + +u16 mc68328_device::rtc_get_int_mask() +{ + constexpr u16 RTCIENR_MASK = 0x001f; + return RTCIENR_MASK; +} + +bool mc68328_device::rtc_get_alarm_match() +{ + return m_hmsr == m_alarm; +} + +void mc68328_base_device::hmsr_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0xb00 +{ + LOGMASKED(LOG_RTC, "%s: hmsr_msw_w: HMSR(MSW) = %04x\n", machine().describe_context(), data); m_hmsr &= ~(mem_mask << 16); m_hmsr |= (data & mem_mask) << 16; - m_hmsr &= 0x1f3f003f; + m_hmsr &= (RTCHMSR_SECONDS | RTCHMSR_MINUTES | RTCHMSR_HOURS); } -uint16_t mc68328_device::hmsr_msw_r() // 0xb00 +u16 mc68328_base_device::hmsr_msw_r() // 0xb00 { - LOGMASKED(LOG_RTC, "hmsr_msw_r: HMSR(MSW): %04x\n", (uint16_t)(m_hmsr >> 16)); - return (uint16_t)(m_hmsr >> 16); + LOGMASKED(LOG_RTC, "%s: hmsr_msw_r: HMSR(MSW): %04x\n", machine().describe_context(), (u16)(m_hmsr >> 16)); + return (u16)(m_hmsr >> 16); } -void mc68328_device::hmsr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xb02 +void mc68328_base_device::hmsr_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0xb02 { - LOGMASKED(LOG_RTC, "hmsr_lsw_w: HMSR(LSW) = %04x\n", data); + LOGMASKED(LOG_RTC, "%s: hmsr_lsw_w: HMSR(LSW) = %04x\n", machine().describe_context(), data); m_hmsr &= 0xffff0000 | (~mem_mask); m_hmsr |= data & mem_mask; - m_hmsr &= 0x1f3f003f; + m_hmsr &= (RTCHMSR_SECONDS | RTCHMSR_MINUTES | RTCHMSR_HOURS); } -uint16_t mc68328_device::hmsr_lsw_r() // 0xb02 +u16 mc68328_base_device::hmsr_lsw_r() // 0xb02 { - LOGMASKED(LOG_RTC, "hmsr_lsw_r: HMSR(LSW): %04x\n", (uint16_t)m_hmsr); - return (uint16_t)m_hmsr; + LOGMASKED(LOG_RTC, "%s: hmsr_lsw_r: HMSR(LSW): %04x\n", machine().describe_context(), (u16)m_hmsr); + return (u16)m_hmsr; } -void mc68328_device::alarm_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xb04 +void mc68328_base_device::alarm_msw_w(offs_t offset, u16 data, u16 mem_mask) // 0xb04 { - LOGMASKED(LOG_RTC, "alarm_msw_w: ALARM(MSW) = %04x\n", data); + LOGMASKED(LOG_RTC, "%s: alarm_msw_w: ALARM(MSW) = %04x\n", machine().describe_context(), data); m_alarm &= ~(mem_mask << 16); m_alarm |= (data & mem_mask) << 16; - m_alarm &= 0x1f3f003f; + m_alarm &= (RTCHMSR_SECONDS | RTCHMSR_MINUTES | RTCHMSR_HOURS); } -uint16_t mc68328_device::alarm_msw_r() // 0xb04 +u16 mc68328_base_device::alarm_msw_r() // 0xb04 { - LOGMASKED(LOG_RTC, "alarm_msw_r: ALARM(MSW): %04x\n", (uint16_t)(m_alarm >> 16)); - return (uint16_t)(m_alarm >> 16); + LOGMASKED(LOG_RTC, "%s: alarm_msw_r: ALARM(MSW): %04x\n", machine().describe_context(), (u16)(m_alarm >> 16)); + return (u16)(m_alarm >> 16); } -void mc68328_device::alarm_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xb06 +void mc68328_base_device::alarm_lsw_w(offs_t offset, u16 data, u16 mem_mask) // 0xb06 { - LOGMASKED(LOG_RTC, "alarm_lsw_w: ALARM(LSW) = %04x\n", data); + LOGMASKED(LOG_RTC, "%s: alarm_lsw_w: ALARM(LSW) = %04x\n", machine().describe_context(), data); m_alarm &= 0xffff0000 | (~mem_mask); m_alarm |= data & mem_mask; - m_alarm &= 0x1f3f003f; + m_alarm &= (RTCHMSR_SECONDS | RTCHMSR_MINUTES | RTCHMSR_HOURS); } -uint16_t mc68328_device::alarm_lsw_r() // 0xb06 +u16 mc68328_base_device::alarm_lsw_r() // 0xb06 { - LOGMASKED(LOG_RTC, "alarm_lsw_r: ALARM(LSW): %04x\n", (uint16_t)m_alarm); - return (uint16_t)m_alarm; + LOGMASKED(LOG_RTC, "%s: alarm_lsw_r: ALARM(LSW): %04x\n", machine().describe_context(), (u16)m_alarm); + return (u16)m_alarm; } -void mc68328_device::rtcctl_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xb0c +void mc68328_base_device::rtcctl_w(offs_t offset, u16 data, u16 mem_mask) // 0xb0c { - LOGMASKED(LOG_RTC, "rtcctl_w: RTCCTL = %04x\n", data); - m_rtcctl = data & 0x00a0; + LOGMASKED(LOG_RTC, "%s: rtcctl_w: RTCCTL = %04x\n", machine().describe_context(), data); + m_rtcctl = data & RTCCTL_MASK; } -uint16_t mc68328_device::rtcctl_r() // 0xb0c +u16 mc68328_base_device::rtcctl_r() // 0xb0c { - LOGMASKED(LOG_RTC, "rtcctl_r: RTCCTL: %04x\n", m_rtcctl); + LOGMASKED(LOG_RTC, "%s: rtcctl_r: RTCCTL: %04x\n", machine().describe_context(), m_rtcctl); return m_rtcctl; } -void mc68328_device::rtcisr_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xb0e +void mc68328_base_device::rtcisr_w(offs_t offset, u16 data, u16 mem_mask) // 0xb0e { - LOGMASKED(LOG_RTC, "rtcisr_w: RTCISR = %04x\n", data); + const bool rtc_int_was_active = rtc_int_is_active(); + LOGMASKED(LOG_RTC, "%s: rtcisr_w: RTCISR = %04x\n", machine().describe_context(), data); m_rtcisr &= ~data; - if (m_rtcisr == 0) + + if (rtc_int_was_active && !rtc_int_is_active()) { set_interrupt_line(INT_RTC, 0); } } -uint16_t mc68328_device::rtcisr_r() // 0xb0e +u16 mc68328_base_device::rtcisr_r() // 0xb0e { - LOGMASKED(LOG_RTC, "rtcisr_r: RTCISR: %04x\n", m_rtcisr); + LOGMASKED(LOG_RTC, "%s: rtcisr_r: RTCISR: %04x\n", machine().describe_context(), m_rtcisr); return m_rtcisr; } -void mc68328_device::rtcienr_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xb10 +void mc68328_base_device::rtcienr_w(offs_t offset, u16 data, u16 mem_mask) // 0xb10 { - LOGMASKED(LOG_RTC, "rtcienr_w: RTCIENR = %04x\n", data); - m_rtcienr = data & 0x001f; + const bool rtc_int_was_active = rtc_int_is_active(); + + LOGMASKED(LOG_RTC, "%s: rtcienr_w: RTCIENR = %04x\n", machine().describe_context(), data); + m_rtcienr = data & rtc_get_int_mask(); + + const bool is_active = rtc_int_is_active(); + if (rtc_int_was_active != is_active) + { + set_interrupt_line(INT_RTC, (int)is_active); + } } -uint16_t mc68328_device::rtcienr_r() // 0xb10 +u16 mc68328_base_device::rtcienr_r() // 0xb10 { - LOGMASKED(LOG_RTC, "rtcienr_r: RTCIENR: %04x\n", m_rtcienr); + LOGMASKED(LOG_RTC, "%s: rtcienr_r: RTCIENR: %04x\n", machine().describe_context(), m_rtcienr); return m_rtcienr; } -void mc68328_device::stpwtch_w(offs_t offset, uint16_t data, uint16_t mem_mask) // 0xb12 +void mc68328_base_device::stpwtch_w(offs_t offset, u16 data, u16 mem_mask) // 0xb12 { - LOGMASKED(LOG_RTC, "stpwtch_w: STPWTCH = %04x\n", data); + LOGMASKED(LOG_RTC, "%s: stpwtch_w: STPWTCH = %04x\n", machine().describe_context(), data); m_stpwtch = data & 0x003f; } -uint16_t mc68328_device::stpwtch_r() // 0xb12 +u16 mc68328_base_device::stpwtch_r() // 0xb12 { - LOGMASKED(LOG_RTC, "stpwtch_r: STPWTCH: %04x\n", m_stpwtch); + LOGMASKED(LOG_RTC, "%s: stpwtch_r: STPWTCH: %04x\n", machine().describe_context(), m_stpwtch); return m_stpwtch; } + + +//------------------------------------------------- +// RTC/alarm hardware - EZ variant +//------------------------------------------------- + +bool mc68ez328_device::rtc_int_is_active() +{ + return (m_rtcisr & m_rtcienr) & RTCINT_RTCIRQ_MASK; +} + +void mc68ez328_device::rtc_advance_seconds() +{ + LOGMASKED(LOG_RTC, "EZ advancing seconds!\n"); + const u32 old_hmsr = m_hmsr; + mc68328_base_device::rtc_advance_seconds(); + + if ((old_hmsr & RTCHMSR_HOURS) != (m_hmsr & RTCHMSR_HOURS)) + { + m_rtcisr |= RTCINT_HOUR; + + if (((m_hmsr & RTCHMSR_HOURS) >> RTCHMSR_HOURS_SHIFT) == 0) + { + m_dayr = (m_dayr + 1) & RTC_DAYS_MASK; + } + } + + if (BIT(m_watchdog, WATCHDOG_EN_BIT)) + { + m_watchdog += 1 << WATCHDOG_CNT_SHIFT; + m_watchdog &= (WATCHDOG_MASK | WATCHDOG_CNT_MASK); + if (((m_watchdog & WATCHDOG_CNT_MASK) >> WATCHDOG_CNT_SHIFT) == 2) + { + if (BIT(m_watchdog, WATCHDOG_ISEL_BIT)) + { + set_interrupt_line(INT_WDT, 1); + } + else + { + reset(); + } + } + } +} + +TIMER_CALLBACK_MEMBER(mc68ez328_device::sample_timer_tick) +{ + if (!BIT(m_rtcctl, RTCCTL_ENABLE_BIT) && !BIT(m_watchdog, WATCHDOG_EN_BIT)) + { + return; + } + + const u8 old_sam_cnt = m_sam_cnt; + m_sam_cnt++; + + const bool rtc_int_was_active = rtc_int_is_active(); + + m_rtcisr |= RTCINT_SAM0; + for (u8 i = 0; i < 7; i++) + { + if (BIT(old_sam_cnt, i) && !BIT(m_sam_cnt, i)) + { + m_rtcisr |= RTCINT_SAM1 << i; + } + } + + if (!rtc_int_was_active && rtc_int_is_active()) + { + set_interrupt_line(INT_RTC, 1); + } +} + +u16 mc68ez328_device::rtc_get_int_mask() +{ + constexpr u16 RTCIENR_MASK = 0xff3f; + return RTCIENR_MASK; +} + +bool mc68ez328_device::rtc_get_alarm_match() +{ + return m_hmsr == m_alarm && m_dayr == m_dayalarm; +} + +void mc68ez328_device::watchdog_w(offs_t offset, u16 data, u16 mem_mask) +{ + LOGMASKED(LOG_RTC, "%s: watchdog_w: WATCHDOG = %04x\n", machine().describe_context(), data); + const u16 old_watchdog = m_watchdog; + m_watchdog = data & WATCHDOG_MASK; + if (BIT(data, WATCHDOG_INTF_BIT)) + { + m_watchdog &= ~WATCHDOG_INTF; + if (BIT(old_watchdog, WATCHDOG_INTF_BIT)) + { + set_interrupt_line(INT_WDT, 0); + } + } +} + +u16 mc68ez328_device::watchdog_r() +{ + LOGMASKED(LOG_RTC, "%s: watchdog_r: WATCHDOG: %04x\n", machine().describe_context(), m_watchdog); + return m_watchdog; +} + +void mc68ez328_device::rtcctl_w(offs_t offset, u16 data, u16 mem_mask) // 0xb0c +{ + const u16 old_rtcctl = m_rtcctl; + mc68328_base_device::rtcctl_w(offset, data, mem_mask); + + if (BIT(old_rtcctl, RTCCTL_38_4_BIT) != BIT(m_rtcctl, RTCCTL_38_4_BIT)) + { + const u32 frequency = BIT(m_rtcctl, RTCCTL_38_4_BIT) ? 38400 : 32768; + m_rtc_sample_timer->adjust(attotime::from_ticks(64, frequency), 0, attotime::from_ticks(64, frequency)); + } +} + +void mc68ez328_device::dayr_w(offs_t offset, u16 data, u16 mem_mask) // 0xb1a +{ + LOGMASKED(LOG_RTC, "%s: dayr_w: DAYR = %04x\n", machine().describe_context(), data); + m_dayr = data & RTC_DAYS_MASK; +} + +void mc68ez328_device::dayalarm_w(offs_t offset, u16 data, u16 mem_mask) // 0xb1c +{ + LOGMASKED(LOG_RTC, "%s: dayalarm_w: DAYALARM = %04x\n", machine().describe_context(), data); + m_dayalarm = data & RTC_DAYS_MASK; +} + +u16 mc68ez328_device::dayr_r() // 0xb1a +{ + LOGMASKED(LOG_RTC, "%s: dayalarm_r: DAYR: %04x\n", machine().describe_context(), m_dayr); + return m_dayr; +} + +u16 mc68ez328_device::dayalarm_r() // 0xb1c +{ + LOGMASKED(LOG_RTC, "%s: dayalarm_r: DAYALARM: %04x\n", machine().describe_context(), m_dayalarm); + return m_dayalarm; +} diff --git a/src/devices/machine/mc68328.h b/src/devices/machine/mc68328.h index 4dd02618088..515c87549f1 100644 --- a/src/devices/machine/mc68328.h +++ b/src/devices/machine/mc68328.h @@ -90,45 +90,40 @@ #include "cpu/m68000/m68000.h" -class mc68328_device : public m68000_device +class mc68328_base_device : public m68000_device { public: typedef device_delegate lcd_info_changed_delegate; - mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + template auto out_port_a() { return m_out_port_a_cb[Line].bind(); } + template auto out_port_b() { return m_out_port_b_cb[Line].bind(); } + template auto out_port_c() { return m_out_port_c_cb[Line].bind(); } + template auto out_port_d() { return m_out_port_d_cb[Line].bind(); } + template auto out_port_e() { return m_out_port_e_cb[Line].bind(); } + template auto out_port_f() { return m_out_port_f_cb[Line].bind(); } + template auto out_port_g() { return m_out_port_g_cb[Line].bind(); } + template auto in_port_a() { return m_in_port_a_cb[Line].bind(); } + template auto in_port_b() { return m_in_port_b_cb[Line].bind(); } + template auto in_port_c() { return m_in_port_c_cb[Line].bind(); } + template auto in_port_d() { return m_in_port_d_cb[Line].bind(); } + template auto in_port_e() { return m_in_port_e_cb[Line].bind(); } + template auto in_port_f() { return m_in_port_f_cb[Line].bind(); } + template auto in_port_g() { return m_in_port_g_cb[Line].bind(); } + + void port_d_in_w(int state, int bit); - auto out_port_a() { return m_out_port_a_cb.bind(); } - auto out_port_b() { return m_out_port_b_cb.bind(); } - auto out_port_c() { return m_out_port_c_cb.bind(); } - auto out_port_d() { return m_out_port_d_cb.bind(); } - auto out_port_e() { return m_out_port_e_cb.bind(); } - auto out_port_f() { return m_out_port_f_cb.bind(); } - auto out_port_g() { return m_out_port_g_cb.bind(); } - auto out_port_j() { return m_out_port_j_cb.bind(); } - auto out_port_k() { return m_out_port_k_cb.bind(); } - auto out_port_m() { return m_out_port_m_cb.bind(); } - auto in_port_a() { return m_in_port_a_cb.bind(); } - auto in_port_b() { return m_in_port_b_cb.bind(); } - auto in_port_c() { return m_in_port_c_cb.bind(); } - auto in_port_d() { return m_in_port_d_cb.bind(); } - auto in_port_e() { return m_in_port_e_cb.bind(); } - auto in_port_f() { return m_in_port_f_cb.bind(); } - auto in_port_g() { return m_in_port_g_cb.bind(); } - auto in_port_j() { return m_in_port_j_cb.bind(); } - auto in_port_k() { return m_in_port_k_cb.bind(); } - auto in_port_m() { return m_in_port_m_cb.bind(); } - auto out_pwm() { return m_out_pwm_cb.bind(); } auto out_spim() { return m_out_spim_cb.bind(); } auto in_spim() { return m_in_spim_cb.bind(); } - DECLARE_WRITE_LINE_MEMBER(set_penirq_line); - void set_port_d_lines(uint8_t state, int bit); + auto out_pwm() { return m_out_pwm_cb.bind(); } auto out_flm() { return m_out_flm_cb.bind(); } auto out_llp() { return m_out_llp_cb.bind(); } auto out_lsclk() { return m_out_lsclk_cb.bind(); } auto out_ld() { return m_out_ld_cb.bind(); } + DECLARE_WRITE_LINE_MEMBER(irq5_w); + template std::enable_if_t::value> set_lcd_info_changed(T &&callback, const char *name) { @@ -136,12 +131,14 @@ public: } protected: + mc68328_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 addr_bits, address_map_constructor internal_map_ctor); + // device-level overrides virtual void device_resolve_objects() override; virtual void device_start() override; virtual void device_reset() override; - enum : uint8_t + enum : u8 { SCR_WDTH8 = 0x01, SCR_DMAP = 0x04, @@ -158,13 +155,6 @@ protected: BLKC_BD = 0x7f, BLKC_BKEN = 0x80, - LPICF_GRAYSCALE_BIT = 0, - LPICF_PBSIZ = 0x06, - LPICF_PBSIZ_1 = 0x00, - LPICF_PBSIZ_2 = 0x02, - LPICF_PBSIZ_4 = 0x04, - LPICF_PBSIZ_INVALID = 0x06, - LPOLCF_PIXPOL = 0x01, LPOLCF_LPPOL_BIT = 1, LPOLCF_FLMPOL_BIT = 2, @@ -174,16 +164,6 @@ protected: LPXCD_MASK = 0x3f, - LCKCON_PCDS_BIT = 0, - LCKCON_DWIDTH = 0x02, - LCKCON_WS = 0x30, - LCKCON_WS_1 = 0x00, - LCKCON_WS_2 = 0x10, - LCKCON_WS_3 = 0x20, - LCKCON_WS_4 = 0x30, - LCKCON_DMA16 = 0x40, - LCKCON_LCDON_BIT = 7, - LBAR_MASK = 0x7f, LPOSR_POS = 0x07, @@ -193,7 +173,7 @@ protected: LFRCM_XMOD = 0xf0, }; - enum : uint16_t + enum : u16 { GRPBASE_VALID = 0x0001, GRPBASE_BASE_ADDR = 0xfff0, @@ -228,25 +208,26 @@ protected: PLLFSR_PROT = 0x4000, PLLFSR_CLK32 = 0x8000, - ICR_POL6 = 0x0100, - ICR_POL3 = 0x0200, - ICR_POL2 = 0x0400, - ICR_POL1 = 0x0800, - ICR_ET6 = 0x1000, - ICR_ET3 = 0x2000, - ICR_ET2 = 0x4000, - ICR_ET1 = 0x8000, + ICR_ET6 = 0x0100, + ICR_ET3 = 0x0200, + ICR_ET2 = 0x0400, + ICR_ET1 = 0x0800, + ICR_POL6 = 0x1000, + ICR_POL3 = 0x2000, + ICR_POL2 = 0x4000, + ICR_POL1 = 0x8000, PWMC_CLKSEL = 0x0007, - PWMC_PWMEN = 0x0010, + PWMC_EN = 0x0010, PWMC_POL = 0x0040, PWMC_PIN = 0x0080, PWMC_LOAD = 0x0100, - PWMC_IRQEN = 0x4000, - PWMC_PWMIRQ = 0x8000, + PWMC_IRQ_EN = 0x4000, + PWMC_IRQ = 0x8000, TCTL_TEN = 0x0001, TCTL_TEN_ENABLE = 0x0001, + TCTL_TEN_BIT = 0, TCTL_CLKSOURCE = 0x000e, TCTL_CLKSOURCE_STOP = 0x0000, TCTL_CLKSOURCE_SYSCLK = 0x0002, @@ -273,11 +254,6 @@ protected: TSTAT_COMP = 0x0001, TSTAT_CAPT = 0x0002, - WCTLR_WDRST = 0x0008, - WCTLR_LOCK = 0x0004, - WCTLR_FI = 0x0002, - WCTLR_WDEN = 0x0001, - SPIS_SPISEN = 0x0100, SPIS_POL = 0x0200, SPIS_PHA = 0x0400, @@ -375,8 +351,9 @@ protected: LGPMR_PAL0 = 0x0700, LGPMR_PAL1 = 0x7000, - RTCCTL_38_4 = 0x0020, - RTCCTL_ENABLE = 0x0080, + RTCCTL_38_4_BIT = 5, + RTCCTL_ENABLE_BIT = 7, + RTCCTL_MASK = 0x00a0, RTCINT_STOPWATCH = 0x0001, RTCINT_MINUTE = 0x0002, @@ -387,7 +364,7 @@ protected: RTCSTPWTCH_MASK = 0x003f, }; - enum : uint32_t + enum : u32 { CSAB_WAIT = 0x00000007, CSAB_RO = 0x00000008, @@ -401,513 +378,425 @@ protected: CSCD_BSW = 0x00010000, CSCD_COMPARE = 0xfff00000, - INT_SPIM = 0x00000001, - INT_TIMER2 = 0x00000002, - INT_UART = 0x00000004, - INT_WDT = 0x00000008, - INT_RTC = 0x00000010, - INT_RESERVED = 0x00000020, - INT_KB = 0x00000040, - INT_PWM = 0x00000080, - INT_INT0 = 0x00000100, - INT_INT1 = 0x00000200, - INT_INT2 = 0x00000400, - INT_INT3 = 0x00000800, - INT_INT4 = 0x00001000, - INT_INT5 = 0x00002000, - INT_INT6 = 0x00004000, - INT_INT7 = 0x00008000, - INT_KBDINTS = 0x0000ff00, - INT_IRQ1 = 0x00010000, - INT_IRQ2 = 0x00020000, - INT_IRQ3 = 0x00040000, - INT_IRQ6 = 0x00080000, - INT_PEN = 0x00100000, - INT_SPIS = 0x00200000, - INT_TIMER1 = 0x00400000, - INT_IRQ7 = 0x00800000, - - INT_M68K_LINE1 = INT_IRQ1, - INT_M68K_LINE2 = INT_IRQ2, - INT_M68K_LINE3 = INT_IRQ3, - INT_M68K_LINE4 = INT_INT0 | INT_INT1 | INT_INT2 | INT_INT3 | INT_INT4 | INT_INT5 | INT_INT6 | INT_INT7 | - INT_PWM | INT_KB | INT_RTC | INT_WDT | INT_UART | INT_TIMER2 | INT_SPIM, - INT_M68K_LINE5 = INT_PEN, - INT_M68K_LINE6 = INT_IRQ6 | INT_TIMER1 | INT_SPIS, - INT_M68K_LINE7 = INT_IRQ7, - INT_M68K_LINE67 = INT_M68K_LINE6 | INT_M68K_LINE7, - INT_M68K_LINE567 = INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7, - INT_M68K_LINE4567 = INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7, - INT_M68K_LINE34567 = INT_M68K_LINE3 | INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7, - INT_M68K_LINE234567 = INT_M68K_LINE2 | INT_M68K_LINE3 | INT_M68K_LINE4 | INT_M68K_LINE5 | INT_M68K_LINE6 | INT_M68K_LINE7, - - INT_IRQ1_SHIFT = 0x00000001, - INT_IRQ2_SHIFT = 0x00000002, - INT_IRQ3_SHIFT = 0x00000004, - INT_IRQ6_SHIFT = 0x00000008, - INT_PEN_SHIFT = 0x00000010, - INT_SPIS_SHIFT = 0x00000020, - INT_TIMER1_SHIFT = 0x00000040, - INT_IRQ7_SHIFT = 0x00000080, + INT_SPIM = 0, + INT_SPIM_MASK = (1 << INT_SPIM), + INT_TIMER2 = 1, + INT_TIMER2_MASK = (1 << INT_TIMER2), + INT_UART = 2, + INT_UART_MASK = (1 << INT_UART), + INT_WDT = 3, + INT_WDT_MASK = (1 << INT_WDT), + INT_RTC = 4, + INT_RTC_MASK = (1 << INT_RTC), + INT_KB = 6, + INT_KB_MASK = (1 << INT_KB), + INT_PWM = 7, + INT_PWM_MASK = (1 << INT_PWM), + INT_INT0 = 8, + INT_INT0_MASK = (1 << INT_INT0), + INT_INT1 = 9, + INT_INT1_MASK = (1 << INT_INT1), + INT_INT2 = 10, + INT_INT2_MASK = (1 << INT_INT2), + INT_INT3 = 11, + INT_INT3_MASK = (1 << INT_INT3), + INT_INT4 = 12, + INT_INT4_MASK = (1 << INT_INT4), + INT_INT5 = 13, + INT_INT5_MASK = (1 << INT_INT5), + INT_INT6 = 14, + INT_INT6_MASK = (1 << INT_INT6), + INT_INT7 = 15, + INT_INT7_MASK = (1 << INT_INT7), + INT_KBDINTS = 8, + INT_KBDINTS_MASK = (1 << INT_KBDINTS), + INT_IRQ1 = 16, + INT_IRQ1_MASK = (1 << INT_IRQ1), + INT_IRQ2 = 17, + INT_IRQ2_MASK = (1 << INT_IRQ2), + INT_IRQ3 = 18, + INT_IRQ3_MASK = (1 << INT_IRQ3), + INT_IRQ6 = 19, + INT_IRQ6_MASK = (1 << INT_IRQ6), + INT_IRQ5 = 20, + INT_IRQ5_MASK = (1 << INT_IRQ5), + INT_SPIS = 21, + INT_SPIS_MASK = (1 << INT_SPIS), + INT_TIMER1 = 22, + INT_TIMER1_MASK = (1 << INT_TIMER1), + INT_IRQ7 = 23, + INT_IRQ7_MASK = (1 << INT_IRQ7), RTCHMSR_SECONDS = 0x0000003f, + RTCHMSR_SECONDS_SHIFT = 0, RTCHMSR_MINUTES = 0x003f0000, + RTCHMSR_MINUTES_SHIFT = 16, RTCHMSR_HOURS = 0x1f000000, + RTCHMSR_HOURS_SHIFT = 24, }; - void scr_w(uint8_t data); // 0x000 + void scr_w(u8 data); - void grpbasea_w(uint16_t data); // 0x100 - void grpbaseb_w(uint16_t data); // 0x102 - void grpbasec_w(uint16_t data); // 0x104 - void grpbased_w(uint16_t data); // 0x106 - void grpmaska_w(uint16_t data); // 0x108 - void grpmaskb_w(uint16_t data); // 0x10a - void grpmaskc_w(uint16_t data); // 0x10c - void grpmaskd_w(uint16_t data); // 0x10e - template void csa_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x110, 0x114, 0x118, 0x11c - template void csa_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x112, 0x116, 0x11a, 0x11e - template void csb_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x120, 0x124, 0x128, 0x12c - template void csb_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x122, 0x126, 0x12a, 0x12e - template void csc_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x130, 0x134, 0x138, 0x13c - template void csc_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x132, 0x136, 0x13a, 0x13e - template void csd_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x140, 0x144, 0x148, 0x14c - template void csd_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x142, 0x146, 0x14a, 0x14e + void grpbasea_w(u16 data); + void grpbaseb_w(u16 data); + void grpbasec_w(u16 data); + void grpbased_w(u16 data); - void pllcr_w(uint16_t data); // 0x200 - void pllfsr_w(uint16_t data); // 0x202 - void pctlr_w(uint8_t data); // 0x207 - void ivr_w(uint8_t data); // 0x300 - void icr_w(uint8_t data); // 0x302 - void imr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x304 - void imr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x306 - void iwr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x308 - void iwr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x30a - void isr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x30c - void isr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x30e - void ipr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x310 - void ipr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0x312 + void pllcr_w(u16 data); + void pllfsr_w(u16 data); + void pctlr_w(u8 data); + void ivr_w(u8 data); + void icr_w(u8 data); + void imr_msw_w(offs_t offset, u16 data, u16 mem_mask); + void imr_lsw_w(offs_t offset, u16 data, u16 mem_mask); + void isr_msw_w(offs_t offset, u16 data, u16 mem_mask); + void isr_lsw_w(offs_t offset, u16 data, u16 mem_mask); + void ipr_msw_w(offs_t offset, u16 data, u16 mem_mask); + void ipr_lsw_w(offs_t offset, u16 data, u16 mem_mask); - void padir_w(uint8_t data); // 0x400 - void padata_w(uint8_t data); // 0x401 - void pasel_w(uint8_t data); // 0x403 - void pbdir_w(uint8_t data); // 0x408 - void pbdata_w(uint8_t data); // 0x409 - void pbsel_w(uint8_t data); // 0x40b - void pcdir_w(uint8_t data); // 0x410 - void pcdata_w(uint8_t data); // 0x411 - void pcsel_w(uint8_t data); // 0x413 - void pddir_w(uint8_t data); // 0x418 - void pddata_w(uint8_t data); // 0x419 - void pdpuen_w(uint8_t data); // 0x41a - void pdpol_w(uint8_t data); // 0x41c - void pdirqen_w(uint8_t data); // 0x41d - void pdirqedge_w(uint8_t data); // 0x41f - void pedir_w(uint8_t data); // 0x420 - void pedata_w(uint8_t data); // 0x421 - void pepuen_w(uint8_t data); // 0x422 - void pesel_w(uint8_t data); // 0x423 - void pfdir_w(uint8_t data); // 0x428 - void pfdata_w(uint8_t data); // 0x429 - void pfpuen_w(uint8_t data); // 0x42a - void pfsel_w(uint8_t data); // 0x42b - void pgdir_w(uint8_t data); // 0x430 - void pgdata_w(uint8_t data); // 0x431 - void pgpuen_w(uint8_t data); // 0x432 - void pgsel_w(uint8_t data); // 0x433 - void pjdir_w(uint8_t data); // 0x438 - void pjdata_w(uint8_t data); // 0x439 - void pjsel_w(uint8_t data); // 0x43b - void pkdir_w(uint8_t data); // 0x440 - void pkdata_w(uint8_t data); // 0x441 - void pkpuen_w(uint8_t data); // 0x442 - void pksel_w(uint8_t data); // 0x443 - void pmdir_w(uint8_t data); // 0x448 - void pmdata_w(uint8_t data); // 0x449 - void pmpuen_w(uint8_t data); // 0x44a - void pmsel_w(uint8_t data); // 0x44b + void padir_w(u8 data); + void padata_w(u8 data); + void pbdir_w(u8 data); + void pbdata_w(u8 data); + void pbsel_w(u8 data); + void pcdir_w(u8 data); + void pcdata_w(u8 data); + void pcsel_w(u8 data); + void pddir_w(u8 data); + void pddata_w(u8 data); + void pdpuen_w(u8 data); + void pdpol_w(u8 data); + void pdirqen_w(u8 data); + void pdirqedge_w(u8 data); + void pedir_w(u8 data); + void pedata_w(u8 data); + void pepuen_w(u8 data); + void pesel_w(u8 data); + void pfdir_w(u8 data); + void pfdata_w(u8 data); + void pfpuen_w(u8 data); + void pfsel_w(u8 data); + void pgdir_w(u8 data); + void pgdata_w(u8 data); + void pgpuen_w(u8 data); + void pgsel_w(u8 data); - void pwmc_w(uint16_t data); // 0x500 - void pwmp_w(uint16_t data); // 0x502 - void pwmw_w(uint16_t data); // 0x504 - void pwmcnt_w(uint16_t data); // 0x506 + virtual void pwmc_w(u16 data) = 0; - template void tctl_w(uint16_t data); // 0x600, 0x60c - template void tprer_w(uint16_t data); // 0x602, 0x60e - template void tcmp_w(uint16_t data); // 0x604, 0x610 - template void tcr_w(uint16_t data); // 0x606, 0x612 - template void tcn_w(uint16_t data); // 0x608, 0x614 - template void tstat_w(uint16_t data); // 0x60a, 0x616 - void wctlr_w(uint16_t data); // 0x618 - void wcmpr_w(uint16_t data); // 0x61a - void wcn_w(uint16_t data); // 0x61c + template void tctl_w(u16 data); + template void tprer_w(u16 data); + template void tcmp_w(u16 data); + template void tcr_w(u16 data); + template void tcn_w(u16 data); + template void tstat_w(u16 data); - void spisr_w(uint16_t data); // 0x700 + void spimdata_w(u16 data); + void spimcont_w(u16 data); - void spimdata_w(uint16_t data); // 0x800 - void spimcont_w(uint16_t data); // 0x802 + void ustcnt_w(u16 data); + void ubaud_w(u16 data); + void urx_w(u16 data); + void utx_w(u16 data); + void umisc_w(u16 data); - void ustcnt_w(uint16_t data); // 0x900 - void ubaud_w(uint16_t data); // 0x902 - void urx_w(uint16_t data); // 0x904 - void utx_w(uint16_t data); // 0x906 - void umisc_w(uint16_t data); // 0x908 + void lssa_msw_w(offs_t offset, u16 data, u16 mem_mask); + void lssa_lsw_w(offs_t offset, u16 data, u16 mem_mask); + void lvpw_w(u8 data); + void lxmax_w(u16 data); + void lymax_w(u16 data); + void lcxp_w(u16 data); + void lcyp_w(u16 data); + void lcwch_w(u16 data); + void lblkc_w(u8 data); + virtual void lpicf_w(u8 data) = 0; + void lpolcf_w(u8 data); + void lacdrc_w(u8 data); + void lpxcd_w(u8 data); + virtual void lckcon_w(u8 data) = 0; + void lposr_w(u8 data); + void lfrcm_w(u8 data); - void lssa_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xa00 - void lssa_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xa02 - void lvpw_w(uint8_t data); // 0xa05 - void lxmax_w(uint16_t data); // 0xa08 - void lymax_w(uint16_t data); // 0xa0a - void lcxp_w(uint16_t data); // 0xa18 - void lcyp_w(uint16_t data); // 0xa1a - void lcwch_w(uint16_t data); // 0xa1c - void lblkc_w(uint8_t data); // 0xa1f - void lpicf_w(uint8_t data); // 0xa20 - void lpolcf_w(uint8_t data); // 0xa21 - void lacdrc_w(uint8_t data); // 0xa23 - void lpxcd_w(uint8_t data); // 0xa25 - void lckcon_w(uint8_t data); // 0xa27 - void llbar_w(uint8_t data); // 0xa29 - void lotcr_w(uint8_t data); // 0xa2b - void lposr_w(uint8_t data); // 0xa2d - void lfrcm_w(uint8_t data); // 0xa31 - void lgpmr_w(uint8_t data); // 0xa32 + void hmsr_msw_w(offs_t offset, u16 data, u16 mem_mask); + void hmsr_lsw_w(offs_t offset, u16 data, u16 mem_mask); + void alarm_msw_w(offs_t offset, u16 data, u16 mem_mask); + void alarm_lsw_w(offs_t offset, u16 data, u16 mem_mask); + virtual void rtcctl_w(offs_t offset, u16 data, u16 mem_mask); + void rtcisr_w(offs_t offset, u16 data, u16 mem_mask); + void rtcienr_w(offs_t offset, u16 data, u16 mem_mask); + void stpwtch_w(offs_t offset, u16 data, u16 mem_mask); - void hmsr_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xb00 - void hmsr_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xb02 - void alarm_msw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xb04 - void alarm_lsw_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xb06 - void rtcctl_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xb0c - void rtcisr_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xb0e - void rtcienr_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xb10 - void stpwtch_w(offs_t offset, uint16_t data, uint16_t mem_mask); // 0xb12 + u8 scr_r(); - uint8_t scr_r(); // 0x000 + u16 grpbasea_r(); + u16 grpbaseb_r(); + u16 grpbasec_r(); + u16 grpbased_r(); - uint16_t grpbasea_r(); // 0x100 - uint16_t grpbaseb_r(); // 0x102 - uint16_t grpbasec_r(); // 0x104 - uint16_t grpbased_r(); // 0x106 - uint16_t grpmaska_r(); // 0x108 - uint16_t grpmaskb_r(); // 0x10a - uint16_t grpmaskc_r(); // 0x10c - uint16_t grpmaskd_r(); // 0x10e + u16 pllcr_r(); + u16 pllfsr_r(); + u8 pctlr_r(); - template uint16_t csa_msw_r(); // 0x110, 0x114, 0x118, 0x11c - template uint16_t csa_lsw_r(); // 0x112, 0x116, 0x11a, 0x11e - template uint16_t csb_msw_r(); // 0x120, 0x124, 0x128, 0x12c - template uint16_t csb_lsw_r(); // 0x122, 0x126, 0x12a, 0x12e - template uint16_t csc_msw_r(); // 0x130, 0x134, 0x138, 0x13c - template uint16_t csc_lsw_r(); // 0x132, 0x136, 0x13a, 0x13e - template uint16_t csd_msw_r(); // 0x140, 0x144, 0x148, 0x14c - template uint16_t csd_lsw_r(); // 0x142, 0x146, 0x14a, 0x14e + u8 ivr_r(); + u16 icr_r(); + u16 imr_msw_r(); + u16 imr_lsw_r(); + u16 isr_msw_r(); + u16 isr_lsw_r(); + u16 ipr_msw_r(); + u16 ipr_lsw_r(); - uint16_t pllcr_r(); // 0x200 - uint16_t pllfsr_r(); // 0x202 - uint8_t pctlr_r(); // 0x207 + u8 padir_r(); + u8 padata_r(); + u8 pbdir_r(); + u8 pbdata_r(); + u8 pbsel_r(); + u8 pcdir_r(); + u8 pcdata_r(); + u8 pcsel_r(); + u8 pddir_r(); + u8 pddata_r(); + u8 pdpuen_r(); + u8 pdpol_r(); + u8 pdirqen_r(); + u8 pdirqedge_r(); + u8 pedir_r(); + u8 pedata_r(); + u8 pepuen_r(); + u8 pesel_r(); + u8 pfdir_r(); + u8 pfdata_r(); + u8 pfpuen_r(); + u8 pfsel_r(); + u8 pgdir_r(); + u8 pgdata_r(); + u8 pgpuen_r(); + u8 pgsel_r(); - uint8_t ivr_r(); // 0x300 - uint16_t icr_r(); // 0x302 - uint16_t imr_msw_r(); // 0x304 - uint16_t imr_lsw_r(); // 0x306 - uint16_t iwr_msw_r(); // 0x308 - uint16_t iwr_lsw_r(); // 0x30a - uint16_t isr_msw_r(); // 0x30c - uint16_t isr_lsw_r(); // 0x30e - uint16_t ipr_msw_r(); // 0x310 - uint16_t ipr_lsw_r(); // 0x312 + virtual u16 pwmc_r() = 0; - uint8_t padir_r(); // 0x400 - uint8_t padata_r(); // 0x401 - uint8_t pasel_r(); // 0x403 - uint8_t pbdir_r(); // 0x408 - uint8_t pbdata_r(); // 0x409 - uint8_t pbsel_r(); // 0x40b - uint8_t pcdir_r(); // 0x410 - uint8_t pcdata_r(); // 0x411 - uint8_t pcsel_r(); // 0x413 - uint8_t pddir_r(); // 0x418 - uint8_t pddata_r(); // 0x419 - uint8_t pdpuen_r(); // 0x41a - uint8_t pdpol_r(); // 0x41c - uint8_t pdirqen_r(); // 0x41d - uint8_t pdirqedge_r(); // 0x41f - uint8_t pedir_r(); // 0x420 - uint8_t pedata_r(); // 0x421 - uint8_t pepuen_r(); // 0x422 - uint8_t pesel_r(); // 0x423 - uint8_t pfdir_r(); // 0x428 - uint8_t pfdata_r(); // 0x429 - uint8_t pfpuen_r(); // 0x42a - uint8_t pfsel_r(); // 0x42b - uint8_t pgdir_r(); // 0x430 - uint8_t pgdata_r(); // 0x431 - uint8_t pgpuen_r(); // 0x432 - uint8_t pgsel_r(); // 0x433 - uint8_t pjdir_r(); // 0x438 - uint8_t pjdata_r(); // 0x439 - uint8_t pjsel_r(); // 0x43b - uint8_t pkdir_r(); // 0x440 - uint8_t pkdata_r(); // 0x441 - uint8_t pkpuen_r(); // 0x442 - uint8_t pksel_r(); // 0x443 - uint8_t pmdata_r(); // 0x449 - uint8_t pmdir_r(); // 0x448 - uint8_t pmpuen_r(); // 0x44a - uint8_t pmsel_r(); // 0x44b + template u16 tctl_r(); + template u16 tprer_r(); + template u16 tcmp_r(); + template u16 tcr_r(); + template u16 tcn_r(); + template u16 tstat_r(); - uint16_t pwmc_r(); // 0x500 - uint16_t pwmp_r(); // 0x502 - uint16_t pwmw_r(); // 0x504 - uint16_t pwmcnt_r(); // 0x506 + u16 spimdata_r(); + u16 spimcont_r(); - template uint16_t tctl_r(); // 0x600, 0x60c - template uint16_t tprer_r(); // 0x602, 0x60e - template uint16_t tcmp_r(); // 0x604, 0x610 - template uint16_t tcr_r(); // 0x606, 0x612 - template uint16_t tcn_r(); // 0x608, 0x614 - template uint16_t tstat_r(); // 0x60a, 0x616 - uint16_t wctlr_r(); // 0x618 - uint16_t wcmpr_r(); // 0x61a - uint16_t wcn_r(); // 0x61c + u16 ustcnt_r(); + u16 ubaud_r(); + u16 urx_r(); + u16 utx_r(); + u16 umisc_r(); - uint16_t spisr_r(); // 0x700 + u16 lssa_msw_r(); + u16 lssa_lsw_r(); + u8 lvpw_r(); + u16 lxmax_r(); + u16 lymax_r(); + u16 lcxp_r(); + u16 lcyp_r(); + u16 lcwch_r(); + u8 lblkc_r(); + u8 lpicf_r(); + u8 lpolcf_r(); + u8 lacdrc_r(); + u8 lpxcd_r(); + u8 lckcon_r(); + u8 lposr_r(); + u8 lfrcm_r(); - uint16_t spimdata_r(); // 0x800 - uint16_t spimcont_r(); // 0x802 - - uint16_t ustcnt_r(); // 0x900 - uint16_t ubaud_r(); // 0x902 - uint16_t urx_r(); // 0x904 - uint16_t utx_r(); // 0x906 - uint16_t umisc_r(); // 0x908 - - uint16_t lssa_msw_r(); // 0xa00 - uint16_t lssa_lsw_r(); // 0xa02 - uint8_t lvpw_r(); // 0xa05 - uint16_t lxmax_r(); // 0xa08 - uint16_t lymax_r(); // 0xa0a - uint16_t lcxp_r(); // 0xa18 - uint16_t lcyp_r(); // 0xa1a - uint16_t lcwch_r(); // 0xa1c - uint8_t lblkc_r(); // 0xa1f - uint8_t lpicf_r(); // 0xa20 - uint8_t lpolcf_r(); // 0xa21 - uint8_t lacdrc_r(); // 0xa23 - uint8_t lpxcd_r(); // 0xa25 - uint8_t lckcon_r(); // 0xa27 - uint8_t llbar_r(); // 0xa29 - uint8_t lotcr_r(); // 0xa2b - uint8_t lposr_r(); // 0xa2d - uint8_t lfrcm_r(); // 0xa31 - uint16_t lgpmr_r(); // 0xa32 - - uint16_t hmsr_msw_r(); // 0xb00 - uint16_t hmsr_lsw_r(); // 0xb02 - uint16_t alarm_msw_r(); // 0xb04 - uint16_t alarm_lsw_r(); // 0xb06 - uint16_t rtcctl_r(); // 0xb0c - uint16_t rtcisr_r(); // 0xb0e - uint16_t rtcienr_r(); // 0xb10 - uint16_t stpwtch_r(); // 0xb12 + u16 hmsr_msw_r(); + u16 hmsr_lsw_r(); + u16 alarm_msw_r(); + u16 alarm_lsw_r(); + u16 rtcctl_r(); + u16 rtcisr_r(); + u16 rtcienr_r(); + u16 stpwtch_r(); // $(FF)FFF000 - uint8_t m_scr; // System Control Register + u8 m_scr; // System Control Register // $(FF)FFF100 - uint16_t m_grpbasea; // Chip Select Group A Base Register - uint16_t m_grpbaseb; // Chip Select Group B Base Register - uint16_t m_grpbasec; // Chip Select Group C Base Register - uint16_t m_grpbased; // Chip Select Group D Base Register - uint16_t m_grpmaska; // Chip Select Group A Mask Register - uint16_t m_grpmaskb; // Chip Select Group B Mask Register - uint16_t m_grpmaskc; // Chip Select Group C Mask Register - uint16_t m_grpmaskd; // Chip Select Group D Mask Register - uint32_t m_csa[4]; // Group A Chip Select Registers - uint32_t m_csb[4]; // Group B Chip Select Registers - uint32_t m_csc[4]; // Group C Chip Select Registers - uint32_t m_csd[4]; // Group D Chip Select Registers + u16 m_grpbasea; // Chip Select Group A Base Register + u16 m_grpbaseb; // Chip Select Group B Base Register + u16 m_grpbasec; // Chip Select Group C Base Register + u16 m_grpbased; // Chip Select Group D Base Register // $(FF)FFF200 - uint16_t m_pllcr; // PLL Control Register - uint16_t m_pllfsr; // PLL Frequency Select Register - uint8_t m_pctlr; // Power Control Register + u16 m_pllcr; // PLL Control Register + u16 m_pllfsr; // PLL Frequency Select Register + u8 m_pctlr; // Power Control Register // $(FF)FFF300 - uint8_t m_ivr; // Interrupt Vector Register - uint16_t m_icr; // Interrupt Control Register - uint32_t m_imr; // Interrupt Mask Register - uint32_t m_iwr; // Interrupt Wakeup Enable Register - uint32_t m_isr; // Interrupt Status Register - uint32_t m_ipr; // Interrupt Pending Register + u8 m_ivr; // Interrupt Vector Register + u16 m_icr; // Interrupt Control Register + u32 m_imr; // Interrupt Mask Register + u32 m_isr; // Interrupt Status Register + u32 m_ipr; // Interrupt Pending Register // $(FF)FFF400 - uint8_t m_padir; // Port A Direction Register - uint8_t m_padata; // Port A Data Register - uint8_t m_pasel; // Port A Select Register + u8 m_padir; // Port A Direction Register + u8 m_padata; // Port A Data Register + u8 m_pasel; // Port A Select Register - uint8_t m_pbdir; // Port B Direction Register - uint8_t m_pbdata; // Port B Data Register - uint8_t m_pbsel; // Port B Select Register + u8 m_pbdir; // Port B Direction Register + u8 m_pbdata; // Port B Data Register + u8 m_pbsel; // Port B Select Register - uint8_t m_pcdir; // Port C Direction Register - uint8_t m_pcdata; // Port C Data Register - uint8_t m_pcsel; // Port C Select Register + u8 m_pcdir; // Port C Direction Register + u8 m_pcdata; // Port C Data Register + u8 m_pcsel; // Port C Select Register - uint8_t m_pddir; // Port D Direction Register - uint8_t m_pddata; // Port D Data Register - uint8_t m_pdpuen; // Port D Pullup Enable Register - uint8_t m_pdpol; // Port D Polarity Register - uint8_t m_pdirqen; // Port D IRQ Enable Register - uint8_t m_pddataedge; // Port D Data Edge Level - uint8_t m_pdirqedge; // Port D IRQ Edge Register + u8 m_pddir; // Port D Direction Register + u8 m_pddata; // Port D Data Register + u8 m_pdpuen; // Port D Pullup Enable Register + u8 m_pdpol; // Port D Polarity Register + u8 m_pdirqen; // Port D IRQ Enable Register + u8 m_pdirqedge; // Port D IRQ Edge Register + u8 m_pdindata; // Port D direct input data (not memory-mapped) - uint8_t m_pedir; // Port E Direction Register - uint8_t m_pedata; // Port E Data Register - uint8_t m_pepuen; // Port E Pullup Enable Register - uint8_t m_pesel; // Port E Select Register + u8 m_pedir; // Port E Direction Register + u8 m_pedata; // Port E Data Register + u8 m_pepuen; // Port E Pullup Enable Register + u8 m_pesel; // Port E Select Register - uint8_t m_pfdir; // Port F Direction Register - uint8_t m_pfdata; // Port F Data Register - uint8_t m_pfpuen; // Port F Pullup Enable Register - uint8_t m_pfsel; // Port F Select Register + u8 m_pfdir; // Port F Direction Register + u8 m_pfdata; // Port F Data Register + u8 m_pfpuen; // Port F Pullup Enable Register + u8 m_pfsel; // Port F Select Register - uint8_t m_pgdir; // Port G Direction Register - uint8_t m_pgdata; // Port G Data Register - uint8_t m_pgpuen; // Port G Pullup Enable Register - uint8_t m_pgsel; // Port G Select Register - - uint8_t m_pjdir; // Port J Direction Register - uint8_t m_pjdata; // Port J Data Register - uint8_t m_pjsel; // Port J Select Register - uint8_t m_pkdir; // Port K Direction Register - uint8_t m_pkdata; // Port K Data Register - uint8_t m_pkpuen; // Port K Pullup Enable Register - uint8_t m_pksel; // Port K Select Register - - uint8_t m_pmdir; // Port M Direction Register - uint8_t m_pmdata; // Port M Data Register - uint8_t m_pmpuen; // Port M Pullup Enable Register - uint8_t m_pmsel; // Port M Select Register + u8 m_pgdir; // Port G Direction Register + u8 m_pgdata; // Port G Data Register + u8 m_pgpuen; // Port G Pullup Enable Register + u8 m_pgsel; // Port G Select Register // $(FF)FFF500 - uint16_t m_pwmc; // PWM Control Register - uint16_t m_pwmp; // PWM Period Register - uint16_t m_pwmw; // PWM Width Register - uint16_t m_pwmcnt; // PWN Counter + u16 m_pwmc; // PWM Control Register + bool m_pwmo; // $(FF)FFF600 - uint16_t m_tctl[2]; // Timer Control Register - uint16_t m_tprer[2]; // Timer Prescaler Register - uint16_t m_tcmp[2]; // Timer Compare Register - uint16_t m_tcr[2]; // Timer Capture Register - uint16_t m_tcn[2]; // Timer Counter - uint16_t m_tstat[2]; // Timer Status - uint16_t m_wctlr; // Watchdog Control Register - uint16_t m_wcmpr; // Watchdog Compare Register - uint16_t m_wcn; // Watchdog Counter - uint16_t m_tclear[2]; // Timer Clearable Status - - // $(FF)FFF700 - uint16_t m_spisr; // SPIS Register + struct timer_regs + { + u16 tctl; // Timer Control Register + u16 tprer; // Timer Prescaler Register + u16 tcmp; // Timer Compare Register + u16 tcr; // Timer Capture Register + u16 tcn; // Timer Counter + u16 tstat; // Timer Status + u16 tclear; // Timer Clearable Status + }; // $(FF)FFF800 - uint16_t m_spimdata; // SPIM Data Register - uint16_t m_spimcont; // SPIM Control/Status Register - bool m_spmtxd; // SPIM Shift-register output (TODO: multiplex onto Port K) - bool m_spmrxd; // SPIM Shift-register input (TODO: multiplex onto Port K) - bool m_spmclk; // SPIM Shift-register clock (TODO: multiplex onto Port K) + u16 m_spimdata; // SPIM Data Register + u16 m_spimcont; // SPIM Control/Status Register + bool m_spmtxd; // SPIM Shift-register output (TODO: multiplex onto Port K) + bool m_spmrxd; // SPIM Shift-register input (TODO: multiplex onto Port K) + bool m_spmclk; // SPIM Shift-register clock (TODO: multiplex onto Port K) + u16 m_spim_bit_read_idx; // Starting bit index for SPI transfers // $(FF)FFF900 - uint16_t m_ustcnt; // UART Status/Control Register - uint16_t m_ubaud; // UART Baud Control Register - uint16_t m_urx; // UART RX Register - uint16_t m_utx; // UART TX Register - uint16_t m_umisc; // UART Misc Register + u16 m_ustcnt; // UART Status/Control Register + u16 m_ubaud; // UART Baud Control Register + u16 m_urx; // UART RX Register + u16 m_utx; // UART TX Register + u16 m_umisc; // UART Misc Register // $(FF)FFFA00 - uint32_t m_lssa; // Screen Starting Address Register - uint8_t m_lvpw; // Virtual Page Width Register - uint16_t m_lxmax; // Screen Width Register - uint16_t m_lymax; // Screen Height Register - uint16_t m_lcxp; // Cursor X Position - uint16_t m_lcyp; // Cursor Y Position - uint16_t m_lcwch; // Cursor Width & Height Register - uint8_t m_lblkc; // Blink Control Register - uint8_t m_lpicf; // Panel Interface Config Register - uint8_t m_lpolcf; // Polarity Config Register - uint8_t m_lacdrc; // ACD (M) Rate Control Register - uint8_t m_lpxcd; // Pixel Clock Divider Register - uint8_t m_lckcon; // Clocking Control Register - uint8_t m_llbar; // Last Buffer Address Register - uint8_t m_lotcr; // Octet Terminal Count Register - uint8_t m_lposr; // Panning Offset Register - uint8_t m_lfrcm; // Frame Rate Control Modulation Register - uint16_t m_lgpmr; // Gray Palette Mapping Register + u32 m_lssa; // Screen Starting Address Register + u8 m_lvpw; // Virtual Page Width Register + u16 m_lxmax; // Screen Width Register + u16 m_lymax; // Screen Height Register + u16 m_lcxp; // Cursor X Position + u16 m_lcyp; // Cursor Y Position + u16 m_lcwch; // Cursor Width & Height Register + u8 m_lblkc; // Blink Control Register + u8 m_lpicf; // Panel Interface Config Register + u8 m_lpolcf; // Polarity Config Register + u8 m_lacdrc; // ACD (M) Rate Control Register + u8 m_lpxcd; // Pixel Clock Divider Register + u8 m_lckcon; // Clocking Control Register + u8 m_llbar; // Last Buffer Address Register + u8 m_lotcr; // Octet Terminal Count Register + u8 m_lposr; // Panning Offset Register + u8 m_lfrcm; // Frame Rate Control Modulation Register + u16 m_lgpmr; // Gray Palette Mapping Register // $(FF)FFFB00 - uint32_t m_hmsr; // RTC Hours Minutes Seconds Register - uint32_t m_alarm; // RTC Alarm Register - uint16_t m_rtcctl; // RTC Control Register - uint16_t m_rtcisr; // RTC Interrupt Status Register - uint16_t m_rtcienr; // RTC Interrupt Enable Register - uint16_t m_stpwtch; // Stopwatch Minutes + u32 m_hmsr; // RTC Hours Minutes Seconds Register + u32 m_alarm; // RTC Alarm Register + u16 m_rtcctl; // RTC Control Register + u16 m_rtcisr; // RTC Interrupt Status Register + u16 m_rtcienr; // RTC Interrupt Enable Register + u16 m_stpwtch; // Stopwatch Minutes - void internal_map(address_map &map); + void base_internal_map(u32 addr_bits, address_map &map); // internal state - void set_interrupt_line(uint32_t line, uint32_t active); - void poll_port_d_interrupts(); - void cpu_space_map(address_map &map); - uint8_t irq_callback(offs_t offset); + u8 irq_callback(offs_t offset); + virtual void register_state_save(); - attotime get_pixclk_rate(); - template uint32_t get_timer_frequency(); - template void maybe_start_timer(uint32_t new_enable); - - void register_state_save(); + void update_ipr_state(u32 changed_mask); + void update_imr_state(u32 changed_mask); + void set_interrupt_line(u32 line, u32 active); + virtual u32 get_irq_mask_for_level(int level) = 0; + virtual int get_irq_level_for_mask(u32 level) = 0; + virtual emu_timer *get_timer(int timer) = 0; + virtual timer_regs &get_timer_regs(int timer) = 0; + virtual u32 get_timer_int(int timer) = 0; + template u32 get_timer_frequency(); + template void update_gptimer_state(); template TIMER_CALLBACK_MEMBER(timer_tick); - TIMER_CALLBACK_MEMBER(pwm_tick); + + virtual u16 lcd_get_lxmax_mask() = 0; + virtual u32 lcd_get_line_word_count() = 0; + virtual attotime lcd_get_line_rate() = 0; + virtual u8 lcd_get_panel_bit_size() = 0; + virtual attotime get_pixclk_rate() = 0; + + TIMER_CALLBACK_MEMBER(refclk_tick); + virtual TIMER_CALLBACK_MEMBER(pwm_tick) = 0; TIMER_CALLBACK_MEMBER(rtc_tick); TIMER_CALLBACK_MEMBER(spim_tick); TIMER_CALLBACK_MEMBER(lcd_scan_tick); void fill_lcd_dma_buffer(); - emu_timer *m_gptimer[2]; - emu_timer *m_rtc; + virtual bool rtc_int_is_active() = 0; + virtual void rtc_advance_seconds(); + virtual u16 rtc_get_int_mask() = 0; + virtual bool rtc_get_alarm_match() = 0; + + emu_timer *m_refclk; emu_timer *m_pwm; + emu_timer *m_rtc; emu_timer *m_spim; emu_timer *m_lcd_scan; bool m_lcd_first_line; - uint32_t m_lcd_sysmem_ptr; - std::unique_ptr m_lcd_line_buffer; - uint32_t m_lcd_line_bit; - uint32_t m_lcd_line_word; + u32 m_lcd_sysmem_ptr; + u32 m_lcd_line_bit; + u32 m_lcd_line_word; bool m_lsclk; + std::unique_ptr m_lcd_line_buffer; - devcb_write8 m_out_port_a_cb; - devcb_write8 m_out_port_b_cb; - devcb_write8 m_out_port_c_cb; - devcb_write8 m_out_port_d_cb; - devcb_write8 m_out_port_e_cb; - devcb_write8 m_out_port_f_cb; - devcb_write8 m_out_port_g_cb; - devcb_write8 m_out_port_j_cb; - devcb_write8 m_out_port_k_cb; - devcb_write8 m_out_port_m_cb; + devcb_write_line::array<8> m_out_port_a_cb; + devcb_write_line::array<8> m_out_port_b_cb; + devcb_write_line::array<8> m_out_port_c_cb; + devcb_write_line::array<8> m_out_port_d_cb; + devcb_write_line::array<8> m_out_port_e_cb; + devcb_write_line::array<8> m_out_port_f_cb; + devcb_write_line::array<8> m_out_port_g_cb; - devcb_read8 m_in_port_a_cb; - devcb_read8 m_in_port_b_cb; - devcb_read8 m_in_port_c_cb; - devcb_read8 m_in_port_d_cb; - devcb_read8 m_in_port_e_cb; - devcb_read8 m_in_port_f_cb; - devcb_read8 m_in_port_g_cb; - devcb_read8 m_in_port_j_cb; - devcb_read8 m_in_port_k_cb; - devcb_read8 m_in_port_m_cb; + devcb_read_line::array<8> m_in_port_a_cb; + devcb_read_line::array<8> m_in_port_b_cb; + devcb_read_line::array<8> m_in_port_c_cb; + devcb_read_line::array<8> m_in_port_d_cb; + devcb_read_line::array<8> m_in_port_e_cb; + devcb_read_line::array<8> m_in_port_f_cb; + devcb_read_line::array<8> m_in_port_g_cb; devcb_write_line m_out_pwm_cb; @@ -920,10 +809,439 @@ protected: devcb_write8 m_out_ld_cb; lcd_info_changed_delegate m_lcd_info_changed_cb; - static const uint32_t VCO_DIVISORS[8]; + static const u32 VCO_DIVISORS[8]; }; +class mc68328_device : public mc68328_base_device +{ +public: + mc68328_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + template auto out_port_j() { return m_out_port_j_cb[Line].bind(); } + template auto out_port_k() { return m_out_port_k_cb[Line].bind(); } + template auto out_port_m() { return m_out_port_m_cb[Line].bind(); } + template auto in_port_j() { return m_in_port_j_cb[Line].bind(); } + template auto in_port_k() { return m_in_port_k_cb[Line].bind(); } + template auto in_port_m() { return m_in_port_m_cb[Line].bind(); } + +protected: + // device-level overrides + virtual void device_resolve_objects() override; + virtual void device_start() override; + virtual void device_reset() override; + +private: + enum : u8 + { + LPICF_GS = 0x01, + LPICF_GS_BIT = 0, + LPICF_PBSIZ = 0x06, + LPICF_PBSIZ_SHIFT = 1, + LPICF_PBSIZ_1 = 0x00, + LPICF_PBSIZ_2 = 0x02, + LPICF_PBSIZ_4 = 0x04, + + LCKCON_PCDS_BIT = 0, + LCKCON_DWIDTH = 0x02, + LCKCON_DWIDTH_BIT = 1, + LCKCON_WS = 0x30, + LCKCON_WS_SHIFT = 4, + LCKCON_WS_1 = 0x00, + LCKCON_WS_2 = 0x10, + LCKCON_WS_3 = 0x20, + LCKCON_WS_4 = 0x30, + LCKCON_DMA16 = 0x40, + LCKCON_DMA16_BIT = 6, + LCKCON_LCDON_BIT = 7, + }; + + enum : u16 + { + PWMC_CLKSEL = 0x0007, + PWMC_PWMEN = 0x0010, + PWMC_POL = 0x0040, + PWMC_PIN = 0x0080, + PWMC_LOAD = 0x0100, + PWMC_IRQEN = 0x4000, + PWMC_PWMIRQ = 0x8000, + + WCTLR_WDRST = 0x0008, + WCTLR_LOCK = 0x0004, + WCTLR_FI = 0x0002, + WCTLR_WDEN = 0x0001, + + RTCIENR_MASK = 0x001f, + }; + + void grpmaska_w(u16 data); + void grpmaskb_w(u16 data); + void grpmaskc_w(u16 data); + void grpmaskd_w(u16 data); + template void csa_msw_w(offs_t offset, u16 data, u16 mem_mask); + template void csa_lsw_w(offs_t offset, u16 data, u16 mem_mask); + template void csb_msw_w(offs_t offset, u16 data, u16 mem_mask); + template void csb_lsw_w(offs_t offset, u16 data, u16 mem_mask); + template void csc_msw_w(offs_t offset, u16 data, u16 mem_mask); + template void csc_lsw_w(offs_t offset, u16 data, u16 mem_mask); + template void csd_msw_w(offs_t offset, u16 data, u16 mem_mask); + template void csd_lsw_w(offs_t offset, u16 data, u16 mem_mask); + + void iwr_msw_w(offs_t offset, u16 data, u16 mem_mask); + void iwr_lsw_w(offs_t offset, u16 data, u16 mem_mask); + + void pasel_w(u8 data); + void pjdir_w(u8 data); + void pjdata_w(u8 data); + void pjsel_w(u8 data); + void pkdir_w(u8 data); + void pkdata_w(u8 data); + void pkpuen_w(u8 data); + void pksel_w(u8 data); + void pmdir_w(u8 data); + void pmdata_w(u8 data); + void pmpuen_w(u8 data); + void pmsel_w(u8 data); + + virtual void pwmc_w(u16 data) override; + void pwmp_w(u16 data); + void pwmw_w(u16 data); + void pwmcnt_w(u16 data); + + void wctlr_w(u16 data); + void wcmpr_w(u16 data); + void wcn_w(u16 data); + + void spisr_w(u16 data); + + virtual void lpicf_w(u8 data) override; + virtual void lckcon_w(u8 data) override; + void llbar_w(u8 data); + void lotcr_w(u8 data); + void lgpmr_w(u8 data); + + u16 grpmaska_r(); + u16 grpmaskb_r(); + u16 grpmaskc_r(); + u16 grpmaskd_r(); + template u16 csa_msw_r(); + template u16 csa_lsw_r(); + template u16 csb_msw_r(); + template u16 csb_lsw_r(); + template u16 csc_msw_r(); + template u16 csc_lsw_r(); + template u16 csd_msw_r(); + template u16 csd_lsw_r(); + + u16 iwr_msw_r(); + u16 iwr_lsw_r(); + + u8 pasel_r(); + u8 pjdir_r(); + u8 pjdata_r(); + u8 pjsel_r(); + u8 pkdir_r(); + u8 pkdata_r(); + u8 pkpuen_r(); + u8 pksel_r(); + u8 pmdata_r(); + u8 pmdir_r(); + u8 pmpuen_r(); + u8 pmsel_r(); + + virtual u16 pwmc_r() override; + u16 pwmp_r(); + u16 pwmw_r(); + u16 pwmcnt_r(); + + u16 wctlr_r(); + u16 wcmpr_r(); + u16 wcn_r(); + + u16 spisr_r(); + + u8 llbar_r(); + u8 lotcr_r(); + u16 lgpmr_r(); + + // $(FF)FFF108 + u16 m_grpmaska; // Chip Select Group A Mask Register + u16 m_grpmaskb; // Chip Select Group B Mask Register + u16 m_grpmaskc; // Chip Select Group C Mask Register + u16 m_grpmaskd; // Chip Select Group D Mask Register + u32 m_csa[4]; // Group A Chip Select Registers + u32 m_csb[4]; // Group B Chip Select Registers + u32 m_csc[4]; // Group C Chip Select Registers + u32 m_csd[4]; // Group D Chip Select Registers + + // $(FF)FFF300 + u32 m_iwr; // Interrupt Wakeup Enable Register + + // $(FF)FFF438 + u8 m_pjdir; // Port J Direction Register + u8 m_pjdata; // Port J Data Register + u8 m_pjsel; // Port J Select Register + + u8 m_pkdir; // Port K Direction Register + u8 m_pkdata; // Port K Data Register + u8 m_pkpuen; // Port K Pullup Enable Register + u8 m_pksel; // Port K Select Register + + u8 m_pmdir; // Port M Direction Register + u8 m_pmdata; // Port M Data Register + u8 m_pmpuen; // Port M Pullup Enable Register + u8 m_pmsel; // Port M Select Register + + // $(FF)FFF502 + u16 m_pwmp; // PWM Period Register + u16 m_pwmw; // PWM Width Register + u16 m_pwmcnt; // PWM Counter + + // $(FF)FFF600 + timer_regs m_timer_regs[2]; + u16 m_wctlr; // Watchdog Control Register + u16 m_wcmpr; // Watchdog Compare Register + u16 m_wcn; // Watchdog Counter + + // $(FF)FFF700 + u16 m_spisr; // SPIS Register + + void internal_map(address_map &map); + void cpu_space_map(address_map &map); + + // internal state + virtual void register_state_save() override; + + virtual u32 get_irq_mask_for_level(int level) override; + virtual int get_irq_level_for_mask(u32 level) override; + + virtual TIMER_CALLBACK_MEMBER(pwm_tick) override; + + virtual emu_timer *get_timer(int timer) override; + virtual timer_regs &get_timer_regs(int timer) override; + virtual u32 get_timer_int(int timer) override; + + virtual u16 lcd_get_lxmax_mask() override; + virtual u32 lcd_get_line_word_count() override; + virtual attotime lcd_get_line_rate() override; + virtual u8 lcd_get_panel_bit_size() override; + virtual attotime get_pixclk_rate() override; + + virtual bool rtc_int_is_active() override; + virtual u16 rtc_get_int_mask() override; + virtual bool rtc_get_alarm_match() override; + + emu_timer *m_gptimer[2]; + + devcb_write_line::array<8> m_out_port_j_cb; + devcb_write_line::array<8> m_out_port_k_cb; + devcb_write_line::array<8> m_out_port_m_cb; + + devcb_read_line::array<8> m_in_port_j_cb; + devcb_read_line::array<8> m_in_port_k_cb; + devcb_read_line::array<8> m_in_port_m_cb; +}; + +class mc68ez328_device : public mc68328_base_device +{ +public: + mc68ez328_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_resolve_objects() override; + virtual void device_start() override; + virtual void device_reset() override; + +private: + enum : u8 + { + LPICF_GS = 0x03, + LPICF_GS_2COL = 0x00, + LPICF_GS_4COL = 0x01, + LPICF_GS_16COL = 0x02, + LPICF_PBSIZ = 0x0c, + LPICF_PBSIZ_SHIFT = 2, + LPICF_PBSIZ_1 = 0x00, + LPICF_PBSIZ_2 = 0x04, + LPICF_PBSIZ_4 = 0x08, + + LCKCON_DWS = 0x0f, + LCKCON_DWS_SHIFT = 0, + LCKCON_DWIDTH = 0x40, + LCKCON_DWIDTH_BIT = 6, + LCKCON_LCDON_BIT = 7, + }; + + enum : u16 + { + CSA_MASK = 0x81ff, + CSB_MASK = 0xf9ff, + CSC_MASK = 0xf9ff, + CSD_MASK = 0xffff, + EMUCS_MASK = 0x0070, + CS_EN_BIT = 0, + CS_SIZ_MASK = 0x000e, + CS_SIZ_SHIFT = 1, + CS_WS_MASK = 0x0070, + CS_WS_SHIFT = 4, + CS_BSW_BIT = 7, + CS_FLASH_BIT = 8, + CS_DRAM_BIT = 9, + CS_COMB_BIT = 10, + CS_UPSIZ_MASK = 0x1800, + CS_UPSIZ_SHIFT = 11, + CS_ROP_BIT = 13, + CS_SOP_BIT = 14, + CS_RO_BIT = 15, + + PWMC_CLKSEL = 0x0003, + PWMC_REPEAT = 0x000c, + PWMC_REPEAT_SHIFT = 2, + PWMC_EN = 0x0010, + PWMC_FIFO_AV = 0x0020, + PWMC_IRQ_EN = 0x0040, + PWMC_IRQ = 0x0080, + PWMC_IRQ_BIT = 7, + PWMC_PRESCALE = 0x7f00, + PWMC_PRESCALE_SHIFT = 8, + PWMC_CLK_SRC = 0x8000, + PWMC_RECALC_MASK = PWMC_CLK_SRC | PWMC_PRESCALE | PWMC_CLKSEL | PWMC_EN, + + WATCHDOG_MASK = 0x0083, + WATCHDOG_EN_BIT = 0, + WATCHDOG_ISEL_BIT = 1, + WATCHDOG_INTF = 0x0080, + WATCHDOG_INTF_BIT = 7, + WATCHDOG_CNT_MASK = 0x0300, + WATCHDOG_CNT_SHIFT = 8, + + RTCINT_HOUR = 0x0020, + RTCINT_SAM0 = 0x0100, + RTCINT_SAM1 = 0x0200, + RTCINT_SAM2 = 0x0400, + RTCINT_SAM3 = 0x0800, + RTCINT_SAM4 = 0x1000, + RTCINT_SAM5 = 0x2000, + RTCINT_SAM6 = 0x4000, + RTCINT_SAM7 = 0x8000, + RTCINT_RTCIRQ_MASK = 0x00ff, + + RTC_DAYS_MASK = 0x01ff, + }; + + enum : u32 + { + INT_MSAM = 22, + INT_MSAM_MASK = (1 << INT_MSAM), + INT_MEMIQ = 23, + INT_MEMIQ_MASK = (1 << INT_MEMIQ), + }; + + void csa_w(offs_t offset, u16 data, u16 mem_mask); + void csb_w(offs_t offset, u16 data, u16 mem_mask); + void csc_w(offs_t offset, u16 data, u16 mem_mask); + void csd_w(offs_t offset, u16 data, u16 mem_mask); + void emucs_w(offs_t offset, u16 data, u16 mem_mask); + + virtual void pwmc_w(u16 data) override; + void pwms_w(offs_t offset, u16 data, u16 mem_mask); + void pwmp_w(u8 data); + void pwmcnt_w(u8 data); + + virtual void lpicf_w(u8 data) override; + virtual void lckcon_w(u8 data) override; + void lrra_w(u8 data); + void pwmr_w(offs_t offset, u16 data, u16 mem_mask); + + void watchdog_w(offs_t offset, u16 data, u16 mem_mask); + virtual void rtcctl_w(offs_t offset, u16 data, u16 mem_mask) override; + void dayr_w(offs_t offset, u16 data, u16 mem_mask); + void dayalarm_w(offs_t offset, u16 data, u16 mem_mask); + + u8 revision_r(offs_t offset); + + u16 csa_r(); + u16 csb_r(); + u16 csc_r(); + u16 csd_r(); + u16 emucs_r(); + + virtual u16 pwmc_r() override; + u16 pwms_r(); + u8 pwmp_r(); + u8 pwmcnt_r(); + + u8 lrra_r(); + u16 pwmr_r(); + + u16 watchdog_r(); + u16 dayr_r(); + u16 dayalarm_r(); + + // $(FF)FFF100 + u16 m_csa; // Group A Chip-Select Register + u16 m_csb; // Group B Chip-Select Register + u16 m_csc; // Group C Chip-Select Register + u16 m_csd; // Group D Chip-Select Register + u16 m_emucs; // Emulation Chip-Select Register + + // $(FF)FFF502 + u8 m_pwmp; // PWM Period Register + u8 m_pwmcnt; // PWM Counter + u8 m_pwmfifo[5]; // PWM FIFO + u8 m_pwmfifo_wr; // PWM FIFO Write Index + u8 m_pwmfifo_rd; // PWM FIFO Read Index + u8 m_pwmfifo_cnt; // PWM FIFO Count + u8 m_pwm_rep_cnt; // PWM Repeat Count + + // $(FF)FFF600 + timer_regs m_timer_regs; + + // $(FF)FFFA00 + u8 m_lrra; // LCD Refresh Rate Adjustment Register + u16 m_pwmr; // PWM Contrast Control Register + + // $(FF)FFFB00 + u16 m_watchdog; // Watchdog Timer Register + u16 m_dayr; // RTC Day Count Register + u16 m_dayalarm; // RTC Day Alarm Register + u8 m_sam_cnt; // RTC Sample Timer Counter (internal, not readable) + + void internal_map(address_map &map); + void cpu_space_map(address_map &map); + + // internal state + virtual void register_state_save() override; + + virtual u32 get_irq_mask_for_level(int level) override; + virtual int get_irq_level_for_mask(u32 level) override; + + void update_pwm_period(bool high_cycle); + void pwm_fifo_push(u8 data); + void pwm_fifo_pop(); + virtual TIMER_CALLBACK_MEMBER(pwm_tick) override; + + virtual emu_timer *get_timer(int timer) override; + virtual timer_regs &get_timer_regs(int timer) override; + virtual u32 get_timer_int(int timer) override; + + virtual u16 lcd_get_lxmax_mask() override; + virtual u32 lcd_get_line_word_count() override; + virtual attotime lcd_get_line_rate() override; + virtual u8 lcd_get_panel_bit_size() override; + virtual attotime get_pixclk_rate() override; + + TIMER_CALLBACK_MEMBER(sample_timer_tick); + virtual bool rtc_int_is_active() override; + virtual void rtc_advance_seconds() override; + virtual u16 rtc_get_int_mask() override; + virtual bool rtc_get_alarm_match() override; + + emu_timer *m_gptimer; + emu_timer *m_rtc_sample_timer; +}; DECLARE_DEVICE_TYPE(MC68328, mc68328_device) +DECLARE_DEVICE_TYPE(MC68EZ328, mc68ez328_device) #endif // MAME_MACHINE_MC68328_H diff --git a/src/devices/video/sed1375.cpp b/src/devices/video/sed1375.cpp new file mode 100644 index 00000000000..793f4f47e2f --- /dev/null +++ b/src/devices/video/sed1375.cpp @@ -0,0 +1,549 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/********************************************************************** + + Epson SED1375 LCD Controller emulation skeleton + + - Currently hard-coded for use with the Palm IIIc driver. + - TODO: Find more test-case systems. + +**********************************************************************/ + +#include "emu.h" +#include "sed1375.h" +#include "screen.h" + +#define LOG_REG_READ (1 << 1) +#define LOG_REG_WRITE (1 << 2) +#define LOG_VRAM_READ (1 << 3) +#define LOG_VRAM_WRITE (1 << 4) +#define LOG_LUT_READ (1 << 5) +#define LOG_LUT_WRITE (1 << 6) +#define LOG_VBL_READ (1 << 7) +#define LOG_ALL (LOG_REG_READ | LOG_REG_WRITE | LOG_VRAM_READ | LOG_VRAM_WRITE | LOG_LUT_READ | LOG_LUT_WRITE | LOG_VBL_READ) + +#define VERBOSE (0) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(SED1375, sed1375_device, "sed1375", "Epson SED1375") + +sed1375_device::sed1375_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, SED1375, tag, owner, clock) + , device_video_interface(mconfig, *this) + , m_vram(*this, "vram", 80 * 1024, ENDIANNESS_BIG) +{ +} + +void sed1375_device::device_start() +{ + save_item(NAME(m_revision)); + save_item(NAME(m_mode)); + save_item(NAME(m_panel_hsize)); + save_item(NAME(m_panel_vsize)); + save_item(NAME(m_fpline_start)); + save_item(NAME(m_hblank_period)); + save_item(NAME(m_fpframe_start)); + save_item(NAME(m_vblank_period)); + save_item(NAME(m_mod_rate)); + save_item(NAME(m_screen_start)); + save_item(NAME(m_screen_start_ovf)); + save_item(NAME(m_mem_addr_offset)); + save_item(NAME(m_screen1_vsize)); + save_item(NAME(m_lut_addr)); + save_item(NAME(m_lut_index)); + save_item(NAME(m_red_lut)); + save_item(NAME(m_green_lut)); + save_item(NAME(m_blue_lut)); + save_item(NAME(m_gpio_config)); + save_item(NAME(m_gpio_status)); + save_item(NAME(m_scratch)); + save_item(NAME(m_swivel_mode)); + save_item(NAME(m_swivel_bytecnt)); +} + +void sed1375_device::device_reset() +{ + m_revision = 0x24; + std::fill(std::begin(m_mode), std::end(m_mode), 0); + m_panel_hsize = 0x03; + m_panel_vsize = 0; + m_fpline_start = 0; + m_hblank_period = 0; + m_fpframe_start = 0; + m_vblank_period = 0; + m_mod_rate = 0; + std::fill(std::begin(m_screen_start), std::end(m_screen_start), 0); + m_screen_start_ovf = 0; + m_mem_addr_offset = 0; + m_screen1_vsize = 0; + m_lut_addr = 0; + m_lut_index = 0; + std::fill(std::begin(m_red_lut), std::end(m_red_lut), 0); + std::fill(std::begin(m_green_lut), std::end(m_green_lut), 0); + std::fill(std::begin(m_blue_lut), std::end(m_blue_lut), 0); + m_gpio_config = 0; + m_gpio_status = 0; + m_scratch = 0; + m_swivel_mode = 0; + m_swivel_bytecnt = 0; +} + +void sed1375_device::map(address_map &map) +{ + map(0x00000, 0x13fff).rw(FUNC(sed1375_device::vram_r), FUNC(sed1375_device::vram_w)); + map(0x1ffe0, 0x1ffe0).r(FUNC(sed1375_device::revision_r)); + map(0x1ffe1, 0x1ffe1).rw(FUNC(sed1375_device::mode0_r), FUNC(sed1375_device::mode0_w)); + map(0x1ffe2, 0x1ffe2).rw(FUNC(sed1375_device::mode1_r), FUNC(sed1375_device::mode1_w)); + map(0x1ffe3, 0x1ffe3).rw(FUNC(sed1375_device::mode2_r), FUNC(sed1375_device::mode2_w)); + map(0x1ffe4, 0x1ffe4).rw(FUNC(sed1375_device::panel_hsize_r), FUNC(sed1375_device::panel_hsize_w)); + map(0x1ffe5, 0x1ffe5).rw(FUNC(sed1375_device::panel_vsize_lsb_r), FUNC(sed1375_device::panel_vsize_lsb_w)); + map(0x1ffe6, 0x1ffe6).rw(FUNC(sed1375_device::panel_vsize_msb_r), FUNC(sed1375_device::panel_vsize_msb_w)); + map(0x1ffe7, 0x1ffe7).rw(FUNC(sed1375_device::fpline_start_r), FUNC(sed1375_device::fpline_start_w)); + map(0x1ffe8, 0x1ffe8).rw(FUNC(sed1375_device::hblank_r), FUNC(sed1375_device::hblank_w)); + map(0x1ffe9, 0x1ffe9).rw(FUNC(sed1375_device::fpframe_start_r), FUNC(sed1375_device::fpframe_start_w)); + map(0x1ffea, 0x1ffea).rw(FUNC(sed1375_device::vblank_r), FUNC(sed1375_device::vblank_w)); + map(0x1ffeb, 0x1ffeb).rw(FUNC(sed1375_device::mod_rate_r), FUNC(sed1375_device::mod_rate_w)); + map(0x1ffec, 0x1ffec).rw(FUNC(sed1375_device::screen1_start_lsb_r), FUNC(sed1375_device::screen1_start_lsb_w)); + map(0x1ffed, 0x1ffed).rw(FUNC(sed1375_device::screen1_start_msb_r), FUNC(sed1375_device::screen1_start_msb_w)); + map(0x1ffee, 0x1ffee).rw(FUNC(sed1375_device::screen2_start_lsb_r), FUNC(sed1375_device::screen2_start_lsb_w)); + map(0x1ffef, 0x1ffef).rw(FUNC(sed1375_device::screen2_start_msb_r), FUNC(sed1375_device::screen2_start_msb_w)); + map(0x1fff0, 0x1fff0).rw(FUNC(sed1375_device::screen1_start_ovf_r), FUNC(sed1375_device::screen1_start_ovf_w)); + map(0x1fff1, 0x1fff1).rw(FUNC(sed1375_device::mem_addr_offset_r), FUNC(sed1375_device::mem_addr_offset_w)); + map(0x1fff2, 0x1fff2).rw(FUNC(sed1375_device::screen1_vsize_lsb_r), FUNC(sed1375_device::screen1_vsize_lsb_w)); + map(0x1fff3, 0x1fff3).rw(FUNC(sed1375_device::screen1_vsize_msb_r), FUNC(sed1375_device::screen1_vsize_msb_w)); + map(0x1fff5, 0x1fff5).rw(FUNC(sed1375_device::lut_addr_r), FUNC(sed1375_device::lut_addr_w)); + map(0x1fff7, 0x1fff7).rw(FUNC(sed1375_device::lut_data_r), FUNC(sed1375_device::lut_data_w)); + map(0x1fff8, 0x1fff8).rw(FUNC(sed1375_device::gpio_config_r), FUNC(sed1375_device::gpio_config_w)); + map(0x1fff9, 0x1fff9).rw(FUNC(sed1375_device::gpio_r), FUNC(sed1375_device::gpio_w)); + map(0x1fffa, 0x1fffa).rw(FUNC(sed1375_device::scratch_r), FUNC(sed1375_device::scratch_w)); + map(0x1fffb, 0x1fffb).rw(FUNC(sed1375_device::swivel_mode_r), FUNC(sed1375_device::swivel_mode_w)); + map(0x1fffc, 0x1fffc).rw(FUNC(sed1375_device::swivel_bytecnt_r), FUNC(sed1375_device::swivel_bytecnt_w)); +} + +u32 sed1375_device::get_pixel(int screen_idx, int x, int y) +{ + const u32 pixels_per_line = (m_panel_hsize + 1) * 8; + const u32 bpp = 1 << ((m_mode[1] & MODE1_BPP_MASK) >> MODE1_BPP_SHIFT); + const u32 pixel_index = y * pixels_per_line + x; + const u32 byte_index = (pixel_index * bpp) / 8; + const u32 bit_index = x % (8 / bpp); + const u8 bpp_mask = (1 << bpp) - 1; + return (m_vram[(m_screen_start[screen_idx] << 1) + byte_index] >> (bit_index * bpp)) & bpp_mask; +} + +u32 sed1375_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + if (BIT(m_mode[1], MODE1_BLANK_BIT)) + { + bitmap.fill(0xff000000, cliprect); + return 0; + } + + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + u32 *dst = &bitmap.pix(y); + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) + { + u32 pix = get_pixel(0, x, y); + if (BIT(m_mode[0], MODE0_TFT_BIT) || BIT(m_mode[0], MODE0_COLOR_BIT)) + { + const u8 r = m_red_lut[pix]; + const u8 g = m_green_lut[pix]; + const u8 b = m_blue_lut[pix]; + *dst++ = 0xff000000 | (((r << 4) | r) << 16) | (((g << 4) | g) << 8) | ((b << 4) | b); + } + else + { + switch ((m_mode[1] & MODE1_BPP_MASK) >> MODE1_BPP_SHIFT) + { + case 0: // 1bpp + *dst++ = 0xff000000 | (pix * 0xffffff); + break; + case 1: // 2bpp + *dst++ = 0xff000000 | (pix * 0x555555); + break; + case 2: // 4bpp + *dst++ = 0xff000000 | (pix * 0x111111); + break; + case 3: // 8bpp + *dst++ = 0xff000000 | (pix * 0x010101); + break; + } + } + } + } + return 0; +} + +void sed1375_device::vram_w(offs_t offset, u8 data) +{ + LOGMASKED(LOG_VRAM_WRITE, "%s: vram_w: VRAM Write[%05x] = %02x\n", machine().describe_context(), offset, data); + m_vram[offset] = data; +} + +u8 sed1375_device::vram_r(offs_t offset) +{ + LOGMASKED(LOG_VRAM_READ, "%s: vram_r: VRAM Read[%05x]: %02x\n", machine().describe_context(), offset, m_vram[offset]); + return m_vram[offset]; +} + +u8 sed1375_device::revision_r() +{ + LOGMASKED(LOG_REG_READ, "%s: revision_r: %02x\n", machine().describe_context(), m_revision); + return m_revision; +} + +void sed1375_device::mode0_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: mode0_w: Mode Register 0 = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_REG_WRITE, "%s Data Width Bits: %d\n", machine().describe_context(), data & MODE0_WIDTH_MASK); + LOGMASKED(LOG_REG_WRITE, "%s Mask FPSHIFT: %d\n", machine().describe_context(), BIT(data, MODE0_FPSHIFT_BIT)); + LOGMASKED(LOG_REG_WRITE, "%s FPFRAME Polarity: %s\n", machine().describe_context(), BIT(data, MODE0_FPFRAME_POL_BIT) ? "Active-High" : "Active-Low"); + LOGMASKED(LOG_REG_WRITE, "%s FPLINE Polarity: %s\n", machine().describe_context(), BIT(data, MODE0_FPLINE_POL_BIT) ? "Active-High" : "Active-Low"); + LOGMASKED(LOG_REG_WRITE, "%s Color/Mono: %s\n", machine().describe_context(), BIT(data, MODE0_COLOR_BIT) ? "Color" : "Mono"); + LOGMASKED(LOG_REG_WRITE, "%s Dual/Single: %s\n", machine().describe_context(), BIT(data, MODE0_DUAL_BIT) ? "Dual" : "Single"); + LOGMASKED(LOG_REG_WRITE, "%s TFT/STN: %s\n", machine().describe_context(), BIT(data, MODE0_TFT_BIT) ? "TFT" : "STN"); + m_mode[0] = data & MODE0_MASK; +} + +u8 sed1375_device::mode0_r() +{ + LOGMASKED(LOG_REG_READ, "%s: mode0_r: Mode Register 0: %02x\n", machine().describe_context(), m_mode[0]); + return m_mode[0]; +} + +void sed1375_device::mode1_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: mode1_w: Mode Register 1 = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_REG_WRITE, "%s Software Video Invert: %d\n", machine().describe_context(), BIT(data, MODE1_SWINVERT_BIT)); + LOGMASKED(LOG_REG_WRITE, "%s Hardware Video Invert: %d\n", machine().describe_context(), BIT(data, MODE1_HWINVERT_BIT)); + LOGMASKED(LOG_REG_WRITE, "%s Frame Repeat: %d\n", machine().describe_context(), BIT(data, MODE1_FRREPEAT_BIT)); + LOGMASKED(LOG_REG_WRITE, "%s Display Blank: %d\n", machine().describe_context(), BIT(data, MODE1_BLANK_BIT)); + LOGMASKED(LOG_REG_WRITE, "%s Input Clock Divider: %d\n", machine().describe_context(), BIT(data, MODE1_CLKDIV_BIT) + 1); + LOGMASKED(LOG_REG_WRITE, "%s High Performance: %d\n", machine().describe_context(), BIT(data, MODE1_HIPERF_BIT)); + LOGMASKED(LOG_REG_WRITE, "%s Bits Per Pixel: %d\n", machine().describe_context(), 1 << ((data & MODE1_BPP_MASK) >> MODE1_BPP_SHIFT)); + m_mode[1] = data & MODE1_MASK; +} + +u8 sed1375_device::mode1_r() +{ + LOGMASKED(LOG_REG_READ, "%s: mode1_r: Mode Register 1: %02x\n", machine().describe_context(), m_mode[1]); + return m_mode[1]; +} + +void sed1375_device::mode2_w(u8 data) +{ + static const char *const SWPWRSAVE_NAMES[4] = { "Software Power Save", "Reserved (1)", "Reserved (2)", "Normal Operation" }; + LOGMASKED(LOG_REG_WRITE, "%s: mode2_w: Mode Register 2 = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_REG_WRITE, "%s Software Power Save Mode: %s\n", machine().describe_context(), SWPWRSAVE_NAMES[data & MODE2_SWPWRSAVE_MASK]); + LOGMASKED(LOG_REG_WRITE, "%s Hardware Power Save: %d\n", machine().describe_context(), BIT(data, MODE2_HWPWRSAVE_BIT)); + LOGMASKED(LOG_REG_WRITE, "%s LCDPWR Override: %d\n", machine().describe_context(), BIT(data, MODE2_LCDPWR_OVR_BIT)); + m_mode[2] = data & MODE2_MASK; +} + +u8 sed1375_device::mode2_r() +{ + LOGMASKED(LOG_REG_READ, "%s: mode2_r: Mode Register 2: %02x\n", machine().describe_context(), m_mode[2]); + return m_mode[2]; +} + +void sed1375_device::panel_hsize_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: panel_hsize_w: Panel Horizontal Size = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_REG_WRITE, "%s: In Pixels: %d\n", machine().describe_context(), ((data & PANEL_HSIZE_MASK) + 1) * 8); + m_panel_hsize = data & PANEL_HSIZE_MASK; +} + +u8 sed1375_device::panel_hsize_r() +{ + LOGMASKED(LOG_REG_READ, "%s: panel_hsize_r: Panel Horizontal Size: %02x\n", machine().describe_context(), m_panel_hsize); + return m_panel_hsize; +} + +void sed1375_device::panel_vsize_lsb_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: panel_vsize_lsb_w: Panel Vertical Size (LSB) = %02x\n", machine().describe_context(), data); + m_panel_vsize = ((m_panel_vsize & 0xff00) | data) & PANEL_VSIZE_MASK; +} + +u8 sed1375_device::panel_vsize_lsb_r() +{ + LOGMASKED(LOG_REG_READ, "%s: panel_vsize_lsb_r: Panel Vertical Size (LSB): %02x\n", machine().describe_context(), m_panel_vsize & 0x00ff); + return m_panel_vsize; +} + +void sed1375_device::panel_vsize_msb_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: panel_vsize_msb_w: Panel Vertical Size (MSB) = %02x\n", machine().describe_context(), data); + m_panel_vsize = ((m_panel_vsize & 0x00ff) | (data << 8)) & PANEL_VSIZE_MASK; +} + +u8 sed1375_device::panel_vsize_msb_r() +{ + LOGMASKED(LOG_REG_READ, "%s: panel_vsize_msb_r: Panel Vertical Size (MSB): %02x\n", machine().describe_context(), m_panel_vsize >> 8); + return m_panel_vsize >> 8; +} + +void sed1375_device::fpline_start_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: fpline_start_w: FPLINE Start Position = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_REG_WRITE, "%s: In Pixels: %d\n", machine().describe_context(), ((data & FPLINE_START_MASK) + 2) * 8); + m_fpline_start = data & FPLINE_START_MASK; +} + +u8 sed1375_device::fpline_start_r() +{ + LOGMASKED(LOG_REG_READ, "%s: fpline_start_r: FPLINE Start Position: %02x\n", machine().describe_context(), m_fpline_start); + return m_fpline_start; +} + +void sed1375_device::hblank_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: hblank_w: Horizontal Blanking Period = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_REG_WRITE, "%s: In Pixels: %d\n", machine().describe_context(), ((data & HBLANK_MASK) + 4) * 8); + m_hblank_period = data & HBLANK_MASK; +} + +u8 sed1375_device::hblank_r() +{ + LOGMASKED(LOG_REG_READ, "%s: hblank_r: Horizontal Blanking Period: %02x\n", machine().describe_context(), m_hblank_period); + return m_hblank_period; +} + +void sed1375_device::fpframe_start_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: fpline_start_w: FPFRAME Start Position = %02x\n", machine().describe_context(), data); + m_fpframe_start = data & FPFRAME_START_MASK; +} + +u8 sed1375_device::fpframe_start_r() +{ + LOGMASKED(LOG_REG_READ, "%s: fpframe_start_r: FPFRAME Start Position: %02x\n", machine().describe_context(), m_fpframe_start); + return m_fpframe_start; +} + +void sed1375_device::vblank_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: vblank_w: Vertical Blanking Period = %02x\n", machine().describe_context(), data); + m_vblank_period = data & VBLANK_MASK; +} + +u8 sed1375_device::vblank_r() +{ + const u8 data = m_vblank_period | (screen().vblank() ? (1 << VBLANK_VBL_BIT) : 0); + LOGMASKED(LOG_VBL_READ, "%s: vblank_r: Vertical Blanking Period/Status: %02x\n", machine().describe_context(), data); + return data; +} + +void sed1375_device::mod_rate_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: mod_rate_w: MOD Rate Register = %02x\n", machine().describe_context(), data); + m_mod_rate = data & MODRATE_MASK; +} + +u8 sed1375_device::mod_rate_r() +{ + LOGMASKED(LOG_REG_READ, "%s: mod_rate_r: MOD Rate Register: %02x\n", machine().describe_context(), m_mod_rate); + return m_mod_rate; +} + +void sed1375_device::screen2_start_lsb_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: screen2_start_w: Screen 2 Start Address (LSB) = %02x\n", machine().describe_context(), data); + m_screen_start[1] = ((m_screen_start[1] & 0xff00) | data) & SCREEN2_START_MASK; +} + +u8 sed1375_device::screen2_start_lsb_r() +{ + LOGMASKED(LOG_REG_READ, "%s: screen2_start_r: Screen 2 Start Address (LSB): %02x\n", machine().describe_context(), (u8)m_screen_start[1]); + return (u8)m_screen_start[1]; +} + +void sed1375_device::screen1_start_msb_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: screen1_start_w: Screen 1 Start Address (MSB) = %02x\n", machine().describe_context(), data); + m_screen_start[0] = ((m_screen_start[0] & 0x00ff) | (data << 8)) & SCREEN1_START_MASK; +} + +u8 sed1375_device::screen1_start_msb_r() +{ + LOGMASKED(LOG_REG_READ, "%s: screen1_start_r: Screen 1 Start Address (MSB): %02x\n", machine().describe_context(), (u8)(m_screen_start[0] >> 8)); + return (u8)(m_screen_start[0] >> 8); +} + +void sed1375_device::screen1_start_lsb_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: screen1_start_w: Screen 1 Start Address (LSB) = %02x\n", machine().describe_context(), data); + m_screen_start[0] = ((m_screen_start[0] & 0xff00) | data) & SCREEN1_START_MASK; +} + +u8 sed1375_device::screen1_start_lsb_r() +{ + LOGMASKED(LOG_REG_READ, "%s: screen1_start_r: Screen 1 Start Address (LSB): %02x\n", machine().describe_context(), (u8)m_screen_start[0]); + return (u8)m_screen_start[0]; +} + +void sed1375_device::screen2_start_msb_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: screen2_start_w: Screen 2 Start Address (MSB) = %02x\n", machine().describe_context(), data); + m_screen_start[1] = ((m_screen_start[1] & 0x00ff) | (data << 8)) & SCREEN2_START_MASK; +} + +u8 sed1375_device::screen2_start_msb_r() +{ + LOGMASKED(LOG_REG_READ, "%s: screen2_start_r: Screen 2 Start Address (MSB): %02x\n", machine().describe_context(), (u8)(m_screen_start[1] >> 8)); + return (u8)(m_screen_start[1] >> 8); +} + +void sed1375_device::screen1_start_ovf_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: screen1_start_ovf_w: Screen Start Address Overflow Register = %02x\n", machine().describe_context(), data); + m_screen_start_ovf = data & START_OVF_MASK; +} + +u8 sed1375_device::screen1_start_ovf_r() +{ + LOGMASKED(LOG_REG_READ, "%s: screen1_start_ovf_r: Screen Start Address Overflow Register: %02x\n", machine().describe_context(), m_screen_start_ovf); + return m_screen_start_ovf; +} + +void sed1375_device::mem_addr_offset_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: mem_addr_offset_w: Memory Address Offset Register = %02x\n", machine().describe_context(), data); + m_mem_addr_offset = data & MEM_ADDR_OFFSET_MASK; +} + +u8 sed1375_device::mem_addr_offset_r() +{ + LOGMASKED(LOG_REG_READ, "%s: mem_addr_offset_r: Memory Address Offset Register: %02x\n", machine().describe_context(), m_mem_addr_offset); + return m_mem_addr_offset; +} + +void sed1375_device::screen1_vsize_lsb_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: screen1_vsize_lsb_w: Screen 1 Vertical Size Register (LSB) = %02x\n", machine().describe_context(), data); + m_screen1_vsize = ((m_screen1_vsize & 0xff00) | data) & SCREEN1_VSIZE_MASK; +} + +u8 sed1375_device::screen1_vsize_lsb_r() +{ + LOGMASKED(LOG_REG_READ, "%s: screen1_vsize_lsb_r: Screen 1 Vertical Size Register (LSB): %02x\n", machine().describe_context(), (u8)m_screen1_vsize); + return (u8)m_screen1_vsize; +} + +void sed1375_device::screen1_vsize_msb_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: screen1_vsize_msb_w: Screen 1 Vertical Size Register (MSB) = %02x\n", machine().describe_context(), data); + m_screen1_vsize = ((m_screen1_vsize & 0x00ff) | (data << 8)) & SCREEN1_VSIZE_MASK; +} + +u8 sed1375_device::screen1_vsize_msb_r() +{ + LOGMASKED(LOG_LUT_READ, "%s: screen1_vsize_msb_r: Screen 1 Vertical Size Register (MSB): %02x\n", machine().describe_context(), (u8)(m_screen1_vsize >> 8)); + return (u8)(m_screen1_vsize >> 8); +} + +void sed1375_device::lut_addr_w(u8 data) +{ + LOGMASKED(LOG_LUT_WRITE, "%s: lut_addr_w: LUT Address Register = %02x\n", machine().describe_context(), data); + m_lut_addr = data & LUT_ADDR_MASK; + m_lut_index = 0; +} + +u8 sed1375_device::lut_addr_r() +{ + LOGMASKED(LOG_LUT_READ, "%s: lut_addr_r: LUT Address Register: %02x\n", machine().describe_context(), m_lut_addr); + return m_lut_addr; +} + +void sed1375_device::lut_data_w(u8 data) +{ + static const char *const LUT_INDEX_NAMES[3] = { "Red", "Green", "Blue" }; + LOGMASKED(LOG_LUT_WRITE, "%s: lut_data_w: LUT Data[%d] = %02x (%s)\n", machine().describe_context(), (u32)m_lut_addr, data, LUT_INDEX_NAMES[m_lut_index]); + + u8 *lut_data[3] = { m_red_lut, m_green_lut, m_blue_lut }; + lut_data[m_lut_index++][m_lut_addr] = (data & LUT_DATA_MASK) >> LUT_DATA_SHIFT; + if (m_lut_index >= 3) + { + m_lut_addr++; + m_lut_index = 0; + } +} + +u8 sed1375_device::lut_data_r() +{ + static const char *const LUT_INDEX_NAMES[3] = { "Red", "Green", "Blue" }; + u8 *lut_data[3] = { m_red_lut, m_green_lut, m_blue_lut }; + const u8 data = lut_data[m_lut_index++][m_lut_addr]; + LOGMASKED(LOG_REG_READ, "%s: lut_data_r: LUT Data[%d]: %02x (%s)\n", machine().describe_context(), (u32)m_lut_addr, data, LUT_INDEX_NAMES[m_lut_index]); + if (m_lut_index >= 3) + { + m_lut_addr++; + m_lut_index = 0; + } + return data; +} + +void sed1375_device::gpio_config_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: gpio_config_w: GPIO Config Register = %02x\n", machine().describe_context(), data); + m_gpio_config = data & GPIO_CONFIG_MASK; +} + +u8 sed1375_device::gpio_config_r() +{ + LOGMASKED(LOG_REG_READ, "%s: gpio_config_r: GPIO Config Register: %02x\n", machine().describe_context(), m_gpio_config); + return m_gpio_config; +} + +void sed1375_device::gpio_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: gpio_w: GPIO Output = %02x\n", machine().describe_context(), data); + m_gpio_status = data & GPIO_STATUS_MASK; +} + +u8 sed1375_device::gpio_r() +{ + LOGMASKED(LOG_REG_READ, "%s: gpio_r: GPIO Input: %02x\n", machine().describe_context(), m_gpio_status); + return m_gpio_status; +} + +void sed1375_device::scratch_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: scratch_w: Scratch Pad Register = %02x\n", machine().describe_context(), data); + m_scratch = data & SCRATCH_MASK; +} + +u8 sed1375_device::scratch_r() +{ + LOGMASKED(LOG_REG_READ, "%s: scratch_r: Scratch Pad Register: %02x\n", machine().describe_context(), m_scratch); + return m_scratch; +} + +void sed1375_device::swivel_mode_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: swivel_mode_w: SwivelView Mode Register = %02x\n", machine().describe_context(), data); + LOGMASKED(LOG_REG_WRITE, "%s: Pixel Clock Select Bits: %d\n", machine().describe_context(), data & SWIVEL_CLKSEL_MASK); + LOGMASKED(LOG_REG_WRITE, "%s: SwivelView Mode Select: %d\n", machine().describe_context(), + !BIT(data, SWIVEL_ENABLE_BIT) ? "Landscape" : (BIT(data, SWIVEL_MODE_BIT) ? "Alternate" : "Default")); + LOGMASKED(LOG_REG_WRITE, "%s: SwivelView Mode Enable: %d\n", machine().describe_context(), BIT(data, SWIVEL_ENABLE_BIT)); + m_swivel_mode = data & SWIVEL_MODE_MASK; +} + +u8 sed1375_device::swivel_mode_r() +{ + LOGMASKED(LOG_REG_READ, "%s: swivel_mode_r: SwivelView Mode Register: %02x\n", machine().describe_context(), m_swivel_mode); + return m_swivel_mode; +} + +void sed1375_device::swivel_bytecnt_w(u8 data) +{ + LOGMASKED(LOG_REG_WRITE, "%s: swivel_bytecnt_w: SwivelView Line Byte Count = %02x\n", machine().describe_context(), data); + m_swivel_bytecnt = data & SWIVEL_BYTECNT_MASK; +} + +u8 sed1375_device::swivel_bytecnt_r() +{ + LOGMASKED(LOG_REG_READ, "%s: swivel_bytecnt_r: SwivelView Line Byte Count: %02x\n", machine().describe_context(), m_swivel_bytecnt); + return m_swivel_bytecnt; +} diff --git a/src/devices/video/sed1375.h b/src/devices/video/sed1375.h new file mode 100644 index 00000000000..3301bea5193 --- /dev/null +++ b/src/devices/video/sed1375.h @@ -0,0 +1,196 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/********************************************************************** + + Epson SED1375 LCD Controller emulation skeleton + + - Currently hard-coded for use with the Palm IIIc driver. + - TODO: Find more test-case systems. + +**********************************************************************/ + +#ifndef MAME_VIDEO_SED1375_H +#define MAME_VIDEO_SED1375_H + +#pragma once + +class sed1375_device : public device_t, + public device_video_interface +{ +public: + // construction/destruction + sed1375_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + void map(address_map &map); + + u32 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; + + u32 get_pixel(int screen_idx, int x, int y); + + void vram_w(offs_t offset, u8 data); + u8 vram_r(offs_t offset); + + void mode0_w(u8 data); + void mode1_w(u8 data); + void mode2_w(u8 data); + void panel_hsize_w(u8 data); + void panel_vsize_lsb_w(u8 data); + void panel_vsize_msb_w(u8 data); + void fpline_start_w(u8 data); + void hblank_w(u8 data); + void fpframe_start_w(u8 data); + void vblank_w(u8 data); + void mod_rate_w(u8 data); + void screen1_start_lsb_w(u8 data); + void screen1_start_msb_w(u8 data); + void screen2_start_lsb_w(u8 data); + void screen2_start_msb_w(u8 data); + void screen1_start_ovf_w(u8 data); + void mem_addr_offset_w(u8 data); + void screen1_vsize_lsb_w(u8 data); + void screen1_vsize_msb_w(u8 data); + void lut_addr_w(u8 data); + void lut_data_w(u8 data); + void gpio_config_w(u8 data); + void gpio_w(u8 data); + void scratch_w(u8 data); + void swivel_mode_w(u8 data); + void swivel_bytecnt_w(u8 data); + + u8 revision_r(); + u8 mode0_r(); + u8 mode1_r(); + u8 mode2_r(); + u8 panel_hsize_r(); + u8 panel_vsize_lsb_r(); + u8 panel_vsize_msb_r(); + u8 fpline_start_r(); + u8 hblank_r(); + u8 fpframe_start_r(); + u8 vblank_r(); + u8 mod_rate_r(); + u8 screen1_start_lsb_r(); + u8 screen1_start_msb_r(); + u8 screen2_start_lsb_r(); + u8 screen2_start_msb_r(); + u8 screen1_start_ovf_r(); + u8 mem_addr_offset_r(); + u8 screen1_vsize_lsb_r(); + u8 screen1_vsize_msb_r(); + u8 lut_addr_r(); + u8 lut_data_r(); + u8 gpio_config_r(); + u8 gpio_r(); + u8 scratch_r(); + u8 swivel_mode_r(); + u8 swivel_bytecnt_r(); + + enum : u8 + { + MODE0_MASK = 0xff, + MODE0_WIDTH_MASK = 0x03, + MODE0_FPSHIFT_BIT = 2, + MODE0_FPFRAME_POL_BIT = 3, + MODE0_FPLINE_POL_BIT = 4, + MODE0_COLOR_BIT = 5, + MODE0_DUAL_BIT = 6, + MODE0_TFT_BIT = 7, + + MODE1_MASK = 0xff, + MODE1_SWINVERT_BIT = 0, + MODE1_HWINVERT_BIT = 1, + MODE1_FRREPEAT_BIT = 2, + MODE1_BLANK_BIT = 3, + MODE1_CLKDIV_BIT = 4, + MODE1_HIPERF_BIT = 5, + MODE1_BPP_MASK = 0xc0, + MODE1_BPP_SHIFT = 6, + + MODE2_MASK = 0x0f, + MODE2_SWPWRSAVE_MASK = 0x03, + MODE2_SWPWRSAVE_SHIFT = 0, + MODE2_HWPWRSAVE_BIT = 2, + MODE2_LCDPWR_OVR_BIT = 3, + + PANEL_HSIZE_MASK = 0x7f, + + FPLINE_START_MASK = 0x1f, + + HBLANK_MASK = 0x1f, + + FPFRAME_START_MASK = 0x3f, + + VBLANK_MASK = 0x3f, + VBLANK_VBL_BIT = 7, + + MODRATE_MASK = 0x3f, + + START_OVF_MASK = 0x01, + + MEM_ADDR_OFFSET_MASK = 0xff, + + LUT_ADDR_MASK = 0xff, + + LUT_DATA_MASK = 0xf0, + LUT_DATA_SHIFT = 4, + + GPIO_CONFIG_MASK = 0x1f, + GPIO_STATUS_MASK = 0x1f, + + SCRATCH_MASK = 0xff, + + SWIVEL_MODE_MASK = 0xc3, + SWIVEL_CLKSEL_MASK = 0x03, + SWIVEL_MODE_BIT = 6, + SWIVEL_ENABLE_BIT = 7, + + SWIVEL_BYTECNT_MASK = 0xff + }; + + enum : u16 + { + PANEL_VSIZE_MASK = 0x03ff, + + SCREEN1_START_MASK = 0xffff, + SCREEN2_START_MASK = 0xffff, + + SCREEN1_VSIZE_MASK = 0x03ff + }; + + memory_share_creator m_vram; + + u8 m_revision; + u8 m_mode[3]; + u8 m_panel_hsize; + u16 m_panel_vsize; + u8 m_fpline_start; + u8 m_hblank_period; + u8 m_fpframe_start; + u8 m_vblank_period; + u8 m_mod_rate; + u16 m_screen_start[2]; + u8 m_screen_start_ovf; + u8 m_mem_addr_offset; + u16 m_screen1_vsize; + u8 m_lut_addr; + u8 m_lut_index; + u8 m_red_lut[256]; + u8 m_green_lut[256]; + u8 m_blue_lut[256]; + u8 m_gpio_config; + u8 m_gpio_status; + u8 m_scratch; + u8 m_swivel_mode; + u8 m_swivel_bytecnt; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(SED1375, sed1375_device) + +#endif // MAME_VIDEO_SED1375_H diff --git a/src/mame/palm/palm.cpp b/src/mame/palm/palm.cpp index b23c1ff8f19..be1036e5e74 100644 --- a/src/mame/palm/palm.cpp +++ b/src/mame/palm/palm.cpp @@ -16,168 +16,177 @@ #include "machine/mc68328.h" #include "machine/ram.h" #include "sound/dac.h" +#include "video/sed1375.h" + #include "emupal.h" #include "screen.h" #include "speaker.h" #include "pilot1k.lh" +#define VERBOSE (0) +#include "logmacro.h" + namespace { -class palm_state : public driver_device +class palm_base_state : public driver_device { public: - palm_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_ram(*this, RAM_TAG), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_io_penx(*this, "PENX"), - m_io_peny(*this, "PENY"), - m_io_penb(*this, "PENB"), - m_io_portd(*this, "PORTD") - { } - - void palmiii(machine_config &config); - void pilot1k(machine_config &config); - void palmvx(machine_config &config); - void palmv(machine_config &config); - void palm(machine_config &config); - void palmpro(machine_config &config); - void pilot5k(machine_config &config); - DECLARE_INPUT_CHANGED_MEMBER(pen_check); - DECLARE_INPUT_CHANGED_MEMBER(button_check); protected: + palm_base_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_ram(*this, RAM_TAG) + , m_screen(*this, "screen") + , m_io_penx(*this, "PENX") + , m_io_peny(*this, "PENY") + , m_io_penb(*this, "PENB") + { } + virtual void machine_start() override; virtual void machine_reset() override; - enum : uint8_t - { - PORTF_Y_VCCN_BIT = 0, - PORTF_Y_GND_BIT = 1, - PORTF_X_VCCN_BIT = 2, - PORTF_X_GND_BIT = 3, - PORTF_LCD_EN_BIT = 4, - PORTF_LCD_VCCN_BIT = 5, - PORTF_LCD_VEE_BIT = 6, - PORTF_ADC_CSN_BIT = 7, - - PORTF_PEN_MASK = 0x8f, - PORTF_X_MASK = (1 << PORTF_X_VCCN_BIT) | (1 << PORTF_Y_GND_BIT), - PORTF_Y_MASK = (1 << PORTF_Y_VCCN_BIT) | (1 << PORTF_X_GND_BIT), - }; - -private: offs_t dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer ¶ms); - void mem_map(address_map &map); void flm_out(int state); void llp_out(int state); - void lsclk_out(int state); - void ld_out(uint8_t data); + virtual void lsclk_out(int state); + void ld_out(u8 data); void lcd_info_changed(double refresh_hz, int width, int height); - uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - void init_palette(palette_device &palette) const; - void port_f_out(uint8_t data); - uint8_t port_c_in(); - uint8_t port_f_in(); + virtual int spi_from_hw(); - int spi_in(); - - required_device m_maincpu; + required_device m_maincpu; required_device m_ram; required_device m_screen; - required_device m_palette; required_ioport m_io_penx; required_ioport m_io_peny; required_ioport m_io_penb; - required_ioport m_io_portd; - uint8_t m_port_f_latch; - - uint16_t m_spim_data; + u16 m_spim_data; bitmap_rgb32 m_lcd_bitmap; int m_lcd_first_line; int m_lcd_line_pulse; int m_lcd_shift_clk; - uint8_t m_lcd_data; + u8 m_lcd_data; int m_lcd_scan_x; int m_lcd_scan_y; static const int EXTRA_ARTWORK_HEIGHT = 60; }; +class palm_state : public palm_base_state +{ +public: + palm_state(const machine_config &mconfig, device_type type, const char *tag) + : palm_base_state(mconfig, type, tag) + , m_palette(*this, "palette") + , m_io_portd(*this, "PORTD") + { } + + void palmiii(machine_config &config); + void pilot1k(machine_config &config); + void palmvx(machine_config &config); + void palmv(machine_config &config); + void palmpro(machine_config &config); + void pilot5k(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER(button_check); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + + void palm_base(machine_config &config); + + void mem_map(address_map &map); + + u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + void init_palette(palette_device &palette) const; + + void check_pen_adc_read(); + void adc_vcc_y_w(int state); + void adc_gnd_y_w(int state); + void adc_vcc_x_w(int state); + void adc_gnd_x_w(int state); + void adc_csn_w(int state); + int power_nmi_r(); + + virtual void lsclk_out(int state) override; + + enum : int + { + PORTF_Y_VCCN_BIT = 0, + PORTF_Y_GND_BIT = 1, + PORTF_X_VCCN_BIT = 2, + PORTF_X_GND_BIT = 3, + PORTF_ADC_CSN_BIT = 7 + }; + + required_device m_palette; + required_ioport m_io_portd; + + u8 m_port_f_latch; + bool m_adc_csn; + bool m_adc_vcc_x; + bool m_adc_gnd_x; + bool m_adc_vcc_y; + bool m_adc_gnd_y; +}; + +class palmiiic_state : public palm_base_state +{ +public: + palmiiic_state(const machine_config &mconfig, device_type type, const char *tag) + : palm_base_state(mconfig, type, tag) + , m_sed1375(*this, "lcdctrl") + , m_rows(*this, "ROW%u", 0u) + { } + + void palmiiic(machine_config &config); + + DECLARE_INPUT_CHANGED_MEMBER(button_check); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + + void mem_map(address_map &map); + + void adc_enable_w(int state); + + template void kbd_row_w(int state); + template void kbd_col_w(int state); + template int kbd_scan_r(); + + void hardware_id_req_w(int state); + + void spi_to_hw(int state); + virtual int spi_from_hw() override; + + required_device m_sed1375; + required_ioport_array<3> m_rows; + + u8 m_key_row_mask; + u8 m_key_col_mask; + bool m_port_d_hardware_id; + bool m_adc_enabled; + u8 m_adc_cmd_bit_count; + u8 m_adc_response_bit_count; + u8 m_adc_cmd; +}; /*************************************************************************** MACHINE HARDWARE ***************************************************************************/ -INPUT_CHANGED_MEMBER(palm_state::pen_check) +// Shared platform hardware + +void palm_base_state::machine_start() { - uint8_t button = m_io_penb->read(); - - if(button) - m_maincpu->set_penirq_line(1); - else - m_maincpu->set_penirq_line(0); -} - -INPUT_CHANGED_MEMBER(palm_state::button_check) -{ - uint8_t button_state = m_io_portd->read(); - m_maincpu->set_port_d_lines(button_state, (int)param); -} - -void palm_state::port_f_out(uint8_t data) -{ - const uint8_t old = m_port_f_latch; - m_port_f_latch = data; - const uint8_t changed = old ^ data; - - if (BIT(changed, PORTF_ADC_CSN_BIT) && !BIT(m_port_f_latch, PORTF_ADC_CSN_BIT)) - { - switch (m_port_f_latch & PORTF_PEN_MASK) - { - case PORTF_X_MASK: - m_spim_data = (0xff - m_io_penx->read()) * 2; - break; - - case PORTF_Y_MASK: - m_spim_data = (0xff - m_io_peny->read()) * 2; - break; - } - } -} - -uint8_t palm_state::port_c_in() -{ - return 0x10; -} - -uint8_t palm_state::port_f_in() -{ - return m_port_f_latch; -} - -int palm_state::spi_in() -{ - int out_state = BIT(m_spim_data, 15); - m_spim_data <<= 1; - m_spim_data |= 1; - return out_state; -} - -void palm_state::machine_start() -{ - address_space &space = m_maincpu->space(AS_PROGRAM); - space.install_ram(0x000000, m_ram->size() - 1, m_ram->pointer()); - - save_item(NAME(m_port_f_latch)); save_item(NAME(m_spim_data)); save_item(NAME(m_lcd_first_line)); @@ -188,10 +197,10 @@ void palm_state::machine_start() save_item(NAME(m_lcd_scan_y)); } -void palm_state::machine_reset() +void palm_base_state::machine_reset() { // Copy boot ROM - uint8_t* bios = memregion("bios")->base(); + u8* bios = memregion("bios")->base(); memset(m_ram->pointer(), 0, m_ram->size()); memcpy(m_ram->pointer(), bios, 0x20000); @@ -205,6 +214,244 @@ void palm_state::machine_reset() m_lcd_scan_y = 0; } +INPUT_CHANGED_MEMBER(palm_base_state::pen_check) +{ + m_maincpu->irq5_w(m_io_penb->read() & 1); +} + +int palm_base_state::spi_from_hw() +{ + int out_state = BIT(m_spim_data, 15); + m_spim_data <<= 1; + m_spim_data |= 1; + return out_state; +} + +// First-generation Palm hardware ("IDT") + +void palm_state::machine_start() +{ + palm_base_state::machine_start(); + address_space &space = m_maincpu->space(AS_PROGRAM); + space.install_ram(0x000000, m_ram->size() - 1, m_ram->pointer()); + + //save_item(NAME(m_port_f_latch)); + save_item(NAME(m_adc_csn)); + save_item(NAME(m_adc_vcc_x)); + save_item(NAME(m_adc_gnd_x)); + save_item(NAME(m_adc_vcc_y)); + save_item(NAME(m_adc_gnd_y)); +} + +void palm_state::machine_reset() +{ + palm_base_state::machine_reset(); + + m_adc_csn = false; + m_adc_vcc_x = false; + m_adc_gnd_x = false; + m_adc_vcc_y = false; + m_adc_gnd_y = false; +} + +INPUT_CHANGED_MEMBER(palm_state::button_check) +{ + const u8 button_state = m_io_portd->read(); + m_maincpu->port_d_in_w(BIT(button_state, param), param); +} + +void palm_state::check_pen_adc_read() +{ + if (!m_adc_csn) + { + if (m_adc_vcc_x && m_adc_gnd_y) + { + m_spim_data = (0xff - m_io_penx->read()) * 2; + } + else if (m_adc_vcc_y && m_adc_gnd_x) + { + m_spim_data = (0xff - m_io_peny->read()) * 2; + } + } +} + +void palm_state::adc_vcc_y_w(int state) +{ + m_adc_vcc_y = state; + check_pen_adc_read(); +} + +void palm_state::adc_gnd_y_w(int state) +{ + m_adc_gnd_y = state; + check_pen_adc_read(); +} + +void palm_state::adc_vcc_x_w(int state) +{ + m_adc_vcc_x = state; + check_pen_adc_read(); +} + +void palm_state::adc_gnd_x_w(int state) +{ + m_adc_gnd_x = state; + check_pen_adc_read(); +} + +void palm_state::adc_csn_w(int state) +{ + m_adc_csn = state; + check_pen_adc_read(); +} + +int palm_state::power_nmi_r() +{ + return 1; +} + +// Palm IIIc hardware ("Austin") + +void palmiiic_state::machine_start() +{ + palm_base_state::machine_start(); + address_space &space = m_maincpu->space(AS_PROGRAM); + space.install_ram(0x000000, m_ram->size() - 1, m_ram->pointer()); + + save_item(NAME(m_key_row_mask)); + save_item(NAME(m_key_col_mask)); + save_item(NAME(m_port_d_hardware_id)); + save_item(NAME(m_adc_enabled)); + save_item(NAME(m_adc_cmd_bit_count)); + save_item(NAME(m_adc_response_bit_count)); + save_item(NAME(m_adc_cmd)); +} + +void palmiiic_state::machine_reset() +{ + palm_base_state::machine_reset(); + + m_key_row_mask = 0; + m_key_col_mask = 0; + + m_port_d_hardware_id = false; + m_adc_enabled = false; + m_adc_cmd_bit_count = 8; + m_adc_response_bit_count = 0; + m_adc_cmd = 0; +} + +INPUT_CHANGED_MEMBER(palmiiic_state::button_check) +{ + const u8 button_state = m_rows[param]->read(); + for (int bit = 0; bit < 4; bit++) + { + m_maincpu->port_d_in_w(BIT(button_state, bit), bit); + } +} + +void palmiiic_state::adc_enable_w(int state) +{ + const bool was_enabled = m_adc_enabled; + m_adc_enabled = !state; + if (!was_enabled && m_adc_enabled) + { + m_adc_cmd_bit_count = 8; + m_spim_data = 0; + } +} + +template +void palmiiic_state::kbd_row_w(int state) +{ + m_key_row_mask &= ~(1 << Line); + m_key_row_mask |= !state << Line; +} + +template +void palmiiic_state::kbd_col_w(int state) +{ + m_key_col_mask &= ~(1 << Line); + m_key_col_mask |= state << Line; +} + +template +int palmiiic_state::kbd_scan_r() +{ + int state = 0; + if (m_port_d_hardware_id) + { + state = BIT(~0x09, Line); + } + else + { + for (int i = 0; i < 3; i++) + { + if (BIT(m_key_row_mask, i)) + { + state |= BIT(m_rows[i]->read(), Line); + } + } + } + return state; +} + +void palmiiic_state::hardware_id_req_w(int state) +{ + m_port_d_hardware_id = !state; +} + +void palmiiic_state::spi_to_hw(int state) +{ + if (m_adc_enabled && m_adc_cmd_bit_count > 0) + { + m_adc_cmd_bit_count--; + m_adc_cmd &= ~(1 << m_adc_cmd_bit_count); + m_adc_cmd |= state << m_adc_cmd_bit_count; + } +} + +int palmiiic_state::spi_from_hw() +{ + int state = palm_base_state::spi_from_hw(); + if (m_adc_enabled && m_adc_cmd_bit_count == 0) + { + if (m_adc_response_bit_count == 0) + { + m_adc_response_bit_count = 16; + const u8 channel = (m_adc_cmd >> 4) & 7; + switch (channel) + { + case 1: // Pen Y + m_spim_data = ((0xff - m_io_peny->read()) * 2) << 3; + break; + case 2: // Battery Level + m_spim_data = 0x7ff8; + break; + case 5: // Pen X + m_spim_data = ((0xff - m_io_penx->read()) * 2) << 3; + break; + case 6: // Dock Serial + m_spim_data = 0; + break; + default: + LOG("%s: Unknown ADC Channel: %d (command %02x)\n", machine().describe_context(), channel, m_adc_cmd); + break; + } + } + else + { + m_adc_response_bit_count--; + if (m_adc_response_bit_count == 0) + { + m_adc_cmd_bit_count = 8; + } + } + } + return state; +} + + /*************************************************************************** LCD HARDWARE ***************************************************************************/ @@ -215,12 +462,12 @@ void palm_state::init_palette(palette_device &palette) const palette.set_pen_color(1, 0x40, 0x40, 0x40); } -void palm_state::flm_out(int state) +void palm_base_state::flm_out(int state) { m_lcd_first_line = state; } -void palm_state::llp_out(int state) +void palm_base_state::llp_out(int state) { const int old = m_lcd_line_pulse; m_lcd_line_pulse = state; @@ -238,13 +485,18 @@ void palm_state::llp_out(int state) } } +void palm_base_state::lsclk_out(int state) +{ + m_lcd_shift_clk = state; +} + void palm_state::lsclk_out(int state) { const int old = m_lcd_shift_clk; - m_lcd_shift_clk = state; + palm_base_state::lsclk_out(state); if (state && !old) { - for (uint8_t i = 0; i < 4; i++) + for (u8 i = 0; i < 4; i++) { m_lcd_bitmap.pix(m_lcd_scan_y, m_lcd_scan_x) = m_palette->pen_color(BIT(m_lcd_data, 3 - i)); m_lcd_scan_x++; @@ -252,12 +504,12 @@ void palm_state::lsclk_out(int state) } } -void palm_state::ld_out(uint8_t data) +void palm_base_state::ld_out(u8 data) { m_lcd_data = data; } -void palm_state::lcd_info_changed(double refresh_hz, int width, int height) +void palm_base_state::lcd_info_changed(double refresh_hz, int width, int height) { m_screen->set_refresh_hz(refresh_hz); m_screen->set_size(width, height + EXTRA_ARTWORK_HEIGHT); @@ -265,19 +517,18 @@ void palm_state::lcd_info_changed(double refresh_hz, int width, int height) m_lcd_bitmap.resize(width, height); } -uint32_t palm_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +u32 palm_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { bitmap.fill(m_palette->pen_color(0)); if (m_lcd_bitmap.valid()) { - uint32_t *src = &m_lcd_bitmap.pix(0); - uint32_t *dst = &bitmap.pix(0); + u32 *src = &m_lcd_bitmap.pix(0); + u32 *dst = &bitmap.pix(0); std::copy_n(src, m_lcd_bitmap.width() * m_lcd_bitmap.height(), dst); } return 0; } - /*************************************************************************** ADDRESS MAPS ***************************************************************************/ @@ -287,35 +538,107 @@ void palm_state::mem_map(address_map &map) map(0xc00000, 0xe07fff).rom().region("bios", 0); } +void palmiiic_state::mem_map(address_map &map) +{ + map(0x00c00000, 0x00e07fff).rom().region("bios", 0); + map(0x10c00000, 0x10e07fff).rom().region("bios", 0); + map(0x1f000000, 0x1f01ffff).m(m_sed1375, FUNC(sed1375_device::map)); +} + + +/*************************************************************************** + INPUTS +***************************************************************************/ + +static INPUT_PORTS_START(palm_base) + PORT_START("PENX") + PORT_BIT(0xff, 0x50, IPT_LIGHTGUN_X) PORT_NAME("Pen X") PORT_MINMAX(0, 0xa0) PORT_SENSITIVITY(50) PORT_CROSSHAIR(X, 1.0, 0.0, 0) + + PORT_START("PENY") + PORT_BIT(0xff, 0x50, IPT_LIGHTGUN_Y) PORT_NAME("Pen Y") PORT_MINMAX(0, 0xa0) PORT_SENSITIVITY(50) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) + + PORT_START("PENB") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Pen Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_base_state, pen_check, 0) +INPUT_PORTS_END + +static INPUT_PORTS_START(palm) + PORT_INCLUDE(palm_base) + + PORT_START("PORTD") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Power") PORT_CODE(KEYCODE_D) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 0) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Up") PORT_CODE(KEYCODE_Y) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 1) + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_NAME("Down") PORT_CODE(KEYCODE_H) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 2) + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_NAME("Button 1") PORT_CODE(KEYCODE_F) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 3) + PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_NAME("Button 2") PORT_CODE(KEYCODE_G) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 4) + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_BUTTON7) PORT_NAME("Button 3") PORT_CODE(KEYCODE_J) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 5) + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_BUTTON8) PORT_NAME("Button 4") PORT_CODE(KEYCODE_K) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 6) + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED) +INPUT_PORTS_END + +static INPUT_PORTS_START(palmez) + PORT_INCLUDE(palm_base) + + PORT_START("ROW0") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Button 1") PORT_CODE(KEYCODE_F) PORT_CHANGED_MEMBER(DEVICE_SELF, palmiiic_state, button_check, 0) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Button 2") PORT_CODE(KEYCODE_G) PORT_CHANGED_MEMBER(DEVICE_SELF, palmiiic_state, button_check, 0) + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_NAME("Button 3") PORT_CODE(KEYCODE_J) PORT_CHANGED_MEMBER(DEVICE_SELF, palmiiic_state, button_check, 0) + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_NAME("Button 4") PORT_CODE(KEYCODE_K) PORT_CHANGED_MEMBER(DEVICE_SELF, palmiiic_state, button_check, 0) + PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED) + + PORT_START("ROW1") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_NAME("Up") PORT_CODE(KEYCODE_Y) PORT_CHANGED_MEMBER(DEVICE_SELF, palmiiic_state, button_check, 1) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON7) PORT_NAME("Down") PORT_CODE(KEYCODE_H) PORT_CHANGED_MEMBER(DEVICE_SELF, palmiiic_state, button_check, 1) + PORT_BIT(0xfc, IP_ACTIVE_HIGH, IPT_UNUSED) + + PORT_START("ROW2") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON8) PORT_NAME("Power") PORT_CODE(KEYCODE_D) PORT_CHANGED_MEMBER(DEVICE_SELF, palmiiic_state, button_check, 2) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON9) PORT_NAME("Contrast") PORT_CODE(KEYCODE_C) PORT_CHANGED_MEMBER(DEVICE_SELF, palmiiic_state, button_check, 2) + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3) + PORT_BIT(0xf8, IP_ACTIVE_HIGH, IPT_UNUSED) +INPUT_PORTS_END + /*************************************************************************** MACHINE DRIVERS ***************************************************************************/ -void palm_state::palm(machine_config &config) +void palm_state::palm_base(machine_config &config) { /* basic machine hardware */ MC68328(config, m_maincpu, 32768*506); /* 16.580608 MHz */ m_maincpu->set_addrmap(AS_PROGRAM, &palm_state::mem_map); m_maincpu->set_dasm_override(FUNC(palm_state::dasm_override)); - m_maincpu->out_port_f().set(FUNC(palm_state::port_f_out)); - m_maincpu->in_port_c().set(FUNC(palm_state::port_c_in)); - m_maincpu->in_port_f().set(FUNC(palm_state::port_f_in)); + + m_maincpu->out_port_f().set(FUNC(palm_state::adc_vcc_y_w)); + m_maincpu->out_port_f().set(FUNC(palm_state::adc_gnd_y_w)); + m_maincpu->out_port_f().set(FUNC(palm_state::adc_vcc_x_w)); + m_maincpu->out_port_f().set(FUNC(palm_state::adc_gnd_x_w)); + m_maincpu->out_port_f().set(FUNC(palm_state::adc_csn_w)); + + m_maincpu->in_port_c<4>().set(FUNC(palm_state::power_nmi_r)); + + m_maincpu->in_port_d<0>().set_ioport(m_io_penb).bit(0); + m_maincpu->in_port_d<1>().set_ioport(m_io_penb).bit(1); + m_maincpu->in_port_d<2>().set_ioport(m_io_penb).bit(2); + m_maincpu->in_port_d<3>().set_ioport(m_io_penb).bit(3); + m_maincpu->in_port_d<4>().set_ioport(m_io_penb).bit(4); + m_maincpu->in_port_d<5>().set_ioport(m_io_penb).bit(5); + m_maincpu->in_port_d<6>().set_ioport(m_io_penb).bit(6); + m_maincpu->in_port_d<7>().set_ioport(m_io_penb).bit(7); + + //m_maincpu->in_port_f().set(FUNC(palm_state::port_f_in)); Port F latch + m_maincpu->out_pwm().set("dac", FUNC(dac_bit_interface::write)); - m_maincpu->in_spim().set(FUNC(palm_state::spi_in)); + m_maincpu->in_spim().set(FUNC(palm_state::spi_from_hw)); m_maincpu->out_flm().set(FUNC(palm_state::flm_out)); m_maincpu->out_llp().set(FUNC(palm_state::llp_out)); m_maincpu->out_lsclk().set(FUNC(palm_state::lsclk_out)); m_maincpu->out_ld().set(FUNC(palm_state::ld_out)); m_maincpu->set_lcd_info_changed(FUNC(palm_state::lcd_info_changed)); - config.set_maximum_quantum(attotime::from_hz(60)); - /* video hardware */ SCREEN(config, m_screen, SCREEN_TYPE_LCD); m_screen->set_refresh_hz(60); - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); - m_screen->set_video_attributes(VIDEO_UPDATE_BEFORE_VBLANK); m_screen->set_size(160, 160); m_screen->set_visarea(0, 159, 0, 159); m_screen->set_screen_update(FUNC(palm_state::screen_update)); @@ -327,26 +650,113 @@ void palm_state::palm(machine_config &config) DAC_1BIT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25); } -static INPUT_PORTS_START( palm ) - PORT_START( "PENX" ) - PORT_BIT( 0xff, 0x50, IPT_LIGHTGUN_X ) PORT_NAME("Pen X") PORT_MINMAX(0, 0xa0) PORT_SENSITIVITY(50) PORT_CROSSHAIR(X, 1.0, 0.0, 0) +void palmiiic_state::palmiiic(machine_config &config) +{ + /* basic machine hardware */ + MC68EZ328(config, m_maincpu, 32768*506); /* 16.580608 MHz */ + m_maincpu->set_addrmap(AS_PROGRAM, &palmiiic_state::mem_map); + m_maincpu->set_dasm_override(FUNC(palmiiic_state::dasm_override)); - PORT_START( "PENY" ) - PORT_BIT( 0xff, 0x50, IPT_LIGHTGUN_Y ) PORT_NAME("Pen Y") PORT_MINMAX(0, 0xa0) PORT_SENSITIVITY(50) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) + m_maincpu->out_port_b<1>().set(FUNC(palmiiic_state::adc_enable_w)); - PORT_START( "PENB" ) - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Pen Button") PORT_CODE(MOUSECODE_BUTTON1) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, pen_check, 0) + m_maincpu->out_port_c<0>().set(FUNC(palmiiic_state::kbd_row_w<0>)); + m_maincpu->out_port_c<1>().set(FUNC(palmiiic_state::kbd_row_w<1>)); + m_maincpu->out_port_c<2>().set(FUNC(palmiiic_state::kbd_row_w<2>)); - PORT_START( "PORTD" ) - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Power") PORT_CODE(KEYCODE_D) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 0) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Up") PORT_CODE(KEYCODE_Y) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 1) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Down") PORT_CODE(KEYCODE_H) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 2) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Button 1") PORT_CODE(KEYCODE_F) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 3) - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("Button 2") PORT_CODE(KEYCODE_G) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 4) - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("Button 3") PORT_CODE(KEYCODE_J) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 5) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_NAME("Button 4") PORT_CODE(KEYCODE_K) PORT_CHANGED_MEMBER(DEVICE_SELF, palm_state, button_check, 6) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) -INPUT_PORTS_END + m_maincpu->out_port_d<0>().set(FUNC(palmiiic_state::kbd_col_w<0>)); + m_maincpu->out_port_d<1>().set(FUNC(palmiiic_state::kbd_col_w<1>)); + m_maincpu->out_port_d<2>().set(FUNC(palmiiic_state::kbd_col_w<2>)); + m_maincpu->out_port_d<3>().set(FUNC(palmiiic_state::kbd_col_w<3>)); + + m_maincpu->out_port_g<2>().set(FUNC(palmiiic_state::hardware_id_req_w)); + + m_maincpu->in_port_d<0>().set(FUNC(palmiiic_state::kbd_scan_r<0>)); + m_maincpu->in_port_d<1>().set(FUNC(palmiiic_state::kbd_scan_r<1>)); + m_maincpu->in_port_d<2>().set(FUNC(palmiiic_state::kbd_scan_r<2>)); + m_maincpu->in_port_d<3>().set(FUNC(palmiiic_state::kbd_scan_r<3>)); + m_maincpu->in_port_d<4>().set_constant(1); // Active-low, indicates hotsync/dock button press + m_maincpu->in_port_d<6>().set_constant(1); // Active-low, indicates external adapter installed + m_maincpu->in_port_d<7>().set_constant(1); // Active-low, indicates pending power failure + + m_maincpu->in_port_f<0>().set_constant(1); // Active-high, indicates LCD is at full power + m_maincpu->in_port_f<6>().set_constant(1); // Active-high, indicates battery enabled + m_maincpu->in_port_f<7>().set_constant(1); // Active-low, determines sync port attachment + + m_maincpu->out_pwm().set("dac", FUNC(dac_bit_interface::write)); + m_maincpu->in_spim().set(FUNC(palmiiic_state::spi_from_hw)); + m_maincpu->out_spim().set(FUNC(palmiiic_state::spi_to_hw)); + m_maincpu->out_flm().set(FUNC(palmiiic_state::flm_out)); + m_maincpu->out_llp().set(FUNC(palmiiic_state::llp_out)); + m_maincpu->out_lsclk().set(FUNC(palmiiic_state::lsclk_out)); + m_maincpu->out_ld().set(FUNC(palmiiic_state::ld_out)); + m_maincpu->set_lcd_info_changed(FUNC(palmiiic_state::lcd_info_changed)); + + /* internal ram */ + RAM(config, RAM_TAG).set_default_size("8M"); + + /* video hardware */ + SED1375(config, m_sed1375); + + SCREEN(config, m_screen, SCREEN_TYPE_LCD); + m_screen->set_refresh_hz(60); + m_screen->set_size(160, 262); + m_screen->set_visarea(0, 160-1, 0, 220-1); + m_screen->set_screen_update(m_sed1375, FUNC(sed1375_device::screen_update)); + + /* audio hardware */ + SPEAKER(config, "speaker").front_center(); + DAC_1BIT(config, "dac", 0).add_route(ALL_OUTPUTS, "speaker", 0.25); +} + +void palm_state::pilot1k(machine_config &config) +{ + palm_base(config); + + /* internal ram */ + RAM(config, RAM_TAG).set_default_size("128K").set_extra_options("512K,1M,2M,4M,8M"); + + config.set_default_layout(layout_pilot1k); +} + +void palm_state::pilot5k(machine_config &config) +{ + palm_base(config); + + /* internal ram */ + RAM(config, RAM_TAG).set_default_size("512K").set_extra_options("1M,2M,4M,8M"); +} + +void palm_state::palmpro(machine_config &config) +{ + palm_base(config); + + /* internal ram */ + RAM(config, RAM_TAG).set_default_size("1M").set_extra_options("2M,4M,8M"); +} + +void palm_state::palmiii(machine_config &config) +{ + palm_base(config); + + /* internal ram */ + RAM(config, RAM_TAG).set_default_size("2M").set_extra_options("4M,8M"); +} + +void palm_state::palmv(machine_config &config) +{ + palm_base(config); + + /* internal ram */ + RAM(config, RAM_TAG).set_default_size("2M").set_extra_options("4M,8M"); +} + +void palm_state::palmvx(machine_config &config) +{ + palm_base(config); + + /* internal ram */ + RAM(config, RAM_TAG).set_default_size("8M"); +} /*************************************************************************** @@ -539,74 +949,24 @@ ROM_START( spt1740 ) ROM_RELOAD(0x000000, 0x004000) ROM_END -void palm_state::pilot1k(machine_config &config) -{ - palm(config); - - /* internal ram */ - RAM(config, RAM_TAG).set_default_size("128K").set_extra_options("512K,1M,2M,4M,8M"); - - config.set_default_layout(layout_pilot1k); -} - -void palm_state::pilot5k(machine_config &config) -{ - palm(config); - - /* internal ram */ - RAM(config, RAM_TAG).set_default_size("512K").set_extra_options("1M,2M,4M,8M"); -} - -void palm_state::palmpro(machine_config &config) -{ - palm(config); - - /* internal ram */ - RAM(config, RAM_TAG).set_default_size("1M").set_extra_options("2M,4M,8M"); -} - -void palm_state::palmiii(machine_config &config) -{ - palm(config); - - /* internal ram */ - RAM(config, RAM_TAG).set_default_size("2M").set_extra_options("4M,8M"); -} - -void palm_state::palmv(machine_config &config) -{ - palm(config); - - /* internal ram */ - RAM(config, RAM_TAG).set_default_size("2M").set_extra_options("4M,8M"); -} - -void palm_state::palmvx(machine_config &config) -{ - palm(config); - - /* internal ram */ - RAM(config, RAM_TAG).set_default_size("8M"); -} - } // anonymous namespace -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1996, pilot1k, 0, 0, pilot1k, palm, palm_state, empty_init, "U.S. Robotics", "Pilot 1000", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND ) -COMP( 1996, pilot5k, pilot1k, 0, pilot5k, palm, palm_state, empty_init, "U.S. Robotics", "Pilot 5000", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND ) -COMP( 1997, palmpers, pilot1k, 0, pilot5k, palm, palm_state, empty_init, "U.S. Robotics", "Palm Pilot Personal", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND ) -COMP( 1997, palmpro, pilot1k, 0, palmpro, palm, palm_state, empty_init, "U.S. Robotics", "Palm Pilot Pro", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND ) -COMP( 1998, palmiii, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm III", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND ) -COMP( 1998, palmiiic, pilot1k, 0, palmiii, palm, palm_state, empty_init, "Palm Inc", "Palm IIIc", MACHINE_NOT_WORKING ) -COMP( 2000, palmm100, pilot1k, 0, palmiii, palm, palm_state, empty_init, "Palm Inc", "Palm m100", MACHINE_NOT_WORKING ) -COMP( 2000, palmm130, pilot1k, 0, palmiii, palm, palm_state, empty_init, "Palm Inc", "Palm m130", MACHINE_NOT_WORKING ) -COMP( 2001, palmm505, pilot1k, 0, palmiii, palm, palm_state, empty_init, "Palm Inc", "Palm m505", MACHINE_NOT_WORKING ) -COMP( 2001, palmm515, pilot1k, 0, palmiii, palm, palm_state, empty_init, "Palm Inc", "Palm m515", MACHINE_NOT_WORKING ) -COMP( 1999, palmv, pilot1k, 0, palmv, palm, palm_state, empty_init, "3Com", "Palm V", MACHINE_NOT_WORKING ) -COMP( 1999, palmvx, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Palm Inc", "Palm Vx", MACHINE_NOT_WORKING ) -COMP( 2001, visor, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Handspring", "Visor Edge", MACHINE_NOT_WORKING ) -COMP( 19??, spt1500, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1500", MACHINE_NOT_WORKING ) -COMP( 19??, spt1700, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1700", MACHINE_NOT_WORKING ) -COMP( 19??, spt1740, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1740", MACHINE_NOT_WORKING ) +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1996, pilot1k, 0, 0, pilot1k, palm, palm_state, empty_init, "U.S. Robotics", "Pilot 1000", MACHINE_SUPPORTS_SAVE ) +COMP( 1996, pilot5k, pilot1k, 0, pilot5k, palm, palm_state, empty_init, "U.S. Robotics", "Pilot 5000", MACHINE_SUPPORTS_SAVE ) +COMP( 1997, palmpers, pilot1k, 0, pilot5k, palm, palm_state, empty_init, "U.S. Robotics", "Palm Pilot Personal", MACHINE_SUPPORTS_SAVE ) +COMP( 1997, palmpro, pilot1k, 0, palmpro, palm, palm_state, empty_init, "U.S. Robotics", "Palm Pilot Pro", MACHINE_SUPPORTS_SAVE ) +COMP( 1998, palmiii, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm III", MACHINE_SUPPORTS_SAVE ) +COMP( 1998, palmiiic, pilot1k, 0, palmiiic, palmez, palmiiic_state, empty_init, "3Com", "Palm IIIc", MACHINE_SUPPORTS_SAVE ) +COMP( 2000, palmm100, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m100", MACHINE_NOT_WORKING ) +COMP( 2000, palmm130, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m130", MACHINE_NOT_WORKING ) +COMP( 2001, palmm505, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m505", MACHINE_NOT_WORKING ) +COMP( 2001, palmm515, pilot1k, 0, palmiii, palm, palm_state, empty_init, "3Com", "Palm m515", MACHINE_NOT_WORKING ) +COMP( 1999, palmv, pilot1k, 0, palmv, palm, palm_state, empty_init, "3Com", "Palm V", MACHINE_NOT_WORKING ) +COMP( 1999, palmvx, pilot1k, 0, palmvx, palm, palm_state, empty_init, "3Com", "Palm Vx", MACHINE_NOT_WORKING ) +COMP( 2001, visor, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Handspring", "Visor Edge", MACHINE_NOT_WORKING ) +COMP( 19??, spt1500, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1500", MACHINE_NOT_WORKING ) +COMP( 19??, spt1700, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1700", MACHINE_NOT_WORKING ) +COMP( 19??, spt1740, pilot1k, 0, palmvx, palm, palm_state, empty_init, "Symbol", "SPT 1740", MACHINE_NOT_WORKING ) #include "palm_dbg.ipp" diff --git a/src/mame/palm/palm_dbg.ipp b/src/mame/palm/palm_dbg.ipp index 81dab407ffc..08cad06df59 100644 --- a/src/mame/palm/palm_dbg.ipp +++ b/src/mame/palm/palm_dbg.ipp @@ -1162,7 +1162,7 @@ static const char *lookup_trap(uint16_t opcode) return nullptr; } -offs_t palm_state::dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer ¶ms) +offs_t palm_base_state::dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer ¶ms) { unsigned result = 0; const char *trap;