mc6845: Use standard device method to adjust input clock (nw)

This commit is contained in:
AJR 2019-04-28 08:10:30 -04:00
parent b01bc82f14
commit 523e9c8cff
20 changed files with 83 additions and 69 deletions

View File

@ -865,10 +865,10 @@ void isa8_aga_device::pc_aga_set_mode( AGA_MODE mode)
switch (m_mode) {
case AGA_COLOR:
m_mc6845->set_clock( XTAL(14'318'181)/8 );
m_mc6845->set_unscaled_clock( XTAL(14'318'181)/8 );
break;
case AGA_MONO:
m_mc6845->set_clock( 16257000/9 );
m_mc6845->set_unscaled_clock( 16257000/9 );
break;
case AGA_OFF:
break;

View File

@ -875,7 +875,7 @@ void isa8_cga_device::mode_control_w(uint8_t data)
// The lowest bit of the mode register selects, among others, the
// input clock to the 6845.
m_crtc->set_clock( ( m_mode_control & 1 ) ? CGA_HCLK : CGA_LCLK );
m_crtc->set_unscaled_clock( ( m_mode_control & 1 ) ? CGA_HCLK : CGA_LCLK );
set_palette_luts();
}

View File

@ -672,7 +672,7 @@ WRITE8_MEMBER( isa8_hercules_device::mode_control_w )
m_update_row_type = -1;
}
m_crtc->set_clock( m_mode_control & 0x02 ? MDA_CLOCK / 16 : MDA_CLOCK / 9 );
m_crtc->set_unscaled_clock( MDA_CLOCK / (m_mode_control & 0x02 ? 16 : 9) );
m_crtc->set_hpixels_per_column( m_mode_control & 0x02 ? 16 : 9 );
}

View File

@ -298,11 +298,11 @@ void wangpc_lvc_device::wangpcbus_aiowc_w(offs_t offset, uint16_t mem_mask, uint
if (OPTION_80_COL)
{
m_crtc->set_clock(XTAL(14'318'181) / 8);
m_crtc->set_unscaled_clock(XTAL(14'318'181) / 8);
}
else
{
m_crtc->set_clock(XTAL(14'318'181) / 16);
m_crtc->set_unscaled_clock(XTAL(14'318'181) / 16);
}
}
break;

View File

@ -99,6 +99,7 @@ mc6845_device::mc6845_device(const machine_config &mconfig, device_type type, co
device_video_interface(mconfig, *this, false),
m_show_border_area(true),
m_interlace_adjust(0),
m_clk_scale(1),
m_visarea_adjust_min_x(0),
m_visarea_adjust_max_x(0),
m_visarea_adjust_min_y(0),
@ -373,8 +374,8 @@ void mos8563_device::register_w(uint8_t data)
{
int dbl = HSS_DBL;
m_horiz_scroll = data & 0xff;
if (dbl && !HSS_DBL) set_clock(m_clock << 1);
if (!dbl && HSS_DBL) set_clock(m_clock >> 1);
if (dbl && !HSS_DBL) { m_clk_scale = 4; recompute_parameters(true); }
if (!dbl && HSS_DBL) { m_clk_scale = 8; recompute_parameters(true); }
break;
}
case 0x1a: m_color = data & 0xff; break;
@ -384,7 +385,7 @@ void mos8563_device::register_w(uint8_t data)
case 0x1e:
m_word_count = data & 0xff;
m_update_ready_bit = 0;
m_block_copy_timer->adjust( attotime::from_ticks( 1, m_clock ) );
m_block_copy_timer->adjust(cclks_to_attotime(1));
break;
case 0x1f:
m_data = data & 0xff;
@ -518,7 +519,7 @@ void mc6845_device::recompute_parameters(bool postload)
vert_sync_pix_width = 0x10;
/* determine the transparent update cycle time, 1 update every 4 character clocks */
m_upd_time = attotime::from_hz(m_clock) * (4 * m_hpixels_per_column);
m_upd_time = cclks_to_attotime(4 * m_hpixels_per_column);
hsync_on_pos = m_horiz_sync_pos * m_hpixels_per_column;
hsync_off_pos = hsync_on_pos + (horiz_sync_char_width * m_hpixels_per_column);
@ -551,7 +552,7 @@ void mc6845_device::recompute_parameters(bool postload)
{
rectangle visarea;
attoseconds_t refresh = HZ_TO_ATTOSECONDS(m_clock) * (m_horiz_char_total + 1) * vert_pix_total;
attotime refresh = cclks_to_attotime((m_horiz_char_total + 1) * vert_pix_total);
// This doubles the vertical resolution, required for 'interlace and video' mode support.
// Tested and works for super80v, which was designed with this in mind (choose green or monochrome colour in config switches).
@ -570,13 +571,13 @@ void mc6845_device::recompute_parameters(bool postload)
visarea.set(0 + m_visarea_adjust_min_x, max_visible_x + m_visarea_adjust_max_x, 0 + m_visarea_adjust_min_y, max_visible_y + m_visarea_adjust_max_y);
LOGMASKED(LOG_CONFIG, "M6845 config screen: HTOTAL: %d VTOTAL: %d MAX_X: %d MAX_Y: %d HSYNC: %d-%d VSYNC: %d-%d Freq: %ffps\n",
horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, 1 / ATTOSECONDS_TO_DOUBLE(refresh));
horiz_pix_total, vert_pix_total, max_visible_x, max_visible_y, hsync_on_pos, hsync_off_pos - 1, vsync_on_pos, vsync_off_pos - 1, refresh.as_hz());
if (has_screen())
screen().configure(horiz_pix_total, vert_pix_total, visarea, refresh);
screen().configure(horiz_pix_total, vert_pix_total, visarea, refresh.as_attoseconds());
if(!m_reconfigure_cb.isnull())
m_reconfigure_cb(horiz_pix_total, vert_pix_total, visarea, refresh);
m_reconfigure_cb(horiz_pix_total, vert_pix_total, visarea, refresh.as_attoseconds());
m_has_valid_parameters = true;
}
@ -599,11 +600,11 @@ void mc6845_device::recompute_parameters(bool postload)
void mc6845_device::update_counters()
{
m_character_counter = m_line_timer->elapsed( ).as_ticks( m_clock );
m_character_counter = attotime_to_cclks(m_line_timer->elapsed());
if ( m_hsync_off_timer ->enabled( ) )
if (m_hsync_off_timer->enabled())
{
m_hsync_width_counter = m_hsync_off_timer ->elapsed( ).as_ticks( m_clock );
m_hsync_width_counter = attotime_to_cclks(m_hsync_off_timer->elapsed());
}
}
@ -771,7 +772,7 @@ void mc6845_device::handle_line_timer()
if ( m_line_enable_ff )
{
/* Schedule DE off signal change */
m_de_off_timer->adjust(attotime::from_ticks( m_horiz_disp, m_clock ));
m_de_off_timer->adjust(cclks_to_attotime(m_horiz_disp));
/* Is cursor visible on this line? */
if ( m_cursor_state &&
@ -783,15 +784,15 @@ void mc6845_device::handle_line_timer()
m_cursor_x = m_cursor_addr - m_line_address;
/* Schedule CURSOR ON signal */
m_cur_on_timer->adjust( attotime::from_ticks( m_cursor_x, m_clock ) );
m_cur_on_timer->adjust(cclks_to_attotime(m_cursor_x));
}
}
/* Schedule HSYNC on signal */
m_hsync_on_timer->adjust( attotime::from_ticks( m_horiz_sync_pos, m_clock ) );
m_hsync_on_timer->adjust(cclks_to_attotime(m_horiz_sync_pos));
/* Schedule our next callback */
m_line_timer->adjust( attotime::from_ticks( m_horiz_char_total + 1, m_clock ) );
m_line_timer->adjust(cclks_to_attotime(m_horiz_char_total + 1));
/* Set VSYNC and DE signals */
set_vsync( new_vsync );
@ -815,7 +816,7 @@ void mc6845_device::device_timer(emu_timer &timer, device_timer_id id, int param
set_cur( true );
/* Schedule CURSOR off signal */
m_cur_off_timer->adjust( attotime::from_ticks( 1, m_clock ) );
m_cur_off_timer->adjust(cclks_to_attotime(1));
break;
case TIMER_CUR_OFF:
@ -830,7 +831,7 @@ void mc6845_device::device_timer(emu_timer &timer, device_timer_id id, int param
set_hsync( true );
/* Schedule HSYNC off signal */
m_hsync_off_timer->adjust( attotime::from_ticks( hsync_width, m_clock ) );
m_hsync_off_timer->adjust(cclks_to_attotime(hsync_width));
}
break;
@ -881,7 +882,7 @@ void mos8563_device::device_timer(emu_timer &timer, device_timer_id id, int para
if (--m_word_count)
{
m_block_copy_timer->adjust( attotime::from_ticks( 1, m_clock ) );
m_block_copy_timer->adjust(cclks_to_attotime(1));
}
else
{
@ -914,20 +915,7 @@ void mc6845_device::assert_light_pen_input()
{
/* compute the pixel coordinate of the NEXT character -- this is when the light pen latches */
/* set the timer that will latch the display address into the light pen registers */
m_light_pen_latch_timer->adjust(attotime::from_ticks( 1, m_clock ));
}
void mc6845_device::set_clock(int clock)
{
/* validate arguments */
assert(clock > 0);
if (clock != m_clock)
{
m_clock = clock;
recompute_parameters(true);
}
m_light_pen_latch_timer->adjust(cclks_to_attotime(1));
}
@ -1056,7 +1044,7 @@ uint32_t mc6845_device::screen_update(screen_device &screen, bitmap_rgb32 &bitma
void mc6845_device::device_start()
{
assert(m_clock > 0);
assert(clock() > 0);
assert(m_hpixels_per_column > 0);
/* resolve callbacks */
@ -1393,6 +1381,7 @@ void mos8563_device::device_start()
save_item(NAME(m_dram_refresh));
save_item(NAME(m_sync_polarity));
save_item(NAME(m_revision));
save_item(NAME(m_clk_scale));
}
@ -1412,7 +1401,7 @@ void mc6845_device::device_reset()
m_out_vsync_cb(false);
if (!m_line_timer->enabled())
m_line_timer->adjust(attotime::from_ticks(m_horiz_char_total + 1, m_clock));
m_line_timer->adjust(cclks_to_attotime(m_horiz_char_total + 1));
m_light_pen_latched = false;
@ -1533,7 +1522,7 @@ mos8563_device::mos8563_device(const machine_config &mconfig, device_type type,
device_palette_interface(mconfig, *this),
m_videoram_space_config("videoram", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(mos8563_device::mos8563_videoram_map), this))
{
set_clock_scale(1.0/8);
m_clk_scale = 8;
}

View File

@ -4,6 +4,29 @@
Motorola MC6845 and compatible CRT controller emulation
***********************************************************************
____ ____
GND 1 |* \__/ | 40 VS
_RESET 2 | | 39 HS
LPSTB 3 | | 38 RA0
MA0 4 | | 37 RA1
MA1 5 | | 36 RA2
MA2 6 | | 35 RA3
MA3 7 | | 34 RA4
MA4 8 | | 33 D0
MA5 9 | | 32 D1
MA6 10 | | 31 D2
MA7 11 | MC6845 | 30 D3
MA8 12 | | 29 D4
MA9 13 | | 28 D5
MA10 14 | | 27 D6
MA11 15 | | 26 D7
MA12 16 | | 25 _CS
MA13 17 | | 24 RS
DE 18 | | 23 E
CURSOR 19 | | 22 R/_W
Vcc 20 |____________| 21 CLK
**********************************************************************/
#ifndef MAME_VIDEO_MC6845_H
@ -93,10 +116,6 @@ public:
/* simulates the LO->HI clocking of the light pen pin (pin 3) */
void assert_light_pen_input();
/* set the clock (pin 21) of the chip */
void set_clock(int clock);
void set_clock(const XTAL &xtal) { set_clock(int(xtal.value())); }
/* set number of pixels per video memory address */
void set_hpixels_per_column(int hpixels_per_column);
@ -115,6 +134,9 @@ protected:
virtual void device_clock_changed() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
attotime cclks_to_attotime(uint64_t clocks) const { return clocks_to_attotime(clocks * m_clk_scale); }
uint64_t attotime_to_cclks(const attotime &duration) const { return attotime_to_clocks(duration) / m_clk_scale; }
bool m_supports_disp_start_addr_r;
bool m_supports_vert_sync_width;
bool m_supports_status_reg_d5;
@ -225,6 +247,8 @@ protected:
int m_noninterlace_adjust; /* adjust max ras in non-interlace mode */
int m_interlace_adjust; /* adjust max ras in interlace mode */
uint32_t m_clk_scale;
/* visible screen area adjustment */
int m_visarea_adjust_min_x;
int m_visarea_adjust_max_x;

View File

@ -194,7 +194,7 @@ WRITE8_MEMBER( apricot_state::i8255_portb_w )
floppy->mon_w(0);
// switch video modes
m_crtc->set_clock(15_MHz_XTAL / (m_video_mode ? 10 : 16));
m_crtc->set_unscaled_clock(15_MHz_XTAL / (m_video_mode ? 10 : 16));
m_crtc->set_hpixels_per_column(m_video_mode ? 10 : 16);
// PB7 Centronics transceiver direction. 0 = output, 1 = input

View File

@ -240,7 +240,7 @@ void bml3_state::m6845_change_clock(u8 setting)
case 0x88: m6845_clock = C80_CLOCK; break; //640 x 200, interlace
}
m_crtc->set_clock(m6845_clock);
m_crtc->set_unscaled_clock(m6845_clock);
}
WRITE8_MEMBER( bml3_state::bml3_hres_reg_w )

View File

@ -149,18 +149,19 @@ WRITE16_MEMBER( dim68k_state::dim68k_video_control_w )
D1 0 = Standard Chars & LoRes; 1 = Alternate Chars & HiRes [not emulated yet]
D0 0 = Non-Mixed (all text or all Graphics); 1 = Mixed (Colour Graphics and Monochrome Text) [not emulated yet]
*/
m_crtc->set_hpixels_per_column((data & 0x40) ? 7 : 8);
unsigned dots = (data & 0x40) ? 7 : 8;
m_crtc->set_hpixels_per_column(dots);
m_video_control = data;
switch (data & 0x18)
{
case 0x00: m_crtc->set_clock(XTAL(14'000'000));
case 0x00: m_crtc->set_unscaled_clock(XTAL(14'000'000) / dots);
break;
case 0x08: m_crtc->set_clock(XTAL(3'579'545));
case 0x08: m_crtc->set_unscaled_clock(XTAL(3'579'545) / dots);
break;
case 0x10: m_crtc->set_clock(XTAL(14'000'000) / 2);
case 0x10: m_crtc->set_unscaled_clock(XTAL(14'000'000) / dots / 2);
break;
case 0x18: m_crtc->set_clock(XTAL(3'579'545) / 2);
case 0x18: m_crtc->set_unscaled_clock(XTAL(3'579'545) / dots / 2);
break;
}
}

View File

@ -411,7 +411,7 @@ WRITE8_MEMBER( mycom_state::mycom_0a_w )
m_cass->output( BIT(data, 2) ? -1.0 : +1.0);
if ( (BIT(data, 7)) != (BIT(m_0a, 7)) )
m_crtc->set_clock(BIT(data, 7) ? 1008000 : 2016000);
m_crtc->set_unscaled_clock(BIT(data, 7) ? 1008000 : 2016000);
m_0a = data;

View File

@ -551,9 +551,9 @@ WRITE8_MEMBER( pasopia7_state::pasopia7_6845_w )
/* double pump the pixel clock if we are in 640 x 200 mode */
if(m_screen_type == 1) // raster
m_crtc->set_clock( (m_x_width) ? VDP_CLOCK*2 : VDP_CLOCK);
m_crtc->set_unscaled_clock( (m_x_width) ? VDP_CLOCK*2 : VDP_CLOCK);
else // lcd
m_crtc->set_clock( (m_x_width) ? LCD_CLOCK*2 : LCD_CLOCK);
m_crtc->set_unscaled_clock( (m_x_width) ? LCD_CLOCK*2 : LCD_CLOCK);
}
}

View File

@ -2140,7 +2140,7 @@ void cbm8296_state::cbm8296(machine_config &config)
PLS100(config, PLA1_TAG);
PLS100(config, PLA2_TAG);
m_crtc->set_clock(XTAL(16'000'000)/16);
m_crtc->device_t::set_clock(XTAL(16'000'000)/16);
m_crtc->set_show_border_area(true);
m_crtc->set_char_width(2*8);
m_crtc->set_update_row_callback(FUNC(pet80_state::cbm8296_update_row), this);

View File

@ -390,7 +390,7 @@ WRITE8_MEMBER( spc1500_state::portc_w)
m_centronics->write_strobe(BIT(data, 7));
m_double_mode = (!m_p5bit && BIT(data, 5)); // double access I/O mode
m_p5bit = BIT(data, 5);
m_vdg->set_clock(VDP_CLOCK/(BIT(data, 2) ? 48 : 24));
m_vdg->set_unscaled_clock(VDP_CLOCK/(BIT(data, 2) ? 48 : 24));
}
READ8_MEMBER( spc1500_state::portb_r)

View File

@ -234,7 +234,7 @@ WRITE8_MEMBER( trs80m2_state::nmi_w )
// 80/40 character mode
m_80_40_char_en = BIT(data, 4);
m_crtc->set_clock(12.48_MHz_XTAL / (m_80_40_char_en ? 16 : 8));
m_crtc->set_unscaled_clock(12.48_MHz_XTAL / (m_80_40_char_en ? 16 : 8));
// RTC interrupt enable
m_enable_rtc_int = BIT(data, 5);

View File

@ -251,7 +251,7 @@ MC6845_UPDATE_ROW( victor9k_state::crtc_update_row )
if (m_hires != hires)
{
m_hires = hires;
m_crtc->set_clock(XTAL(30'000'000) / width);
m_crtc->set_unscaled_clock(XTAL(30'000'000) / width);
m_crtc->set_hpixels_per_column(width);
}

View File

@ -1510,7 +1510,7 @@ WRITE8_MEMBER( x1_state::x1_portc_w )
m_hres_320 = data & 0x40;
/* set up the pixel clock according to the above divider */
m_crtc->set_clock(VDP_CLOCK/((m_hres_320) ? 48 : 24));
m_crtc->set_unscaled_clock(VDP_CLOCK/((m_hres_320) ? 48 : 24));
if(!BIT(data, 5) && BIT(m_io_switch, 5))
m_iobank->set_bank(1);

View File

@ -2179,7 +2179,7 @@ The exception is the case where none of b7-b0 are reset (i.e. port &FBFF), which
{
m_aleste_mode = data;
logerror("EXTEND: Port &FABF write 0x%02x\n",data);
m_crtc->set_clock( ( m_aleste_mode & 0x02 ) ? ( XTAL(16'000'000) / 8 ) : ( XTAL(16'000'000) / 16 ) );
m_crtc->set_unscaled_clock( ( m_aleste_mode & 0x02 ) ? ( XTAL(16'000'000) / 8 ) : ( XTAL(16'000'000) / 16 ) );
}
mface2 = dynamic_cast<cpc_multiface2_device*>(get_expansion_device(machine(),"multiface2"));

View File

@ -175,13 +175,13 @@ WRITE8_MEMBER(bbc_state::video_ula_w)
m_hd6845->set_hpixels_per_column(m_pixels_per_byte);
if (m_video_ula.clock_rate_6845)
m_hd6845->set_clock(16_MHz_XTAL / 8);
m_hd6845->set_unscaled_clock(16_MHz_XTAL / 8);
else
m_hd6845->set_clock(16_MHz_XTAL / 16);
m_hd6845->set_unscaled_clock(16_MHz_XTAL / 16);
// FIXME: double clock for MODE7 until interlace is implemented
if (m_video_ula.teletext_normal_select)
m_hd6845->set_clock(16_MHz_XTAL / 8);
m_hd6845->set_unscaled_clock(16_MHz_XTAL / 8);
break;
// Set a palette register in the Video ULA
case 1:

View File

@ -233,17 +233,17 @@ WRITE8_MEMBER( pc1512_state::vdu_w )
case ALPHA_40:
case GRAPHICS_1:
m_vdu->set_hpixels_per_column(8);
m_vdu->set_clock(XTAL(28'636'363)/32);
m_vdu->set_unscaled_clock(XTAL(28'636'363)/32);
break;
case ALPHA_80:
m_vdu->set_hpixels_per_column(8);
m_vdu->set_clock(XTAL(28'636'363)/16);
m_vdu->set_unscaled_clock(XTAL(28'636'363)/16);
break;
case GRAPHICS_2:
m_vdu->set_hpixels_per_column(16);
m_vdu->set_clock(XTAL(28'636'363)/32);
m_vdu->set_unscaled_clock(XTAL(28'636'363)/32);
break;
}
}

View File

@ -607,11 +607,11 @@ void pcvideo_pcjr_device::pc_pcjr_mode_switch()
/* Determine mc6845 input clock */
if ( m_reg.data[0] & 0x01 )
{
m_mc6845->set_clock( XTAL(14'318'181)/8 );
m_mc6845->set_unscaled_clock( XTAL(14'318'181)/8 );
}
else
{
m_mc6845->set_clock( XTAL(14'318'181)/16 );
m_mc6845->set_unscaled_clock( XTAL(14'318'181)/16 );
}
/* color or b/w? */