Added a fixed frequency monitor emulation to src/emu/video.

This implementation takes an analog composite signal, extracts hsync, vsync and field information in addition to greyscale video. 
Currently needed for pong.
This commit is contained in:
Couriersud 2013-10-16 20:53:19 +00:00
parent ab4939c07e
commit f28956e82d
4 changed files with 395 additions and 0 deletions

2
.gitattributes vendored
View File

@ -1886,6 +1886,8 @@ src/emu/video/dm9368.h svneol=native#text/plain
src/emu/video/ef9340_1.c svneol=native#text/plain
src/emu/video/ef9340_1.h svneol=native#text/plain
src/emu/video/ef9341_chargen.h svneol=native#text/plain
src/emu/video/fixfreq.c svneol=native#text/plain
src/emu/video/fixfreq.h svneol=native#text/plain
src/emu/video/generic.c svneol=native#text/plain
src/emu/video/generic.h svneol=native#text/plain
src/emu/video/h63484.c svneol=native#text/plain

276
src/emu/video/fixfreq.c Normal file
View File

@ -0,0 +1,276 @@
/***************************************************************************
fixfreq.h
2013 Couriersud
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.
***************************************************************************/
#include "emu.h"
#include "fixfreq.h"
/***************************************************************************
Local variables
***************************************************************************/
//#define VERBOSE_OUT(x) printf x
#define VERBOSE_OUT(x)
/***************************************************************************
Static declarations
***************************************************************************/
//ModeLine "720x480@30i" 13.5 720 736 799 858 480 486 492 525 interlace -hsync -vsync
fixedfreq_interface fixedfreq_mode_ntsc720 = {
13500000,
720,736,799,858,
480,486,492,525,
2, /* interlaced */
0.3
};
//ModeLine "704x480@30i" 13.5 704 728 791 858 480 486 492 525
fixedfreq_interface fixedfreq_mode_ntsc704 = {
13500000,
704,728,791,858,
480,486,492,525,
2, /* interlaced */
0.3
};
/***************************************************************************
Fixed frequency monitor
***************************************************************************/
// device type definition
const device_type FIXFREQ = &device_creator<fixedfreq_device>;
fixedfreq_device::fixedfreq_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_video_interface(mconfig, *this, false)
{
}
fixedfreq_device::fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, FIXFREQ, "FIXFREQ", tag, owner, clock, "fixfreq", __FILE__),
device_video_interface(mconfig, *this, false)
{
}
void fixedfreq_device::device_config_complete()
{
const fixedfreq_interface *intf = reinterpret_cast<const fixedfreq_interface *>(static_config());
if ( intf != NULL )
{
*static_cast<fixedfreq_interface *>(this) = *intf;
}
else
{
*static_cast<fixedfreq_interface *>(this) = fixedfreq_mode_ntsc704;
}
}
void fixedfreq_device::device_start()
{
m_cur_bm = 0;
m_vid = 0.0;
m_vint = 0.0;
m_last_x = 0;
m_last_y = 0;
m_refresh = attotime::zero;
m_bitmap[0] = NULL;
m_bitmap[1] = NULL;
m_last_time = attotime::zero;
m_last_hsync_time = attotime::zero;
m_last_vsync_time = attotime::zero;
//m_vblank_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vga_device::vblank_timer_cb),this));
recompute_parameters(false);
m_sig_vsync = 0;
m_sig_composite = 0;
m_sig_field = 0;
}
void fixedfreq_device::device_reset()
{
}
void fixedfreq_device::device_post_load()
{
//recompute_parameters(true);
}
void fixedfreq_device::recompute_parameters(bool postload)
{
bool needs_realloc = (m_htotal != m_hbackporch) && (m_vtotal != m_vbackporch);
if (m_bitmap[0] != NULL || needs_realloc)
auto_free(machine(), m_bitmap[0]);
if (m_bitmap[1] != NULL || needs_realloc)
auto_free(machine(), m_bitmap[0]);
m_htotal = m_hbackporch;
m_vtotal = m_vbackporch;
/* sync separator */
m_int_trig = (exp(- 3.0/(3.0+3.0))) - exp(-1.0);
m_mult = (double) (m_monitor_clock) / m_htotal; // / (3.0 + 3.0);
VERBOSE_OUT(("trigger %f with len %f\n", m_int_trig, 1e6 / m_mult));
m_bitmap[0] = auto_bitmap_rgb32_alloc(machine(),m_htotal, m_vtotal);
m_bitmap[1] = auto_bitmap_rgb32_alloc(machine(),m_htotal, m_vtotal);
rectangle visarea(
m_hbackporch - m_hfrontporch,
m_hbackporch - m_hfrontporch + m_hvisible - 1,
m_vbackporch - m_vfrontporch,
m_vbackporch - m_vfrontporch + m_vvisible - 1);
m_clock_period = attotime::from_hz(m_monitor_clock);
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::update_screen_parameters(attotime refresh)
{
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());
}
int fixedfreq_device::sync_separator(attotime time, double newval)
{
int last_vsync = m_sig_vsync;
int last_comp = m_sig_composite;
int ret = 0;
m_vint += ((double) m_sig_composite - 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 */
VERBOSE_OUT(("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 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);
return 0;
}
void fixedfreq_device::update_vid(double newval, attotime cur_time)
{
static attotime m_last_time = attotime(0,0);
static attotime m_line_time = attotime(0,0);
bitmap_rgb32 *bm = m_bitmap[m_cur_bm];
int pixels = round((cur_time - m_line_time).as_double() / m_clock_period.as_double());
attotime time = (cur_time - m_last_time);
if ((newval == m_vid))
return;
ATTR_UNUSED int sync = sync_separator(time, newval);
if (m_last_y < bm->height())
{
rgb_t col;
if (m_vid < m_sync_threshold)
col = MAKE_RGB(255, 0, 0);
else
{
int colv = (int) ((m_vid - m_sync_threshold) / 3.2 * 255.0);
col = MAKE_RGB(colv, colv, colv);
}
if (m_vid < m_sync_threshold)
while (0 && pixels >= m_htotal)
{
bm->plot_box(m_last_x, m_last_y + m_sig_field, m_htotal - 1 - m_last_x, 1, col);
pixels -= m_htotal;
m_last_x = 0;
}
bm->plot_box(m_last_x, m_last_y + m_sig_field, pixels - m_last_x, 1, col);
m_last_x = pixels;
}
if (sync & 1) VERBOSE_OUT(("VSYNC %d %d\n", pixels, m_last_y + m_sig_field));
if (sync & 2)
VERBOSE_OUT(("HSYNC up %d\n", pixels));
if (sync & 4)
VERBOSE_OUT(("HSYNC down %f %d %f\n", time.as_double()* 1e6, pixels, m_vid));
//VERBOSE_OUT(("%d\n", m_last_x);
if (sync & 1)
{
m_last_y = 0;
// toggle bitmap
m_cur_bm ^= 1;
update_screen_parameters(cur_time - m_last_vsync_time);
m_last_vsync_time = cur_time;
}
if (sync & 2)
{
m_last_y += m_fieldcount;
m_last_x = 0;
m_line_time = cur_time;
}
m_last_time = cur_time;
m_vid = newval;
}
/***************************************************************************/

108
src/emu/video/fixfreq.h Normal file
View File

@ -0,0 +1,108 @@
/***************************************************************************
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 FIXFREQ_H
#define FIXFREQ_H
#include "emu.h"
#define FIXFREQ_INTERFACE(name) \
const fixedfreq_interface (name) =
#define MCFG_FIXFREQ_ADD(_tag, _screen_tag, _config) \
MCFG_SCREEN_ADD(_screen_tag, RASTER) \
MCFG_SCREEN_RAW_PARAMS(13500000, 858, 0, 858, 525, 0, 525) \
MCFG_SCREEN_UPDATE_DEVICE(_tag, fixedfreq_device, screen_update) \
MCFG_DEVICE_ADD(_tag, FIXFREQ, 0) \
MCFG_VIDEO_SET_SCREEN(_screen_tag) \
MCFG_DEVICE_CONFIG(_config)
struct fixedfreq_interface {
UINT32 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;
};
extern fixedfreq_interface fixedfreq_mode_ntsc704;
extern fixedfreq_interface fixedfreq_mode_ntsc720;
// ======================> vga_device
class fixedfreq_device : public device_t,
public device_video_interface,
public fixedfreq_interface
{
public:
// construction/destruction
fixedfreq_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
fixedfreq_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
virtual UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void update_vid(const double newval, const attotime cur_time);
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
virtual void device_reset();
virtual void device_post_load();
//virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
void recompute_parameters(bool postload);
void update_screen_parameters(attotime refresh);
private:
int sync_separator(attotime time, double newval);
int m_htotal;
int m_vtotal;
double m_vid;
int m_last_x;
int m_last_y;
attotime m_last_time;
attotime m_last_hsync_time;
attotime m_last_vsync_time;
attotime m_refresh;
attotime m_clock_period;
bitmap_rgb32 *m_bitmap[2];
int m_cur_bm;
/* sync separator */
double m_vint;
double m_int_trig;
double m_mult;
int m_sig_vsync;
int m_sig_composite;
int m_sig_field;
protected:
};
// device type definition
extern const device_type FIXFREQ;
#endif /* FIXFREQ_H */

View File

@ -104,6 +104,15 @@ ifneq ($(filter EF9340_1,$(VIDEOS)),)
VIDEOOBJS+= $(VIDEOOBJ)/ef9340_1.o
endif
#-------------------------------------------------
#
#@src/emu/video/fixfreq.h,VIDEOS += FIXFREQ
#-------------------------------------------------
ifneq ($(filter FIXFREQ,$(VIDEOS)),)
VIDEOOBJS+= $(VIDEOOBJ)/fixfreq.o
endif
#-------------------------------------------------
#
#@src/emu/video/h63484.h,VIDEOS += H63484