From 6fa344d29556e0ed1d058a5656a50127214caece Mon Sep 17 00:00:00 2001 From: AJR Date: Wed, 21 Mar 2018 19:02:06 -0400 Subject: scn2674: Add preliminary support for SCN2672 variant --- src/devices/video/scn2674.cpp | 144 ++++++++++++++++++++++++++++++++++++++++-- src/devices/video/scn2674.h | 29 ++++++++- src/mame/drivers/tv965.cpp | 19 +++--- 3 files changed, 177 insertions(+), 15 deletions(-) diff --git a/src/devices/video/scn2674.cpp b/src/devices/video/scn2674.cpp index f14ff5ac92c..726450ee7f6 100644 --- a/src/devices/video/scn2674.cpp +++ b/src/devices/video/scn2674.cpp @@ -1,7 +1,8 @@ // license:BSD-3-Clause // copyright-holders:Carl /* - SCN2674 - Advanced Video Display Controller (AVDC) (Video Chip) + SCN2672 - Programmable Video Timing Controller (PVTC) + SCN2674 - Advanced Video Display Controller (AVDC) */ #include "emu.h" @@ -17,6 +18,7 @@ #include "logmacro.h" +DEFINE_DEVICE_TYPE(SCN2672, scn2672_device, "scn2672", "Signetics SCN2672 PVTC") DEFINE_DEVICE_TYPE(SCN2674, scn2674_device, "scn2674", "Signetics SCN2674 AVDC") @@ -25,8 +27,18 @@ ADDRESS_MAP_START(scn2674_device::scn2674_vram) AM_RANGE(0x0000, 0xffff) AM_NOP ADDRESS_MAP_END +scn2672_device::scn2672_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : scn2674_device(mconfig, SCN2672, tag, owner, clock) +{ +} + scn2674_device::scn2674_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, SCN2674, tag, owner, clock) + : scn2674_device(mconfig, SCN2674, tag, owner, clock) +{ +} + +scn2674_device::scn2674_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) , device_video_interface(mconfig, *this) , device_memory_interface(mconfig, *this) , m_intr_cb(*this) @@ -169,7 +181,7 @@ void scn2674_device::device_reset() m_cursor_underline_position = 0; m_cursor_rate_divisor = 0; m_cursor_blink = false; - m_vsync_width = 0; + m_vsync_width = 3; // fixed for SCN2672 m_display_buffer_first_address = 0; m_display_buffer_last_address = 0; m_display_pointer_address = 0; @@ -191,6 +203,130 @@ void scn2674_device::device_reset() m_intr_cb(CLEAR_LINE); } +// 11 Initialization Registers (8-bit each) +void scn2672_device::write_init_regs(uint8_t data) +{ + //LOGMASKED(LOG_COMMAND, "scn2674_write_init_regs %02x %02x\n",m_IR_pointer,data); + + switch (m_IR_pointer) + { + case 0: + m_double_ht_wd = BIT(data, 7); + m_scanline_per_char_row = ((data & 0x78) >> 3) + 1; + m_csync_select = BIT(data, 2); + m_buffer_mode_select = data & 0x03; + + LOGMASKED(LOG_IR, "IR0 - Scanlines per Character Row %02i\n", m_scanline_per_char_row);//value+1 = scanlines + LOGMASKED(LOG_IR, "IR0 - %s Output Selected\n", m_csync_select ? "CSYNC" : "VSYNC"); + switch (m_buffer_mode_select) + { + case 0: + LOGMASKED(LOG_IR, "IR0 - Independent Buffer Mode\n"); + break; + + case 1: + LOGMASKED(LOG_IR, "IR0 - Transparent Buffer Mode\n"); + break; + + case 2: + LOGMASKED(LOG_IR, "IR0 - Shared Buffer Mode\n"); + break; + + case 3: + LOGMASKED(LOG_IR, "IR0 - Row Buffer Mode\n"); + break; + } + break; + + case 1: + m_interlace_enable = BIT(data, 7); + m_equalizing_constant = (data & 0x7f) + 1; + + LOGMASKED(LOG_IR, "IR1 - Interlace %s\n", m_interlace_enable ? "on" : "off"); + LOGMASKED(LOG_IR, "IR1 - Equalizing Constant %02i CCLKs\n", m_equalizing_constant); + break; + + case 2: + m_horz_sync_width = (((data & 0x78) >> 3) * 2) + 2; + m_horz_back_porch = ((data & 0x07) * 4) + 1; + + LOGMASKED(LOG_IR, "IR2 - Horizontal Sync Width %02i CCLKs\n", m_horz_sync_width); + LOGMASKED(LOG_IR, "IR2 - Horizontal Back Porch %02i CCLKs\n", m_horz_back_porch); + break; + + case 3: + m_vert_front_porch = (((data & 0xe0) >> 5) * 4) + 4; + m_vert_back_porch = ((data & 0x1f) * 2) + 4; + + LOGMASKED(LOG_IR, "IR3 - Vertical Front Porch %02i Lines\n", m_vert_front_porch); + LOGMASKED(LOG_IR, "IR3 - Vertical Back Porch %02i Lines\n", m_vert_back_porch); + break; + + case 4: + m_rows_per_screen = (data & 0x7f) + 1; + m_character_blink_rate_divisor = BIT(data, 7) ? 32 : 16; + + LOGMASKED(LOG_IR, "IR4 - Rows Per Screen %02i\n", m_rows_per_screen); + LOGMASKED(LOG_IR, "IR4 - Character Blink Rate = 1/%02i\n", m_character_blink_rate_divisor); + break; + + case 5: + m_character_per_row = data + 1; + LOGMASKED(LOG_IR, "IR5 - Active Characters Per Row %02i\n", m_character_per_row); + break; + + case 6: + m_cursor_last_scanline = data & 0x0f; + m_cursor_first_scanline = (data & 0xf0) >> 4; + LOGMASKED(LOG_IR, "IR6 - First Line of Cursor %02i\n", m_cursor_first_scanline); + LOGMASKED(LOG_IR, "IR6 - Last Line of Cursor %02i\n", m_cursor_last_scanline); + break; + + case 7: + m_cursor_underline_position = data & 0x0f; + m_double_ht_wd = BIT(data, 4); + m_cursor_blink = BIT(data, 5); + + LOGMASKED(LOG_IR, "IR7 - Underline Position %02i\n", m_cursor_underline_position); + LOGMASKED(LOG_IR, "IR7 - Double Height %s\n", m_double_ht_wd ? "on" : "off"); + LOGMASKED(LOG_IR, "IR7 - Cursor blink %s\n", m_cursor_blink ? "on" : "off"); + LOGMASKED(LOG_IR, "IR7 - Light pen line %02i\n", ((data & 0xc0) >> 6) * 2 + 3); + break; + + case 8: + m_display_buffer_first_address = (m_display_buffer_first_address & 0xf00) | data; + LOGMASKED(LOG_IR, "IR8 - Display Buffer First Address LSB %02x\n", m_display_buffer_first_address & 0xff); + break; + + case 9: + m_display_buffer_first_address = (m_display_buffer_first_address & 0x0ff) | (data & 0x0f) << 4; + m_display_buffer_last_address = (data & 0xf0) >> 4; + LOGMASKED(LOG_IR, "IR9 - Display Buffer First Address MSB %01x\n", m_display_buffer_first_address >> 8); + LOGMASKED(LOG_IR, "IR9 - Display Buffer Last Address %02x\n", m_display_buffer_last_address); + break; + + case 10: + m_cursor_rate_divisor = BIT(data, 7) ? 32 : 16; + m_split_register[0] = data & 0x7f; + LOGMASKED(LOG_IR, "IR10 - Split Register %02x\n", m_split_register[0]); + LOGMASKED(LOG_IR, "IR10 - Cursor rate 1/%02i\n", m_cursor_rate_divisor); + break; + + case 11: // not valid! + case 12: + case 13: + case 14: + case 15: + break; + } + + // Don't reconfigure if the display isn't turned on (incomplete configurations may generate invalid screen parameters) + if (m_display_enabled) + recompute_parameters(); + + m_IR_pointer = std::min(m_IR_pointer + 1, 10); +} + // 15 Initialization Registers (8-bit each) void scn2674_device::write_init_regs(uint8_t data) { @@ -206,7 +342,7 @@ void scn2674_device::write_init_regs(uint8_t data) LOGMASKED(LOG_IR, "IR0 - Double Ht Wd %s\n", m_double_ht_wd ? "on" : "off");//affects IR14 as well LOGMASKED(LOG_IR, "IR0 - Scanlines per Character Row %02i\n", m_scanline_per_char_row);//value+1 = scanlines - LOGMASKED(LOG_IR, "IR0 - %s Output Selected\n", m_csync_select ? "CSYNC" : "HSYNC"); + LOGMASKED(LOG_IR, "IR0 - %s Output Selected\n", m_csync_select ? "CSYNC" : "VSYNC"); switch (m_buffer_mode_select) { case 0: diff --git a/src/devices/video/scn2674.h b/src/devices/video/scn2674.h index 7c7c212a0ad..09706a8d675 100644 --- a/src/devices/video/scn2674.h +++ b/src/devices/video/scn2674.h @@ -6,6 +6,18 @@ #pragma once +#define MCFG_SCN2672_INTR_CALLBACK(_intr) \ + devcb = &downcast(*device).set_intr_callback(DEVCB_##_intr); + +#define MCFG_SCN2672_CHARACTER_WIDTH(_value) \ + downcast(*device).set_character_width(_value); + +#define MCFG_SCN2672_DRAW_CHARACTER_CALLBACK_OWNER(_class, _method) \ + downcast(*device).set_display_callback(scn2672_device::draw_character_delegate(&_class::_method, #_class "::" #_method, this)); + +#define SCN2672_DRAW_CHARACTER_MEMBER(_name) void _name(bitmap_rgb32 &bitmap, int x, int y, uint8_t linecount, uint8_t charcode, uint16_t address, uint8_t cursor, uint8_t dw, uint8_t lg, uint8_t ul, uint8_t blink) + + #define MCFG_SCN2674_INTR_CALLBACK(_intr) \ devcb = &downcast(*device).set_intr_callback(DEVCB_##_intr); @@ -17,6 +29,7 @@ #define SCN2674_DRAW_CHARACTER_MEMBER(_name) void _name(bitmap_rgb32 &bitmap, int x, int y, uint8_t linecount, uint8_t charcode, uint16_t address, uint8_t cursor, uint8_t dw, uint8_t lg, uint8_t ul, uint8_t blink) + class scn2674_device : public device_t, public device_video_interface, public device_memory_interface @@ -39,13 +52,15 @@ public: uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); protected: + scn2674_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + virtual void device_start() override; virtual void device_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; virtual space_config_vector memory_space_config() const override; -private: +//protected: bitmap_rgb32 m_bitmap; devcb_write_line m_intr_cb; @@ -99,7 +114,7 @@ private: uint16_t m_address; int m_start1change; - void write_init_regs(uint8_t data); + virtual void write_init_regs(uint8_t data); void set_gfx_enabled(bool enabled); void set_display_enabled(bool enabled, int n); void set_cursor_enabled(bool enabled); @@ -121,7 +136,17 @@ private: }; }; +class scn2672_device : public scn2674_device +{ +public: + scn2672_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void write_init_regs(uint8_t data); +}; + +DECLARE_DEVICE_TYPE(SCN2672, scn2672_device) DECLARE_DEVICE_TYPE(SCN2674, scn2674_device) #endif // MAME_VIDEO_SCN2674_H diff --git a/src/mame/drivers/tv965.cpp b/src/mame/drivers/tv965.cpp index d654679917f..03c5a316352 100644 --- a/src/mame/drivers/tv965.cpp +++ b/src/mame/drivers/tv965.cpp @@ -13,7 +13,7 @@ TeleVideo 9320 appears to run on similar hardware with a 2681 DUART replacing th #include "cpu/g65816/g65816.h" #include "machine/mos6551.h" #include "machine/nvram.h" -//#include "video/scn2674.h" +#include "video/scn2674.h" #include "screen.h" class tv965_state : public driver_device @@ -27,7 +27,7 @@ public: void tv965(machine_config &config); private: - u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + SCN2672_DRAW_CHARACTER_MEMBER(draw_character); DECLARE_READ8_MEMBER(ga_hack_r); @@ -38,9 +38,8 @@ private: required_device m_screen; }; -u32 tv965_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +SCN2672_DRAW_CHARACTER_MEMBER(tv965_state::draw_character) { - return 0; } READ8_MEMBER(tv965_state::ga_hack_r) @@ -51,6 +50,7 @@ READ8_MEMBER(tv965_state::ga_hack_r) void tv965_state::mem_map(address_map &map) { map(0x00000, 0x01fff).ram().share("nvram"); + map(0x02000, 0x02007).rw("crtc", FUNC(scn2672_device::read), FUNC(scn2672_device::write)); map(0x04000, 0x04000).r(this, FUNC(tv965_state::ga_hack_r)); map(0x06200, 0x06203).rw("acia1", FUNC(mos6551_device::read), FUNC(mos6551_device::write)); map(0x06400, 0x06403).rw("acia2", FUNC(mos6551_device::read), FUNC(mos6551_device::write)); @@ -80,12 +80,13 @@ MACHINE_CONFIG_START(tv965_state::tv965) MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_RAW_PARAMS(26.9892_MHz_XTAL, 1020, 0, 800, 378, 0, 350) //MCFG_SCREEN_RAW_PARAMS(44.4528_MHz_XTAL, 1680, 0, 1320, 378, 0, 350) - MCFG_SCREEN_UPDATE_DRIVER(tv965_state, screen_update) + MCFG_SCREEN_UPDATE_DEVICE("crtc", scn2672_device, screen_update) - //MCFG_DEVICE_ADD("crtc", SCN2672, 26.9892_MHz_XTAL / 10) - //MCFG_SCN2672_CHARACTER_WIDTH(10) - //MCFG_SCN2672_DRAW_CHARACTER_CALLBACK_OWNER(tv965_state, draw_character) - //MCFG_VIDEO_SET_SCREEN("screen") + MCFG_DEVICE_ADD("crtc", SCN2672, 26.9892_MHz_XTAL / 10) + MCFG_SCN2672_CHARACTER_WIDTH(10) + MCFG_SCN2672_DRAW_CHARACTER_CALLBACK_OWNER(tv965_state, draw_character) + MCFG_SCN2672_INTR_CALLBACK(INPUTLINE("maincpu", INPUT_LINE_NMI)) + MCFG_VIDEO_SET_SCREEN("screen") MCFG_DEVICE_ADD("acia1", MOS6551, 0) MCFG_MOS6551_XTAL(3.6864_MHz_XTAL / 2) // divider not verified, possibly even programmable -- cgit v1.2.3