mirror of
https://github.com/holub/mame
synced 2025-05-13 01:24:20 +03:00
168 lines
4.3 KiB
C
168 lines
4.3 KiB
C
/***************************************************************************
|
|
|
|
vbiparse.c
|
|
|
|
Parse Philips codes and other data from VBI lines.
|
|
|
|
Copyright Nicola Salmoria and the MAME Team.
|
|
Visit http://mamedev.org for licensing and usage restrictions.
|
|
|
|
***************************************************************************/
|
|
|
|
#include "osdcore.h"
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
CONSTANTS
|
|
***************************************************************************/
|
|
|
|
#define MAX_SOURCE_WIDTH 1024
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
IMPLEMENTATION
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
vbi_parse_manchester_code - parse a Manchester
|
|
code from a line of video data
|
|
-------------------------------------------------*/
|
|
|
|
int vbi_parse_manchester_code(const UINT16 *source, int sourcewidth, int sourceshift, int expectedbits, UINT8 *result)
|
|
{
|
|
UINT8 srcabs[MAX_SOURCE_WIDTH];
|
|
UINT8 min, max, mid, srcabsval;
|
|
double clock, bestclock;
|
|
int x, firstedge;
|
|
int besterr;
|
|
|
|
/* fail if the width is too large */
|
|
if (sourcewidth > MAX_SOURCE_WIDTH)
|
|
return 0;
|
|
|
|
/* find highs and lows in the line */
|
|
min = 0xff;
|
|
max = 0x00;
|
|
for (x = 0; x < sourcewidth; x++)
|
|
{
|
|
UINT8 rawsrc = source[x] >> sourceshift;
|
|
min = MIN(min, rawsrc);
|
|
max = MAX(max, rawsrc);
|
|
}
|
|
|
|
/* bail if the line is all black or all white */
|
|
if (max < 0x80 || min > 0x80)
|
|
return 0;
|
|
|
|
/* determine the midpoint and then set the thresholds to be halfway */
|
|
mid = (min + max) / 2;
|
|
min = mid - (mid - min) / 2;
|
|
max = mid + (max - mid) / 2;
|
|
|
|
/* convert the source into absolute high/low */
|
|
srcabsval = (source[0] > mid);
|
|
for (x = 0; x < sourcewidth; x++)
|
|
{
|
|
UINT8 rawsrc = source[x] >> sourceshift;
|
|
if (rawsrc >= max)
|
|
srcabsval = 1;
|
|
else if (rawsrc <= min)
|
|
srcabsval = 0;
|
|
srcabs[x] = srcabsval;
|
|
}
|
|
|
|
/* find the first transition; this is assumed to be the middle of the first bit */
|
|
for (x = 0; x < sourcewidth - 1; x++)
|
|
if (srcabs[x] != srcabs[x + 1])
|
|
break;
|
|
if (x == sourcewidth - 1)
|
|
return 0;
|
|
firstedge = x;
|
|
|
|
/* now scan to find a clock that has a nearby transition on each beat */
|
|
bestclock = 0;
|
|
besterr = 1000;
|
|
for (clock = (double)sourcewidth / (double)expectedbits; clock >= 2.0; clock -= 1.0 / (double)expectedbits)
|
|
{
|
|
int error = 0;
|
|
|
|
/* scan for all the expected bits */
|
|
for (x = 1; x < expectedbits; x++)
|
|
{
|
|
int curbit = firstedge + (double)x * clock;
|
|
|
|
/* exact match? */
|
|
if (srcabs[curbit + 0] != srcabs[curbit + 1])
|
|
continue;
|
|
|
|
/* off-by-one? */
|
|
if (srcabs[curbit + 1 + 0] != srcabs[curbit + 1 + 1] || srcabs[curbit - 1 + 0] != srcabs[curbit - 1 + 1])
|
|
{
|
|
/* only continue if we're still in the running */
|
|
if (++error < besterr)
|
|
continue;
|
|
}
|
|
|
|
/* anything else fails immediately */
|
|
break;
|
|
}
|
|
|
|
/* if we got to the end, this is the best candidate so far */
|
|
if (x == expectedbits)
|
|
{
|
|
besterr = error;
|
|
bestclock = clock;
|
|
}
|
|
}
|
|
|
|
/* if nobody matched, fail */
|
|
if (bestclock == 0)
|
|
return 0;
|
|
|
|
/* now extract the bits */
|
|
for (x = 0; x < expectedbits; x++)
|
|
{
|
|
int leftbit = firstedge + ((double)x - 0.25) * bestclock;
|
|
int rightbit = firstedge + ((double)x + 0.25) * bestclock;
|
|
int left = srcabs[leftbit];
|
|
int right = srcabs[rightbit];
|
|
|
|
/* all bits should be marked by transitions; fail if we don't get one */
|
|
if (left == right)
|
|
return 0;
|
|
result[x] = (left < right);
|
|
}
|
|
return expectedbits;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
vbi_parse_white_flag - compute the "white
|
|
flag" from a line of video data
|
|
-------------------------------------------------*/
|
|
|
|
int vbi_parse_white_flag(const UINT16 *source, int sourcewidth, int sourceshift)
|
|
{
|
|
int minval = 0xff;
|
|
int maxval = 0x00;
|
|
int avgval = 0x00;
|
|
int diff;
|
|
int x;
|
|
|
|
/* compute minimum, maximum, and average values across the line */
|
|
for (x = 0; x < sourcewidth; x++)
|
|
{
|
|
UINT8 yval = source[x] >> sourceshift;
|
|
minval = MIN(yval, minval);
|
|
maxval = MAX(yval, maxval);
|
|
avgval += yval;
|
|
}
|
|
avgval /= sourcewidth;
|
|
diff = maxval - minval;
|
|
|
|
/* if there's a spread of at least 0x20, and the average is above 3/4 of the center, call it good */
|
|
return (diff >= 0x20) && (avgval >= minval + 3 * diff / 4);
|
|
}
|