#include <mach/mach.h>
#include <mach/thread_switch.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <math.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
__private_extern__ float
ratioOver( float a, float b )
{
if( a > b)
return( a / b );
else
return( b / a );
}
static int
IODisplayGetCVTSyncWidth( int horizontalActive, int verticalActive )
{
enum {
kCVTAspect4By3 = 4,
kCVTAspect16By9 = 5,
kCVTAspect16By10 = 6,
kCVTAspect5By4 = 7,
kCVTAspect15By9 = 7,
kCVTAspectUnknown = 10
};
float ratio = ((float) horizontalActive) / ((float) verticalActive);
if (ratioOver(ratio, 4.0 / 3.0) <= 1.03125)
return (kCVTAspect4By3);
if (ratioOver(ratio, 16.0 / 9.0) <= 1.03125)
return (kCVTAspect16By9);
if (ratioOver(ratio, 16.0 / 10.0) <= 1.03125)
return (kCVTAspect16By10);
if (ratioOver(ratio, 5.0 / 4.0) <= 1.03125)
return (kCVTAspect5By4);
if (ratioOver(ratio, 15.0 / 9.0) <= 1.03125)
return (kCVTAspect15By9);
return (kCVTAspectUnknown);
}
void GenTiming ( int requestedWidth, int requestedHeight,
float frameRate, boolean_t needInterlace,
int genType )
{
int charSize = 8;
float m = 600; float c = 40; float k = 128;
float j = 20;
float cPrime = ((c - j) * k / 256) + j;
float mPrime = k / 256 * m;
float fieldRate; float interlace = needInterlace ? 0.5 : 0.0;
float interlaceFactor = needInterlace ? 2.0 : 1.0;
fieldRate = frameRate * interlaceFactor;
int leftMargin = 0;
int rightMargin = 0;
int horizontalActive = roundf(requestedWidth / charSize) * charSize
+ leftMargin + rightMargin;
int verticalActive = roundf(requestedHeight / interlaceFactor); int topMargin = 0;
int bottomMargin = 0;
int verticalSyncWidth; int verticalSyncAndBackPorch; int verticalSyncFrontPorch;
int horizontalTotal; int horizontalBlanking; int horizontalSyncWidth;
if (0 == genType)
verticalSyncWidth = 3;
else
verticalSyncWidth = IODisplayGetCVTSyncWidth(horizontalActive, verticalActive * interlaceFactor);
if (0 == genType)
{
float horizontalSyncPercent = 8.0/100.0; float verticalSyncAndBackPorchTime = 550e-6; int minVerticalFrontPorch = 1; float estimatedHorizontalPeriod; float verticalFieldTotal; float estimatedFieldRate;
estimatedHorizontalPeriod =
((1 / fieldRate) - verticalSyncAndBackPorchTime)
/ (verticalActive + (2 * topMargin) + minVerticalFrontPorch + interlace);
verticalSyncAndBackPorch = roundf(verticalSyncAndBackPorchTime / estimatedHorizontalPeriod);
verticalSyncFrontPorch = minVerticalFrontPorch;
verticalFieldTotal = verticalActive + topMargin + bottomMargin
+ verticalSyncAndBackPorch + interlace + minVerticalFrontPorch;
estimatedFieldRate = 1.0 / estimatedHorizontalPeriod / verticalFieldTotal;
float hPeriod = estimatedHorizontalPeriod / (fieldRate / estimatedFieldRate);
printf("hPeriod %.9f us, ", hPeriod*1e6);
printf("hFreq %.9f kHz\n", 1/hPeriod/1e3);
float idealDutyCycle = cPrime - (mPrime * hPeriod * 1e6 / 1000.0);
horizontalBlanking = 2 * charSize * roundf(
(horizontalActive * idealDutyCycle / (100.0 - idealDutyCycle)
/ (2 * charSize)));
horizontalTotal = horizontalActive + horizontalBlanking;
float pixelFreq = horizontalTotal / hPeriod;
printf("pixFreq %.9f Mhz\n", pixelFreq/1e6);
horizontalSyncWidth = roundf(horizontalSyncPercent * horizontalTotal / charSize) * charSize;
}
else if (1 == genType)
{
float horizontalSyncPercent = 8.0/100.0; float verticalSyncAndBackPorchTime = 550e-6; int minVerticalBackPorch = 6; int minVerticalFrontPorch = 3; float estimatedHorizontalPeriod; float verticalFieldTotal;
estimatedHorizontalPeriod =
((1 / fieldRate) - verticalSyncAndBackPorchTime)
/ (verticalActive + (topMargin + bottomMargin) + minVerticalFrontPorch + interlace);
verticalSyncAndBackPorch = 1 + truncf(verticalSyncAndBackPorchTime / estimatedHorizontalPeriod);
if (verticalSyncAndBackPorch < (verticalSyncWidth + minVerticalBackPorch))
verticalSyncAndBackPorch = verticalSyncWidth + minVerticalBackPorch;
verticalSyncFrontPorch = minVerticalFrontPorch;
verticalFieldTotal = verticalActive + topMargin + bottomMargin
+ verticalSyncAndBackPorch + interlace + minVerticalFrontPorch;
float idealDutyCycle = cPrime - (mPrime * estimatedHorizontalPeriod * 1e6 / 1000.0);
if (idealDutyCycle < 20.0)
idealDutyCycle = 20.0;
horizontalBlanking = 2 * charSize * truncf(
(horizontalActive * idealDutyCycle / (100.0 - idealDutyCycle)
/ (2 * charSize)));
horizontalTotal = horizontalActive + horizontalBlanking;
float frequencyStep = 0.25e6; float pixelFrequency = frequencyStep * truncf(
(horizontalTotal / estimatedHorizontalPeriod) / frequencyStep);
printf("pixFreq %.9f Mhz\n", pixelFrequency/1e6);
float horizontalFrequency = pixelFrequency / horizontalTotal;
printf("hPeriod %.9f us, ", (1/horizontalFrequency)*1e6);
printf("hFreq %.9f kHz\n", horizontalFrequency/1e3);
horizontalSyncWidth = charSize * truncf(
horizontalSyncPercent * horizontalTotal / charSize);
}
else
{
float minVerticalBlankTime = 460e-6; float estimatedHorizontalPeriod; int verticalBlanking; int minVerticalBackPorch = 6;
verticalSyncFrontPorch = 3; horizontalBlanking = 160; horizontalSyncWidth = 32;
estimatedHorizontalPeriod = ((1 / fieldRate) - minVerticalBlankTime)
/ (verticalActive + topMargin + bottomMargin);
verticalBlanking = truncf(minVerticalBlankTime / estimatedHorizontalPeriod) + 1;
if (verticalBlanking < (verticalSyncFrontPorch + verticalSyncWidth + minVerticalBackPorch))
verticalBlanking = (verticalSyncFrontPorch + verticalSyncWidth + minVerticalBackPorch);
verticalSyncAndBackPorch = verticalBlanking - verticalSyncFrontPorch;
int verticalFieldTotal = verticalBlanking + verticalActive
+ topMargin + bottomMargin + interlace;
horizontalTotal = horizontalActive + horizontalBlanking;
float frequencyStep = 0.25e6; float pixelFrequency = frequencyStep * truncf(
(horizontalTotal * verticalFieldTotal * fieldRate) / frequencyStep);
printf("pixFreq %.9f Mhz\n", pixelFrequency/1e6);
float horizontalFrequency = pixelFrequency / horizontalTotal;
printf("hPeriod %.9f us, ", (1/horizontalFrequency)*1e6);
printf("hFreq %.9f kHz\n", horizontalFrequency/1e3);
}
int verticalTotal = interlaceFactor *
(verticalActive + topMargin + bottomMargin
+ verticalSyncAndBackPorch + interlace + verticalSyncFrontPorch);
int horizontalSyncOffset = (horizontalBlanking / 2) - horizontalSyncWidth;
float verticalOddBlanking = verticalSyncAndBackPorch + verticalSyncFrontPorch;
float verticalEvenBlanking = verticalSyncAndBackPorch + 2 * interlace + verticalSyncFrontPorch;
float verticalSyncOddFrontPorch = verticalSyncFrontPorch + interlace;
printf("hTotal %d(%d), hFP %d(%d), hBlank %d(%d), hSync %d(%d)\n",
horizontalTotal/8, horizontalTotal, horizontalSyncOffset/8,
horizontalSyncOffset, horizontalBlanking/8, horizontalBlanking,
horizontalSyncWidth/8, horizontalSyncWidth);
printf("vTotal %d, vFP %.1f(E:%.1f), vBlank %.1f(E:%.1f), vSync %d\n\n",
verticalTotal, verticalSyncOddFrontPorch, (float) verticalSyncFrontPorch,
verticalOddBlanking, verticalEvenBlanking, verticalSyncWidth);
}
int main (int argc, char * argv[])
{
char * endstr;
boolean_t needInterlace = FALSE;
int requestedWidth = 1400, requestedHeight = 1050;
float frameRate = 60.0;
requestedWidth = strtol(argv[1], 0, 0);
requestedHeight = strtol(argv[2], 0, 0);
frameRate = strtol(argv[3], &endstr, 0);
needInterlace = (endstr[0] == 'i') || (endstr[0] == 'I');
printf("\nGTF:\n\n");
GenTiming( requestedWidth, requestedHeight, frameRate, needInterlace, 0 );
printf("\nCVT:\n\n");
GenTiming( requestedWidth, requestedHeight, frameRate, needInterlace, 1 );
printf("\nCVT reduced blank:\n\n");
GenTiming( requestedWidth, requestedHeight, frameRate, needInterlace, 2 );
return(0);
}