summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/fixfreq.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/fixfreq.cpp')
-rw-r--r--src/devices/video/fixfreq.cpp408
1 files changed, 198 insertions, 210 deletions
diff --git a/src/devices/video/fixfreq.cpp b/src/devices/video/fixfreq.cpp
index 58eec1722e3..a64c6d812b3 100644
--- a/src/devices/video/fixfreq.cpp
+++ b/src/devices/video/fixfreq.cpp
@@ -19,216 +19,194 @@
//#define VERBOSE 1
#include "logmacro.h"
+
/***************************************************************************
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)
+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_vid(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_vint(0), m_int_trig(0), m_mult(0), m_sig_vsync(0), m_sig_composite(0), m_sig_field(0)
{
- 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;
- m_intf.vsync_start_cb(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::update_bm(const time_type &time)
+fixedfreq_device::fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : fixedfreq_device(mconfig, FIXFREQ, tag, owner, clock)
{
- 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;
-
- uint32_t col(0xffff0000); // Mark sync areas
-
- if (m_sync_signal >= m_desc.m_sync_threshold)
- col = m_col;
-
- m_intf.plot_hline(m_last_x, m_last_y + m_sig_field * has_fields, pixels - m_last_x, col);
- m_last_x = pixels;
}
-void fixedfreq_monitor_state::update_composite_monochrome(const time_type &time, const double data)
+void fixedfreq_device::device_start()
{
- update_bm(time);
- update_sync_channel(time, data);
-
- int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0);
- if (colv > 255)
- colv = 255;
- if (colv < 0)
- m_col = 0xffff0000;
- else
- m_col = 0xff000000 | (colv<<16) | (colv<<8) | colv;
-}
+ m_htotal = 0;
+ m_vtotal = 0;
+
+ m_vid = 0.0;
+ m_last_x = 0;
+ m_last_y = 0;
+ m_last_time = attotime::zero;
+ m_line_time = attotime::zero;
+ m_last_hsync_time = attotime::zero;
+ m_last_vsync_time = attotime::zero;
+ m_refresh = attotime::zero;
+ m_clock_period = attotime::zero;
+ //bitmap_rgb32 *m_bitmap[2];
+ m_cur_bm = 0;
-void fixedfreq_monitor_state::update_red(const time_type &time, const double data)
-{
- update_bm(time);
-
- int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0);
- if (colv > 255)
- colv = 255;
- if (colv < 0)
- colv = 0;
- m_col = (m_col & 0xff00ffff) | (colv<<16);
-}
+ /* sync separator */
+ m_vint = 0.0;
+ m_int_trig = 0.0;
+ m_mult = 0.0;
+
+ m_sig_vsync = 0;
+ m_sig_composite = 0;
+ m_sig_field = 0;
+
+ 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(false);
+
+ save_item(NAME(m_vid));
+ save_item(NAME(m_last_x));
+ save_item(NAME(m_last_y));
+ save_item(NAME(m_last_time));
+ save_item(NAME(m_line_time));
+ save_item(NAME(m_last_hsync_time));
+ save_item(NAME(m_last_vsync_time));
+ save_item(NAME(m_refresh));
+ save_item(NAME(m_clock_period));
+ //save_item(NAME(m_bitmap[0]));
+ //save_item(NAME(m_bitmap[1]));
+ save_item(NAME(m_cur_bm));
-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;
- if (colv < 0)
- colv = 0;
- m_col = (m_col & 0xffff00ff) | (colv<<8);
-}
+ /* sync separator */
+ save_item(NAME(m_vint));
+ save_item(NAME(m_int_trig));
+ save_item(NAME(m_mult));
-void fixedfreq_monitor_state::update_blue(const time_type &time, const double data)
-{
- update_bm(time);
- //update_sync_channel(ctime, data);
+ save_item(NAME(m_sig_vsync));
+ save_item(NAME(m_sig_composite));
+ save_item(NAME(m_sig_field));
- int colv = (int) ((data - m_desc.m_sync_threshold) * m_desc.m_gain * 255.0);
- if (colv > 255)
- colv = 255;
- if (colv < 0)
- colv = 0;
- m_col = (m_col & 0xffffff00) | colv;
-}
-void fixedfreq_monitor_state::update_sync(const time_type &time, const double data)
-{
- update_bm(time);
- update_sync_channel(time, data);
}
-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_cur_bm(0),
- m_htotal(0),
- m_vtotal(0),
- m_refresh_period(time_type(0)),
- m_monitor(),
- m_state(m_monitor, *this)
+void fixedfreq_device::device_reset()
{
+ m_last_time = attotime::zero;
+ m_line_time = attotime::zero;
+ m_last_hsync_time = attotime::zero;
+ m_last_vsync_time = attotime::zero;
+ m_vint = 0;
+
}
-fixedfreq_device::fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : fixedfreq_device(mconfig, FIXFREQ, tag, owner, clock)
+
+void fixedfreq_device::device_post_load()
{
+ //recompute_parameters(true);
}
-void fixedfreq_device::device_config_complete()
+void fixedfreq_device::recompute_parameters(bool postload)
{
- if (!has_screen())
- return;
+ bool needs_realloc = (m_htotal != m_hbackporch) && (m_vtotal != m_vbackporch);
- if (!screen().refresh_attoseconds())
- 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 (m_bitmap[0] != nullptr || needs_realloc)
+ m_bitmap[0] = nullptr;
+ if (m_bitmap[1] != nullptr || needs_realloc)
+ m_bitmap[1] = nullptr;
- if (!screen().has_screen_update())
- screen().set_screen_update(screen_update_rgb32_delegate(FUNC(fixedfreq_device::screen_update), this));
-}
+ m_htotal = m_hbackporch;
+ m_vtotal = m_vbackporch;
-void fixedfreq_device::device_start()
-{
+ /* sync separator */
- m_refresh_period = time_type(0);
+ m_int_trig = (exp(- 3.0/(3.0+3.0))) - exp(-1.0);
+ m_mult = (double) (m_monitor_clock) / (double) m_htotal * 1.0; // / (3.0 + 3.0);
+ LOG("trigger %f with len %f\n", m_int_trig, 1e6 / m_mult);
- m_cur_bm = 0;
+ m_bitmap[0] = std::make_unique<bitmap_rgb32>(m_htotal, m_vtotal);
+ m_bitmap[1] = std::make_unique<bitmap_rgb32>(m_htotal, m_vtotal);
- m_htotal = m_monitor.m_hbackporch;
- m_vtotal = m_monitor.m_vbackporch;
- m_bitmap[0] = std::make_unique<bitmap_rgb32>(m_htotal * m_monitor.m_hscale, m_vtotal);
- m_bitmap[1] = std::make_unique<bitmap_rgb32>(m_htotal * m_monitor.m_hscale, m_vtotal);
-
- m_state.start();
-
- // 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_state.m_clock_period));
- //save_item(NAME(m_bitmap[0]));
- //save_item(NAME(m_bitmap[1]));
- save_item(NAME(m_cur_bm));
+ rectangle visarea(
+ m_hbackporch - m_hfrontporch,
+ m_hbackporch - m_hfrontporch + m_hvisible - 1,
+ m_vbackporch - m_vfrontporch,
+ m_vbackporch - m_vfrontporch + m_vvisible - 1);
- /* sync separator */
- 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));
+ m_clock_period = attotime::from_hz(m_monitor_clock);
- save_item(NAME(m_state.m_sig_vsync));
- save_item(NAME(m_state.m_sig_composite));
- save_item(NAME(m_state.m_sig_field));
+ m_refresh = attotime::from_hz(m_monitor_clock) * m_vtotal * m_htotal;
+ screen().configure(m_htotal, m_vtotal, visarea, m_refresh.as_attoseconds());
}
-void fixedfreq_device::device_reset()
+void fixedfreq_device::update_screen_parameters(const attotime &refresh)
{
- m_state.reset();
+ rectangle visarea(
+// m_hsync - m_hvisible,
+// m_hsync - 1 ,
+ m_hbackporch - m_hfrontporch,
+ m_hbackporch - m_hfrontporch + m_hvisible - 1,
+ m_vbackporch - m_vfrontporch,
+ m_vbackporch - m_vfrontporch + m_vvisible - 1);
+
+ m_refresh = refresh;
+ screen().configure(m_htotal, m_vtotal, visarea, m_refresh.as_attoseconds());
}
-void fixedfreq_device::device_post_load()
+int fixedfreq_device::sync_separator(const attotime &time, double newval)
{
- //recompute_parameters();
+ int last_vsync = m_sig_vsync;
+ int last_comp = m_sig_composite;
+ int ret = 0;
+
+ m_vint += ((double) last_comp - m_vint) * (1.0 - exp(-time.as_double() * m_mult));
+ m_sig_composite = (newval < m_sync_threshold) ? 1 : 0 ;
+
+ m_sig_vsync = (m_vint > m_int_trig) ? 1 : 0;
+
+ if (!last_vsync && m_sig_vsync)
+ {
+ /* TODO - time since last hsync and field detection */
+ ret |= 1;
+ }
+ 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 */
+ ret |= 2;
+ }
+ if (last_comp && !m_sig_composite)
+ {
+ /* falling composite */
+ ret |= 4;
+ }
+ return ret;
}
uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@@ -238,62 +216,72 @@ uint32_t fixedfreq_device::screen_update(screen_device &screen, bitmap_rgb32 &bi
return 0;
}
-void fixedfreq_device::vsync_start_cb(double refresh_time)
-{
- // toggle bitmap
- m_cur_bm ^= 1;
-
- rectangle visarea(m_monitor.minh(), m_monitor.maxh(), m_monitor.minv(), m_monitor.maxv());
-
- m_refresh_period = refresh_time;
- screen().configure(m_htotal * m_monitor.m_hscale, m_vtotal, visarea, DOUBLE_TO_ATTOSECONDS(m_refresh_period));
-}
-
-void fixedfreq_device::plot_hline(int x, int y, int w, uint32_t col)
+NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_vid)
{
bitmap_rgb32 *bm = m_bitmap[m_cur_bm].get();
- if (y < bm->height())
- bm->plot_box(x, y, w, 1, col);
-}
+ const int has_fields = (m_fieldcount > 1) ? 1: 0;
-NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_composite_monochrome)
-{
- // double is good enough for this exercise;
+ int pixels = round((time - m_line_time).as_double() / m_clock_period.as_double());
+ attotime delta_time = (time - m_last_time);
- const time_type ctime = time.as_double();
- m_state.update_composite_monochrome(ctime, data);
-}
+ if (data == m_vid)
+ return;
-NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_red)
-{
- // double is good enough for this exercise;
+ ATTR_UNUSED int sync = sync_separator(delta_time, data);
- const time_type ctime = time.as_double();
- m_state.update_red(ctime, data);
-}
+ if (m_last_y < bm->height())
+ {
+ rgb_t col;
-NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_green)
-{
- // double is good enough for this exercise;
+ if (m_vid < m_sync_threshold)
+ // Mark sync areas
+ col = rgb_t(255, 0, 0);
+ else
+ {
+ int colv = (int) ((m_vid - m_sync_threshold) * m_gain * 255.0);
+ if (colv > 255)
+ colv = 255;
+ col = rgb_t(colv, colv, colv);
+ }
- const time_type ctime = time.as_double();
- m_state.update_green(ctime, data);
-}
+ bm->plot_box(m_last_x, m_last_y + m_sig_field * has_fields, pixels - m_last_x, 1, col);
+ m_last_x = pixels;
+ }
+ if (sync & 1)
+ {
+ LOG("VSYNC %d %d\n", pixels, m_last_y + m_sig_field);
+ }
+ if (sync & 2)
+ {
+ LOG("HSYNC up %d\n", pixels);
+ //if (m_last_y == 27) printf("HSYNC up %d %d\n", m_last_y, pixels);
+ }
+ if (sync & 4)
+ {
+ LOG("HSYNC down %f %d %f\n", time.as_double()* 1e6, pixels, m_vid);
+ }
-NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_blue)
-{
- // double is good enough for this exercise;
+ if (sync & 1)
+ {
+ 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;
+ }
- const time_type ctime = time.as_double();
- m_state.update_blue(ctime, data);
-}
+ // FIXME: pixels > 50 filters some spurious hysnc on line 27 in breakout
+ if ((sync & 2) && !m_sig_vsync && (pixels > 100))
+ {
+ m_last_y += m_fieldcount;
+ m_last_x = 0;
+ m_line_time = time;
+ }
-NETDEV_ANALOG_CALLBACK_MEMBER(fixedfreq_device::update_sync)
-{
- // double is good enough for this exercise;
+ m_last_time = time;
+ m_vid = data;
- const time_type ctime = time.as_double();
- m_state.update_sync(ctime, data);
}
+
/***************************************************************************/