diff options
| author | 2026-05-13 17:40:50 +0100 | |
|---|---|---|
| committer | 2026-05-13 18:40:50 +0200 | |
| commit | b66dcb71a2a699526f2ffd9261c20d9ab4876fc4 (patch) | |
| tree | 80cfaaa63fec0099b0ce65beb6c9b2303f8c99ba /src/devices | |
| parent | 53ae362496ad8b8800a057c3c274e65033f574f9 (diff) | |
Current Plug & Play / Handhelds PR / GPL951xx milestone (9 new sets, 3 softlist entries) (#15334)
- continued work on GPL951xx and GPL162xx further documenting registers / differences
- created stub device for GPL951xx RTC allowing some sets to boot a bit further
- added LCDC to GPL951xx based games (all of them have one) and allow bftetris to render graphics as it programs it directly
- added 'timebase' timers to GPL951xx and GPL162xx emulation, which was also required by bftetris and others. Discovered that bornkidh and beijuehh have a protection function in the timebase interrupt that needs studying (disabled it in those cases for now)
- added 'scheduler' interrupt to GPL162xx instead of unknown timer hack, used by smartfp
- moved some code out into devices
- split GPL951xx and GPL162xx implementations as despite similarities there are many differences and sharing a base doesn't make much sense
- removed some hacks (dressmtv doesn't boot to title anymore, but that will be addressed later)
- moved a few files around (GPL951xx has no TV out, so moved those out of tvgames)
New working systems
-------------------
TV Joy Pro 15-in-1 (2500) [Team Europe, David Haywood]
TV Joy Pro 30-in-1 (2501) [Team Europe, David Haywood]
New clones marked not working
-----------------------------
Punirunes (HXR-1 PCB) [Team Europe]
New systems marked not working
------------------------------
Popstar Karaoke [Team Europe, David Haywood]
Wild King (Japan) [Team Europe, David Haywood]
Jewel Pad (Japan) [Team Europe, David Haywood]
Kimi mo Pokemon Hakase! Rotom Pad (Japan) [Team Europe]
Popstarz Karaoke (GK8000) [Team Europe]
Mini Arcade Machine 240-in-1 (translucent case) [Team Europe, David Haywood]
New software list items marked not working
------------------------------------------
popstar_cart.xml:
Popstar Karaoke - 5 Songs [Team Europe, David Haywood]
Popstar Karaoke Vol. 1 [Team Europe, David Haywood]
Popstar Karaoke Vol. 2 [Team Europe, David Haywood]
Diffstat (limited to 'src/devices')
| -rw-r--r-- | src/devices/machine/generalplus_gpl1625x_soc.cpp | 1 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl162xx_soc.cpp | 942 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl162xx_soc.h | 139 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl162xx_soc_video.cpp | 18 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl951xx_rtc.cpp | 151 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl951xx_rtc.h | 54 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl951xx_soc.cpp | 811 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl951xx_soc.h | 175 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_dma.cpp | 288 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_dma.h | 53 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_timebase.cpp | 208 | ||||
| -rw-r--r-- | src/devices/machine/generalplus_gpl_timebase.h | 57 |
12 files changed, 2279 insertions, 618 deletions
diff --git a/src/devices/machine/generalplus_gpl1625x_soc.cpp b/src/devices/machine/generalplus_gpl1625x_soc.cpp index c80303cc02e..444e577b3dd 100644 --- a/src/devices/machine/generalplus_gpl1625x_soc.cpp +++ b/src/devices/machine/generalplus_gpl1625x_soc.cpp @@ -317,6 +317,7 @@ // 78e0 - TimerE_Ctrl // 78e2 - TimerE_Preload // 78e4 - TimerE_UpCount + // 78e8 - TimerF_Ctrl // 78ea - TimerF_Preload // 78ec - TimerF_UpCount diff --git a/src/devices/machine/generalplus_gpl162xx_soc.cpp b/src/devices/machine/generalplus_gpl162xx_soc.cpp index 575a9741df5..c2975929bdf 100644 --- a/src/devices/machine/generalplus_gpl162xx_soc.cpp +++ b/src/devices/machine/generalplus_gpl162xx_soc.cpp @@ -60,9 +60,18 @@ sunplus_gcm394_base_device::sunplus_gcm394_base_device(const machine_config &mco m_space_read_cb(*this, 0), m_space_write_cb(*this), m_dma_complete_cb(*this), - m_alt_periodic_irq(false), m_boot_mode(0), - m_cs_callback(*this, DEVICE_SELF, FUNC(sunplus_gcm394_base_device::default_cs_callback)) + m_cs_callback(*this, DEVICE_SELF, FUNC(sunplus_gcm394_base_device::default_cs_callback)), + m_timer_a(*this, "timer_a"), + m_timer_b(*this, "timer_b"), + m_timer_c(*this, "timer_c"), + m_timer_d(*this, "timer_d"), + m_timer_e(*this, "timer_e"), + m_timer_f(*this, "timer_f"), + m_scheduler(*this, "scheduler"), + m_gpl_dma(*this, "gpl_dma"), + m_gpl_timebase(*this, "gpl_timebase"), + m_disable_timebase_interrupts(false) { } @@ -80,242 +89,40 @@ void sunplus_gcm394_base_device::default_cs_callback(u16 cs0, u16 cs1, u16 cs2, } -// **************************************** SYSTEM DMA device ************************************************* - -u16 sunplus_gcm394_base_device::read_dma_params(int channel, int offset) -{ - u16 retdata = m_dma_params[offset][channel]; - LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::read_dma_params (channel %01x) %01x returning %04x\n", machine().describe_context(), channel, offset, retdata); - return retdata; -} - -void sunplus_gcm394_base_device::write_dma_params(int channel, int offset, u16 data) -{ - LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::write_dma_params (channel %01x) %01x %04x\n", machine().describe_context(), channel, offset, data); - - m_dma_params[offset][channel] = data; - - // TODO: very likely DMA happens whenever the length is not 0, as long as it's been enabled previously - // jak_prft doesn't rewrite the offset 0 register between requests, and instead writes the length - // as the final thing for each new request. other games do not write the length last, but turn off - // register 0 before writing params, and enable it again afterwards - // if that's the case, this code can be refactored to work on 'length' instead of the m_dma_latched - - if (offset == 3) - { - m_dma_latched[channel] = true; - - if (m_dma_params[0][channel] & 1) - trigger_systemm_dma(channel); - } - - if (offset == 0 && (data & 1)) - { - if (m_dma_latched[channel]) - trigger_systemm_dma(channel); - } - -} - - -u16 sunplus_gcm394_base_device::system_dma_params_channel0_r(offs_t offset) -{ - return read_dma_params(0, offset); -} - - -void sunplus_gcm394_base_device::system_dma_params_channel0_w(offs_t offset, u16 data) -{ - write_dma_params(0, offset, data); -} - -u16 sunplus_gcm394_base_device::system_dma_params_channel1_r(offs_t offset) -{ - return read_dma_params(1, offset); -} - -void sunplus_gcm394_base_device::system_dma_params_channel1_w(offs_t offset, u16 data) -{ - write_dma_params(1, offset, data); -} - -u16 sunplus_gcm394_base_device::system_dma_params_channel2_r(offs_t offset) -{ - return read_dma_params(2, offset); -} - -void sunplus_gcm394_base_device::system_dma_params_channel2_w(offs_t offset, u16 data) -{ - write_dma_params(2, offset, data); -} - -u16 sunplus_gcm394_base_device::system_dma_params_channel3_r(offs_t offset) -{ - return read_dma_params(3, offset); -} - -void sunplus_gcm394_base_device::system_dma_params_channel3_w(offs_t offset, u16 data) -{ - write_dma_params(3, offset, data); -} - - - - -u16 sunplus_gcm394_base_device::system_dma_status_r() -{ - LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_status_r (7abf)\n", machine().describe_context()); - - // bit 0 = channel 0 ready - // bit 1 = channel 1 ready - - return 0x00ff; -} - -void sunplus_gcm394_base_device::trigger_systemm_dma(int channel) -{ - u16 mode = m_dma_params[0][channel]; - u32 source = m_dma_params[1][channel] | (m_dma_params[4][channel] << 16); - u32 dest = m_dma_params[2][channel] | (m_dma_params[5][channel] << 16) ; - u32 length = m_dma_params[3][channel] | (m_dma_params[6][channel] << 16); - int sourcedelta = 0; - int destdelta = 0; - - if ((mode & 0xa0) == 0x00) - sourcedelta = 1; - else if ((mode & 0xa0) == 0x20) - sourcedelta = -1; - - if ((mode & 0x50) == 0x00) - destdelta = 1; - else if ((mode & 0x50) == 0x10) - destdelta = -1; - - LOGMASKED(LOG_GCM394_SYSDMA, "%s:possible DMA operation with params mode:%04x source:%08x (word offset) dest:%08x (word offset) length:%08x (words) while csbank is %02x\n", machine().describe_context(), mode, source, dest, length, m_membankswitch_7810 ); - - // wrlshunt transfers ROM to RAM, all RAM write addresses have 0x800000 in the destination set - - source &= 0x0fffffff; - length &= 0x0fffffff; // gormiti - - for (int i = 0; i < length; i++) - { - u16 val; - if (mode & 0x1000) - { - val = (read_space(source) & 0xFF) | (read_space(source) << 8); - i++; - } - else - { - val = read_space(source); - } - - source += sourcedelta; - - if (mode & 0x2000) - { - write_space(dest, val & 0xFF); - dest += destdelta; - write_space(dest, val >> 8); - } - else - { - write_space(dest, val); - } - - dest += destdelta; - } - - m_dma_complete_cb(1); // allow some driver specific hacks for service modes - - // clear params after operation - m_dma_params[0][channel] = m_dma_params[0][channel] & 0x00f7; - - m_dma_params[1][channel] = m_dma_params[2][channel] = m_dma_params[3][channel] = m_dma_params[4][channel] = m_dma_params[5][channel] = m_dma_params[6][channel] = 0x0000; - m_dma_latched[channel] = false; - - //machine().debug_break(); -} - -void sunplus_gcm394_base_device::system_dma_7abf_unk_w(u16 data) -{ - // if this isn't trigger, is it enable? (which could maybe used as similar if DMA only starts to happen if unmasked?) - - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_7abf_unk_w %04x\n", machine().describe_context(), data); -} - -u16 sunplus_gcm394_base_device::system_dma_memtype_r() -{ - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_memtype_r\n", machine().describe_context()); - return m_system_dma_memtype; -} - -void sunplus_gcm394_base_device::system_dma_memtype_w(u16 data) -{ - static char const* const types[16] = - { - "Unused / USB", - "DAC CHA", - "UART TX", - "UART RX", - "SD/MMC", - "NAND Flash", - "Serial Interface", - "DAC CHB", - "ADC Audo Sample Full", - "SPI TX", - "SPI RX", - "RESERVED (c)", - "RESERVED (d)", - "RESERVED (e)", - "RESERVED (f)" - }; - - m_system_dma_memtype = data; - - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_dma_memtype_w %04x (CH3: %s | CH2: %s | CH1: %s | CH0: %s )\n", machine().describe_context(), data, - types[((m_system_dma_memtype>>12)&0xf)], - types[((m_system_dma_memtype>>8)&0xf)], - types[((m_system_dma_memtype>>4)&0xf)], - types[((m_system_dma_memtype)&0xf)]); - -} - -u16 sunplus_gcm394_base_device::system_7a35_r() +u16 sunplus_gcm394_base_device::usb_7a35_r() { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a35_r\n", machine().describe_context()); + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a35_r\n", machine().describe_context()); return machine().rand(); } -u16 sunplus_gcm394_base_device::system_7a37_r() +u16 sunplus_gcm394_base_device::usb_7a37_r() { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a37_r\n", machine().describe_context()); + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a37_r\n", machine().describe_context()); return machine().rand(); } -u16 sunplus_gcm394_base_device::system_7a39_r() +u16 sunplus_gcm394_base_device::usb_7a39_r() { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a39_r\n", machine().describe_context()); + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a39_r\n", machine().describe_context()); return machine().rand(); } -u16 sunplus_gcm394_base_device::system_7a3a_r() +u16 sunplus_gcm394_base_device::usb_7a3a_r() { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a3a_r\n", machine().describe_context()); + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a3a_r\n", machine().describe_context()); return machine().rand(); } -u16 sunplus_gcm394_base_device::system_7a46_r() +u16 sunplus_gcm394_base_device::usb_7a46_r() { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a46_r\n", machine().describe_context()); + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a46_r\n", machine().describe_context()); return machine().rand(); } -u16 sunplus_gcm394_base_device::system_7a54_r() +u16 sunplus_gcm394_base_device::usb_7a54_r() { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::system_7a54_r\n", machine().describe_context()); + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::usb_7a54_r\n", machine().describe_context()); return machine().rand(); } @@ -327,11 +134,11 @@ u16 sunplus_gcm394_base_device::power_state_r() return 0x0002; } -u16 sunplus_gcm394_base_device::unkarea_78fb_status_r() +u16 sunplus_gcm394_base_device::dac_pga_r() { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_78fb_status_r\n", machine().describe_context()); - m_78fb ^= 0x0100; // status flag for something? - return m_78fb; + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::dac_pga_r\n", machine().describe_context()); + m_dac_pga ^= 0x0100; // status flag for something? + return m_dac_pga; } // sets bit 0x0002 then expects it to have cleared @@ -340,13 +147,33 @@ void sunplus_gcm394_base_device::cache_ctrl_w(u16 data) { LOGMASKED(LOG_GCM394, // **************************************** 78xx region stubs ************************************************* -u16 sunplus_gcm394_base_device::unkarea_782d_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_782d_r\n", machine().describe_context()); return m_782d; } -void sunplus_gcm394_base_device::unkarea_782d_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_782d_w %04x\n", machine().describe_context(), data); m_782d = data; } +u16 sunplus_gcm394_base_device::raw_war_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::raw_war_r\n", machine().describe_context()); return m_782d; } +void sunplus_gcm394_base_device::raw_war_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::raw_war_w %04x\n", machine().describe_context(), data); m_782d = data; } -u16 sunplus_gcm394_base_device::unkarea_7803_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7803_r\n", machine().describe_context()); return m_sys_ctrl; } -void sunplus_gcm394_base_device::unkarea_7803_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7803_w %04x\n", machine().describe_context(), data); m_sys_ctrl = data; } +u16 sunplus_gcm394_base_device::sys_ctrl_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::sys_ctrl_r\n", machine().describe_context()); return m_sys_ctrl; } +void sunplus_gcm394_base_device::sys_ctrl_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::sys_ctrl_w %04x\n", machine().describe_context(), data); m_sys_ctrl = data; } -void sunplus_gcm394_base_device::clock_ctrl_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::clock_ctrl_w %04x\n", machine().describe_context(), data); m_clock_ctrl = data; } +void sunplus_gcm394_base_device::clock_ctrl_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::clock_ctrl_w %04x\n", machine().describe_context(), data); + m_clock_ctrl = data; +} + +u16 sunplus_gcm394_base_device::clk_ctrl0_r() +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::clk_ctrl0_r\n", machine().describe_context()); + return 0x0000; +} + +void sunplus_gcm394_base_device::clk_ctrl0_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::clk_ctrl0 %04x\n", machine().describe_context(), data); +} + +void sunplus_gcm394_base_device::watchdog_ctrl_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::watchdog_ctrl_w %04x\n", machine().describe_context(), data); +} void sunplus_gcm394_base_device::waitmode_enter_780c_w(u16 data) { @@ -387,6 +214,17 @@ void sunplus_gcm394_base_device::pllchange_w(u16 data) m_pllchange = data; } +u16 sunplus_gcm394_base_device::pllclkwait_r() +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::pllclkwait_r\n", machine().describe_context()); + return 0x0000; +} + +void sunplus_gcm394_base_device::pllclkwait_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::pllclkwait_w %04x\n", machine().describe_context(), data); +} + void sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w(offs_t offset, u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::chipselect_csx_memory_device_control_w %04x (782x registers offset %d)\n", machine().describe_context(), data, offset); @@ -417,7 +255,7 @@ void sunplus_gcm394_base_device::device_post_load() m_cs_callback(m_782x[0], m_782x[1], m_782x[2], m_782x[3], m_782x[4]); } -void sunplus_gcm394_base_device::unkarea_7835_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7835_w %04x\n", machine().describe_context(), data); m_7835 = data; } +void sunplus_gcm394_base_device::mcs0_page_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::mcs0_page_w %04x\n", machine().describe_context(), data); m_7835 = data; } // IO here? @@ -588,7 +426,7 @@ void sunplus_gcm394_base_device::iod_data_w(u16 data) u16 sunplus_gcm394_base_device::iod_buffer_r() { LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::iod_buffer_r\n", machine().describe_context()); - return 0xffff;// m_7871; + return 0xffff; } void sunplus_gcm394_base_device::iod_buffer_w(u16 data) @@ -643,6 +481,18 @@ void sunplus_gcm394_base_device::iod_mux_w(u16 data) LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::iod_mux_w %04x\n", machine().describe_context(), data); } +u16 sunplus_gcm394_base_device::ioe_buffer_r() +{ + LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioe_buffer_r\n", machine().describe_context()); + return 0xffff; +} + +void sunplus_gcm394_base_device::ioe_buffer_w(u16 data) +{ + LOGMASKED(LOG_GCM394_IO, "%s:sunplus_gcm394_base_device::ioe_buffer_w %04x\n", machine().describe_context(), data); + //m_porte_out(data); +} + u16 sunplus_gcm394_base_device::ioe_dir_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::ioe_dir_r\n", machine().describe_context()); @@ -667,11 +517,27 @@ void sunplus_gcm394_base_device::ioe_attrib_w(u16 data) m_ioe_attrib = data; } -void sunplus_gcm394_base_device::int_status1_w(u16 data) -{ - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status1_w %04x\n", machine().describe_context(), data); - m_int_status1 = data; -} + +// P_INT_Status1 (different on GPL162xx vs GP95xx) +// 15 KEYIF +// 14 ADCRIF +// 13 TFTUFIF +// 12 TFTEIF +// +// 11 UTIRIF +// 10 SPIIF +// 9 FPIF +// 8 +// +// 7 ASIF +// 6 +// 5 AUDBIF +// 4 AUDAIF + +// 3 USB +// 2 DMA +// 1 EXTBIF +// 0 EXTAIF u16 sunplus_gcm394_base_device::int_status1_r() { @@ -679,10 +545,87 @@ u16 sunplus_gcm394_base_device::int_status1_r() return 0x0000;// machine().rand(); } +void sunplus_gcm394_base_device::int_status1_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status1_w %04x\n", machine().describe_context(), data); + //m_int_status1 = data; +} + +// P_INT_Status2 (different on GPL162xx vs GP95xx) +// 15 TMDIF +// 14 TMCIF +// 13 TMBIF +// 12 TMAIF +// +// 11 KSIF +// 10 TMBCIF +// 9 TMBBIF +// 8 TMBAIF +// +// 7 SDC2 +// 6 SDC1 +// 5 +// 4 NAND +// +// 3 +// 2 SCHIF +// 1 ALMIF +// 0 HMSIF + u16 sunplus_gcm394_base_device::int_status2_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status2_r\n", machine().describe_context()); - return 0xffff;// machine().rand(); + u16 ret = 0; + + if (m_gpl_timebase->timebasea_irq_flag()) + ret |= 0x0100; + + if (m_gpl_timebase->timebaseb_irq_flag()) + ret |= 0x0200; + + if (m_gpl_timebase->timebasec_irq_flag()) + ret |= 0x0400; + + return ret; +} + +void sunplus_gcm394_base_device::int_status2_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status2_w %04x\n", machine().describe_context(), data); + // none of this bits are listed as wrieable for GPL95xx or GPL162xx +} + +// P_INT_Status3 (different on GPL162xx vs GP95xx) +// 15 +// 14 +// 13 +// 12 +// +// 11 +// 10 +// 9 +// 8 UMAA +// +// 7 +// 6 +// 5 +// 4 +// +// 3 +// 2 BEAT +// 1 ENV +// 0 CHANNEL + +u16 sunplus_gcm394_base_device::int_status3_r() +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status3_r\n", machine().describe_context()); + return 0x0000; +} + +void sunplus_gcm394_base_device::int_status3_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::int_status3_w %04x\n", machine().describe_context(), data); + // bit 2 (SPU Beat Interrupt) is listed as R/W for GPL95, but not GPL162? (verify) } void sunplus_gcm394_base_device::int_priority_1_w(u16 data) @@ -709,58 +652,115 @@ void sunplus_gcm394_base_device::mint_ctrl_w(u16 data) m_misc_int_ctrl = data; } -void sunplus_gcm394_base_device::timebasea_ctrl_w(u16 data) +// FIQ +// many sources can be set to FIQ +// +// IRQ0 +// Audio Channel A FIFO Empty +// Audio Channel B FIFO Empty +// +// IRQ1 +// ? +// +// IRQ2 +// External interrupt A +// +// IRQ3 +// SPI interrupt +// DMA interrupt +// USB interrupt +// +// IRQ4 +// Timer A/B/C/D interrupt +// SPU interrupt +// +// IRQ5 +// Key Change interrupt +// PPU interrupt +// NAND Overflow/Underflow interrupt +// +// IRQ6 +// Timebase C interrupt +// Scheduler interrupt (RTC) +// SDC2 Controller interrupt +// +// IRQ7 +// Timebase A interrupt +// Timebase B interrupt +// Alarm interrupt +// Hour/Minute/Second/Half-Second interrupt (RTC) +// Unexpected memory access interrupt + +void sunplus_gcm394_base_device::update_interrupts(int state) { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebasea_ctrl_w %04x\n", machine().describe_context(), data); - m_timebasea_ctrl = data; + if ((m_gpl_timebase->timebasea_irq_flag() && !m_disable_timebase_interrupts) || (m_gpl_timebase->timebaseb_irq_flag() && !m_disable_timebase_interrupts)) + { + set_state_unsynced(UNSP_IRQ7_LINE, ASSERT_LINE); + } + else + { + set_state_unsynced(UNSP_IRQ7_LINE, CLEAR_LINE); + } + + if ((m_gpl_timebase->timebasec_irq_flag() && !m_disable_timebase_interrupts) || (m_rtc_int_status & 0x0100)) + { + set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE); + } + else + { + set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE); + } } -void sunplus_gcm394_base_device::timebaseb_ctrl_w(u16 data) + +// programmable timers + +TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_a_cb) { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_w %04x\n", machine().describe_context(), data); - m_timebaseb_ctrl = data; } -u16 sunplus_gcm394_base_device::timebasec_ctrl_r() +TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_b_cb) { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebasec_ctrl_r\n", machine().describe_context()); - return 0xffff;// m_timebasec_ctrl; } -void sunplus_gcm394_base_device::timebasec_ctrl_w(u16 data) +TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_c_cb) { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebasec_ctrl_w %04x\n", machine().describe_context(), data); - m_timebasec_ctrl = data; } -void sunplus_gcm394_base_device::timebase_reset_w(u16 data) +TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_d_cb) { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timebase_reset_w %04x\n", machine().describe_context(), data); - m_timebase_reset = data; } -u16 sunplus_gcm394_base_device::cha_ctrl_r() +TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_e_cb) { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::cha_ctrl_r\n", machine().describe_context()); - return 0xffff; } -void sunplus_gcm394_base_device::cha_ctrl_w(u16 data) +TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::timer_f_cb) { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::cha_ctrl_w %04x\n", machine().describe_context(), data); - m_cha_ctrl = data; } u16 sunplus_gcm394_base_device::timera_ctrl_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timera_ctrl_r\n", machine().describe_context()); - return machine().rand(); + return m_timera_ctrl; +} + +void sunplus_gcm394_base_device::timera_ctrl_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timera_ctrl_w %04x\n", machine().describe_context(), data); + m_timera_ctrl = data; } u16 sunplus_gcm394_base_device::timerb_ctrl_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timerb_ctrl_r\n", machine().describe_context()); - return 0xffff; + return m_timerb_ctrl; +} + +void sunplus_gcm394_base_device::timerb_ctrl_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::timerb_ctrl_w %04x\n", machine().describe_context(), data); + m_timerb_ctrl = data; } u16 sunplus_gcm394_base_device::timerc_ctrl_r() @@ -775,14 +775,74 @@ u16 sunplus_gcm394_base_device::timerd_ctrl_r() return machine().rand(); } -// **************************************** 793x uknown region stubs ************************************************* +// CHA (for sound output) + +u16 sunplus_gcm394_base_device::cha_ctrl_r() +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::cha_ctrl_r\n", machine().describe_context()); + return 0xffff; +} + +void sunplus_gcm394_base_device::cha_ctrl_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::cha_ctrl_w %04x\n", machine().describe_context(), data); + m_cha_ctrl = data; +} + + +// UART -u16 sunplus_gcm394_base_device::unkarea_7904_r() +u16 sunplus_gcm394_base_device::uart_status_r() { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7904_r\n", machine().describe_context()); + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::uart_status_r\n", machine().describe_context()); return machine().rand(); // lazertag waits on a bit, status flag for something? } +// RTC + +TIMER_DEVICE_CALLBACK_MEMBER(sunplus_gcm394_base_device::scheduler_cb) +{ + if (m_rtc_int_ctrl & 0x0100) + { + logerror("scheduler setting\n"); + m_rtc_int_status |= 0x0100; + update_interrupts(1); + } +} + + +// P_RTC_Ctrl +// +// 15 RTCEN - RTC Module Enable +// 14 +// 13 +// 12 + +// 11 +// 10 ALMEN - Alarm Function Enable +// 9 HMSEN - Hour/Minute/Second Update Enable +// 8 SCHEN - Scheduler Function Enable + +// 7 +// 6 +// 5 +// 4 + +// 3 +// 2 SCHSEL[2] - Secheduler Period +// 1 SCHSEL[1] +// 0 SCHSEL[0] +// +// Scheduler Periods are +// 0: 16hz +// 1: 32Hz +// 2: 64Hz +// 3: 128Hz +// 4: 256Hz +// 5: 512Hz +// 6: 1024Hz +// 7: 2048Hz + u16 sunplus_gcm394_base_device::rtc_ctrl_r() { // does this return data written, or is it a status flag? @@ -792,10 +852,60 @@ u16 sunplus_gcm394_base_device::rtc_ctrl_r() void sunplus_gcm394_base_device::rtc_ctrl_w(u16 data) { - LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_ctrl_w %04x\n", machine().describe_context(), data); + u16 no_use = data & 0x78f8; + u8 rtcen = (data & 0x8000) >> 15; + u8 almen = (data & 0x0400) >> 10; + u8 hmsen = (data & 0x0200) >> 9; + u8 schen = (data & 0x0100) >> 8; + u8 schsel = (data & 0x0007) >> 0; + + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_ctrl_w %04x (unused %04x, rtc enable %d, alarm enable %d, hours/min/sec enable %d, scheduler enable %d, schselect %01x)\n", machine().describe_context(), data, no_use, rtcen, almen, hmsen, schen, schsel); m_rtc_ctrl = data; + + if (rtcen) + { + if (schen) + { + //logerror("scheduler timer enabled\n"); + attotime period = attotime::from_hz(1 << (4 + schsel)); + m_scheduler->adjust(period, 0, period); + } + else + { + //logerror("scheduler timer disabled\n"); + m_scheduler->adjust(attotime::never); + } + } + else + { + //logerror("scheduler timer disabled\n"); + m_scheduler->adjust(attotime::never); + } + } +// P_RTC_INT_Status +// +// 15 +// 14 +// 13 +// 12 + +// 11 +// 10 ALMIEF/C - Alarm Interrupt Flag/Clear +// 9 +// 8 SCHIF/C - Scheduler Interrupt Flag/Clear + +// 7 +// 6 +// 5 +// 4 + +// 3 HRIF/C - Hour Interrupt Flag/Clear +// 2 MINIF/C - Minute Interrupt Flag/Clear +// 1 SECIF/C - Second Interrupt Flag/Clear +// 0 HSECIF/C - Half Second Interrupt Flag/Clear + // value of 7935 is read then written in irq6, nothing happens unless bit 0x0100 was set, which could be some kind of irq source being acked? u16 sunplus_gcm394_base_device::rtc_int_status_r() { @@ -807,11 +917,50 @@ void sunplus_gcm394_base_device::rtc_int_status_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_status_w %04x\n", machine().describe_context(), data); m_rtc_int_status &= ~data; - //checkirq6(); + update_interrupts(1); } -u16 sunplus_gcm394_base_device::rtc_int_ctrl_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_ctrl_r\n", machine().describe_context()); return 0x0000; } -void sunplus_gcm394_base_device::rtc_int_ctrl_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_ctrl_w %04x\n", machine().describe_context(), data); m_rtc_int_ctrl = data; } +// P_RTC_INT_Ctrl +// +// 15 +// 14 +// 13 +// 12 + +// 11 +// 10 ALMIEN - Alarm Interrupt Enable (IRQ7) +// 9 +// 8 SCHIEN - Scheduler Interrupt Enable (IRQ6) + +// 7 +// 6 +// 5 +// 4 + +// 3 HRIEN - Hour Interrupt Enable +// 2 MINIEN - Minute Interrupt Enable +// 1 SECIEN - Second Interrupt Enable +// 0 HSECIEN - Half Second Interrupt Enable + +u16 sunplus_gcm394_base_device::rtc_int_ctrl_r() +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_ctrl_r\n", machine().describe_context()); + return m_rtc_int_ctrl; +} + +void sunplus_gcm394_base_device::rtc_int_ctrl_w(u16 data) +{ + u16 no_use = data & 0xfaf0; + u8 almien = (data & 0x0400) >> 10; + u8 schien = (data & 0x0100) >> 8; + u8 hrien = (data & 0x0008) >> 3; + u8 minien = (data & 0x0004) >> 2; + u8 secien = (data & 0x0002) >> 1; + u8 hsecien = (data & 0x0001) >> 0; + + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::rtc_int_ctrl_w %04x (unused %04x, alarm irq enable %d, scheduler irq enable %d, hour irq enable %d, minute irq enable %d, second irq enable %d, half-second irq enable %d)\n", machine().describe_context(), data, no_use, almien, schien, hrien, minien, secien, hsecien); + m_rtc_int_ctrl = data; +} // **************************************** 794x SPI ************************************************* @@ -835,13 +984,30 @@ void sunplus_gcm394_base_device::spi_7942_txdata_w(u16 data) // **************************************** 796x unknown ************************************************* -void sunplus_gcm394_base_device::unkarea_7960_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7960_w %04x\n", machine().describe_context(), data); m_7960 = data; } +void sunplus_gcm394_base_device::adc_setup_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::adc_setup_w %04x\n", machine().describe_context(), data); + m_adc_setup = data; +} // 7961 and 7962 are used by dressmtv when detecting battery status, adc? -u16 sunplus_gcm394_base_device::unkarea_7961_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7961_r\n", machine().describe_context()); return 0xffff; /* return m_7961; */ } -void sunplus_gcm394_base_device::unkarea_7961_w(u16 data) { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7961_w %04x\n", machine().describe_context(), data); m_7961 = data; } +u16 sunplus_gcm394_base_device::madc_ctrl_r() +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::madc_ctrl_r\n", machine().describe_context()); + return 0xffff; /* return m_madc_ctrl; */ +} -u16 sunplus_gcm394_base_device::unkarea_7962_r() { LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::unkarea_7962_r\n", machine().describe_context()); return 0xffff; } +void sunplus_gcm394_base_device::madc_ctrl_w(u16 data) +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::madc_ctrl_w %04x\n", machine().describe_context(), data); + m_madc_ctrl = data; +} + +u16 sunplus_gcm394_base_device::madc_data_r() +{ + LOGMASKED(LOG_GCM394, "%s:sunplus_gcm394_base_device::madc_data_r\n", machine().describe_context()); + return 0xffff; +} // **************************************** fallthrough logger etc. ************************************************* @@ -1011,6 +1177,7 @@ void sunplus_gcm394_base_device::unk_w(offs_t offset, u16 data) // 7806 - Reset_Flag // 7807 - Clock_Ctrl // 7808 - LVR_Ctrl +// 7809 - P_IO_Map_Ctrl // 780a - Watchdog_Ctrl // 780b - Watchdog_Clear // 780c - WAIT @@ -1325,23 +1492,25 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) // 78xx region = system regs? // ###################################################################################################################################################################################### - map(0x007803, 0x007803).rw(FUNC(sunplus_gcm394_base_device::unkarea_7803_r), FUNC(sunplus_gcm394_base_device::unkarea_7803_w)); + map(0x007803, 0x007803).rw(FUNC(sunplus_gcm394_base_device::sys_ctrl_r), FUNC(sunplus_gcm394_base_device::sys_ctrl_w)); + map(0x007804, 0x007804).rw(FUNC(sunplus_gcm394_base_device::clk_ctrl0_r), FUNC(sunplus_gcm394_base_device::clk_ctrl0_w)); map(0x007807, 0x007807).w(FUNC(sunplus_gcm394_base_device::clock_ctrl_w)); // 7808 - // 780a - + map(0x00780a, 0x00780a).w(FUNC(sunplus_gcm394_base_device::watchdog_ctrl_w)); + map(0x00780b, 0x00780b).nopw(); // watchdog clear map(0x00780c, 0x00780c).w(FUNC(sunplus_gcm394_base_device::waitmode_enter_780c_w)); map(0x00780f, 0x00780f).r(FUNC(sunplus_gcm394_base_device::power_state_r)); map(0x007810, 0x007810).rw(FUNC(sunplus_gcm394_base_device::membankswitch_7810_r), FUNC(sunplus_gcm394_base_device::membankswitch_7810_w)); // 7810 Bank Switch Control Register (P_BankSwitch_Ctrl) (maybe) - map(0x007819, 0x007819).rw(FUNC(sunplus_gcm394_base_device::cache_ctrl_r), FUNC(sunplus_gcm394_base_device::cache_ctrl_w)); + map(0x007816, 0x007816).w(FUNC(sunplus_gcm394_base_device::unkarea_7816_w)); // undocumented, check what writes it - map(0x007816, 0x007816).w(FUNC(sunplus_gcm394_base_device::unkarea_7816_w)); map(0x007817, 0x007817).w(FUNC(sunplus_gcm394_base_device::pllchange_w)); + map(0x007818, 0x007818).rw(FUNC(sunplus_gcm394_base_device::pllclkwait_r), FUNC(sunplus_gcm394_base_device::pllclkwait_w)); // 7818 - PLLCLKWait + map(0x007819, 0x007819).rw(FUNC(sunplus_gcm394_base_device::cache_ctrl_r), FUNC(sunplus_gcm394_base_device::cache_ctrl_w)); // ###################################################################################################################################################################################### // 782x region = memory config / control @@ -1353,10 +1522,10 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) // 0047 | 0044 7823 Chip Select (CS3) Memory Device Control (P_MC53_Ctrl) // 0047 | 0044 7824 Chip Select (CS4) Memory Device Control (P_MC54_Ctrl) - map(0x00782d, 0x00782d).rw(FUNC(sunplus_gcm394_base_device::unkarea_782d_r), FUNC(sunplus_gcm394_base_device::unkarea_782d_w)); // on startup + map(0x00782d, 0x00782d).rw(FUNC(sunplus_gcm394_base_device::raw_war_r), FUNC(sunplus_gcm394_base_device::raw_war_w)); // on startup // 782f - map(0x007835, 0x007835).w(FUNC(sunplus_gcm394_base_device::unkarea_7835_w)); + map(0x007835, 0x007835).w(FUNC(sunplus_gcm394_base_device::mcs0_page_w)); // 783a // 783b @@ -1364,51 +1533,69 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) // 783d // 783e - // 7840 - accessed by code in RAM when changing bank in tkmag220 - // 7841 - ^^ + // 7840 - accessed by code in RAM when changing bank in tkmag220 (P_Mem_Ctrl on GPL162xxA) + // 7841 - ^^ (P_Addr_Ctrl on GPL162xxA) // ###################################################################################################################################################################################### - // 786x - 787x - IO related? + // 786x - 788x - IO related + // on GPL162xx the ports each have different capability / features + // and there are a few other bits mixed in here // ###################################################################################################################################################################################### map(0x007860, 0x007860).rw(FUNC(sunplus_gcm394_base_device::ioa_data_r), FUNC(sunplus_gcm394_base_device::ioa_data_w)); // 7860 I/O PortA Data Register map(0x007861, 0x007861).rw(FUNC(sunplus_gcm394_base_device::ioa_buffer_r), FUNC(sunplus_gcm394_base_device::ioa_buffer_w)); // 7861 I/O PortA Buffer Register map(0x007862, 0x007862).rw(FUNC(sunplus_gcm394_base_device::ioa_dir_r), FUNC(sunplus_gcm394_base_device::ioa_dir_w)); // 7862 I/O PortA Direction Register map(0x007863, 0x007863).rw(FUNC(sunplus_gcm394_base_device::ioa_attrib_r), FUNC(sunplus_gcm394_base_device::ioa_attrib_w)); // 7863 I/O PortA Attribute Register + // 7864 P_IOA_Drv map(0x007868, 0x007868).rw(FUNC(sunplus_gcm394_base_device::iob_data_r), FUNC(sunplus_gcm394_base_device::iob_data_w)); // on startup // 7868 I/O PortB Data Register map(0x007869, 0x007869).rw(FUNC(sunplus_gcm394_base_device::iob_buffer_r), FUNC(sunplus_gcm394_base_device::iob_buffer_w)); // 7869 I/O PortB Buffer Register // jak_s500 map(0x00786a, 0x00786a).rw(FUNC(sunplus_gcm394_base_device::iob_dir_r), FUNC(sunplus_gcm394_base_device::iob_dir_w)); // 786a I/O PortB Direction Register map(0x00786b, 0x00786b).rw(FUNC(sunplus_gcm394_base_device::iob_attrib_r), FUNC(sunplus_gcm394_base_device::iob_attrib_w)); // 786b I/O PortB Attribute Register - // 786c I/O PortB Latch / Wakeup + // 786c P_IOB_Latch (I/O PortB Latch / Wakeup) + // 786d P_IOB_Drv map(0x007870, 0x007870).rw(FUNC(sunplus_gcm394_base_device::ioc_data_r) ,FUNC(sunplus_gcm394_base_device::ioc_data_w)); // 7870 I/O PortC Data Register map(0x007871, 0x007871).rw(FUNC(sunplus_gcm394_base_device::ioc_buffer_r), FUNC(sunplus_gcm394_base_device::ioc_buffer_w)); // 7871 I/O PortC Buffer Register map(0x007872, 0x007872).rw(FUNC(sunplus_gcm394_base_device::ioc_dir_r), FUNC(sunplus_gcm394_base_device::ioc_dir_w)); // 7872 I/O PortC Direction Register map(0x007873, 0x007873).rw(FUNC(sunplus_gcm394_base_device::ioc_attrib_r), FUNC(sunplus_gcm394_base_device::ioc_attrib_w)); // 7873 I/O PortC Attribute Register - - // 7874 (data 0x1249) (bkrankp data 0x36db) + // 7874 P_SDRAM_Drv (data 0x1249) (bkrankp data 0x36db) + // 7875 P_IOC_Drv + // 7876 P_SDRAM_Dly (SDRAM Port Delay Adjustment Register) + // 7877 P_IOC_Latch (I/O PortC Latch Register for Wakeup) map(0x007878, 0x007878).rw(FUNC(sunplus_gcm394_base_device::iod_data_r) ,FUNC(sunplus_gcm394_base_device::iod_data_w)); // 7878 I/O PortD Data Register map(0x007879, 0x007879).rw(FUNC(sunplus_gcm394_base_device::iod_buffer_r), FUNC(sunplus_gcm394_base_device::iod_buffer_w)); // 7879 I/O PortD Buffer Register map(0x00787a, 0x00787a).rw(FUNC(sunplus_gcm394_base_device::iod_dir_r), FUNC(sunplus_gcm394_base_device::iod_dir_w)); // 787a I/O PortD Direction Register map(0x00787b, 0x00787b).rw(FUNC(sunplus_gcm394_base_device::iod_attib_r), FUNC(sunplus_gcm394_base_device::iod_attib_w)); // 787b I/O PortD Attribute Register map(0x00787c, 0x00787c).rw(FUNC(sunplus_gcm394_base_device::iod_drv_r), FUNC(sunplus_gcm394_base_device::iod_drv_w)); // P_IOD_Drv - I/O PortD Driving Capability Register - map(0x00787d, 0x00787d).rw(FUNC(sunplus_gcm394_base_device::iod_mux_r), FUNC(sunplus_gcm394_base_device::iod_mux_w)); // 787e (data 0x1249) (bkrankp data 0x36db) - - // 7880 + // 787d - P_IOD_Dly (I/O PortD Delay Adjustment Register) + // 787e - P_CS_Drc (CS Port Driving Capability) + // 787f - P_CS_Dly (CS Port Delay Adjustment Register) + // 7880 - P_IOE_DATA + map(0x007881, 0x007881).rw(FUNC(sunplus_gcm394_base_device::ioe_buffer_r), FUNC(sunplus_gcm394_base_device::ioe_buffer_w)); map(0x007882, 0x007882).rw(FUNC(sunplus_gcm394_base_device::ioe_dir_r), FUNC(sunplus_gcm394_base_device::ioe_dir_w)); map(0x007883, 0x007883).rw(FUNC(sunplus_gcm394_base_device::ioe_attrib_r), FUNC(sunplus_gcm394_base_device::ioe_attrib_w)); - - // 0x7888 (data 0x1249) (bkrankp data 0x36db), written with 7874 / 787c / 787e above + // 7884 - P_IOE_Drv + + // 0x7888 - P_MEM_DRV + // 0x7889 - P_MEM_DLY0 + // 0x788a - P_MEM_DLY1 + // 0x788b - P_MEM_DLY2 + // 0x788c - P_MEM_DLY3 + // 0x788d - P_MEM_DLY4 + // 0x788e - P_MEM_DLY5 + // 0x788f - P_MEM_DLY6 // ###################################################################################################################################################################################### // 78ax - interrupt controller? // ###################################################################################################################################################################################### map(0x0078a0, 0x0078a0).rw(FUNC(sunplus_gcm394_base_device::int_status1_r), FUNC(sunplus_gcm394_base_device::int_status1_w)); - map(0x0078a1, 0x0078a1).r(FUNC(sunplus_gcm394_base_device::int_status2_r)); + map(0x0078a1, 0x0078a1).rw(FUNC(sunplus_gcm394_base_device::int_status2_r), FUNC(sunplus_gcm394_base_device::int_status2_w)); + // 78a2 (is int_status3 on GPL95xx) + map(0x0078a3, 0x0078a3).rw(FUNC(sunplus_gcm394_base_device::int_status3_r), FUNC(sunplus_gcm394_base_device::int_status3_w)); map(0x0078a4, 0x0078a4).w(FUNC(sunplus_gcm394_base_device::int_priority_1_w)); map(0x0078a5, 0x0078a5).w(FUNC(sunplus_gcm394_base_device::int_priority_2_w)); @@ -1420,34 +1607,60 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) // 78bx - timer control? // ###################################################################################################################################################################################### - map(0x0078b0, 0x0078b0).w(FUNC(sunplus_gcm394_base_device::timebasea_ctrl_w)); // 78b0 TimeBase A Control Register (P_TimeBaseA_Ctrl) - map(0x0078b1, 0x0078b1).w(FUNC(sunplus_gcm394_base_device::timebaseb_ctrl_w)); // 78b1 TimeBase B Control Register (P_TimeBaseB_Ctrl) - map(0x0078b2, 0x0078b2).rw(FUNC(sunplus_gcm394_base_device::timebasec_ctrl_r), FUNC(sunplus_gcm394_base_device::timebasec_ctrl_w)); // 78b2 TimeBase C Control Register (P_TimeBaseC_Ctrl) + map(0x0078b0, 0x0078b0).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebasea_ctrl_r), FUNC(gpl_timebase_device::timebasea_ctrl_w)); // 78b0 TimeBase A Control Register (P_TimeBaseA_Ctrl) + map(0x0078b1, 0x0078b1).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebaseb_ctrl_r), FUNC(gpl_timebase_device::timebaseb_ctrl_w)); // 78b1 TimeBase B Control Register (P_TimeBaseB_Ctrl) + map(0x0078b2, 0x0078b2).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebasec_ctrl_r), FUNC(gpl_timebase_device::timebasec_ctrl_w)); // 78b2 TimeBase C Control Register (P_TimeBaseC_Ctrl) + + map(0x0078b8, 0x0078b8).w(m_gpl_timebase, FUNC(gpl_timebase_device::timebase_reset_w)); // 78b8 - TimeBase_Reset - map(0x0078b8, 0x0078b8).w(FUNC(sunplus_gcm394_base_device::timebase_reset_w)); // 78b8 TimeBase Counter Reset Register (P_TimeBase_Reset) - map(0x0078c0, 0x0078c0).r(FUNC(sunplus_gcm394_base_device::timera_ctrl_r)); // beijuehh + map(0x0078c0, 0x0078c0).rw(FUNC(sunplus_gcm394_base_device::timera_ctrl_r), FUNC(sunplus_gcm394_base_device::timera_ctrl_w)); // beijuehh + // 78c1 - TimerA_CCCtrl + // 78c2 - TimerA_Preload + // 78c3 - TimerA_CCReg + // 78c4 - TimerA_UpCount - map(0x0078c8, 0x0078c8).r(FUNC(sunplus_gcm394_base_device::timerb_ctrl_r)); // dressmtv + map(0x0078c8, 0x0078c8).rw(FUNC(sunplus_gcm394_base_device::timerb_ctrl_r), FUNC(sunplus_gcm394_base_device::timerb_ctrl_w)); // dressmtv + // 78c9 - TimerB_CCCtrl + // 78ca - TimerB_Preload + // 78cb - TimerB_CCReg + // 78cc - TimerB_UpCount map(0x0078d0, 0x0078d0).r(FUNC(sunplus_gcm394_base_device::timerc_ctrl_r)); // jak_s500 + // 78d1 - TimerC_CCCtrl + // 78d2 - TimerC_Preload + // 78d3 - TimerC_CCReg + // 78d4 - TimerC_UpCount map(0x0078d8, 0x0078d8).r(FUNC(sunplus_gcm394_base_device::timerd_ctrl_r)); // jak_tsh + // 78da - TimerD_Preload + // 78dc - TimerD_UpCount + // 78e0 - TimerE_Ctrl + // 78e2 - TimerE_Preload + // 78e4 - TimerE_UpCount + + // 78e8 - TimerF_Ctrl + // 78ea - TimerF_Preload + // 78ec - TimerF_UpCount // ###################################################################################################################################################################################### - // 78fx - unknown + // 78fx - DAC FIFO etc. // ###################################################################################################################################################################################### map(0x0078f0, 0x0078f0).rw(FUNC(sunplus_gcm394_base_device::cha_ctrl_r), FUNC(sunplus_gcm394_base_device::cha_ctrl_w)); - map(0x0078fb, 0x0078fb).r(FUNC(sunplus_gcm394_base_device::unkarea_78fb_status_r)); + map(0x0078fb, 0x0078fb).r(FUNC(sunplus_gcm394_base_device::dac_pga_r)); // ###################################################################################################################################################################################### - // 793x - misc? + // 790x - UART // ###################################################################################################################################################################################### - map(0x007904, 0x007904).r(FUNC(sunplus_gcm394_base_device::unkarea_7904_r)); // lazertag after a while + map(0x007904, 0x007904).r(FUNC(sunplus_gcm394_base_device::uart_status_r)); // lazertag after a while + + // ###################################################################################################################################################################################### + // 792x -793x - RTC + // ###################################################################################################################################################################################### map(0x007934, 0x007934).rw(FUNC(sunplus_gcm394_base_device::rtc_ctrl_r), FUNC(sunplus_gcm394_base_device::rtc_ctrl_w)); map(0x007935, 0x007935).rw(FUNC(sunplus_gcm394_base_device::rtc_int_status_r), FUNC(sunplus_gcm394_base_device::rtc_int_status_w)); @@ -1465,33 +1678,35 @@ void sunplus_gcm394_base_device::base_internal_map(address_map &map) map(0x007945, 0x007945).r(FUNC(sunplus_gcm394_base_device::spi_7945_misc_control_reg_r)); // 7945 P_SPI_Misc - SPI Misc Control Register (jak_s500 accelerometer) // ###################################################################################################################################################################################### - // 796x - unknown + // 796x - ADC // ###################################################################################################################################################################################### - // possible adc? - map(0x007960, 0x007960).w(FUNC(sunplus_gcm394_base_device::unkarea_7960_w)); - map(0x007961, 0x007961).rw(FUNC(sunplus_gcm394_base_device::unkarea_7961_r), FUNC(sunplus_gcm394_base_device::unkarea_7961_w)); - map(0x007962, 0x007962).r(FUNC(sunplus_gcm394_base_device::unkarea_7962_r)); + map(0x007960, 0x007960).w(FUNC(sunplus_gcm394_base_device::adc_setup_w)); + map(0x007961, 0x007961).rw(FUNC(sunplus_gcm394_base_device::madc_ctrl_r), FUNC(sunplus_gcm394_base_device::madc_ctrl_w)); + map(0x007962, 0x007962).r(FUNC(sunplus_gcm394_base_device::madc_data_r)); // ###################################################################################################################################################################################### - // 7axx region = system (including dma) + // 7axx region = usb? // ###################################################################################################################################################################################### - // USB? - map(0x007a35, 0x007a35).r(FUNC(sunplus_gcm394_base_device::system_7a35_r)); // wlsair60 - map(0x007a37, 0x007a37).r(FUNC(sunplus_gcm394_base_device::system_7a37_r)); // wlsair60 - map(0x007a39, 0x007a39).r(FUNC(sunplus_gcm394_base_device::system_7a39_r)); // wlsair60 - map(0x007a3a, 0x007a3a).r(FUNC(sunplus_gcm394_base_device::system_7a3a_r)); // ? - map(0x007a46, 0x007a46).r(FUNC(sunplus_gcm394_base_device::system_7a46_r)); // wlsair60 - map(0x007a54, 0x007a54).r(FUNC(sunplus_gcm394_base_device::system_7a54_r)); // wlsair60 + map(0x007a35, 0x007a35).r(FUNC(sunplus_gcm394_base_device::usb_7a35_r)); // wlsair60 + map(0x007a37, 0x007a37).r(FUNC(sunplus_gcm394_base_device::usb_7a37_r)); // wlsair60 + map(0x007a39, 0x007a39).r(FUNC(sunplus_gcm394_base_device::usb_7a39_r)); // wlsair60 + map(0x007a3a, 0x007a3a).r(FUNC(sunplus_gcm394_base_device::usb_7a3a_r)); // ? + map(0x007a46, 0x007a46).r(FUNC(sunplus_gcm394_base_device::usb_7a46_r)); // wlsair60 + map(0x007a54, 0x007a54).r(FUNC(sunplus_gcm394_base_device::usb_7a54_r)); // wlsair60 + + // ###################################################################################################################################################################################### + // 7a80 - 7abf = dma controller + // ###################################################################################################################################################################################### - map(0x007a80, 0x007a87).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel0_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel0_w)); - map(0x007a88, 0x007a8f).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel1_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel1_w)); // jak_tsm writes here - map(0x007a90, 0x007a97).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel2_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel2_w)); // bkrankp writes here (is this on all types or just SPI?) - map(0x007a98, 0x007a9f).rw(FUNC(sunplus_gcm394_base_device::system_dma_params_channel3_r), FUNC(sunplus_gcm394_base_device::system_dma_params_channel3_w)); // not seen, but probably + map(0x007a80, 0x007a87).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel0_r), FUNC(gpl_dma_device::system_dma_params_channel0_w)); + map(0x007a88, 0x007a8f).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel1_r), FUNC(gpl_dma_device::system_dma_params_channel1_w)); // jak_tsm writes here + map(0x007a90, 0x007a97).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel2_r), FUNC(gpl_dma_device::system_dma_params_channel2_w)); // bkrankp writes here (is this on all types or just SPI?) + map(0x007a98, 0x007a9f).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel3_r), FUNC(gpl_dma_device::system_dma_params_channel3_w)); // not seen, but probably - map(0x007abe, 0x007abe).rw(FUNC(sunplus_gcm394_base_device::system_dma_memtype_r), FUNC(sunplus_gcm394_base_device::system_dma_memtype_w)); // 7abe - written with DMA stuff (source type for each channel so that device handles timings properly?) - map(0x007abf, 0x007abf).rw(FUNC(sunplus_gcm394_base_device::system_dma_status_r), FUNC(sunplus_gcm394_base_device::system_dma_7abf_unk_w)); + map(0x007abe, 0x007abe).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_memtype_r), FUNC(gpl_dma_device::system_dma_memtype_w)); // 7abe - written with DMA stuff (source type for each channel so that device handles timings properly?) + map(0x007abf, 0x007abf).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_status_r), FUNC(gpl_dma_device::system_dma_status_w)); // ###################################################################################################################################################################################### // 7bxx-7fxx = audio @@ -1580,10 +1795,6 @@ void sunplus_gcm394_base_device::device_start() m_cs_callback.resolve(); - m_unk_timer = timer_alloc(FUNC(sunplus_gcm394_base_device::unknown_tick), this); - m_unk_timer->adjust(attotime::never); - - save_item(NAME(m_dma_params)); save_item(NAME(m_sys_ctrl)); save_item(NAME(m_clock_ctrl)); save_item(NAME(m_membankswitch_7810)); @@ -1610,38 +1821,24 @@ void sunplus_gcm394_base_device::device_start() save_item(NAME(m_int_priority_2)); save_item(NAME(m_int_priority_3)); save_item(NAME(m_misc_int_ctrl)); - save_item(NAME(m_timebasea_ctrl)); - save_item(NAME(m_timebaseb_ctrl)); - save_item(NAME(m_timebasec_ctrl)); - save_item(NAME(m_timebase_reset)); save_item(NAME(m_cha_ctrl)); - save_item(NAME(m_78fb)); + save_item(NAME(m_dac_pga)); save_item(NAME(m_rtc_ctrl)); save_item(NAME(m_rtc_int_status)); save_item(NAME(m_rtc_int_ctrl)); - save_item(NAME(m_7960)); - save_item(NAME(m_7961)); - save_item(NAME(m_system_dma_memtype)); + save_item(NAME(m_adc_setup)); + save_item(NAME(m_madc_ctrl)); save_item(NAME(m_csbase)); save_item(NAME(m_romtype)); + save_item(NAME(m_timera_ctrl)); + save_item(NAME(m_timerb_ctrl)); } void sunplus_gcm394_base_device::device_reset() { unsp_20_device::device_reset(); - for (int j = 0; j < 3; j++) - { - for (int i = 0; i < 7; i++) - { - m_dma_params[i][j] = 0x0000; - } - m_dma_latched[j] = false; - } - - // 78xx unknown - - m_78fb = 0x0000; + m_dac_pga = 0x0000; m_782d = 0x0000; m_clock_ctrl = 0x0000; @@ -1685,25 +1882,17 @@ void sunplus_gcm394_base_device::device_reset() m_misc_int_ctrl = 0x0000; - m_timebasea_ctrl = 0x0000; - m_timebaseb_ctrl = 0x0000; - m_timebasec_ctrl = 0x0000; - - m_timebase_reset = 0x0000; m_cha_ctrl = 0x0000; - // 79xx unknown - m_rtc_ctrl = 0x0000; m_rtc_int_status = 0x0000; m_rtc_int_ctrl = 0x0000; - m_7960 = 0x0000; - m_7961 = 0x0000; - - m_system_dma_memtype = 0x0000; + m_adc_setup = 0x0000; + m_madc_ctrl = 0x0000; - m_unk_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60)); + m_timera_ctrl = 0x0000; + m_timerb_ctrl = 0x0000; m_spg_video->reset(); } @@ -1713,8 +1902,8 @@ IRQ_CALLBACK_MEMBER(sunplus_gcm394_base_device::irq_vector_cb) { //logerror("irq_vector_cb %d\n", irqline); - if (irqline == UNSP_IRQ6_LINE) - set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE); + //if (irqline == UNSP_IRQ6_LINE) + // set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE); if (irqline == UNSP_IRQ4_LINE) set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE); @@ -1723,16 +1912,6 @@ IRQ_CALLBACK_MEMBER(sunplus_gcm394_base_device::irq_vector_cb) } -void sunplus_gcm394_base_device::checkirq6() -{ -/* - if (m_rtc_int_status & 0x0100) - set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE); - else - set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE); -*/ -} - /* the IRQ6 interrupt on Wrlshunt reads 78a1, checks bit 0400 if it IS set, just increases value in RAM at 1a2e (no ack) @@ -1757,20 +1936,6 @@ void sunplus_gcm394_base_device::checkirq6() */ - -TIMER_CALLBACK_MEMBER(sunplus_gcm394_base_device::unknown_tick) -{ - m_rtc_int_status |= 0x0100; - - if (m_alt_periodic_irq) - set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE); - else - set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE); - - // checkirq6(); -} - - void sunplus_gcm394_base_device::audioirq_w(int state) { //set_state_unsynced(UNSP_IRQ5_LINE, state); @@ -1812,21 +1977,40 @@ void sunplus_gcm394_base_device::write_space(offs_t offset, u16 data) } } - +void sunplus_gcm394_base_device::dma_complete(int state) +{ + m_dma_complete_cb(state); +} void sunplus_gcm394_base_device::device_add_mconfig(machine_config &config) { SUNPLUS_GCM394_AUDIO(config, m_spg_audio, DERIVED_CLOCK(1, 1)); m_spg_audio->write_irq_callback().set(FUNC(sunplus_gcm394_base_device::audioirq_w)); m_spg_audio->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space)); - m_spg_audio->add_route(0, *this, 1.0, 0); m_spg_audio->add_route(1, *this, 1.0, 1); + GPL_DMA(config, m_gpl_dma, 0); + m_gpl_dma->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space)); + m_gpl_dma->space_write_callback().set(FUNC(sunplus_gcm394_base_device::write_space)); + m_gpl_dma->dma_complete_callback().set(FUNC(sunplus_gcm394_base_device::dma_complete)); + + GPL_TIMEBASE(config, m_gpl_timebase, 0); + m_gpl_timebase->updateirqs_callback().set(FUNC(sunplus_gcm394_base_device::update_interrupts)); + GCM394_VIDEO(config, m_spg_video, DERIVED_CLOCK(1, 1), DEVICE_SELF, m_screen); m_spg_video->write_video_irq_callback().set(FUNC(sunplus_gcm394_base_device::videoirq_w)); m_spg_video->space_read_callback().set(FUNC(sunplus_gcm394_base_device::read_space)); m_spg_video->set_video_space(DEVICE_SELF, AS_PROGRAM); + + TIMER(config, "timer_a").configure_generic(FUNC(sunplus_gcm394_base_device::timer_a_cb)); + TIMER(config, "timer_b").configure_generic(FUNC(sunplus_gcm394_base_device::timer_b_cb)); + TIMER(config, "timer_c").configure_generic(FUNC(sunplus_gcm394_base_device::timer_c_cb)); + TIMER(config, "timer_d").configure_generic(FUNC(sunplus_gcm394_base_device::timer_d_cb)); + TIMER(config, "timer_e").configure_generic(FUNC(sunplus_gcm394_base_device::timer_e_cb)); + TIMER(config, "timer_f").configure_generic(FUNC(sunplus_gcm394_base_device::timer_f_cb)); + + TIMER(config, "scheduler").configure_generic(FUNC(sunplus_gcm394_base_device::scheduler_cb)); } diff --git a/src/devices/machine/generalplus_gpl162xx_soc.h b/src/devices/machine/generalplus_gpl162xx_soc.h index ca779e9412e..eed874be1c4 100644 --- a/src/devices/machine/generalplus_gpl162xx_soc.h +++ b/src/devices/machine/generalplus_gpl162xx_soc.h @@ -12,8 +12,13 @@ #pragma once #include "cpu/unsp/unsp.h" +#include "machine/timer.h" + #include "screen.h" #include "emupal.h" + +#include "generalplus_gpl_dma.h" +#include "generalplus_gpl_timebase.h" #include "generalplus_gpl162xx_soc_video.h" #include "spg2xx_audio.h" @@ -43,6 +48,9 @@ public: auto nand_read_callback() { return m_nand_read_cb.bind(); } + // hack for beijuehh / bornkidh + void disable_timebase_interrupts() { m_disable_timebase_interrupts = true; } + template <typename... T> void set_cs_config_callback(T &&... args) { m_cs_callback.set(std::forward<T>(args)...); } template <typename T> void set_cs_space(T &&tag, int no) { @@ -55,7 +63,6 @@ public: void vblank(int state) { m_spg_video->vblank(state); } void set_bootmode(int mode) { m_boot_mode = mode; } - void set_alt_periodic_irq(bool alt) { m_alt_periodic_irq = alt; } IRQ_CALLBACK_MEMBER(irq_vector_cb); void default_cs_callback(u16 cs0, u16 cs1, u16 cs2, u16 cs3, u16 cs4 ); @@ -98,9 +105,6 @@ protected: optional_address_space m_cs_space; u32 m_csbase; - u16 m_dma_params[8][4]; - bool m_dma_latched[4]; - // unk 78xx u16 m_sys_ctrl; @@ -144,25 +148,21 @@ protected: u16 m_misc_int_ctrl; - u16 m_timebasea_ctrl; - u16 m_timebaseb_ctrl; - u16 m_timebasec_ctrl; - - u16 m_timebase_reset; - u16 m_cha_ctrl; - u16 m_78fb; + u16 m_dac_pga; // unk 79xx u16 m_rtc_ctrl; u16 m_rtc_int_status; u16 m_rtc_int_ctrl; - u16 m_7960; - u16 m_7961; + u16 m_adc_setup; + u16 m_madc_ctrl; + + u16 m_timera_ctrl; + u16 m_timerb_ctrl; - u16 m_system_dma_memtype; u16 internalrom_lower32_r(offs_t offset); @@ -177,34 +177,29 @@ protected: devcb_write16 m_space_write_cb; devcb_write_line m_dma_complete_cb; + TIMER_DEVICE_CALLBACK_MEMBER(timer_a_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_b_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_c_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_d_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_e_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_f_cb); + TIMER_DEVICE_CALLBACK_MEMBER(scheduler_cb); + u16 unk_r(offs_t offset); void unk_w(offs_t offset, u16 data); - void write_dma_params(int channel, int offset, u16 data); - u16 read_dma_params(int channel, int offset); - void trigger_systemm_dma(int channel); - - u16 system_dma_params_channel0_r(offs_t offset); - void system_dma_params_channel0_w(offs_t offset, u16 data); - u16 system_dma_params_channel1_r(offs_t offset); - void system_dma_params_channel1_w(offs_t offset, u16 data); - u16 system_dma_params_channel2_r(offs_t offset); - void system_dma_params_channel2_w(offs_t offset, u16 data); - u16 system_dma_params_channel3_r(offs_t offset); - void system_dma_params_channel3_w(offs_t offset, u16 data); - u16 system_dma_status_r(); - void system_dma_7abf_unk_w(u16 data); - u16 system_dma_memtype_r(); - void system_dma_memtype_w(u16 data); u16 power_state_r(); - u16 unkarea_78fb_status_r(); + u16 dac_pga_r(); - u16 unkarea_7803_r(); - void unkarea_7803_w(u16 data); + u16 sys_ctrl_r(); + void sys_ctrl_w(u16 data); void clock_ctrl_w(u16 data); + u16 clk_ctrl0_r(); + void clk_ctrl0_w(u16 data); + void waitmode_enter_780c_w(u16 data); u16 membankswitch_7810_r(); @@ -213,15 +208,20 @@ protected: void unkarea_7816_w(u16 data); void pllchange_w(u16 data); + u16 pllclkwait_r(); + void pllclkwait_w(u16 data); + + void watchdog_ctrl_w(u16 data); + u16 cache_ctrl_r(); void cache_ctrl_w(u16 data); void chipselect_csx_memory_device_control_w(offs_t offset, u16 data); - void unkarea_7835_w(u16 data); + void mcs0_page_w(u16 data); - u16 unkarea_782d_r(); - void unkarea_782d_w(u16 data); + u16 raw_war_r(); + void raw_war_w(u16 data); // Port A u16 ioa_data_r(); @@ -267,16 +267,20 @@ protected: u16 iod_mux_r(); void iod_mux_w(u16 data); - + u16 ioe_buffer_r(); + void ioe_buffer_w(u16 data); u16 ioe_dir_r(); void ioe_dir_w(u16 data); u16 ioe_attrib_r(); void ioe_attrib_w(u16 data); void int_status1_w(u16 data); + void int_status2_w(u16 data); + void int_status3_w(u16 data); u16 int_status1_r(); u16 int_status2_r(); + u16 int_status3_r(); void int_priority_1_w(u16 data); void int_priority_2_w(u16 data); @@ -284,16 +288,13 @@ protected: void mint_ctrl_w(u16 data); - void timebasea_ctrl_w(u16 data); - void timebaseb_ctrl_w(u16 data); - - u16 timebasec_ctrl_r(); - void timebasec_ctrl_w(u16 data); - - void timebase_reset_w(u16 data); - + virtual void update_interrupts(int state); + u16 timera_ctrl_r(); + void timera_ctrl_w(u16 data); + u16 timerb_ctrl_r(); + void timerb_ctrl_w(u16 data); u16 timerc_ctrl_r(); u16 timerd_ctrl_r(); @@ -301,7 +302,7 @@ protected: u16 cha_ctrl_r(); void cha_ctrl_w(u16 data); - u16 unkarea_7904_r(); + u16 uart_status_r(); u16 rtc_ctrl_r(); void rtc_ctrl_w(u16 data); @@ -316,35 +317,45 @@ protected: u16 spi_7945_misc_control_reg_r(); void spi_7942_txdata_w(u16 data); - void unkarea_7960_w(u16 data); - u16 unkarea_7961_r(); - void unkarea_7961_w(u16 data); - u16 unkarea_7962_r(); + void adc_setup_w(u16 data); + u16 madc_ctrl_r(); + void madc_ctrl_w(u16 data); + u16 madc_data_r(); void videoirq_w(int state); void audioirq_w(int state); - u16 system_7a35_r(); - u16 system_7a37_r(); - u16 system_7a39_r(); - u16 system_7a3a_r(); - u16 system_7a46_r(); - u16 system_7a54_r(); - - void checkirq6(); - - emu_timer *m_unk_timer; - - TIMER_CALLBACK_MEMBER(unknown_tick); + u16 usb_7a35_r(); + u16 usb_7a37_r(); + u16 usb_7a39_r(); + u16 usb_7a3a_r(); + u16 usb_7a46_r(); + u16 usb_7a54_r(); inline u16 read_space(offs_t offset); inline void write_space(offs_t offset, u16 data); - bool m_alt_periodic_irq; // might be multiple timers, might be a register to configure, currently a config option. - // config registers (external pins) int m_boot_mode; // 2 pins determine boot mode, likely only read at power-on sunplus_gcm394_cs_callback_device m_cs_callback; + + required_device<timer_device> m_timer_a; + required_device<timer_device> m_timer_b; + required_device<timer_device> m_timer_c; + required_device<timer_device> m_timer_d; + required_device<timer_device> m_timer_e; + required_device<timer_device> m_timer_f; + required_device<timer_device> m_scheduler; + + required_device<gpl_dma_device> m_gpl_dma; + required_device<gpl_timebase_device> m_gpl_timebase; + + // config/hacks + bool m_disable_timebase_interrupts; + +private: + void dma_complete(int state); + }; diff --git a/src/devices/machine/generalplus_gpl162xx_soc_video.cpp b/src/devices/machine/generalplus_gpl162xx_soc_video.cpp index faf840213d7..cf5b56ce346 100644 --- a/src/devices/machine/generalplus_gpl162xx_soc_video.cpp +++ b/src/devices/machine/generalplus_gpl162xx_soc_video.cpp @@ -312,6 +312,11 @@ void gcm394_base_video_device::device_reset() m_sprite_7022_gfxbase_lsb = 0; m_sprite_702d_gfxbase_msb = 0; + + m_page0_addr_lsb = 0; + m_page0_addr_msb = 0; + m_page1_addr_lsb = 0; + m_page1_addr_msb = 0; m_page2_addr_lsb = 0; m_page2_addr_msb = 0; m_page3_addr_lsb = 0; @@ -327,7 +332,10 @@ u32 gcm394_base_video_device::screen_update(screen_device &screen, bitmap_rgb32 // The 'bitmap test mode' in jak_car2 requires this to be black instead. // jak_s500 briely sets pen 0 of the layer to magenta, but then ends up erasing it + bool readfromcsspace = true; + if (!m_cs_space) + readfromcsspace = false; if (0) { @@ -398,12 +406,12 @@ u32 gcm394_base_video_device::screen_update(screen_device &screen, bitmap_rgb32 for (int i = 0; i < 4; i++) { - m_renderer->draw_page(true, m_703a_palettebank, cliprect, scanline, i, m_page0_addr_msb, m_page0_addr_lsb, m_tmap0_scroll, m_tmap0_regs, mem, m_paletteram, m_rowscroll, 0); - m_renderer->draw_page(true, m_703a_palettebank, cliprect, scanline, i, m_page1_addr_msb, m_page1_addr_lsb, m_tmap1_scroll, m_tmap1_regs, mem, m_paletteram, m_rowscroll, 1); - m_renderer->draw_page(true, m_703a_palettebank, cliprect, scanline, i, m_page2_addr_msb, m_page2_addr_lsb, m_tmap2_scroll, m_tmap2_regs, mem, m_paletteram, m_rowscroll, 2); - m_renderer->draw_page(true, m_703a_palettebank, cliprect, scanline, i, m_page3_addr_msb, m_page3_addr_lsb, m_tmap3_scroll, m_tmap3_regs, mem, m_paletteram, m_rowscroll, 3); + m_renderer->draw_page(readfromcsspace, m_703a_palettebank, cliprect, scanline, i, m_page0_addr_msb, m_page0_addr_lsb, m_tmap0_scroll, m_tmap0_regs, mem, m_paletteram, m_rowscroll, 0); + m_renderer->draw_page(readfromcsspace, m_703a_palettebank, cliprect, scanline, i, m_page1_addr_msb, m_page1_addr_lsb, m_tmap1_scroll, m_tmap1_regs, mem, m_paletteram, m_rowscroll, 1); + m_renderer->draw_page(readfromcsspace, m_703a_palettebank, cliprect, scanline, i, m_page2_addr_msb, m_page2_addr_lsb, m_tmap2_scroll, m_tmap2_regs, mem, m_paletteram, m_rowscroll, 2); + m_renderer->draw_page(readfromcsspace, m_703a_palettebank, cliprect, scanline, i, m_page3_addr_msb, m_page3_addr_lsb, m_tmap3_scroll, m_tmap3_regs, mem, m_paletteram, m_rowscroll, 3); - m_renderer->draw_sprites(true, m_use_legacy_mode ? 2 : 1, m_703a_palettebank, highres, cliprect, scanline, i, sprites_addr, mem, m_paletteram, m_spriteram); + m_renderer->draw_sprites(readfromcsspace, m_use_legacy_mode ? 2 : 1, m_703a_palettebank, highres, cliprect, scanline, i, sprites_addr, mem, m_paletteram, m_spriteram); } m_renderer->apply_saturation_and_fade(bitmap, cliprect, scanline); diff --git a/src/devices/machine/generalplus_gpl951xx_rtc.cpp b/src/devices/machine/generalplus_gpl951xx_rtc.cpp new file mode 100644 index 00000000000..da303406d4a --- /dev/null +++ b/src/devices/machine/generalplus_gpl951xx_rtc.cpp @@ -0,0 +1,151 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#include "emu.h" +#include "generalplus_gpl951xx_rtc.h" + +#define LOG_RTC (1U << 1) + +#define VERBOSE (0) + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(GPL951XX_RTC, gpl951xx_rtc_device, "gpl951xx_rtc", "GPL951XX Real Time Clock") + +gpl951xx_rtc_device::gpl951xx_rtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, GPL951XX_RTC, tag, owner, clock), + device_memory_interface(mconfig, *this), + m_space_config("rtc", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(gpl951xx_rtc_device::rtc_regs), this)) +{ +} + +device_memory_interface::space_config_vector gpl951xx_rtc_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(0, &m_space_config) + }; +} + +inline uint8_t gpl951xx_rtc_device::readbyte(offs_t address) +{ + return space().read_byte(address); +} + +inline void gpl951xx_rtc_device::writebyte(offs_t address, uint8_t data) +{ + space().write_byte(address, data); +} + +void gpl951xx_rtc_device::device_validity_check(validity_checker &valid) const +{ +} + +void gpl951xx_rtc_device::device_start() +{ + save_item(NAME(m_rtc_addr)); + save_item(NAME(m_read_dat)); + save_item(NAME(m_write_dat)); + + save_item(NAME(m_reg40)); + save_item(NAME(m_reg50)); +} + +void gpl951xx_rtc_device::device_reset() +{ + m_rtc_addr = 0; + m_read_dat = 0; + m_write_dat = 0; + + m_reg40 = 0; + m_reg50 = 0; +} + +u8 gpl951xx_rtc_device::reg00_r() +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg00_r\n", machine().describe_context()); + return 0x00; +} + +u8 gpl951xx_rtc_device::reg01_r() +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg01_r\n", machine().describe_context()); + return 0x01; +} + +void gpl951xx_rtc_device::reg40_w(u8 data) +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg40_w %02x\n", machine().describe_context(), data); + m_reg40 = data; +} + +u8 gpl951xx_rtc_device::reg50_r() +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg50_r\n", machine().describe_context()); + return m_reg50; +} + +void gpl951xx_rtc_device::reg50_w(u8 data) +{ + LOGMASKED(LOG_RTC, "%s: gpl951xx_rtc_device::reg50_w %02x\n", machine().describe_context(), data); + m_reg50 = data; +} + +void gpl951xx_rtc_device::rtc_regs(address_map &map) +{ + if (!has_configured_map(0)) + { + map(0x00, 0x00).r(FUNC(gpl951xx_rtc_device::reg00_r)); + map(0x01, 0x01).r(FUNC(gpl951xx_rtc_device::reg01_r)); + map(0x40, 0x40).w(FUNC(gpl951xx_rtc_device::reg40_w)); + map(0x50, 0x50).rw(FUNC(gpl951xx_rtc_device::reg50_r), FUNC(gpl951xx_rtc_device::reg50_w)); + // 0x80 - 0x8f reserved + map(0x90, 0xff).ram(); + } +} + + +u16 gpl951xx_rtc_device::rtc_readdata_r() +{ + LOGMASKED(LOG_RTC, "%s: rtc_readdata_r\n", machine().describe_context()); + return m_read_dat; +} + +// 15-1 unused +// 0 RDY +u16 gpl951xx_rtc_device::rtc_ready_r() +{ + LOGMASKED(LOG_RTC, "%s: rtc_ready_r\n", machine().describe_context()); + return 0x0001; +} + + +// 15-1 unused +// 0 SIEN (Serial interface enabled) +void gpl951xx_rtc_device::rtc_ctrl_w(u16 data) +{ + LOGMASKED(LOG_RTC, "%s: rtc_ctrl_w %04x\n", machine().describe_context(), data); +} + +void gpl951xx_rtc_device::rtc_addr_w(u16 data) +{ + LOGMASKED(LOG_RTC, "%s: rtc_addr_w %04x\n", machine().describe_context(), data); + m_rtc_addr = data & 0xff; +} + +void gpl951xx_rtc_device::rtc_writedata_w(u16 data) +{ + LOGMASKED(LOG_RTC, "%s: rtc_writedata_w %04x\n", machine().describe_context(), data); + m_write_dat = data; +} + +// 15-2 unused +// 1 Read Request +// 0 Write Request +void gpl951xx_rtc_device::rtc_request_w(u16 data) +{ + LOGMASKED(LOG_RTC, "%s: rtc_request_w %04x\n", machine().describe_context(), data); + if (data & 1) + writebyte(m_rtc_addr, m_write_dat); + if (data & 2) + m_read_dat = readbyte(m_rtc_addr); +} diff --git a/src/devices/machine/generalplus_gpl951xx_rtc.h b/src/devices/machine/generalplus_gpl951xx_rtc.h new file mode 100644 index 00000000000..11d011fe21b --- /dev/null +++ b/src/devices/machine/generalplus_gpl951xx_rtc.h @@ -0,0 +1,54 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#ifndef MAME_MACHINE_GENERALPLUS_GPL951XX_RTC_H +#define MAME_MACHINE_GENERALPLUS_GPL951XX_RTC_H + +#pragma once + +class gpl951xx_rtc_device : public device_t, + public device_memory_interface +{ +public: + + gpl951xx_rtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void rtc_regs(address_map &map) ATTR_COLD; + + u16 rtc_readdata_r(); + u16 rtc_ready_r(); + void rtc_ctrl_w(u16 data); + void rtc_addr_w(u16 data); + void rtc_writedata_w(u16 data); + void rtc_request_w(u16 data); + +protected: + virtual void device_validity_check(validity_checker &valid) const override; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual space_config_vector memory_space_config() const override; + +private: + const address_space_config m_space_config; + + inline uint8_t readbyte(offs_t address); + inline void writebyte(offs_t address, uint8_t data); + + u8 reg00_r(); + u8 reg01_r(); + + void reg40_w(u8 data); + + u8 reg50_r(); + void reg50_w(u8 data); + + u8 m_rtc_addr; + u8 m_read_dat; + u8 m_write_dat; + + u8 m_reg40; + u8 m_reg50; +}; + +DECLARE_DEVICE_TYPE(GPL951XX_RTC, gpl951xx_rtc_device) + +#endif // MAME_MACHINE_GENERALPLUS_GPL951XX_RTC_H diff --git a/src/devices/machine/generalplus_gpl951xx_soc.cpp b/src/devices/machine/generalplus_gpl951xx_soc.cpp index 6d6eb8a4f79..3c961475fa0 100644 --- a/src/devices/machine/generalplus_gpl951xx_soc.cpp +++ b/src/devices/machine/generalplus_gpl951xx_soc.cpp @@ -5,8 +5,10 @@ #include "generalplus_gpl951xx_soc.h" #define LOG_SPIFC (1U << 1) +#define LOG_TFT (1U << 2) +#define LOG_OTHER (1U << 3) -#define VERBOSE (LOG_SPIFC) +#define VERBOSE (LOG_SPIFC | LOG_TFT | LOG_OTHER) #include "logmacro.h" @@ -309,8 +311,24 @@ void generalplus_gpl951xx_device::spifc_ctrl2_w(u16 data) m_spifc_ctrl2 = data; } +u16 generalplus_gpl951xx_device::spi_improve_r() +{ + LOGMASKED(LOG_SPIFC, "%s: spi_improve_r\n", machine().describe_context()); + return 0x0000; +} + +void generalplus_gpl951xx_device::spi_improve_w(u16 data) +{ + LOGMASKED(LOG_SPIFC, "%s: spi_improve_w %04x\n", machine().describe_context(), data); +} + // Other bits +void generalplus_gpl951xx_device::pm_ctrl_w(u16 data) +{ + LOGMASKED(LOG_SPIFC, "%s: pm_ctrl_w %04x\n", machine().describe_context(), data); +} + u16 generalplus_gpl951xx_device::pllsel_r() { logerror("%s: pllsel_r\n", machine().describe_context()); @@ -324,19 +342,6 @@ void generalplus_gpl951xx_device::pllsel_w(u16 data) m_pllchange = data; } - -u16 generalplus_gpl951xx_device::rtc_readdata_r() -{ - return 0xffff; // hangs if returning 0 -} - -u16 generalplus_gpl951xx_device::rtc_ready_r() -{ - // status bits? - return machine().rand(); -} - - u16 generalplus_gpl951xx_device::byte_swap_r() { return m_byteswap; @@ -351,12 +356,13 @@ void generalplus_gpl951xx_device::byte_swap_w(u16 data) void generalplus_gpl951xx_device::device_start() { - sunplus_gcm394_base_device::device_start(); + unsp_20_device::device_start(); + save_item(NAME(m_byteswap)); - save_item(NAME(m_gpl951xx_timerg_ctrl)); - save_item(NAME(m_gpl951xx_timerg_preload)); - save_item(NAME(m_gpl951xx_timerh_ctrl)); - save_item(NAME(m_gpl951xx_timerh_preload)); + save_item(NAME(m_timerg_ctrl)); + save_item(NAME(m_timerg_preload)); + save_item(NAME(m_timerh_ctrl)); + save_item(NAME(m_timerh_preload)); save_item(NAME(m_spifc_ctrl)); save_item(NAME(m_spifc_ctrl2)); save_item(NAME(m_spifc_addr)); @@ -367,18 +373,32 @@ void generalplus_gpl951xx_device::device_start() save_item(NAME(m_spifc_timing)); save_item(NAME(m_bytes_in_spifc_rx_fifo)); save_item(NAME(m_spi_bank)); + save_item(NAME(m_memmode_wcmd)); save_item(NAME(m_spifc_rx_fifo)); save_item(NAME(m_spifc_rx_read_latch)); + save_item(NAME(m_io_dir)); + save_item(NAME(m_io_attrib)); + save_item(NAME(m_sys_ctrl)); + save_item(NAME(m_clock_ctrl)); + save_item(NAME(m_cache_ctrl)); + save_item(NAME(m_int_priority_1)); + save_item(NAME(m_int_priority_2)); + save_item(NAME(m_int_priority_3)); + save_item(NAME(m_misc_int_ctrl)); + save_item(NAME(m_cha_ctrl)); + save_item(NAME(m_pllchange)); } void generalplus_gpl951xx_device::device_reset() { - sunplus_gcm394_base_device::device_reset(); + unsp_20_device::device_reset(); + m_spg_video->reset(); + m_byteswap = 0; - m_gpl951xx_timerg_ctrl = 0; - m_gpl951xx_timerg_preload = 0; - m_gpl951xx_timerh_ctrl = 0; - m_gpl951xx_timerh_preload = 0; + m_timerg_ctrl = 0; + m_timerg_preload = 0; + m_timerh_ctrl = 0; + m_timerh_preload = 0; m_spifc_ctrl = 0; m_spifc_ctrl2 = 0; m_spifc_addr = 0; @@ -389,8 +409,23 @@ void generalplus_gpl951xx_device::device_reset() m_spifc_timing = 0; m_bytes_in_spifc_rx_fifo = 0; m_spifc_rx_read_latch = 0; - + m_memmode_wcmd = 0; m_spi_bank = 0; + m_sys_ctrl = 0; + m_clock_ctrl = 0; + m_cache_ctrl = 0; + m_int_priority_1 = 0; + m_int_priority_2 = 0; + m_int_priority_3 = 0; + m_misc_int_ctrl = 0; + m_cha_ctrl = 0; + m_pllchange = 0; + + for (int i = 0; i < 6; i++) + { + m_io_dir[i] = 0; + m_io_attrib[i] = 0; + } for (int i = 0; i < 16 * 2; i++) m_spifc_rx_fifo[i] = 0; @@ -398,16 +433,16 @@ void generalplus_gpl951xx_device::device_reset() // Timers -u16 generalplus_gpl951xx_device::gpl951xx_timerg_preload_r() +u16 generalplus_gpl951xx_device::timerg_preload_r() { - logerror("%s: gpl951xx_timerg_preload_r\n", machine().describe_context()); - return m_gpl951xx_timerg_preload; + logerror("%s: timerg_preload_r\n", machine().describe_context()); + return m_timerg_preload; } -void generalplus_gpl951xx_device::gpl951xx_timerg_preload_w(u16 data) +void generalplus_gpl951xx_device::timerg_preload_w(u16 data) { - logerror("%s: gpl951xx_timerg_preload_w %04x\n", machine().describe_context(), data); - m_gpl951xx_timerg_preload = data; + logerror("%s: timerg_preload_w %04x\n", machine().describe_context(), data); + m_timerg_preload = data; } // P_TimerG_Ctrl @@ -429,14 +464,14 @@ void generalplus_gpl951xx_device::gpl951xx_timerg_preload_w(u16 data) // 1 SRCASEL[1] // 0 SRCASEL[0] -u16 generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_r() +u16 generalplus_gpl951xx_device::timerg_ctrl_r() { - logerror("%s: gpl951xx_timerg_ctrl_r\n", machine().describe_context()); - u16 ret = m_gpl951xx_timerg_ctrl; + logerror("%s: timerg_ctrl_r\n", machine().describe_context()); + u16 ret = m_timerg_ctrl; return ret; } -void generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_w(u16 data) +void generalplus_gpl951xx_device::timerg_ctrl_w(u16 data) { u8 tmgif_clear = (data & 0x8000) >> 15; u8 tmgie = (data & 0x4000) >> 14; @@ -446,16 +481,18 @@ void generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_w(u16 data) u8 srcbsel = (data & 0x0070) >> 4; u8 srcasel = (data & 0x000f) >> 0; - logerror("%s: gpl951xx_timerg_ctrl_w %04x (tmgif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), data, tmgif_clear, tmgie, tmgen, ext0sel, ext1sel, srcbsel, srcasel); + logerror("%s: timerg_ctrl_w %04x (tmgif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), data, tmgif_clear, tmgie, tmgen, ext0sel, ext1sel, srcbsel, srcasel); if (data & 0x8000) - m_gpl951xx_timerg_ctrl &= 0x7fff; + { + m_timerg_ctrl &= 0x7fff; + } - if ((data & 0x2000) != (m_gpl951xx_timerg_ctrl & 0x2000)) + if ((data & 0x2000) != (m_timerg_ctrl & 0x2000)) { if (data & 0x2000) { - m_timer_g->adjust(attotime::zero, 0, attotime::from_hz(8'000'000)); + m_timer_g->adjust(attotime::zero, 0, attotime::from_hz(2000)); } else { @@ -463,19 +500,20 @@ void generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_w(u16 data) } } - m_gpl951xx_timerg_ctrl = (m_gpl951xx_timerg_ctrl & 0x8000) | (data & 0x7fff); + m_timerg_ctrl = (m_timerg_ctrl & 0x8000) | (data & 0x7fff); + update_interrupts(1); } -u16 generalplus_gpl951xx_device::gpl951xx_timerh_preload_r() +u16 generalplus_gpl951xx_device::timerh_preload_r() { - logerror("%s: gpl951xx_timerh_preload_r\n", machine().describe_context()); - return m_gpl951xx_timerh_preload; + logerror("%s: timerh_preload_r\n", machine().describe_context()); + return m_timerh_preload; } -void generalplus_gpl951xx_device::gpl951xx_timerh_preload_w(u16 data) +void generalplus_gpl951xx_device::timerh_preload_w(u16 data) { - logerror("%s: gpl951xx_timerh_preload_w %04x\n", machine().describe_context(), data); - m_gpl951xx_timerh_preload = data; + logerror("%s: timerh_preload_w %04x\n", machine().describe_context(), data); + m_timerh_preload = data; } // P_TimerH_Ctrl @@ -500,14 +538,14 @@ void generalplus_gpl951xx_device::gpl951xx_timerh_preload_w(u16 data) // 1 SRCASEL[1] // 0 SRCASEL[0] -u16 generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_r() +u16 generalplus_gpl951xx_device::timerh_ctrl_r() { - u16 ret = m_gpl951xx_timerh_ctrl; - logerror("%s: gpl951xx_timerh_ctrl_r (returning %04x)\n", machine().describe_context(), ret); + u16 ret = m_timerh_ctrl; + logerror("%s: timerh_ctrl_r (returning %04x)\n", machine().describe_context(), ret); return ret; } -void generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_w(u16 data) +void generalplus_gpl951xx_device::timerh_ctrl_w(u16 data) { u8 tmhif_clear = (data & 0x8000) >> 15; u8 tmhie = (data & 0x4000) >> 14; @@ -517,21 +555,21 @@ void generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_w(u16 data) u8 srcbsel = (data & 0x0070) >> 4; u8 srcasel = (data & 0x000f) >> 0; - logerror("%s: gpl951xx_timerh_ctrl_w %04x (tmhif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), data, tmhif_clear, tmhie, tmhen, ext0sel, ext1sel, srcbsel, srcasel); + logerror("%s: timerh_ctrl_w %04x (tmhif_clear %01x) (interrupt enabled %01x) (timer enabled %01x) (ext0sel %01x) (ext1sel %01x) (srcbsel %01x) (srcasel %01x)\n", machine().describe_context(), data, tmhif_clear, tmhie, tmhen, ext0sel, ext1sel, srcbsel, srcasel); if (data & 0x8000) { logerror("cleared timerh flag\n"); - m_gpl951xx_timerh_ctrl &= 0x7fff; + m_timerh_ctrl &= 0x7fff; } - if ((data & 0x2000) != (m_gpl951xx_timerh_ctrl & 0x2000)) + if ((data & 0x2000) != (m_timerh_ctrl & 0x2000)) { logerror("changed\n"); if (data & 0x2000) { logerror("started timerh\n"); - m_timer_h->adjust(attotime::zero, 0, attotime::from_hz(8'000'000)); + m_timer_h->adjust(attotime::zero, 0, attotime::from_hz(2000)); } else { @@ -540,10 +578,114 @@ void generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_w(u16 data) } - m_gpl951xx_timerh_ctrl = (m_gpl951xx_timerh_ctrl & 0x8000) | (data & 0x7fff); + m_timerh_ctrl = (m_timerh_ctrl & 0x8000) | (data & 0x7fff); + update_interrupts(1); +} + + +// TFT + +// 15 +// 14 +// 13 +// 12 +// +// 11 +// 10 +// 9 +// 8 +// +// 7 MEM_STATE[3] or HSTS[1] - horizontal status register +// 6 MEM_STATE[2] or HSTS[0] +// 5 MEM_STATE[1] or VSTS[1] - vertical status register +// 4 MEM_STATE[0] or VSTS[0] +// +// 3 +// 2 +// 1 Frame Interrupt Occured +// 0 + +u16 generalplus_gpl951xx_device::tft_status_r() +{ + u16 ret = 0x0000; + LOGMASKED(LOG_TFT, "%s: tft_status_r\n", machine().describe_context()); + return ret; +} + +// 15 VSU +// 14 INLA +// 13 BEN +// 12 HCMP +// +// 11 DINV +// 10 CINV +// 9 HINV +// 8 VINV +// +// 7 MODE[3] +// 6 MODE[2] +// 5 MODE[1] +// 4 MODE[0] +// +// 3 CLK_SEL[2] +// 2 CLK_SEL[1] +// 1 CLK_SEL[0] +// 0 TFTEN +void generalplus_gpl951xx_device::tft_ctrl_w(u16 data) +{ + u8 vsu = (data & 0x8000) >> 15; + u8 inla = (data & 0x4000) >> 14; + u8 ben = (data & 0x2000) >> 13; + u8 hcmp = (data & 0x1000) >> 12; + u8 dinv = (data & 0x0800) >> 11; + u8 cinv = (data & 0x0400) >> 10; + u8 hinv = (data & 0x0200) >> 9; + u8 vinv = (data & 0x0100) >> 8; + u8 mode = (data & 0x00f0) >> 4; + u8 clk_s = (data & 0x000e) >> 1; + u8 tften = (data & 0x0001) >> 0; + + static const char* modenames[16] = + { + "0: UPS051 mode", + "1: UPS052 mode", + "2: CCIR656 mode", + "3: PARALLEL mode", + "4: TOCN mode", + "5: reserved", + "6: reserved", + "7: reserved", + "8: I80 CMD write", + "9: I80 CMD read", + "a: I80 DATA write", + "b: I80 DATA read", + "c: I80 Continuous mode", + "d: I80 Single mode", + "e: reserved", + "f: reserved" + }; + + LOGMASKED(LOG_TFT, "%s: tft_ctrl_w %04x (vsa %1x inla %1x ben %1x hcmp %1x dinv %1x cinv %1x hinv %1x vinv %1x mode (%s) clck_s %1x tft_en %1x\n", machine().describe_context(), data, + vsu, inla, ben, hcmp, dinv, cinv, hinv, vinv, modenames[mode], clk_s, tften); + + if (tften) + { + if (mode == 0x8) + m_i80_cmd_out(m_memmode_wcmd); + else if (mode == 0x0a) + m_i80_data_out(m_memmode_wcmd); + } +} + +void generalplus_gpl951xx_device::tft_memmode_wcmd_w(u16 data) +{ + LOGMASKED(LOG_TFT, "%s: tft_memmode_wcmd_w %04x\n", machine().describe_context(), data); + m_memmode_wcmd = data; } +// + u16 generalplus_gpl951xx_device::spi_bank_r() { LOGMASKED(LOG_SPIFC, "%s: spi_bank_r\n", machine().describe_context()); @@ -556,6 +698,298 @@ void generalplus_gpl951xx_device::spi_bank_w(u16 data) m_spi_bank = data; } +u16 generalplus_gpl951xx_device::int_status3_r() +{ + u16 ret = 0; + LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_status3_r\n", machine().describe_context()); + + if (m_timerh_ctrl & 0x8000) + ret |= 0x8000; + + if (m_timerg_ctrl & 0x8000) + ret |= 0x4000; + + return ret; +} + +void generalplus_gpl951xx_device::int_status3_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s: generalplus_gpl951xx_device::int_status3_w %04x\n", machine().describe_context(), data); + // bit 2 (SPU Beat Interrupt) is listed as R/W for GPL95, but not GPL162? (verify) +} + +TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_a_cb) +{ +} + +TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_b_cb) +{ +} + +TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_c_cb) +{ +} + +TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_d_cb) +{ +} + +TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_e_cb) +{ +} + +TIMER_DEVICE_CALLBACK_MEMBER(generalplus_gpl951xx_device::timer_f_cb) +{ +} + + +template<int Port> +u16 generalplus_gpl951xx_device::io_data_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_data_r\n", machine().describe_context(), m_portnames[Port]); + return m_port_in[Port](); +} + +template<int Port> +void generalplus_gpl951xx_device::io_data_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_data_w %04x\n", machine().describe_context(), m_portnames[Port], data); + m_port_out[Port](data); +} + +template<int Port> +u16 generalplus_gpl951xx_device::io_buffer_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_buffer_r\n", machine().describe_context(), m_portnames[Port]); + return m_port_in[Port](); +} + +template<int Port> +void generalplus_gpl951xx_device::io_buffer_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_buffer_w %04x\n", machine().describe_context(), m_portnames[Port], data); + m_port_out[Port](data); +} + +template<int Port> +u16 generalplus_gpl951xx_device::io_dir_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_dir_r\n", machine().describe_context(), m_portnames[Port]); + return m_io_dir[Port]; +} + +template<int Port> +void generalplus_gpl951xx_device::io_dir_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_dir_w %04x\n", machine().describe_context(), m_portnames[Port], data); + m_io_dir[Port] = data; +} + +template<int Port> +u16 generalplus_gpl951xx_device::io_attrib_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_attrib_r\n", machine().describe_context(), m_portnames[Port]); + return m_io_attrib[Port]; +} + +template<int Port> +void generalplus_gpl951xx_device::io_attrib_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_attrib_w %04x\n", machine().describe_context(), m_portnames[Port], data); + m_io_attrib[Port] = data; +} + +template<int Port> +u16 generalplus_gpl951xx_device::io_drv_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_drv_r\n", machine().describe_context(), m_portnames[Port]); + return 0xffff; +} + +template<int Port> +void generalplus_gpl951xx_device::io_drv_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_drv_w %04x\n", machine().describe_context(), m_portnames[Port], data); +} + +template<int Port> +u16 generalplus_gpl951xx_device::io_mux_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_mux_r\n", machine().describe_context(), m_portnames[Port]); + return 0xffff; +} + +template<int Port> +void generalplus_gpl951xx_device::io_mux_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_mux_w %04x\n", machine().describe_context(), m_portnames[Port], data); +} + +template<int Port> +u16 generalplus_gpl951xx_device::io_latch_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_latch_r\n", machine().describe_context(), m_portnames[Port]); + return 0xffff; +} + +template<int Port> +void generalplus_gpl951xx_device::io_latch_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_latch_w %04x\n", machine().describe_context(), m_portnames[Port], data); +} + +template<int Port> +u16 generalplus_gpl951xx_device::io_keyen_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_keyen_r\n", machine().describe_context(), m_portnames[Port]); + return 0xffff; +} + +template<int Port> +void generalplus_gpl951xx_device::io_keyen_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::io_%s_keyen_w %04x\n", machine().describe_context(), m_portnames[Port], data); +} + +// Misc + +u16 generalplus_gpl951xx_device::sys_ctrl_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::sys_ctrl_r\n", machine().describe_context()); + return m_sys_ctrl; +} + +void generalplus_gpl951xx_device::sys_ctrl_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::sys_ctrl_w %04x\n", machine().describe_context(), data); + m_sys_ctrl = data; +} + +void generalplus_gpl951xx_device::clock_ctrl_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::clock_ctrl_w %04x\n", machine().describe_context(), data); + m_clock_ctrl = data; +} + +u16 generalplus_gpl951xx_device::clk_ctrl0_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::clk_ctrl0_r\n", machine().describe_context()); + return 0x0000; +} + +void generalplus_gpl951xx_device::clk_ctrl0_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::clk_ctrl0 %04x\n", machine().describe_context(), data); +} + +void generalplus_gpl951xx_device::watchdog_ctrl_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::watchdog_ctrl_w %04x\n", machine().describe_context(), data); +} + +u16 generalplus_gpl951xx_device::power_state_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::power_state_r\n", machine().describe_context()); + return 0x0002; +} + +u16 generalplus_gpl951xx_device::pllclkwait_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::pllclkwait_r\n", machine().describe_context()); + return 0x0000; +} + +void generalplus_gpl951xx_device::pllclkwait_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::pllclkwait_w %04x\n", machine().describe_context(), data); +} + +// sets bit 0x0002 then expects it to have cleared +u16 generalplus_gpl951xx_device::cache_ctrl_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::cache_ctrl_r\n", machine().describe_context()); + return m_cache_ctrl & ~ 0x0002; +} + +void generalplus_gpl951xx_device::cache_ctrl_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::cache_ctrl_w %04x\n", machine().describe_context(), data); + m_cache_ctrl = data; +} + +u16 generalplus_gpl951xx_device::int_status1_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_status1_r\n", machine().describe_context()); + return 0x0000; +} + +void generalplus_gpl951xx_device::int_status1_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_status1_w %04x\n", machine().describe_context(), data); + //m_int_status1 = data; +} + +u16 generalplus_gpl951xx_device::int_status2_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_status2_r\n", machine().describe_context()); + u16 ret = 0; + + if (m_gpl_timebase->timebasea_irq_flag()) + ret |= 0x0100; + + if (m_gpl_timebase->timebaseb_irq_flag()) + ret |= 0x0200; + + if (m_gpl_timebase->timebasec_irq_flag()) + ret |= 0x0400; + + return ret; +} + +void generalplus_gpl951xx_device::int_status2_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_status2_w %04x\n", machine().describe_context(), data); + // none of this bits are listed as writeable for GPL95xx or GPL162xx +} + +void generalplus_gpl951xx_device::int_priority_1_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_priority_1_w %04x\n", machine().describe_context(), data); + m_int_priority_1 = data; +} + +void generalplus_gpl951xx_device::int_priority_2_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_priority_2_w %04x\n", machine().describe_context(), data); + m_int_priority_2 = data; +} + +void generalplus_gpl951xx_device::int_priority_3_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::int_priority_3_w %04x\n", machine().describe_context(), data); + m_int_priority_3 = data; +} + +void generalplus_gpl951xx_device::mint_ctrl_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::mint_ctrl_w %04x\n", machine().describe_context(), data); + m_misc_int_ctrl = data; +} + +// CHA (for sound output) + +u16 generalplus_gpl951xx_device::cha_ctrl_r() +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::cha_ctrl_r\n", machine().describe_context()); + return 0xffff; +} + +void generalplus_gpl951xx_device::cha_ctrl_w(u16 data) +{ + LOGMASKED(LOG_OTHER, "%s:generalplus_gpl951xx_device::cha_ctrl_w %04x\n", machine().describe_context(), data); + m_cha_ctrl = data; +} + u16 generalplus_gpl951xx_device::spi_direct_r(offs_t offset) { @@ -585,6 +1019,19 @@ u16 generalplus_gpl951xx_device::spi_direct_bank_r(offs_t offset) } +template<int Port> +void generalplus_gpl951xx_device::add_port(address_map &map, u32 base) +{ + map(base + 0x0, base + 0x0).rw(FUNC(generalplus_gpl951xx_device::io_data_r<Port>), FUNC(generalplus_gpl951xx_device::io_data_w<Port>)); + map(base + 0x1, base + 0x1).rw(FUNC(generalplus_gpl951xx_device::io_buffer_r<Port>), FUNC(generalplus_gpl951xx_device::io_buffer_w<Port>)); + map(base + 0x2, base + 0x2).rw(FUNC(generalplus_gpl951xx_device::io_dir_r<Port>), FUNC(generalplus_gpl951xx_device::io_dir_w<Port>)); + map(base + 0x3, base + 0x3).rw(FUNC(generalplus_gpl951xx_device::io_attrib_r<Port>), FUNC(generalplus_gpl951xx_device::io_attrib_w<Port>)); + map(base + 0x4, base + 0x4).rw(FUNC(generalplus_gpl951xx_device::io_drv_r<Port>), FUNC(generalplus_gpl951xx_device::io_drv_w<Port>)); + map(base + 0x5, base + 0x5).rw(FUNC(generalplus_gpl951xx_device::io_mux_r<Port>), FUNC(generalplus_gpl951xx_device::io_mux_w<Port>)); + map(base + 0x6, base + 0x6).rw(FUNC(generalplus_gpl951xx_device::io_latch_r<Port>), FUNC(generalplus_gpl951xx_device::io_latch_w<Port>)); + map(base + 0x7, base + 0x7).rw(FUNC(generalplus_gpl951xx_device::io_keyen_r<Port>), FUNC(generalplus_gpl951xx_device::io_keyen_w<Port>)); +} + void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) { map(0x000000, 0x0027ff).ram().share("mainram"); @@ -620,7 +1067,7 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // map(0x007042, 0x007042).rw(m_spg_video, FUNC(gcm394_base_video_device::sprite_7042_extra_r), FUNC(gcm394_base_video_device::sprite_7042_extra_w)); // 7042 - SControl // - // 7050 - TFT_Ctrl + map(0x007050, 0x007050).w(FUNC(generalplus_gpl951xx_device::tft_ctrl_w)); // 7050 - TFT_Ctrl // 7051 - TFT_V_Width // 7052 - TFT_VSync_Setup // 7053 - TFT_V_Start @@ -630,8 +1077,8 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 7057 - TFT_H_Start // 7058 - TFT_H_End // 7059 - TFT_RGB_Ctrl - // 705a - TFT_Status - // 705b - TFT_MemMode_WCmd + map(0x00705a, 0x00705a).r(FUNC(generalplus_gpl951xx_device::tft_status_r)); // 705a - TFT_Status + map(0x00705b, 0x00705b).w(FUNC(generalplus_gpl951xx_device::tft_memmode_wcmd_w)); // 705b - TFT_MemMode_WCmd // 705c - TFT_MemMode_RCmd // // 705e - STN_PIC_SEG @@ -692,14 +1139,14 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 7800 - BodyID // 7801 - unused // 7802 - PwrKey_State - // 7803 - SYS_CTRL - // 7804 - CLK_Ctrl0 + map(0x007803, 0x007803).rw(FUNC(generalplus_gpl951xx_device::sys_ctrl_r), FUNC(generalplus_gpl951xx_device::sys_ctrl_w)); // 7803 - SYS_CTRL (seems quite different between SoCs) + map(0x007804, 0x007804).rw(FUNC(generalplus_gpl951xx_device::clk_ctrl0_r), FUNC(generalplus_gpl951xx_device::clk_ctrl0_w)); // 7804 - CLK_Ctrl0 // 7805 - CLK_Ctrl1 // 7806 - Reset_Flag map(0x007807, 0x007807).w(FUNC(generalplus_gpl951xx_device::clock_ctrl_w)); // 7807 - Clock_Ctrl // 7808 - LVR_Ctrl - // 7809 - PM_Ctrl - // 780a - Watchdog_Ctrl + map(0x00780a, 0x00780a).w(FUNC(generalplus_gpl951xx_device::pm_ctrl_w)); // 7809 - PM_Ctrl + map(0x00780a, 0x00780a).w(FUNC(generalplus_gpl951xx_device::watchdog_ctrl_w)); // 780a - Watchdog_Ctrl map(0x00780b, 0x00780b).nopw(); // Watchdog_Clear // 780c - WAIT // 780d - HALT @@ -713,7 +1160,7 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 7815 - unused // 7816 - unused map(0x007817, 0x007817).rw(FUNC(generalplus_gpl951xx_device::pllsel_r), FUNC(generalplus_gpl951xx_device::pllsel_w)); // 7817 - PLL_Sel - // 7818 - PLLWaitCLK + map(0x007818, 0x007818).rw(FUNC(generalplus_gpl951xx_device::pllclkwait_r), FUNC(generalplus_gpl951xx_device::pllclkwait_w)); // 7818 - PLLWaitCLK map(0x007819, 0x007819).rw(FUNC(generalplus_gpl951xx_device::cache_ctrl_r), FUNC(generalplus_gpl951xx_device::cache_ctrl_w)); // 7819 - Cache_Ctrl // 781a - Cache_HitRate // 781b - unused @@ -729,6 +1176,8 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 7832 - CHECKSUM0_HB // 7833 - CHECKSUM1_HB // + map(0x007840, 0x007840).rw(FUNC(generalplus_gpl951xx_device::spi_improve_r), FUNC(generalplus_gpl951xx_device::spi_improve_w));// 7840 - P_SPI_Improve + // // 7848 - ECC_LPRL_HB // 7849 - ECC_LPRH_HB // 784a - ECC_CPR_HB @@ -755,67 +1204,25 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 785e - ECC_ERR0_LB or BCH_Parity5 // 785f - ECC_ERR1_LB or BCH_Parity6 - map(0x007860, 0x007860).rw(FUNC(generalplus_gpl951xx_device::ioa_data_r), FUNC(generalplus_gpl951xx_device::ioa_data_w)); // 7860 - IOA_Data - map(0x007861, 0x007861).rw(FUNC(generalplus_gpl951xx_device::ioa_buffer_r), FUNC(generalplus_gpl951xx_device::ioa_buffer_w)); // 7861 - IOA_Buffer - map(0x007862, 0x007862).rw(FUNC(generalplus_gpl951xx_device::ioa_dir_r), FUNC(generalplus_gpl951xx_device::ioa_dir_w)); // 7862 - IOA_Dir - map(0x007863, 0x007863).rw(FUNC(generalplus_gpl951xx_device::ioa_attrib_r), FUNC(generalplus_gpl951xx_device::ioa_attrib_w)); // 7863 - IOA_Attrib - // 7864 - IOA_Drv - // 7865 - IOA_Mux - // 7866 - IOA_Latch - // 7867 - IOA_KeyEN - - map(0x007868, 0x007868).rw(FUNC(generalplus_gpl951xx_device::iob_data_r), FUNC(generalplus_gpl951xx_device::iob_data_w)); // 7868 - IOB_Data - map(0x007869, 0x007869).rw(FUNC(generalplus_gpl951xx_device::iob_buffer_r), FUNC(generalplus_gpl951xx_device::iob_buffer_w)); // 7869 - IOB_Buffer - map(0x00786a, 0x00786a).rw(FUNC(generalplus_gpl951xx_device::iob_dir_r), FUNC(generalplus_gpl951xx_device::iob_dir_w)); // 786a - IOB_Dir - map(0x00786b, 0x00786b).rw(FUNC(generalplus_gpl951xx_device::iob_attrib_r), FUNC(generalplus_gpl951xx_device::iob_attrib_w)); // 786b - IOB_Attrib - // 786c - IOB_Drv - // 786d - IOB_Mux - // 786e - IOB_Latch - // 786f - IOB_KeyEN - - map(0x007870, 0x007870).rw(FUNC(generalplus_gpl951xx_device::ioc_data_r) ,FUNC(generalplus_gpl951xx_device::ioc_data_w)); // 7870 - IOC_Data - map(0x007871, 0x007871).rw(FUNC(generalplus_gpl951xx_device::ioc_buffer_r), FUNC(generalplus_gpl951xx_device::ioc_buffer_w)); // 7871 - IOC_Buffer - map(0x007872, 0x007872).rw(FUNC(generalplus_gpl951xx_device::ioc_dir_r), FUNC(generalplus_gpl951xx_device::ioc_dir_w)); // 7872 - IOC_Dir - map(0x007873, 0x007873).rw(FUNC(generalplus_gpl951xx_device::ioc_attrib_r), FUNC(generalplus_gpl951xx_device::ioc_attrib_w)); // 7873 - IOC_Attrib - // 7874 - IOC_Drv - // 7875 - IOC_Mux - // 7876 - IOC_Latch - // 7877 - IOC_KeyEN - - map(0x007878, 0x007878).rw(FUNC(generalplus_gpl951xx_device::iod_data_r) ,FUNC(generalplus_gpl951xx_device::iod_data_w)); // 7878 - IOD_Data - map(0x007879, 0x007879).rw(FUNC(generalplus_gpl951xx_device::iod_buffer_r), FUNC(generalplus_gpl951xx_device::iod_buffer_w)); // 7879 - IOD_Buffer - map(0x00787a, 0x00787a).rw(FUNC(generalplus_gpl951xx_device::iod_dir_r), FUNC(generalplus_gpl951xx_device::iod_dir_w)); // 787a - IOD_Dir - map(0x00787b, 0x00787b).rw(FUNC(generalplus_gpl951xx_device::iod_attib_r), FUNC(generalplus_gpl951xx_device::iod_attib_w)); // 787b - IOD_Attrib - map(0x00787c, 0x00787c).rw(FUNC(generalplus_gpl951xx_device::iod_drv_r), FUNC(generalplus_gpl951xx_device::iod_drv_w)); // 787c - IOD_Drv - map(0x00787d, 0x00787d).rw(FUNC(generalplus_gpl951xx_device::iod_mux_r), FUNC(generalplus_gpl951xx_device::iod_mux_w)); // 787d - IOD_Mux - - // 7880 - IOE_Data - // 7881 - IOE_Buffer - // 7882 - IOE_Dir - // 7883 - IOE_Attrib - // 7884 - IOE_Drv - // 7885 - IOE_Mux - // 7886 - IOE_Latch - // 7877 - IOE_KeyEN - - // 7888 - IOF_Data - // 7889 - IOF_Buffer - // 788a - IOF_Dir - // 788b - IOF_Attrib - // 788c - IOF_Drv - // 788d - IOF_Mux - // 788e - IOF_Latch - // 788f - IOF_KeyEN + // Ports addresses on GPL951xx have more logical arrangement compared to GPL162xx + // and there is an additional 'Port F' + + add_port<0>(map, 0x007860); // 0x7860 - 0x7867 - Port A + add_port<1>(map, 0x007868); // 0x7868 - 0x786f - Port B + add_port<2>(map, 0x007870); // 0x7870 - 0x7877 - Port C + add_port<3>(map, 0x007878); // 0x7878 - 0x787f - Port D + add_port<4>(map, 0x007880); // 0x7880 - 0x7887 - Port E + add_port<5>(map, 0x007888); // 0x7888 - 0x788f - Port F map(0x0078a0, 0x0078a0).rw(FUNC(generalplus_gpl951xx_device::int_status1_r), FUNC(generalplus_gpl951xx_device::int_status1_w)); // 78a0 - INT_Status1 - map(0x0078a1, 0x0078a1).r(FUNC(generalplus_gpl951xx_device::int_status2_r)); // 78a1 - INT_Status2 - // 78a2 - INT_Status3 - // 78a3 - INT_Priority1 - map(0x0078a4, 0x0078a4).w(FUNC(generalplus_gpl951xx_device::int_priority_1_w)); // 78a4 - INT_Priority2 - map(0x0078a5, 0x0078a5).w(FUNC(generalplus_gpl951xx_device::int_priority_2_w)); // 78a5 - INT_Priority3 - map(0x0078a6, 0x0078a6).w(FUNC(generalplus_gpl951xx_device::int_priority_3_w)); // 78a6 - MINT_Ctrl + map(0x0078a1, 0x0078a1).rw(FUNC(generalplus_gpl951xx_device::int_status2_r), FUNC(generalplus_gpl951xx_device::int_status2_w)); // 78a1 - INT_Status2 + map(0x0078a2, 0x0078a2).rw(FUNC(generalplus_gpl951xx_device::int_status3_r), FUNC(generalplus_gpl951xx_device::int_status3_w)); // 78a2 - INT_Status3 + map(0x0078a3, 0x0078a3).w(FUNC(generalplus_gpl951xx_device::int_priority_1_w)); // 78a3 - INT_Priority1 + map(0x0078a4, 0x0078a4).w(FUNC(generalplus_gpl951xx_device::int_priority_2_w)); // 78a4 - INT_Priority2 + map(0x0078a5, 0x0078a5).w(FUNC(generalplus_gpl951xx_device::int_priority_3_w)); // 78a5 - INT_Priority3 + map(0x0078a6, 0x0078a6).w(FUNC(generalplus_gpl951xx_device::mint_ctrl_w)); // 78a6 - MINT_Ctrl // 78a7 - IOAB_KCIEN - map(0x0078a8, 0x0078a8).w(FUNC(generalplus_gpl951xx_device::mint_ctrl_w)); // 78a8 - IOC_KCIEN + // 78a8 - IOC_KCIEN // 78a9 - IOE_KCIEN // 78aa - IOF_KCIEN // 78ab - IOAB_KCIFC @@ -823,11 +1230,11 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 78ad - IOE_ KCIFC // 78ae - IOF_ KCIFC - map(0x0078b0, 0x0078b0).w(FUNC(generalplus_gpl951xx_device::timebasea_ctrl_w)); // 78b0 - TimeBaseA_Ctrl - map(0x0078b1, 0x0078b1).w(FUNC(generalplus_gpl951xx_device::timebaseb_ctrl_w)); // 78b1 - TimeBaseB_Ctrl - map(0x0078b2, 0x0078b2).rw(FUNC(generalplus_gpl951xx_device::timebasec_ctrl_r), FUNC(generalplus_gpl951xx_device::timebasec_ctrl_w)); // 78b2 - TimeBaseC_Ctrl + map(0x0078b0, 0x0078b0).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebasea_ctrl_r), FUNC(gpl_timebase_device::timebasea_ctrl_w)); // 78b0 TimeBase A Control Register (P_TimeBaseA_Ctrl) + map(0x0078b1, 0x0078b1).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebaseb_ctrl_r), FUNC(gpl_timebase_device::timebaseb_ctrl_w)); // 78b1 TimeBase B Control Register (P_TimeBaseB_Ctrl) + map(0x0078b2, 0x0078b2).rw(m_gpl_timebase, FUNC(gpl_timebase_device::timebasec_ctrl_r), FUNC(gpl_timebase_device::timebasec_ctrl_w)); // 78b2 TimeBase C Control Register (P_TimeBaseC_Ctrl) - map(0x0078b8, 0x0078b8).w(FUNC(generalplus_gpl951xx_device::timebase_reset_w)); // 78b8 - TimeBase_Reset + map(0x0078b8, 0x0078b8).w(m_gpl_timebase, FUNC(gpl_timebase_device::timebase_reset_w)); // 78b8 - TimeBase_Reset // 78c0 - I2C_Ctrl // 78c1 - I2C_Status @@ -837,17 +1244,17 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 78c5 - I2C_Clk // 78c6 - I2C_MISC - map(0x0078e0, 0x0078e0).rw(FUNC(generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_r), FUNC(generalplus_gpl951xx_device::gpl951xx_timerg_ctrl_w)); // 78e0 - gpl951xx_timerg_Ctrl + map(0x0078e0, 0x0078e0).rw(FUNC(generalplus_gpl951xx_device::timerg_ctrl_r), FUNC(generalplus_gpl951xx_device::timerg_ctrl_w)); // 78e0 - timerg_Ctrl // 78e1 - map(0x0078e2, 0x0078e2).rw(FUNC(generalplus_gpl951xx_device::gpl951xx_timerg_preload_r), FUNC(generalplus_gpl951xx_device::gpl951xx_timerg_preload_w)); // 78e2 - gpl951xx_timerg_Preload + map(0x0078e2, 0x0078e2).rw(FUNC(generalplus_gpl951xx_device::timerg_preload_r), FUNC(generalplus_gpl951xx_device::timerg_preload_w)); // 78e2 - timerg_Preload // 78e3 // 78e4 - TimerG_UpCount // 78e5 // 78e6 // 78e7 - map(0x0078e8, 0x0078e8).rw(FUNC(generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_r), FUNC(generalplus_gpl951xx_device::gpl951xx_timerh_ctrl_w)); // gpl951xx_timerh_Ctrl + map(0x0078e8, 0x0078e8).rw(FUNC(generalplus_gpl951xx_device::timerh_ctrl_r), FUNC(generalplus_gpl951xx_device::timerh_ctrl_w)); // timerh_Ctrl // 78e9 - map(0x0078ea, 0x0078ea).rw(FUNC(generalplus_gpl951xx_device::gpl951xx_timerh_preload_r), FUNC(generalplus_gpl951xx_device::gpl951xx_timerh_preload_w)); // 78ea - gpl951xx_timerh_Preload + map(0x0078ea, 0x0078ea).rw(FUNC(generalplus_gpl951xx_device::timerh_preload_r), FUNC(generalplus_gpl951xx_device::timerh_preload_w)); // 78ea - timerh_Preload // 78eb // 78ec - TimerH_UpCount // 78ed @@ -919,19 +1326,19 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 79be - MICAGC_Enable // 79bf - MICAGC_Status - // 79f0 - RTC_Ctrl - // 79f1 - RTC_Addr - // 79f2 - RTC_WriteData - // 79f3 - RTC_Request - map(0x0079f4, 0x0079f4).r(FUNC(generalplus_gpl951xx_device::rtc_ready_r)); // RTC_Ready - map(0x0079f5, 0x0079f5).r(FUNC(generalplus_gpl951xx_device::rtc_readdata_r)); // RTC_ReadData + map(0x0079f0, 0x0079f0).w(m_rtc, FUNC(gpl951xx_rtc_device::rtc_ctrl_w)); // 79f0 - RTC_Ctrl + map(0x0079f1, 0x0079f1).w(m_rtc, FUNC(gpl951xx_rtc_device::rtc_addr_w)); // 79f1 - RTC_Addr + map(0x0079f2, 0x0079f2).w(m_rtc, FUNC(gpl951xx_rtc_device::rtc_writedata_w)); // 79f2 - RTC_WriteData + map(0x0079f3, 0x0079f3).w(m_rtc, FUNC(gpl951xx_rtc_device::rtc_request_w)); // 79f3 - RTC_Request + map(0x0079f4, 0x0079f4).r(m_rtc, FUNC(gpl951xx_rtc_device::rtc_ready_r)); // RTC_Ready + map(0x0079f5, 0x0079f5).r(m_rtc, FUNC(gpl951xx_rtc_device::rtc_readdata_r)); // RTC_ReadData // 79f6 // 79f7 // 79f8 // 79fa // 79fb - RTC_ClkDiv - // 7a00 - TimerA_Ctr + // 7a00 - TimerA_Ctrl // 7a01 - TimerA_CCPB_Ctrl // 7a02 - TimerA_Preload // 7a03 - TimerA_CCPB_Reg @@ -993,9 +1400,9 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // 7a55 - USBD_BOBufPointer // 7a56 - USBD_EP0RTR // 7a57 - USBD_EP0RR - // 7a58 - USBD_ EP0VR - // 7a59 - USBD_ EP0IR - // 7a5a - USBD_ EP0LR + // 7a58 - USBD_EP0VR + // 7a59 - USBD_EP0IR + // 7a5a - USBD_EP0LR // // 7a60 - USBD_DMAWrtCountL // 7a61 - USBD_DMAWrtCountH @@ -1009,15 +1416,15 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) // // 7a6c - USBD_INTF - map(0x007a80, 0x007a87).rw(FUNC(generalplus_gpl951xx_device::system_dma_params_channel0_r), FUNC(generalplus_gpl951xx_device::system_dma_params_channel0_w)); - map(0x007a88, 0x007a8f).rw(FUNC(generalplus_gpl951xx_device::system_dma_params_channel1_r), FUNC(generalplus_gpl951xx_device::system_dma_params_channel1_w)); + map(0x007a80, 0x007a87).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel0_r), FUNC(gpl_dma_device::system_dma_params_channel0_w)); + map(0x007a88, 0x007a8f).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_params_channel1_r), FUNC(gpl_dma_device::system_dma_params_channel1_w)); // // 7ab0 - DMA_SPRISize0 // 7ab1 - DMA_SPRISize1 // // 7abd - DMA_LineLength - map(0x007abe, 0x007abe).rw(FUNC(generalplus_gpl951xx_device::system_dma_memtype_r), FUNC(generalplus_gpl951xx_device::system_dma_memtype_w)); // 7abe - DMA_SS - map(0x007abf, 0x007abf).rw(FUNC(generalplus_gpl951xx_device::system_dma_status_r), FUNC(generalplus_gpl951xx_device::system_dma_7abf_unk_w)); // 7abf - DMA_INT + map(0x007abe, 0x007abe).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_memtype_r), FUNC(gpl_dma_device::system_dma_memtype_w)); // 7abe - DMA_SS + map(0x007abf, 0x007abf).rw(m_gpl_dma, FUNC(gpl_dma_device::system_dma_status_r), FUNC(gpl_dma_device::system_dma_status_w)); // 7abf - DMA_INT // // 7ac0 - CTS_Ctrl1 // 7ac1 - CTS_CH @@ -1074,33 +1481,139 @@ void generalplus_gpl951xx_device::gpspi_direct_internal_map(address_map &map) map(0x200000, 0x3fffff).r(FUNC(generalplus_gpl951xx_device::spi_direct_bank_r)); } +void generalplus_gpl951xx_device::update_interrupts(int state) +{ + if (m_gpl_timebase->timebasea_irq_flag() || m_gpl_timebase->timebaseb_irq_flag()) + { + set_state_unsynced(UNSP_IRQ7_LINE, ASSERT_LINE); + } + else + { + set_state_unsynced(UNSP_IRQ7_LINE, CLEAR_LINE); + } + + if (m_gpl_timebase->timebasec_irq_flag()) + { + set_state_unsynced(UNSP_IRQ6_LINE, ASSERT_LINE); + } + else + { + set_state_unsynced(UNSP_IRQ6_LINE, CLEAR_LINE); + } + + if (((m_timerg_ctrl & 0x8000) && (m_timerg_ctrl & 0x4000)) || + ((m_timerh_ctrl & 0x8000) && (m_timerh_ctrl & 0x4000))) + { + set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE); + } + else + { + set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE); + } +} + TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::timer_g_cb ) { - m_gpl951xx_timerg_ctrl |= 0x8000; + m_timerg_ctrl |= 0x8000; + update_interrupts(1); } TIMER_DEVICE_CALLBACK_MEMBER( generalplus_gpl951xx_device::timer_h_cb ) { - m_gpl951xx_timerh_ctrl |= 0x8000; + m_timerh_ctrl |= 0x8000; + update_interrupts(1); +} + +u16 generalplus_gpl951xx_device::read_space(offs_t offset) +{ + address_space &space = this->space(AS_PROGRAM); + u16 val = space.read_word(offset); + return val; +} + +void generalplus_gpl951xx_device::write_space(offs_t offset, u16 data) +{ + address_space &space = this->space(AS_PROGRAM); + space.write_word(offset, data); +} + +IRQ_CALLBACK_MEMBER(generalplus_gpl951xx_device::irq_vector_cb) +{ + if (irqline == UNSP_IRQ4_LINE) + set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE); + + return 0; +} + +void generalplus_gpl951xx_device::audioirq_w(int state) +{ + //set_state_unsynced(UNSP_IRQ5_LINE, state); +} + +void generalplus_gpl951xx_device::videoirq_w(int state) +{ + set_state_unsynced(UNSP_IRQ5_LINE, state); } void generalplus_gpl951xx_device::device_add_mconfig(machine_config &config) { - sunplus_gcm394_base_device::device_add_mconfig(config); + SUNPLUS_GCM394_AUDIO(config, m_spg_audio, DERIVED_CLOCK(1, 1)); + m_spg_audio->write_irq_callback().set(FUNC(generalplus_gpl951xx_device::audioirq_w)); + m_spg_audio->space_read_callback().set(FUNC(generalplus_gpl951xx_device::read_space)); + m_spg_audio->add_route(0, *this, 1.0, 0); + m_spg_audio->add_route(1, *this, 1.0, 1); + + GPL_DMA(config, m_gpl_dma, 0); + m_gpl_dma->space_read_callback().set(FUNC(generalplus_gpl951xx_device::read_space)); + m_gpl_dma->space_write_callback().set(FUNC(generalplus_gpl951xx_device::write_space)); + + GPL_TIMEBASE(config, m_gpl_timebase, 0); + m_gpl_timebase->updateirqs_callback().set(FUNC(generalplus_gpl951xx_device::update_interrupts)); + + GCM394_VIDEO(config, m_spg_video, DERIVED_CLOCK(1, 1), DEVICE_SELF, m_screen); + m_spg_video->write_video_irq_callback().set(FUNC(generalplus_gpl951xx_device::videoirq_w)); + m_spg_video->space_read_callback().set(FUNC(generalplus_gpl951xx_device::read_space)); + m_spg_video->set_video_space(DEVICE_SELF, AS_PROGRAM); + + TIMER(config, "timer_a").configure_generic(FUNC(generalplus_gpl951xx_device::timer_a_cb)); + TIMER(config, "timer_b").configure_generic(FUNC(generalplus_gpl951xx_device::timer_b_cb)); + TIMER(config, "timer_c").configure_generic(FUNC(generalplus_gpl951xx_device::timer_c_cb)); + TIMER(config, "timer_d").configure_generic(FUNC(generalplus_gpl951xx_device::timer_d_cb)); + TIMER(config, "timer_e").configure_generic(FUNC(generalplus_gpl951xx_device::timer_e_cb)); + TIMER(config, "timer_f").configure_generic(FUNC(generalplus_gpl951xx_device::timer_f_cb)); TIMER(config, "timer_g").configure_generic(FUNC(generalplus_gpl951xx_device::timer_g_cb)); TIMER(config, "timer_h").configure_generic(FUNC(generalplus_gpl951xx_device::timer_h_cb)); + + GPL951XX_RTC(config, m_rtc, 0); } DEFINE_DEVICE_TYPE(GPL951XX, generalplus_gpl951xx_device, "gpl951xx", "GeneralPlus GPL951xx") -generalplus_gpl951xx_device::generalplus_gpl951xx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - sunplus_gcm394_base_device(mconfig, GPL951XX, tag, owner, clock, address_map_constructor(FUNC(generalplus_gpl951xx_device::gpspi_direct_internal_map), this)), +generalplus_gpl951xx_device::generalplus_gpl951xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal) : + unsp_20_device(mconfig, type, tag, owner, clock, internal), + device_mixer_interface(mconfig, *this), m_spi_out(*this), m_spi_out_cmd(*this), m_spi_reset(*this), + m_i80_cmd_out(*this), + m_i80_data_out(*this), + m_port_in(*this, 0), + m_port_out(*this), m_timer_g(*this, "timer_g"), - m_timer_h(*this, "timer_h") + m_timer_h(*this, "timer_h"), + m_rtc(*this, "rtc"), + m_gpl_dma(*this, "gpl_dma"), + m_gpl_timebase(*this, "gpl_timebase"), + m_screen(*this, finder_base::DUMMY_TAG), + m_spg_video(*this, "spgvideo"), + m_spg_audio(*this, "spgaudio"), + m_mainram(*this, "mainram") +{ +} + +generalplus_gpl951xx_device::generalplus_gpl951xx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + generalplus_gpl951xx_device(mconfig, GPL951XX, tag, owner, clock, address_map_constructor(FUNC(generalplus_gpl951xx_device::gpspi_direct_internal_map), this)) { } diff --git a/src/devices/machine/generalplus_gpl951xx_soc.h b/src/devices/machine/generalplus_gpl951xx_soc.h index 799b3168162..5c0814ba8f7 100644 --- a/src/devices/machine/generalplus_gpl951xx_soc.h +++ b/src/devices/machine/generalplus_gpl951xx_soc.h @@ -6,11 +6,22 @@ #pragma once -#include "generalplus_gpl162xx_soc.h" + +#include "cpu/unsp/unsp.h" #include "machine/timer.h" -class generalplus_gpl951xx_device : public sunplus_gcm394_base_device +#include "screen.h" +#include "emupal.h" + +#include "generalplus_gpl_dma.h" +#include "generalplus_gpl_timebase.h" +#include "generalplus_gpl162xx_soc_video.h" +#include "generalplus_gpl951xx_rtc.h" +#include "spg2xx_audio.h" + + +class generalplus_gpl951xx_device : public unsp_20_device, public device_mixer_interface { public: template <typename T> @@ -18,9 +29,6 @@ public: generalplus_gpl951xx_device(mconfig, tag, owner, clock) { m_screen.set_tag(std::forward<T>(screen_tag)); - //m_csbase = 0x30000; - // TODO: is cs_space even used by this type? - m_csbase = 0xffffffff; } generalplus_gpl951xx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); @@ -31,12 +39,36 @@ public: auto spi_out_cmd() { return m_spi_out_cmd.bind(); } auto spi_reset() { return m_spi_reset.bind(); } + auto i80_cmd_out() { return m_i80_cmd_out.bind(); } + auto i80_data_out() { return m_i80_data_out.bind(); } + + auto porta_in() { return m_port_in[0].bind(); } + auto portb_in() { return m_port_in[1].bind(); } + auto portc_in() { return m_port_in[2].bind(); } + auto portd_in() { return m_port_in[3].bind(); } + auto porte_in() { return m_port_in[4].bind(); } + auto portf_in() { return m_port_in[5].bind(); } + + auto porta_out() { return m_port_out[0].bind(); } + auto portb_out() { return m_port_out[1].bind(); } + auto portc_out() { return m_port_out[2].bind(); } + auto portd_out() { return m_port_out[3].bind(); } + auto porte_out() { return m_port_out[4].bind(); } + auto portf_out() { return m_port_out[5].bind(); } + void recieve_spi_fifo_data(u8 data); + IRQ_CALLBACK_MEMBER(irq_vector_cb); + u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { return m_spg_video->screen_update(screen, bitmap, cliprect); } + void vblank(int state) { m_spg_video->vblank(state); } + protected: + generalplus_gpl951xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal); + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; void gpspi_direct_internal_map(address_map &map) ATTR_COLD; + template<int Port> void add_port(address_map& map, u32 base) ATTR_COLD; virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; @@ -67,6 +99,15 @@ private: u16 spifc_ctrl2_r(); void spifc_ctrl2_w(u16 data); + u16 spi_improve_r(); + void spi_improve_w(u16 data); + + void pm_ctrl_w(u16 data); + + u16 tft_status_r(); + void tft_ctrl_w(u16 data); + void tft_memmode_wcmd_w(u16 data); + u16 pllsel_r(); void pllsel_w(u16 data); @@ -74,19 +115,34 @@ private: u16 byte_swap_r(); void byte_swap_w(u16 data); - // RTC - u16 rtc_readdata_r(); - u16 rtc_ready_r(); - // Timers (different compared to GPL162xx) - u16 gpl951xx_timerg_ctrl_r(); - void gpl951xx_timerg_ctrl_w(u16 data); - u16 gpl951xx_timerg_preload_r(); - void gpl951xx_timerg_preload_w(u16 data); - u16 gpl951xx_timerh_ctrl_r(); - void gpl951xx_timerh_ctrl_w(u16 data); - u16 gpl951xx_timerh_preload_r(); - void gpl951xx_timerh_preload_w(u16 data); + u16 timerg_ctrl_r(); + void timerg_ctrl_w(u16 data); + u16 timerg_preload_r(); + void timerg_preload_w(u16 data); + u16 timerh_ctrl_r(); + void timerh_ctrl_w(u16 data); + u16 timerh_preload_r(); + void timerh_preload_w(u16 data); + + static constexpr std::string m_portnames[6] = { "a", "b", "c", "d", "e", "f" }; + + template<int Port> u16 io_data_r(); + template<int Port> void io_data_w(u16 data); + template<int Port> u16 io_buffer_r(); + template<int Port> void io_buffer_w(u16 data); + template<int Port> u16 io_dir_r(); + template<int Port> void io_dir_w(u16 data); + template<int Port> u16 io_attrib_r(); + template<int Port> void io_attrib_w(u16 data); + template<int Port> u16 io_drv_r(); + template<int Port> void io_drv_w(u16 data); + template<int Port> u16 io_mux_r(); + template<int Port> void io_mux_w(u16 data); + template<int Port> u16 io_latch_r(); + template<int Port> void io_latch_w(u16 data); + template<int Port> u16 io_keyen_r(); + template<int Port> void io_keyen_w(u16 data); u16 spi_bank_r(); void spi_bank_w(u16 data); @@ -96,15 +152,60 @@ private: u8 get_byte_from_rx_fifo(); + u16 sys_ctrl_r(); + void sys_ctrl_w(u16 data); + + void clock_ctrl_w(u16 data); + u16 clk_ctrl0_r(); + void clk_ctrl0_w(u16 data); + + u16 power_state_r(); + void watchdog_ctrl_w(u16 data); + + u16 pllclkwait_r(); + void pllclkwait_w(u16 data); + + u16 cache_ctrl_r(); + void cache_ctrl_w(u16 data); + + void int_status1_w(u16 data); + void int_status2_w(u16 data); + void int_status3_w(u16 data); + u16 int_status1_r(); + u16 int_status2_r(); + u16 int_status3_r(); + void int_priority_1_w(u16 data); + void int_priority_2_w(u16 data); + void int_priority_3_w(u16 data); + void mint_ctrl_w(u16 data); + + u16 cha_ctrl_r(); + void cha_ctrl_w(u16 data); + + void update_interrupts(int state); + + void audioirq_w(int state); + void videoirq_w(int state); + + inline u16 read_space(offs_t offset); + inline void write_space(offs_t offset, u16 data); + TIMER_DEVICE_CALLBACK_MEMBER(timer_g_cb); TIMER_DEVICE_CALLBACK_MEMBER(timer_h_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_a_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_b_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_c_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_d_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_e_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timer_f_cb); + u16 m_byteswap; - u16 m_gpl951xx_timerg_preload; - u16 m_gpl951xx_timerg_ctrl; - u16 m_gpl951xx_timerh_preload; - u16 m_gpl951xx_timerh_ctrl; + u16 m_timerg_preload; + u16 m_timerg_ctrl; + u16 m_timerh_preload; + u16 m_timerh_ctrl; u16 m_spifc_ctrl; u16 m_spifc_ctrl2; @@ -118,8 +219,27 @@ private: u8 m_spifc_rx_fifo[16 * 2]; u16 m_spifc_rx_read_latch; + u16 m_io_dir[6]; + u16 m_io_attrib[6]; + + u16 m_sys_ctrl; + u16 m_clock_ctrl; + u16 m_cache_ctrl; + + u16 m_int_priority_1; + u16 m_int_priority_2; + u16 m_int_priority_3; + + u16 m_misc_int_ctrl; + + u16 m_cha_ctrl; + + u16 m_pllchange; + u16 m_spi_bank; + u16 m_memmode_wcmd; + // config u8 *m_spiregion; u32 m_spisize; @@ -128,9 +248,22 @@ private: devcb_write8 m_spi_out_cmd; devcb_write8 m_spi_reset; + devcb_write16 m_i80_cmd_out; + devcb_write16 m_i80_data_out; + + devcb_read16::array<6> m_port_in; + devcb_write16::array<6> m_port_out; + // devices required_device<timer_device> m_timer_g; required_device<timer_device> m_timer_h; + required_device<gpl951xx_rtc_device> m_rtc; + required_device<gpl_dma_device> m_gpl_dma; + required_device<gpl_timebase_device> m_gpl_timebase; + required_device<screen_device> m_screen; + required_device<gcm394_video_device> m_spg_video; + required_device<sunplus_gcm394_audio_device> m_spg_audio; + required_shared_ptr<u16> m_mainram; }; DECLARE_DEVICE_TYPE(GPL951XX, generalplus_gpl951xx_device) diff --git a/src/devices/machine/generalplus_gpl_dma.cpp b/src/devices/machine/generalplus_gpl_dma.cpp new file mode 100644 index 00000000000..5d6510246fb --- /dev/null +++ b/src/devices/machine/generalplus_gpl_dma.cpp @@ -0,0 +1,288 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#include "emu.h" +#include "generalplus_gpl_dma.h" + +#define LOG_GCM394_SYSDMA (1U << 1) + +#define VERBOSE (LOG_GCM394_SYSDMA) + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(GPL_DMA, gpl_dma_device, "gpl_dma", "Generalplus GPL162xx / GPL951xx System DMA") + +gpl_dma_device::gpl_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, GPL_DMA, tag, owner, clock), + m_space_read_cb(*this, 0), + m_space_write_cb(*this), + m_dma_complete_cb(*this) +{ +} + +void gpl_dma_device::device_start() +{ + save_item(NAME(m_dma_params)); + save_item(NAME(m_dma_latched)); + save_item(NAME(m_system_dma_memtype)); +} + +void gpl_dma_device::device_reset() +{ + for (int j = 0; j < 4; j++) + { + for (int i = 0; i < 8; i++) + { + m_dma_params[i][j] = 0x0000; + } + m_dma_latched[j] = 0; + } + + m_system_dma_memtype = 0x0000; +} + + +// **************************************** SYSTEM DMA device ************************************************* + +// note, GPL162xx has 4 channels, GPL951xx only has 2 +// sources also differ + +u16 gpl_dma_device::read_dma_params(int channel, int offset) +{ + u16 retdata = m_dma_params[offset][channel]; + LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::read_dma_params (channel %01x) %01x returning %04x\n", machine().describe_context(), channel, offset, retdata); + return retdata; +} + +void gpl_dma_device::write_dma_params(int channel, int offset, u16 data) +{ + LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::write_dma_params (channel %01x) %01x %04x\n", machine().describe_context(), channel, offset, data); + + m_dma_params[offset][channel] = data; + + // TODO: very likely DMA happens whenever the length is not 0, as long as it's been enabled previously + // jak_prft doesn't rewrite the offset 0 register between requests, and instead writes the length + // as the final thing for each new request. other games do not write the length last, but turn off + // register 0 before writing params, and enable it again afterwards + // if that's the case, this code can be refactored to work on 'length' instead of the m_dma_latched + + if (offset == 3) + { + m_dma_latched[channel] = true; + + if (m_dma_params[0][channel] & 1) + trigger_systemm_dma(channel); + } + + if (offset == 0 && (data & 1)) + { + if (m_dma_latched[channel]) + trigger_systemm_dma(channel); + } + +} + + +u16 gpl_dma_device::system_dma_params_channel0_r(offs_t offset) +{ + return read_dma_params(0, offset); +} + + +void gpl_dma_device::system_dma_params_channel0_w(offs_t offset, u16 data) +{ + write_dma_params(0, offset, data); +} + +u16 gpl_dma_device::system_dma_params_channel1_r(offs_t offset) +{ + return read_dma_params(1, offset); +} + +void gpl_dma_device::system_dma_params_channel1_w(offs_t offset, u16 data) +{ + write_dma_params(1, offset, data); +} + +u16 gpl_dma_device::system_dma_params_channel2_r(offs_t offset) +{ + return read_dma_params(2, offset); +} + +void gpl_dma_device::system_dma_params_channel2_w(offs_t offset, u16 data) +{ + write_dma_params(2, offset, data); +} + +u16 gpl_dma_device::system_dma_params_channel3_r(offs_t offset) +{ + return read_dma_params(3, offset); +} + +void gpl_dma_device::system_dma_params_channel3_w(offs_t offset, u16 data) +{ + write_dma_params(3, offset, data); +} + +// P_DMA_INT +// +// 15 +// 14 +// 13 +// 12 +// +// 11 CH3BY - channel busy flags (read only) +// 10 CH2BY +// 9 CH1BY +// 8 CH0BY +// +// 7 CH3TOIF - channel timeout flags +// 6 CH2TOIF +// 5 CH1TOIF +// 4 CH0TOIF +// +// 3 CH3IF - channel complete interrupt flags (write to clear) +// 2 CH2IF +// 1 CH1IF +// 0 CH0IF + +u16 gpl_dma_device::system_dma_status_r() +{ + LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_status_r (7abf)\n", machine().describe_context()); + return 0x00ff; +} + +void gpl_dma_device::system_dma_status_w(u16 data) +{ + // writes to the low 4 bits clear the channel complete interrupt flags + LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_status_w %04x\n", machine().describe_context(), data); +} + +// m_dma_params[0] is P_DMA_Ctrl +// +// 15 WriteReq (0 = request data out, 1 = request data in) +// 14 TM (0 = single transfer mode, 1 = demand transfer mode) +// 13 TARByte (0 = 16-bit target, 1 = 8-bit target) +// 12 SRCByte (0 = 16-bit source, 1 = 8-bit source) + +// 11 TD[1] (00 = Memory to Memory, 01 = Memory to I/O, 10 = I/O to Memory, 11 = invalid) +// 10 TD[0] +// 9 RS (1 = reset channel) +// 8 CIE (1 = enable DMA interrupt) + +// 7 SF (0 = increase/decrease source enabled, 1 = no increment) +// 6 DF (0 = increase/decrease dest enabled, 1 = no increment) +// 5 SD (0 = increase source, 1 = decrease source) +// 4 DD (0 = increase dest, 1 = decrease dest) + +// 3 DBF(r)/NORM_I(w) (DBF: 1 = DMA Double Buffer Full, NORM_I: DMA Normal Interrupt mode) +// 2 MODE (0 = Software Mode/Auto Mode, 1 = External Mode request) +// 1 BS(r/o) (0 = DMA idle, 1 = DMA busy) +// 0 CE (0 = Channel Disabled, 1 = Channel Enabled) + +void gpl_dma_device::trigger_systemm_dma(int channel) +{ + u16 mode = m_dma_params[0][channel]; + u32 source = m_dma_params[1][channel] | (m_dma_params[4][channel] << 16); + u32 dest = m_dma_params[2][channel] | (m_dma_params[5][channel] << 16) ; + u32 length = m_dma_params[3][channel] | (m_dma_params[6][channel] << 16); + int sourcedelta = 0; + int destdelta = 0; + + if ((mode & 0xa0) == 0x00) + sourcedelta = 1; + else if ((mode & 0xa0) == 0x20) + sourcedelta = -1; + + if ((mode & 0x50) == 0x00) + destdelta = 1; + else if ((mode & 0x50) == 0x10) + destdelta = -1; + + LOGMASKED(LOG_GCM394_SYSDMA, "%s:possible DMA operation with params mode:%04x source:%08x (word offset) dest:%08x (word offset) length:%08x (words)\n", machine().describe_context(), mode, source, dest, length ); + + // wrlshunt transfers ROM to RAM, all RAM write addresses have 0x800000 in the destination set + + source &= 0x0fffffff; + length &= 0x0fffffff; // gormiti + + for (int i = 0; i < length; i++) + { + u16 val; + if (mode & 0x1000) + { + val = (m_space_read_cb(source) & 0xFF) | (m_space_read_cb(source) << 8); + i++; + } + else + { + val = m_space_read_cb(source); + } + + source += sourcedelta; + + if (mode & 0x2000) + { + m_space_write_cb(dest, val & 0xFF); + dest += destdelta; + m_space_write_cb(dest, val >> 8); + } + else + { + m_space_write_cb(dest, val); + } + + dest += destdelta; + } + + m_dma_complete_cb(1); // allow some driver specific hacks for service modes + + // clear params after operation + m_dma_params[0][channel] = m_dma_params[0][channel] & 0x00f7; + + m_dma_params[1][channel] = m_dma_params[2][channel] = m_dma_params[3][channel] = m_dma_params[4][channel] = m_dma_params[5][channel] = m_dma_params[6][channel] = 0x0000; + m_dma_latched[channel] = false; + + //machine().debug_break(); +} + + + +u16 gpl_dma_device::system_dma_memtype_r() +{ + LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_memtype_r\n", machine().describe_context()); + return m_system_dma_memtype; +} + +void gpl_dma_device::system_dma_memtype_w(u16 data) +{ + // these sources differ between models + static char const* const types[16] = + { + "Unused / USB", + "DAC CHA", + "UART TX", + "UART RX", + "SDC/MMC 1", // reserved (GPL951xx) + "NAND Flash", + "Serial Interface", // ADC Auto Sample Full (GPL951xx) + "DAC CHB", + "ADC Auto Sample Full", // MIC ADC Auto Sample Full (GPL951xx) + "SPI TX", + "SPI RX", + "USB ISO Out", // reserved (GPL951xx) + "USB ISO In", // reserved (GPL951xx) + "SDC/MMC 2", // reserved (GPL951xx) + "SPUL", // SPI1 TX (GP951xx) + "SPUH" // SPI1 RX (GP951xx) + }; + + m_system_dma_memtype = data; + + LOGMASKED(LOG_GCM394_SYSDMA, "%s:sunplus_gcm394_base_device::system_dma_memtype_w %04x (CH3: %s | CH2: %s | CH1: %s | CH0: %s )\n", machine().describe_context(), data, + types[((m_system_dma_memtype>>12)&0xf)], + types[((m_system_dma_memtype>>8)&0xf)], + types[((m_system_dma_memtype>>4)&0xf)], + types[((m_system_dma_memtype)&0xf)]); + +} diff --git a/src/devices/machine/generalplus_gpl_dma.h b/src/devices/machine/generalplus_gpl_dma.h new file mode 100644 index 00000000000..de914250bf0 --- /dev/null +++ b/src/devices/machine/generalplus_gpl_dma.h @@ -0,0 +1,53 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#ifndef MAME_MACHINE_GENERALPLUS_GPL_DMA_H +#define MAME_MACHINE_GENERALPLUS_GPL_DMA_H + +#pragma once + +class gpl_dma_device : public device_t +{ +public: + gpl_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto space_read_callback() { return m_space_read_cb.bind(); } + auto space_write_callback() { return m_space_write_cb.bind(); } + auto dma_complete_callback() { return m_dma_complete_cb.bind(); } + + u16 system_dma_status_r(); + void system_dma_status_w(u16 data); + u16 system_dma_memtype_r(); + void system_dma_memtype_w(u16 data); + + void write_dma_params(int channel, int offset, u16 data); + u16 read_dma_params(int channel, int offset); + + u16 system_dma_params_channel0_r(offs_t offset); + void system_dma_params_channel0_w(offs_t offset, u16 data); + u16 system_dma_params_channel1_r(offs_t offset); + void system_dma_params_channel1_w(offs_t offset, u16 data); + u16 system_dma_params_channel2_r(offs_t offset); + void system_dma_params_channel2_w(offs_t offset, u16 data); + u16 system_dma_params_channel3_r(offs_t offset); + void system_dma_params_channel3_w(offs_t offset, u16 data); + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + void trigger_systemm_dma(int channel); + +private: + + u16 m_system_dma_memtype; + u16 m_dma_params[8][4]; + u8 m_dma_latched[4]; + + devcb_read16 m_space_read_cb; + devcb_write16 m_space_write_cb; + devcb_write_line m_dma_complete_cb; +}; + +DECLARE_DEVICE_TYPE(GPL_DMA, gpl_dma_device) + +#endif // MAME_MACHINE_GENERALPLUS_GPL_DMA_H diff --git a/src/devices/machine/generalplus_gpl_timebase.cpp b/src/devices/machine/generalplus_gpl_timebase.cpp new file mode 100644 index 00000000000..6c5464d26e9 --- /dev/null +++ b/src/devices/machine/generalplus_gpl_timebase.cpp @@ -0,0 +1,208 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#include "emu.h" +#include "generalplus_gpl_timebase.h" + +#define LOG_TIMEBASE (1U << 1) + +#define VERBOSE (0) + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(GPL_TIMEBASE, gpl_timebase_device, "gpl_timebase", "Generalplus GPL162xx / GPL951xx System Timebase") + +gpl_timebase_device::gpl_timebase_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, GPL_TIMEBASE, tag, owner, clock), + m_timebase_a(*this, "timebase_a"), + m_timebase_b(*this, "timebase_b"), + m_timebase_c(*this, "timebase_c"), + m_updateirqs_cb(*this) +{ +} + +void gpl_timebase_device::device_start() +{ + save_item(NAME(m_timebasea_ctrl)); + save_item(NAME(m_timebaseb_ctrl)); + save_item(NAME(m_timebasec_ctrl)); + save_item(NAME(m_timebase_reset)); +} + +void gpl_timebase_device::device_reset() +{ + m_timebasea_ctrl = 0x0000; + m_timebaseb_ctrl = 0x0000; + m_timebasec_ctrl = 0x0000; + m_timebase_reset = 0x0000; +} + + +// Timebase ('fixed' frequency timers) +// (each can select from 3 different frequencies, different for each timer) + + +TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_a_cb ) +{ + // sets bit 15 in m_timebasec_ctrl, also visible (as read only) in P_INT_Status2, bit 8 + // uses IRQ7 (FIQ option not available) + m_timebasea_ctrl |= 0x8000; + m_updateirqs_cb(1); +} + +// P_TimeBaseA_Ctrl +// +// 15 TMBAIF/C +// 14 TMBAIE +// 13 TMBAEN +// 12 +// +// 11 +// 10 +// 9 +// 8 +// 7 +// 6 +// 5 +// 4 +// 3 +// 2 +// 1 TMBAS[1] +// 0 TMBAS[0] 00 = Reserved, 01 = 1Hz, 10 = 2Hz, 11 = 4Hz + +u16 gpl_timebase_device::timebasea_ctrl_r() +{ + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasea_ctrl_r\n", machine().describe_context()); + return m_timebasea_ctrl; +} + +void gpl_timebase_device::timebasea_ctrl_w(u16 data) +{ + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasea_ctrl_w %04x\n", machine().describe_context(), data); + + if (data & 0x8000) + { + m_timebasea_ctrl = data & 0x7fff; + m_updateirqs_cb(1); + } + else + { + m_timebasea_ctrl = data; + } + + if ((m_timebasea_ctrl & 0x6000) == 0x6000) + { + switch (m_timebasea_ctrl & 0x0003) + { + case 0x00: m_timebase_a->adjust(attotime::never); break; // invalid + case 0x01: m_timebase_a->adjust(attotime::from_hz(1)); break; + case 0x02: m_timebase_a->adjust(attotime::from_hz(2)); break; + case 0x03: m_timebase_a->adjust(attotime::from_hz(4)); break; + } + } + else + { + m_timebase_a->adjust(attotime::never); + } +} + +TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_b_cb ) +{ + // sets bit 15 in m_timebaseb_ctrl, also visible (as read only) in P_INT_Status2, bit 9 + // uses IRQ7 (FIQ option not available) + m_timebaseb_ctrl |= 0x8000; + m_updateirqs_cb(1); +} + +u16 gpl_timebase_device::timebaseb_ctrl_r() +{ + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_r\n", machine().describe_context()); + return m_timebaseb_ctrl; +} + +void gpl_timebase_device::timebaseb_ctrl_w(u16 data) +{ + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebaseb_ctrl_w %04x\n", machine().describe_context(), data); + + if (data & 0x8000) + { + m_timebaseb_ctrl = data & 0x7fff; + m_updateirqs_cb(1); + } + else + { + m_timebaseb_ctrl = data; + } + + if ((m_timebaseb_ctrl & 0x6000) == 0x6000) + { + switch (m_timebaseb_ctrl & 0x0003) + { + case 0x00: m_timebase_b->adjust(attotime::from_hz(8)); break; + case 0x01: m_timebase_b->adjust(attotime::from_hz(16)); break; + case 0x02: m_timebase_b->adjust(attotime::from_hz(32)); break; + case 0x03: m_timebase_b->adjust(attotime::from_hz(64)); break; + } + } + else + { + m_timebase_b->adjust(attotime::never); + } +} + +TIMER_DEVICE_CALLBACK_MEMBER( gpl_timebase_device::timebase_c_cb ) +{ + // sets bit 15 in m_timebasec_ctrl, also visible (as read only) in P_INT_Status2, bit 10 + // uses IRQ6 (FIQ option not available) + m_timebasec_ctrl |= 0x8000; + m_updateirqs_cb(1); +} + +u16 gpl_timebase_device::timebasec_ctrl_r() +{ + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasec_ctrl_r\n", machine().describe_context()); + return m_timebasec_ctrl; +} + +void gpl_timebase_device::timebasec_ctrl_w(u16 data) +{ + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebasec_ctrl_w %04x\n", machine().describe_context(), data); + + if (data & 0x8000) + { + m_timebasec_ctrl = data & 0x7fff; + m_updateirqs_cb(1); + } + else + { + m_timebasec_ctrl = data; + } + + if ((m_timebasec_ctrl & 0x6000) == 0x6000) + { + switch (m_timebasec_ctrl & 0x0003) + { + case 0x00: m_timebase_c->adjust(attotime::from_hz(128)); break; + case 0x01: m_timebase_c->adjust(attotime::from_hz(256)); break; + case 0x02: m_timebase_c->adjust(attotime::from_hz(512)); break; + case 0x03: m_timebase_c->adjust(attotime::from_hz(1024)); break; + } + } + else + { + m_timebase_c->adjust(attotime::never); + } +} + +void gpl_timebase_device::timebase_reset_w(u16 data) +{ + LOGMASKED(LOG_TIMEBASE, "%s:sunplus_gcm394_base_device::timebase_reset_w %04x\n", machine().describe_context(), data); + m_timebase_reset = data; +} + +void gpl_timebase_device::device_add_mconfig(machine_config &config) +{ + TIMER(config, "timebase_a").configure_generic(FUNC(gpl_timebase_device::timebase_a_cb)); + TIMER(config, "timebase_b").configure_generic(FUNC(gpl_timebase_device::timebase_b_cb)); + TIMER(config, "timebase_c").configure_generic(FUNC(gpl_timebase_device::timebase_c_cb)); +} diff --git a/src/devices/machine/generalplus_gpl_timebase.h b/src/devices/machine/generalplus_gpl_timebase.h new file mode 100644 index 00000000000..a6ad4969009 --- /dev/null +++ b/src/devices/machine/generalplus_gpl_timebase.h @@ -0,0 +1,57 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +#ifndef MAME_MACHINE_GENERALPLUS_GPL_TIMEBASE_H +#define MAME_MACHINE_GENERALPLUS_GPL_TIMEBASE_H + +#pragma once + +#include "machine/timer.h" + +class gpl_timebase_device : public device_t +{ +public: + gpl_timebase_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + bool timebasea_irq_flag() { return m_timebasea_ctrl & 0x8000 ? true : false; } + bool timebaseb_irq_flag() { return m_timebaseb_ctrl & 0x8000 ? true : false; } + bool timebasec_irq_flag() { return m_timebasec_ctrl & 0x8000 ? true : false; } + + auto updateirqs_callback() { return m_updateirqs_cb.bind(); } + + u16 timebasea_ctrl_r(); + void timebasea_ctrl_w(u16 data); + + u16 timebaseb_ctrl_r(); + void timebaseb_ctrl_w(u16 data); + + u16 timebasec_ctrl_r(); + void timebasec_ctrl_w(u16 data); + + void timebase_reset_w(u16 data); + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + +private: + TIMER_DEVICE_CALLBACK_MEMBER(timebase_a_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timebase_b_cb); + TIMER_DEVICE_CALLBACK_MEMBER(timebase_c_cb); + + u16 m_timebasea_ctrl; + u16 m_timebaseb_ctrl; + u16 m_timebasec_ctrl; + + u16 m_timebase_reset; + + required_device<timer_device> m_timebase_a; + required_device<timer_device> m_timebase_b; + required_device<timer_device> m_timebase_c; + + devcb_write_line m_updateirqs_cb; +}; + +DECLARE_DEVICE_TYPE(GPL_TIMEBASE, gpl_timebase_device) + +#endif // MAME_MACHINE_GENERALPLUS_GPL_TIMEBASE_H |
