// license:BSD-3-Clause // copyright-holders:Couriersud /*************************************************************************** fixfreq.h Fixed frequency monochrome monitor emulation The driver is intended for drivers which provide an analog video signal. VSYNC and HSYNC levels are used to create the bitmap. ***************************************************************************/ #ifndef MAME_VIDEO_FIXFREQ_H #define MAME_VIDEO_FIXFREQ_H #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_intf { virtual ~fixedfreq_monitor_intf() = default; virtual void vsync_start_cb(double refresh_time) = 0; virtual void plot_hline(int x, int y, int w, uint32_t col) = 0; }; struct fixedfreq_monitor_state { using time_type = double; fixedfreq_monitor_state(fixedfreq_monitor_desc &desc, fixedfreq_monitor_intf &intf) : m_desc(desc), m_intf(intf), m_sync_signal(0), m_col(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_min_frame_period(time_type(0)) {} /*** * \brief To be called after monitor parameters are set */ void start() { // 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; // htotal = m_desc.m_hbackporch; // 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_desc.m_hbackporch * 1.0; // / (3.0 + 3.0); //LOG("trigger %f with len %f\n", m_vsync_threshold, 1e6 / m_vsync_filter_timeconst); m_clock_period = 1.0 / m_desc.m_monitor_clock; // Minimum frame period to be passed to video system ? m_min_frame_period = 0.25 * m_clock_period * m_desc.m_vbackporch * m_desc.m_hbackporch; m_intf.vsync_start_cb(m_min_frame_period); } void reset() { m_sync_signal = 0; m_col = 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; } 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; uint32_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; time_type m_min_frame_period; }; // ======================> fixedfreq_device class fixedfreq_device : public device_t, public device_video_interface, public 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.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_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_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_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 { set_monitor_clock(13500000); set_horz_params(720, 736, 799, 858); set_vert_params(480, 486, 492, 525); set_fieldcount(2); set_threshold(0.3); } void set_mode_ntsc704() //ModeLine "704x480@30i" 13.5 704 728 791 858 480 486 492 525 { set_monitor_clock(13500000); set_horz_params(704, 728, 791, 858); set_vert_params(480, 486, 492, 525); set_fieldcount(2); set_threshold(0.3); } virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); NETDEV_ANALOG_CALLBACK_MEMBER(update_composite_monochrome); NETDEV_ANALOG_CALLBACK_MEMBER(update_red); NETDEV_ANALOG_CALLBACK_MEMBER(update_green); NETDEV_ANALOG_CALLBACK_MEMBER(update_blue); NETDEV_ANALOG_CALLBACK_MEMBER(update_sync); protected: fixedfreq_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); // device-level overrides virtual void device_config_complete() override; virtual void device_start() override; virtual void device_reset() override; virtual void device_post_load() override; //virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); void vsync_start_cb(double refresh_time) override; void plot_hline(int x, int y, int w, uint32_t col) override; private: std::unique_ptr m_bitmap[2]; int m_cur_bm; int m_htotal; int m_vtotal; time_type m_refresh_period; /* adjustable by drivers */ fixedfreq_monitor_desc m_monitor; fixedfreq_monitor_state m_state; }; // device type definition DECLARE_DEVICE_TYPE(FIXFREQ, fixedfreq_device) #endif // MAME_VIDEO_FIXFREQ_H