scn2674: Add BREQ output; get a bit smarter about screen reconfiguration (nw)

This commit is contained in:
AJR 2018-10-28 01:34:37 -04:00
parent 3ee2d47303
commit 742b89c16b
3 changed files with 57 additions and 20 deletions

View File

@ -14,7 +14,7 @@
#define LOG_COMMAND (1 << 1)
#define LOG_INTR (1 << 2)
#define LOG_READ (1 << 3)
#define VERBOSE (0)
#define VERBOSE (1)
#include "logmacro.h"
@ -43,6 +43,7 @@ scn2674_device::scn2674_device(const machine_config &mconfig, device_type type,
, device_video_interface(mconfig, *this)
, device_memory_interface(mconfig, *this)
, m_intr_cb(*this)
, m_breq_cb(*this)
, m_IR_pointer(0)
, m_screen1_address(0), m_screen2_address(0)
, m_cursor_address(0)
@ -103,6 +104,7 @@ void scn2674_device::device_start()
// resolve callbacks
m_display_cb.bind_relative_to(*owner());
m_intr_cb.resolve_safe();
m_breq_cb.resolve_safe();
m_scanline_timer = timer_alloc(TIMER_SCANLINE);
screen().register_screen_bitmap(m_bitmap);
@ -221,9 +223,12 @@ void scn2672_device::write_init_regs(uint8_t data)
{
//LOGMASKED(LOG_COMMAND, "scn2674_write_init_regs %02x %02x\n",m_IR_pointer,data);
bool parameters_changed = false;
switch (m_IR_pointer)
{
case 0:
parameters_changed = m_scanline_per_char_row != ((data & 0x78) >> 3) + 1;
m_double_ht_wd = BIT(data, 7);
m_scanline_per_char_row = ((data & 0x78) >> 3) + 1;
m_csync_select = BIT(data, 2);
@ -252,6 +257,8 @@ void scn2672_device::write_init_regs(uint8_t data)
break;
case 1:
parameters_changed = m_equalizing_constant != (data & 0x7f) + 1;
m_interlace_enable = BIT(data, 7);
m_equalizing_constant = (data & 0x7f) + 1;
@ -260,6 +267,8 @@ void scn2672_device::write_init_regs(uint8_t data)
break;
case 2:
parameters_changed = m_horz_sync_width != (((data & 0x78) >> 3) * 2) + 2;
m_horz_sync_width = (((data & 0x78) >> 3) * 2) + 2;
m_horz_back_porch = ((data & 0x07) * 4) + 1;
@ -268,6 +277,9 @@ void scn2672_device::write_init_regs(uint8_t data)
break;
case 3:
parameters_changed = m_vert_front_porch != (((data & 0xe0) >> 5) * 4) + 4
|| m_vert_back_porch != ((data & 0x1f) * 2) + 4;
m_vert_front_porch = (((data & 0xe0) >> 5) * 4) + 4;
m_vert_back_porch = ((data & 0x1f) * 2) + 4;
@ -276,6 +288,8 @@ void scn2672_device::write_init_regs(uint8_t data)
break;
case 4:
parameters_changed = m_rows_per_screen != (data & 0x7f) + 1;
m_rows_per_screen = (data & 0x7f) + 1;
m_character_blink_rate_divisor = BIT(data, 7) ? 32 : 16;
@ -284,6 +298,8 @@ void scn2672_device::write_init_regs(uint8_t data)
break;
case 5:
parameters_changed = m_character_per_row != data + 1;
m_character_per_row = data + 1;
LOGMASKED(LOG_IR, "IR5 - Active Characters Per Row %02i\n", m_character_per_row);
break;
@ -333,8 +349,7 @@ void scn2672_device::write_init_regs(uint8_t data)
break;
}
// Don't reconfigure if the display isn't turned on (incomplete configurations may generate invalid screen parameters)
if (m_display_enabled)
if (parameters_changed)
recompute_parameters();
m_IR_pointer = std::min(m_IR_pointer + 1, 10);
@ -345,9 +360,12 @@ void scn2674_device::write_init_regs(uint8_t data)
{
//LOGMASKED(LOG_COMMAND, "scn2674_write_init_regs %02x %02x\n",m_IR_pointer,data);
bool parameters_changed = false;
switch (m_IR_pointer)
{
case 0:
parameters_changed = m_scanline_per_char_row != ((data & 0x78) >> 3) + 1;
m_double_ht_wd = BIT(data, 7);
m_scanline_per_char_row = ((data & 0x78) >> 3) + 1;
m_csync_select = BIT(data, 2);
@ -377,6 +395,8 @@ void scn2674_device::write_init_regs(uint8_t data)
break;
case 1:
parameters_changed = m_equalizing_constant != (data & 0x7f) + 1;
m_interlace_enable = BIT(data, 7);
m_equalizing_constant = (data & 0x7f) + 1;
@ -385,6 +405,8 @@ void scn2674_device::write_init_regs(uint8_t data)
break;
case 2:
parameters_changed = m_horz_sync_width != (((data & 0x78) >> 3) * 2) + 2;
m_use_row_table = BIT(data, 7);
m_horz_sync_width = (((data & 0x78) >> 3) * 2) + 2;
m_horz_back_porch = ((data & 0x07) * 4) - 1;
@ -395,6 +417,9 @@ void scn2674_device::write_init_regs(uint8_t data)
break;
case 3:
parameters_changed = m_vert_front_porch != (((data & 0xe0) >> 5) * 4) + 4
|| m_vert_back_porch != ((data & 0x1f) * 2) + 4;
m_vert_front_porch = (((data & 0xe0) >> 5) * 4) + 4;
m_vert_back_porch = ((data & 0x1f) * 2) + 4;
@ -403,6 +428,8 @@ void scn2674_device::write_init_regs(uint8_t data)
break;
case 4:
parameters_changed = m_rows_per_screen != (data & 0x7f) + 1;
m_rows_per_screen = (data & 0x7f) + 1;
m_character_blink_rate_divisor = BIT(data, 7) ? 128 : 64;
@ -411,6 +438,8 @@ void scn2674_device::write_init_regs(uint8_t data)
break;
case 5:
parameters_changed = m_character_per_row != data + 1;
m_character_per_row = data + 1;
LOGMASKED(LOG_IR, "IR5 - Active Characters Per Row %02i\n", m_character_per_row);
break;
@ -429,6 +458,7 @@ void scn2674_device::write_init_regs(uint8_t data)
m_cursor_rate_divisor = BIT(data, 4) ? 64 : 32;
m_cursor_blink = BIT(data, 5);
parameters_changed = m_vsync_width != vsync_table[(data & 0xc0) >> 6];
m_vsync_width = vsync_table[(data & 0xc0) >> 6];
LOGMASKED(LOG_IR, "IR7 - Underline Position %02i\n", m_cursor_underline_position);
@ -499,8 +529,7 @@ void scn2674_device::write_init_regs(uint8_t data)
break;
}
// Don't reconfigure if the display isn't turned on (incomplete configurations may generate invalid screen parameters)
if (m_display_enabled)
if (parameters_changed)
recompute_parameters();
m_IR_pointer = std::min(m_IR_pointer + 1, 14);
@ -601,13 +630,7 @@ void scn2674_device::write_interrupt_mask(bool enabled, uint8_t bits)
if (BIT(changed_bits, 3))
LOGMASKED(LOG_INTR, "Line Zero IRQ %s\n", enabled ? "enabled" : "disabled");
if (BIT(changed_bits, 4))
{
LOGMASKED(LOG_INTR, "V-Blank IRQ %s\n", enabled ? "enabled" : "disabled");
// hack to allow PC-X to get its first interrupt
if (BIT(bits, 4) && !m_display_enabled)
recompute_parameters();
}
}
void scn2674_device::write_delayed_command(uint8_t data)
@ -925,6 +948,12 @@ WRITE8_MEMBER( scn2674_device::write )
void scn2674_device::recompute_parameters()
{
if (!m_equalizing_constant || !m_character_per_row || !m_rows_per_screen)
{
m_scanline_timer->adjust(attotime::never);
return;
}
int horiz_chars_total = (m_equalizing_constant + (m_horz_sync_width << 1)) << 1;
int horiz_pix_total = horiz_chars_total * m_hpixels_per_column;
int vert_pix_total = m_rows_per_screen * m_scanline_per_char_row + m_vert_front_porch + m_vert_back_porch + m_vsync_width;
@ -932,12 +961,6 @@ void scn2674_device::recompute_parameters()
int max_visible_x = (m_character_per_row * m_hpixels_per_column) - 1;
int max_visible_y = (m_rows_per_screen * m_scanline_per_char_row) - 1;
if (!horiz_pix_total || !vert_pix_total)
{
m_scanline_timer->adjust(attotime::never);
return;
}
//attoseconds_t refresh = clocks_to_attotime(horiz_chars_total * vert_pix_total).as_attoseconds();
LOGMASKED(LOG_IR, "width %u height %u max_x %u max_y %u refresh %f\n", horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, ATTOSECONDS_TO_HZ(refresh));
@ -996,7 +1019,11 @@ void scn2674_device::device_timer(emu_timer &timer, device_timer_id id, int para
m_irq_register |= 0x08;
m_intr_cb(ASSERT_LINE);
}
if (m_buffer_mode_select == 3)
m_breq_cb(ASSERT_LINE);
}
else if (m_buffer_mode_select == 3)
m_breq_cb(CLEAR_LINE);
// Handle screen splits
for (int s = 0; s < 2; s++)

View File

@ -22,7 +22,9 @@ public:
// static configuration
auto intr_callback() { return m_intr_cb.bind(); }
auto breq_callback() { return m_breq_cb.bind(); }
void set_character_width(int value) { m_hpixels_per_column = value; }
template <class FunctionClass>
void set_display_callback(void (FunctionClass::*callback)(bitmap_rgb32 &, int, int, uint8_t, uint8_t, uint8_t, uint16_t, bool, bool, bool, bool, bool), const char *name)
{
@ -59,6 +61,7 @@ protected:
//protected:
bitmap_rgb32 m_bitmap;
devcb_write_line m_intr_cb;
devcb_write_line m_breq_cb;
uint8_t m_IR_pointer;
uint16_t m_screen1_address;

View File

@ -21,6 +21,7 @@ public:
qvt201_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_mainnmi(*this, "mainnmi")
, m_eia(*this, "eia")
, m_screen(*this, "screen")
, m_p_chargen(*this, "chargen")
@ -40,6 +41,7 @@ private:
void mem_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<input_merger_device> m_mainnmi;
required_device<rs232_port_device> m_eia;
required_device<screen_device> m_screen;
required_region_ptr<u8> m_p_chargen;
@ -73,11 +75,12 @@ WRITE8_MEMBER(qvt201_state::duart_out_w)
// OP3 = 132/_80
// OP4 = SRV
// OP5 = BLOCK/_UL
// OP6 = preset NMI flipflop
// OP6 = preset MBC NMI flipflop
// OP7 = _DATA/TALK (EIA pin 14)
m_eia->write_rts(BIT(data, 0));
m_eia->write_dtr(BIT(data, 1));
m_mainnmi->in_w<1>(!BIT(data, 6));
}
void qvt201_state::mem_map(address_map &map)
@ -100,8 +103,11 @@ MACHINE_CONFIG_START(qvt201_state::qvt201)
MCFG_DEVICE_ADD("maincpu", Z80, 3.6864_MHz_XTAL)
MCFG_DEVICE_PROGRAM_MAP(mem_map) // IORQ is not used at all
MCFG_INPUT_MERGER_ANY_HIGH("mainint") // open collector
MCFG_INPUT_MERGER_OUTPUT_HANDLER(INPUTLINE("maincpu", 0))
input_merger_device &mainint(INPUT_MERGER_ANY_HIGH(config, "mainint")); // open collector
mainint.output_handler().set_inputline("maincpu", INPUT_LINE_IRQ0);
input_merger_device &mainnmi(INPUT_MERGER_ALL_HIGH(config, "mainnmi"));
mainnmi.output_handler().set_inputline("maincpu", INPUT_LINE_NMI);
MCFG_DEVICE_ADD("duart", SCN2681, 3.6864_MHz_XTAL) // XTAL not directly connected
MCFG_MC68681_IRQ_CALLBACK(WRITELINE("mainint", input_merger_device, in_w<1>))
@ -126,6 +132,7 @@ MACHINE_CONFIG_START(qvt201_state::qvt201)
scn2672_device &crtc(SCN2672(config, "crtc", 48.654_MHz_XTAL / 30));
crtc.set_character_width(10); // 9 in 132-column mode
crtc.intr_callback().set("mainint", FUNC(input_merger_device::in_w<0>));
crtc.breq_callback().set("mainnmi", FUNC(input_merger_device::in_w<0>));
crtc.set_screen("screen");
MACHINE_CONFIG_END