fixedfreq: Separate interface from implementation. (nw)

This commit is contained in:
couriersud 2019-03-12 02:01:13 +01:00
parent e80276bb23
commit 275cd544f0
2 changed files with 355 additions and 257 deletions

View File

@ -24,33 +24,115 @@
Fixed frequency monitor
***************************************************************************/
// device type definition
DEFINE_DEVICE_TYPE(FIXFREQ, fixedfreq_device, "fixfreq", "Fixed-Frequency Monochrome Monitor")
void fixedfreq_monitor_state::update_sync_channel(const time_type &time, const double newval)
{
const time_type delta_time = time - m_last_sync_time;
const int last_vsync = m_sig_vsync;
const int last_comp = m_sig_composite;
m_vsync_filter += ((double) last_comp - m_vsync_filter) * (1.0 - exp(-delta_time * m_vsync_filter_timeconst));
m_sig_composite = (newval < m_desc.m_sync_threshold) ? 1 : 0 ;
m_sig_vsync = (m_vsync_filter > m_vsync_threshold) ? 1 : 0;
if (!last_vsync && m_sig_vsync)
{
//LOG("VSYNC %d %d\n", m_last_x, m_last_y + m_sig_field);
m_last_y = m_desc.m_vbackporch - m_desc.m_vsync;
// toggle bitmap
m_cur_bm ^= 1;
m_intf.update_screen_parameters(time - m_last_vsync_time);
m_last_vsync_time = time;
}
else if (last_vsync && !m_sig_vsync)
{
m_sig_field = last_comp; /* force false-progressive */
m_sig_field = (m_sig_field ^ 1) ^ last_comp; /* if there is no field switch, auto switch */
//LOG("Field: %d\n", m_sig_field);
}
if (!last_comp && m_sig_composite)
{
/* TODO - time since last hsync and field detection */
//LOG("HSYNC up %d\n", m_last_x);
// FIXME: pixels > 50 filters some spurious hysnc on line 27 in breakout
if (!m_sig_vsync && (m_last_x > m_desc.m_hscale * 100))
{
m_last_y += m_desc.m_fieldcount;
m_last_x = 0;
m_line_time = time;
}
//if (m_last_y == 27) printf("HSYNC up %d %d\n", m_last_y, pixels);
}
else if (last_comp && !m_sig_composite)
{
/* falling composite */
//LOG("HSYNC down %f %d %f\n", time * 1e6, m_last_x, m_sync_signal);
}
m_sync_signal = newval;
m_last_sync_time = time;
}
void fixedfreq_monitor_state::recompute_parameters()
{
bool needs_realloc = (m_htotal != m_desc.m_hbackporch) && (m_vtotal != m_desc.m_vbackporch);
if (m_bitmap[0] != nullptr || needs_realloc)
m_bitmap[0] = nullptr;
if (m_bitmap[1] != nullptr || needs_realloc)
m_bitmap[1] = nullptr;
m_htotal = m_desc.m_hbackporch;
m_vtotal = m_desc.m_vbackporch;
/* sync separator */
m_vsync_threshold = (exp(- 3.0/(3.0+3.0))) - exp(-1.0);
m_vsync_filter_timeconst = (double) (m_desc.m_monitor_clock) / (double) m_htotal * 1.0; // / (3.0 + 3.0);
//LOG("trigger %f with len %f\n", m_vsync_threshold, 1e6 / m_vsync_filter_timeconst);
m_bitmap[0] = std::make_unique<bitmap_rgb32>(m_htotal * m_desc.m_hscale, m_vtotal);
m_bitmap[1] = std::make_unique<bitmap_rgb32>(m_htotal * m_desc.m_hscale, m_vtotal);
m_clock_period = 1.0 / m_desc.m_monitor_clock;
m_intf.update_screen_parameters(m_clock_period * m_vtotal * m_htotal);
}
void fixedfreq_monitor_state::update_bm(const time_type &time)
{
const int pixels = round((time - m_line_time) * m_desc.m_hscale / m_clock_period);
const int has_fields = (m_desc.m_fieldcount > 1) ? 1: 0;
bitmap_rgb32 *bm = m_bitmap[m_cur_bm].get();
if (m_last_y < bm->height())
{
rgb_t col(255, 0, 0); // Mark sync areas
if (m_sync_signal >= m_desc.m_sync_threshold)
{
col = m_col;
}
bm->plot_box(m_last_x, m_last_y + m_sig_field * has_fields, pixels - m_last_x, 1, col);
m_last_x = pixels;
}
}
fixedfreq_device::fixedfreq_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, false),
m_htotal(0),
m_vtotal(0),
m_hscale(1), // FIXME: this should be modified by static initialization
m_sync_signal(0),
m_last_x(0),
m_last_y(0),
m_cur_bm(0),
// default to NTSC "704x480@30i"
m_monitor_clock(13500000),
m_hvisible(704),
m_hfrontporch(728),
m_hsync(791),
m_hbackporch(858),
m_vvisible(480),
m_vfrontporch(486),
m_vsync(492),
m_vbackporch(525),
m_fieldcount(2),
m_sync_threshold(0.3),
m_gain(1.0 / 3.7),
m_vsync_filter(0), m_vsync_threshold(0), m_vsync_filter_timeconst(0), m_sig_vsync(0), m_sig_composite(0), m_sig_field(0)
m_refresh_period(time_type(0)),
m_monitor(),
m_state(m_monitor, *this)
{
}
@ -65,7 +147,9 @@ void fixedfreq_device::device_config_complete()
return;
if (!screen().refresh_attoseconds())
screen().set_raw(m_monitor_clock, m_hbackporch, 0, m_hbackporch, m_vbackporch, 0, m_vbackporch);
screen().set_raw(m_monitor.m_monitor_clock, m_monitor.m_hbackporch, 0,
m_monitor.m_hbackporch, m_monitor.m_vbackporch, 0,
m_monitor.m_vbackporch);
if (!screen().has_screen_update())
screen().set_screen_update(screen_update_rgb32_delegate(FUNC(fixedfreq_device::screen_update), this));
@ -73,57 +157,35 @@ void fixedfreq_device::device_config_complete()
void fixedfreq_device::device_start()
{
m_htotal = 0;
m_vtotal = 0;
m_sync_signal = 0.0;
m_col = rgb_t(0,0,0);
m_last_x = 0;
m_last_y = 0;
m_last_sync_time = time_type(0);
m_line_time = time_type(0);
m_last_hsync_time = time_type(0);
m_last_vsync_time = time_type(0);
m_refresh_period = time_type(0);
m_clock_period = time_type(0);
//bitmap_rgb32 *m_bitmap[2];
m_cur_bm = 0;
/* sync separator */
m_vsync_filter = 0.0;
m_vsync_threshold = 0.0;
m_vsync_filter_timeconst = 0.0;
m_state.dev_start_helper();
m_sig_vsync = 0;
m_sig_composite = 0;
m_sig_field = 0;
m_state.recompute_parameters();
m_bitmap[0] = nullptr;
m_bitmap[1] = nullptr;
//m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this));
recompute_parameters();
save_item(NAME(m_sync_signal));
save_item(NAME(m_last_x));
save_item(NAME(m_last_y));
save_item(NAME(m_last_sync_time));
save_item(NAME(m_line_time));
save_item(NAME(m_last_hsync_time));
save_item(NAME(m_last_vsync_time));
// FIXME: will be done by netlist going forward
save_item(NAME(m_state.m_sync_signal));
save_item(NAME(m_state.m_last_x));
save_item(NAME(m_state.m_last_y));
save_item(NAME(m_state.m_last_sync_time));
save_item(NAME(m_state.m_line_time));
save_item(NAME(m_state.m_last_hsync_time));
save_item(NAME(m_state.m_last_vsync_time));
save_item(NAME(m_refresh_period));
save_item(NAME(m_clock_period));
save_item(NAME(m_state.m_clock_period));
//save_item(NAME(m_bitmap[0]));
//save_item(NAME(m_bitmap[1]));
save_item(NAME(m_cur_bm));
save_item(NAME(m_state.m_cur_bm));
/* sync separator */
save_item(NAME(m_vsync_filter));
save_item(NAME(m_vsync_threshold));
save_item(NAME(m_vsync_filter_timeconst));
save_item(NAME(m_state.m_vsync_filter));
save_item(NAME(m_state.m_vsync_threshold));
save_item(NAME(m_state.m_vsync_filter_timeconst));
save_item(NAME(m_sig_vsync));
save_item(NAME(m_sig_composite));
save_item(NAME(m_sig_field));
save_item(NAME(m_state.m_sig_vsync));
save_item(NAME(m_state.m_sig_composite));
save_item(NAME(m_state.m_sig_field));
@ -131,12 +193,7 @@ void fixedfreq_device::device_start()
void fixedfreq_device::device_reset()
{
m_last_sync_time = time_type(0);
m_line_time = time_type(0);
m_last_hsync_time = time_type(0);
m_last_vsync_time = time_type(0);
m_vsync_filter = 0;
m_state.dev_reset_helper();
}
@ -145,130 +202,27 @@ void fixedfreq_device::device_post_load()
//recompute_parameters();
}
void fixedfreq_device::recompute_parameters()
{
bool needs_realloc = (m_htotal != m_hbackporch) && (m_vtotal != m_vbackporch);
if (m_bitmap[0] != nullptr || needs_realloc)
m_bitmap[0] = nullptr;
if (m_bitmap[1] != nullptr || needs_realloc)
m_bitmap[1] = nullptr;
m_htotal = m_hbackporch;
m_vtotal = m_vbackporch;
/* sync separator */
m_vsync_threshold = (exp(- 3.0/(3.0+3.0))) - exp(-1.0);
m_vsync_filter_timeconst = (double) (m_monitor_clock) / (double) m_htotal * 1.0; // / (3.0 + 3.0);
LOG("trigger %f with len %f\n", m_vsync_threshold, 1e6 / m_vsync_filter_timeconst);
m_bitmap[0] = std::make_unique<bitmap_rgb32>(m_htotal * m_hscale, m_vtotal);
m_bitmap[1] = std::make_unique<bitmap_rgb32>(m_htotal * m_hscale, m_vtotal);
m_clock_period = 1.0 / m_monitor_clock;
update_screen_parameters(m_clock_period * m_vtotal * m_htotal);
}
void fixedfreq_device::update_screen_parameters(const time_type &refresh)
{
rectangle visarea(
(m_hbackporch - m_hfrontporch) * m_hscale,
(m_hbackporch - m_hfrontporch + m_hvisible) * m_hscale - 1,
m_vbackporch - m_vfrontporch,
m_vbackporch - m_vfrontporch + m_vvisible - 1);
rectangle visarea(m_monitor.minh(), m_monitor.maxh(), m_monitor.minv(), m_monitor.maxv());
m_refresh_period = refresh;
screen().configure(m_htotal * m_hscale, m_vtotal, visarea, DOUBLE_TO_ATTOSECONDS(m_refresh_period));
}
void fixedfreq_device::update_sync_channel(const time_type &time, const double newval)
{
const time_type delta_time = time - m_last_sync_time;
const int last_vsync = m_sig_vsync;
const int last_comp = m_sig_composite;
m_vsync_filter += ((double) last_comp - m_vsync_filter) * (1.0 - exp(-delta_time * m_vsync_filter_timeconst));
m_sig_composite = (newval < m_sync_threshold) ? 1 : 0 ;
m_sig_vsync = (m_vsync_filter > m_vsync_threshold) ? 1 : 0;
if (!last_vsync && m_sig_vsync)
{
LOG("VSYNC %d %d\n", m_last_x, m_last_y + m_sig_field);
m_last_y = m_vbackporch - m_vsync;
// toggle bitmap
m_cur_bm ^= 1;
update_screen_parameters(time - m_last_vsync_time);
m_last_vsync_time = time;
}
else if (last_vsync && !m_sig_vsync)
{
m_sig_field = last_comp; /* force false-progressive */
m_sig_field = (m_sig_field ^ 1) ^ last_comp; /* if there is no field switch, auto switch */
LOG("Field: %d\n", m_sig_field);
}
if (!last_comp && m_sig_composite)
{
/* TODO - time since last hsync and field detection */
LOG("HSYNC up %d\n", m_last_x);
// FIXME: pixels > 50 filters some spurious hysnc on line 27 in breakout
if (!m_sig_vsync && (m_last_x > m_hscale * 100))
{
m_last_y += m_fieldcount;
m_last_x = 0;
m_line_time = time;
}
//if (m_last_y == 27) printf("HSYNC up %d %d\n", m_last_y, pixels);
}
else if (last_comp && !m_sig_composite)
{
/* falling composite */
LOG("HSYNC down %f %d %f\n", time * 1e6, m_last_x, m_sync_signal);
}
m_sync_signal = newval;
m_last_sync_time = time;
}
void fixedfreq_device::update_bm(const time_type &time)
{
const int pixels = round((time - m_line_time) * m_hscale / m_clock_period);
const int has_fields = (m_fieldcount > 1) ? 1: 0;
bitmap_rgb32 *bm = m_bitmap[m_cur_bm].get();
if (m_last_y < bm->height())
{
rgb_t col(255, 0, 0); // Mark sync areas
if (m_sync_signal >= m_sync_threshold)
{
col = m_col;
}
bm->plot_box(m_last_x, m_last_y + m_sig_field * has_fields, pixels - m_last_x, 1, col);
m_last_x = pixels;
}
screen().configure(m_state.m_htotal * m_monitor.m_hscale, m_state.m_vtotal, visarea, DOUBLE_TO_ATTOSECONDS(m_refresh_period));
}
uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
copybitmap(bitmap, *m_bitmap[!m_cur_bm], 0, 0, 0, 0, cliprect);
copybitmap(bitmap, *m_state.m_bitmap[!m_state.m_cur_bm], 0, 0, 0, 0, cliprect);
return 0;
}
NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_composite_monochrome)
void fixedfreq_monitor_state::update_composite_monochrome(const time_type &time, const double data)
{
// double is good enough for this exercise;
update_bm(time);
update_sync_channel(time, data);
const time_type ctime = time.as_double();
update_bm(ctime);
update_sync_channel(ctime, data);
int colv = (int) ((data - m_sync_threshold) * m_gain * 255.0);
int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0);
if (colv > 255)
colv = 255;
if (colv < 0)
@ -277,18 +231,61 @@ NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_composite_monochrome)
m_col = rgb_t(colv, colv, colv);
}
void fixedfreq_monitor_state::update_red(const time_type &time, const double data)
{
update_bm(time);
//update_sync_channel(ctime, data);
int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0);
if (colv > 255)
colv = 255;
m_col.set_r(colv);
}
void fixedfreq_monitor_state::update_green(const time_type &time, const double data)
{
update_bm(time);
//update_sync_channel(ctime, data);
int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0);
if (colv > 255)
colv = 255;
m_col.set_g(colv);
}
void fixedfreq_monitor_state::update_blue(const time_type &time, const double data)
{
update_bm(time);
//update_sync_channel(ctime, data);
int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0);
if (colv > 255)
colv = 255;
m_col.set_b(colv);
}
void fixedfreq_monitor_state::update_sync(const time_type &time, const double data)
{
update_bm(time);
update_sync_channel(time, data);
}
NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_composite_monochrome)
{
// double is good enough for this exercise;
const time_type ctime = time.as_double();
m_state.update_composite_monochrome(ctime, data);
}
NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_red)
{
// double is good enough for this exercise;
const time_type ctime = time.as_double();
update_bm(ctime);
//update_sync_channel(ctime, data);
int colv = (int) ((data - m_sync_threshold) * m_gain * 255.0);
if (colv > 255)
colv = 255;
m_col.set_r(colv);
m_state.update_red(ctime, data);
}
NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_green)
@ -296,13 +293,7 @@ NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_green)
// double is good enough for this exercise;
const time_type ctime = time.as_double();
update_bm(ctime);
//update_sync_channel(ctime, data);
int colv = (int) ((data - m_sync_threshold) * m_gain * 255.0);
if (colv > 255)
colv = 255;
m_col.set_g(colv);
m_state.update_green(ctime, data);
}
NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_blue)
@ -310,13 +301,7 @@ NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_blue)
// double is good enough for this exercise;
const time_type ctime = time.as_double();
update_bm(ctime);
//update_sync_channel(ctime, data);
int colv = (int) ((data - m_sync_threshold) * m_gain * 255.0);
if (colv > 255)
colv = 255;
m_col.set_b(colv);
m_state.update_blue(ctime, data);
}
NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_sync)
@ -324,8 +309,7 @@ NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_sync)
// double is good enough for this exercise;
const time_type ctime = time.as_double();
update_bm(ctime);
update_sync_channel(ctime, data);
m_state.update_sync(ctime, data);
}
/***************************************************************************/

View File

@ -17,35 +17,188 @@
#include "machine/netlist.h"
#include "screen.h"
struct fixedfreq_monitor_desc
{
fixedfreq_monitor_desc()
// default to NTSC "704x480@30i"
: m_monitor_clock(13500000),
m_hvisible(704),
m_hfrontporch(728),
m_hsync(791),
m_hbackporch(858),
m_vvisible(480),
m_vfrontporch(486),
m_vsync(492),
m_vbackporch(525),
m_fieldcount(2),
m_sync_threshold(0.3),
m_gain(1.0 / 3.7),
m_hscale(1)
{}
int minh() const { return (m_hbackporch - m_hfrontporch) * m_hscale; }
int maxh() const { return (m_hbackporch - m_hfrontporch + m_hvisible) * m_hscale - 1; }
int minv() const { return m_vbackporch - m_vfrontporch; }
int maxv() const { return m_vbackporch - m_vfrontporch + m_vvisible - 1; }
uint32_t m_monitor_clock;
int m_hvisible;
int m_hfrontporch;
int m_hsync;
int m_hbackporch;
int m_vvisible;
int m_vfrontporch;
int m_vsync;
int m_vbackporch;
int m_fieldcount;
double m_sync_threshold;
double m_gain;
int m_hscale;
};
struct fixedfreq_monitor_state
{
typedef double time_type;
struct fixedfreq_monitor_intf
{
virtual ~fixedfreq_monitor_intf() = default;
virtual void update_screen_parameters(const time_type &refresh) = 0;
};
fixedfreq_monitor_state(fixedfreq_monitor_desc &desc, fixedfreq_monitor_intf &intf)
: m_desc(desc),
m_intf(intf),
m_sync_signal(0),
m_last_x(0),
m_last_y(0),
m_last_sync_time(time_type(0)),
m_line_time(time_type(0)),
m_last_hsync_time(time_type(0)),
m_last_vsync_time(time_type(0)),
m_clock_period(time_type(0)),
m_vsync_filter(0),
m_vsync_threshold(0),
m_vsync_filter_timeconst(0),
m_sig_vsync(0),
m_sig_composite(0),
m_sig_field(0),
m_cur_bm(0),
m_htotal(0),
m_vtotal(0)
{}
void dev_start_helper()
{
// FIXME: once moved to netlist this may no longer be necessary.
// Only copies constructor init
m_sync_signal = 0.0;
m_col = rgb_t(0,0,0);
m_last_x = 0;
m_last_y = 0;
m_last_sync_time = time_type(0);
m_line_time = time_type(0);
m_last_hsync_time = time_type(0);
m_last_vsync_time = time_type(0);
m_clock_period = time_type(0);
/* sync separator */
m_vsync_filter = 0.0;
m_vsync_threshold = 0.0;
m_vsync_filter_timeconst = 0.0;
m_sig_vsync = 0;
m_sig_composite = 0;
m_sig_field = 0;
m_cur_bm = 0;
m_bitmap[0] = nullptr;
m_bitmap[1] = nullptr;
m_htotal = 0;
m_vtotal = 0;
}
void dev_reset_helper()
{
m_last_sync_time = time_type(0);
m_line_time = time_type(0);
m_last_hsync_time = time_type(0);
m_last_vsync_time = time_type(0);
m_vsync_filter = 0;
}
void recompute_parameters();
void update_sync_channel(const time_type &time, const double newval);
void update_bm(const time_type &time);
void update_composite_monochrome(const time_type &time, const double newval);
void update_red(const time_type &time, const double data);
void update_green(const time_type &time, const double data);
void update_blue(const time_type &time, const double data);
void update_sync(const time_type &time, const double data);
const fixedfreq_monitor_desc &m_desc;
fixedfreq_monitor_intf &m_intf;
double m_sync_signal;
rgb_t m_col;
int m_last_x;
int m_last_y;
time_type m_last_sync_time;
time_type m_line_time;
time_type m_last_hsync_time;
time_type m_last_vsync_time;
time_type m_clock_period;
/* sync separator */
double m_vsync_filter;
double m_vsync_threshold;
double m_vsync_filter_timeconst;
int m_sig_vsync;
int m_sig_composite;
int m_sig_field;
std::unique_ptr<bitmap_rgb32> m_bitmap[2];
int m_cur_bm;
int m_htotal;
int m_vtotal;
};
// ======================> fixedfreq_device
class fixedfreq_device : public device_t, public device_video_interface
class fixedfreq_device : public device_t, public device_video_interface,
public fixedfreq_monitor_state::fixedfreq_monitor_intf
{
public:
using time_type = fixedfreq_monitor_state::time_type;
// construction/destruction
fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// inline configuration helpers
void set_monitor_clock(uint32_t clock) { m_monitor_clock = clock; }
void set_fieldcount(int count) { m_fieldcount = count; }
void set_threshold(double threshold) { m_sync_threshold = threshold; }
void set_gain(double gain) { m_gain = gain; }
void set_monitor_clock(uint32_t clock) { m_monitor.m_monitor_clock = clock; }
void set_fieldcount(int count) { m_monitor.m_fieldcount = count; }
void set_threshold(double threshold) { m_monitor.m_sync_threshold = threshold; }
void set_gain(double gain) { m_monitor.m_gain = gain; }
void set_horz_params(int visible, int frontporch, int sync, int backporch)
{
m_hvisible = visible;
m_hfrontporch = frontporch;
m_hsync = sync;
m_hbackporch = backporch;
m_monitor.m_hvisible = visible;
m_monitor.m_hfrontporch = frontporch;
m_monitor.m_hsync = sync;
m_monitor.m_hbackporch = backporch;
}
void set_vert_params(int visible, int frontporch, int sync, int backporch)
{
m_vvisible = visible;
m_vfrontporch = frontporch;
m_vsync = sync;
m_vbackporch = backporch;
m_monitor.m_vvisible = visible;
m_monitor.m_vfrontporch = frontporch;
m_monitor.m_vsync = sync;
m_monitor.m_vbackporch = backporch;
}
void set_horz_scale(int hscale) { m_hscale = hscale; }
void set_horz_scale(int hscale) { m_monitor.m_hscale = hscale; }
// pre-defined configurations
void set_mode_ntsc720() //ModeLine "720x480@30i" 13.5 720 736 799 858 480 486 492 525 interlace -hsync -vsync
@ -76,8 +229,6 @@ public:
protected:
typedef double time_type;
fixedfreq_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
@ -87,53 +238,16 @@ protected:
virtual void device_post_load() override;
//virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
void update_screen_parameters(const time_type &refresh);
void update_screen_parameters(const time_type &refresh) override;
private:
void update_sync_channel(const time_type &time, const double newval);
void update_bm(const time_type &time);
void recompute_parameters();
int m_htotal;
int m_vtotal;
int m_hscale;
double m_sync_signal;
rgb_t m_col;
int m_last_x;
int m_last_y;
time_type m_last_sync_time;
time_type m_line_time;
time_type m_last_hsync_time;
time_type m_last_vsync_time;
time_type m_refresh_period;
time_type m_clock_period;
std::unique_ptr<bitmap_rgb32> m_bitmap[2];
int m_cur_bm;
/* adjustable by drivers */
uint32_t m_monitor_clock;
int m_hvisible;
int m_hfrontporch;
int m_hsync;
int m_hbackporch;
int m_vvisible;
int m_vfrontporch;
int m_vsync;
int m_vbackporch;
int m_fieldcount;
double m_sync_threshold;
double m_gain;
fixedfreq_monitor_desc m_monitor;
fixedfreq_monitor_state m_state;
/* sync separator */
double m_vsync_filter;
double m_vsync_threshold;
double m_vsync_filter_timeconst;
int m_sig_vsync;
int m_sig_composite;
int m_sig_field;
};