mirror of
https://github.com/marqs85/ossc.git
synced 2026-04-25 16:18:03 +00:00
Release 0.67.
- Code cleanup - Some project files added - PAL linetriple added - FPGA PLL parameters optimized - Reduced jitter on low video clock sources
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
//
|
||||
// This file is part of Open Source Scan Converter project.
|
||||
//
|
||||
@@ -24,378 +24,407 @@
|
||||
#include "i2c_opencores.h"
|
||||
#include "tvp7002.h"
|
||||
|
||||
//#define SYNCBYPASS // Bypass VGA syncs (for debug - needed for interlace?)
|
||||
//#define EXTADCCLK // Use external ADC clock (external osc)
|
||||
//#define ADCPOWERDOWN // Power-down ADCs
|
||||
//#define PLLPOSTDIV // Double-rate PLL with div-by-2 (decrease jitter?)
|
||||
//#define SYNCBYPASS // Bypass VGA syncs (for debug - needed for interlace?)
|
||||
//#define EXTADCCLK // Use external ADC clock (external osc)
|
||||
//#define ADCPOWERDOWN // Power-down ADCs
|
||||
//#define PLLPOSTDIV // Double-rate PLL with div-by-2 (decrease jitter?)
|
||||
|
||||
/* Y'Pb'Pr' to R'G'B' CSC coefficients.
|
||||
*
|
||||
* Coefficients from "Colour Space Conversions" (http://www.poynton.com/PDFs/coloureq.pdf).
|
||||
*/
|
||||
const ypbpr_to_rgb_csc_t csc_coeffs[] = {
|
||||
{ "Rec. 601", 0x2000, 0x0000, 0x2CE5, 0x2000, 0xF4FD, 0xE926, 0x2000, 0x38BC, 0x0000 }, // eq. 101
|
||||
{ "Rec. 709", 0x2000, 0x0000, 0x323E, 0x2000, 0xFA04, 0xF113, 0x2000, 0x3B61, 0x0000 }, // eq. 105
|
||||
{ "Rec. 601", 0x2000, 0x0000, 0x2CE5, 0x2000, 0xF4FD, 0xE926, 0x2000, 0x38BC, 0x0000 }, // eq. 101
|
||||
{ "Rec. 709", 0x2000, 0x0000, 0x323E, 0x2000, 0xFA04, 0xF113, 0x2000, 0x3B61, 0x0000 }, // eq. 105
|
||||
};
|
||||
|
||||
extern mode_data_t video_modes[];
|
||||
|
||||
static inline void tvp_set_hpllcoast(alt_u8 pre, alt_u8 post) {
|
||||
tvp_writereg(TVP_HPLLPRECOAST, pre);
|
||||
tvp_writereg(TVP_HPLLPOSTCOAST, post);
|
||||
static inline void tvp_set_hpllcoast(alt_u8 pre, alt_u8 post)
|
||||
{
|
||||
tvp_writereg(TVP_HPLLPRECOAST, pre);
|
||||
tvp_writereg(TVP_HPLLPOSTCOAST, post);
|
||||
}
|
||||
|
||||
static inline void tvp_set_ssthold(alt_u8 vsdetect_thold) {
|
||||
tvp_writereg(TVP_SSTHOLD, vsdetect_thold);
|
||||
static inline void tvp_set_ssthold(alt_u8 vsdetect_thold)
|
||||
{
|
||||
tvp_writereg(TVP_SSTHOLD, vsdetect_thold);
|
||||
}
|
||||
|
||||
static void tvp_set_clamp(video_format fmt) {
|
||||
switch (fmt) {
|
||||
case FORMAT_RGBS:
|
||||
case FORMAT_RGBHV:
|
||||
case FORMAT_RGsB:
|
||||
//select bottom clamp (RGB)
|
||||
tvp_writereg(TVP_SOGTHOLD, 0x58);
|
||||
break;
|
||||
case FORMAT_YPbPr:
|
||||
//select mid clamp for Pb & Pr
|
||||
tvp_writereg(TVP_SOGTHOLD, 0x5D);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
static void tvp_set_clamp(video_format fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case FORMAT_RGBS:
|
||||
case FORMAT_RGBHV:
|
||||
case FORMAT_RGsB:
|
||||
//select bottom clamp (RGB)
|
||||
tvp_writereg(TVP_SOGTHOLD, 0x58);
|
||||
break;
|
||||
case FORMAT_YPbPr:
|
||||
//select mid clamp for Pb & Pr
|
||||
tvp_writereg(TVP_SOGTHOLD, 0x5D);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void tvp_set_clamp_position(video_type type) {
|
||||
switch (type) {
|
||||
case VIDEO_LDTV:
|
||||
tvp_writereg(TVP_CLAMPSTART, 0x2);
|
||||
tvp_writereg(TVP_CLAMPWIDTH, 0x6);
|
||||
break;
|
||||
case VIDEO_SDTV:
|
||||
case VIDEO_EDTV:
|
||||
case VIDEO_PC:
|
||||
tvp_writereg(TVP_CLAMPSTART, 0x6);
|
||||
tvp_writereg(TVP_CLAMPWIDTH, 0x10);
|
||||
break;
|
||||
case VIDEO_HDTV:
|
||||
tvp_writereg(TVP_CLAMPSTART, 0x32);
|
||||
tvp_writereg(TVP_CLAMPWIDTH, 0x20);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
static void tvp_set_clamp_position(video_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case VIDEO_LDTV:
|
||||
tvp_writereg(TVP_CLAMPSTART, 0x2);
|
||||
tvp_writereg(TVP_CLAMPWIDTH, 0x6);
|
||||
break;
|
||||
case VIDEO_SDTV:
|
||||
case VIDEO_EDTV:
|
||||
case VIDEO_PC:
|
||||
tvp_writereg(TVP_CLAMPSTART, 0x6);
|
||||
tvp_writereg(TVP_CLAMPWIDTH, 0x10);
|
||||
break;
|
||||
case VIDEO_HDTV:
|
||||
tvp_writereg(TVP_CLAMPSTART, 0x32);
|
||||
tvp_writereg(TVP_CLAMPWIDTH, 0x20);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void tvp_set_alc(video_type type) {
|
||||
//disable ALC
|
||||
//tvp_writereg(TVP_ALCEN, 0x00);
|
||||
//tvp_writereg(TVP_ALCEN, 0x80);
|
||||
static void tvp_set_alc(video_type type)
|
||||
{
|
||||
//disable ALC
|
||||
//tvp_writereg(TVP_ALCEN, 0x00);
|
||||
//tvp_writereg(TVP_ALCEN, 0x80);
|
||||
|
||||
//set analog (coarse) gain to max recommended value (-> 91% of the ADC range with 0.7Vpp input)
|
||||
tvp_writereg(TVP_BG_CGAIN, 0x88);
|
||||
tvp_writereg(TVP_R_CGAIN, 0x08);
|
||||
//set analog (coarse) gain to max recommended value (-> 91% of the ADC range with 0.7Vpp input)
|
||||
tvp_writereg(TVP_BG_CGAIN, 0x88);
|
||||
tvp_writereg(TVP_R_CGAIN, 0x08);
|
||||
|
||||
//set rest of the gain digitally (fine) to utilize 100% of the range at the output (0.91*(1+(26/256)) = 1)
|
||||
tvp_writereg(TVP_R_FGAIN, 26);
|
||||
tvp_writereg(TVP_G_FGAIN, 26);
|
||||
tvp_writereg(TVP_B_FGAIN, 26);
|
||||
//set rest of the gain digitally (fine) to utilize 100% of the range at the output (0.91*(1+(26/256)) = 1)
|
||||
tvp_writereg(TVP_R_FGAIN, 26);
|
||||
tvp_writereg(TVP_G_FGAIN, 26);
|
||||
tvp_writereg(TVP_B_FGAIN, 26);
|
||||
|
||||
//select ALC placement
|
||||
switch (type) {
|
||||
case VIDEO_LDTV:
|
||||
tvp_writereg(TVP_ALCPLACE, 0x9);
|
||||
break;
|
||||
case VIDEO_SDTV:
|
||||
case VIDEO_EDTV:
|
||||
case VIDEO_PC:
|
||||
tvp_writereg(TVP_ALCPLACE, 0x18);
|
||||
break;
|
||||
case VIDEO_HDTV:
|
||||
tvp_writereg(TVP_ALCPLACE, 0x5A);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//select ALC placement
|
||||
switch (type) {
|
||||
case VIDEO_LDTV:
|
||||
tvp_writereg(TVP_ALCPLACE, 0x9);
|
||||
break;
|
||||
case VIDEO_SDTV:
|
||||
case VIDEO_EDTV:
|
||||
case VIDEO_PC:
|
||||
tvp_writereg(TVP_ALCPLACE, 0x18);
|
||||
break;
|
||||
case VIDEO_HDTV:
|
||||
tvp_writereg(TVP_ALCPLACE, 0x5A);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline alt_u32 tvp_readreg(alt_u32 regaddr) {
|
||||
I2C_start(I2CA_BASE, TVP_BASE, 0);
|
||||
I2C_write(I2CA_BASE, regaddr, 1); //don't use repeated start as it seems unreliable at 400kHz
|
||||
I2C_start(I2CA_BASE, TVP_BASE, 1);
|
||||
return I2C_read(I2CA_BASE,1);
|
||||
inline alt_u32 tvp_readreg(alt_u32 regaddr)
|
||||
{
|
||||
I2C_start(I2CA_BASE, TVP_BASE, 0);
|
||||
I2C_write(I2CA_BASE, regaddr, 1); //don't use repeated start as it seems unreliable at 400kHz
|
||||
I2C_start(I2CA_BASE, TVP_BASE, 1);
|
||||
return I2C_read(I2CA_BASE,1);
|
||||
}
|
||||
|
||||
inline void tvp_writereg(alt_u32 regaddr, alt_u8 data) {
|
||||
I2C_start(I2CA_BASE, TVP_BASE, 0);
|
||||
I2C_write(I2CA_BASE, regaddr, 0);
|
||||
I2C_write(I2CA_BASE, data, 1);
|
||||
inline void tvp_writereg(alt_u32 regaddr, alt_u8 data)
|
||||
{
|
||||
I2C_start(I2CA_BASE, TVP_BASE, 0);
|
||||
I2C_write(I2CA_BASE, regaddr, 0);
|
||||
I2C_write(I2CA_BASE, data, 1);
|
||||
}
|
||||
|
||||
inline void tvp_reset() {
|
||||
usleep(10000);
|
||||
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00);
|
||||
usleep(10000);
|
||||
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x01);
|
||||
usleep(10000);
|
||||
inline void tvp_reset()
|
||||
{
|
||||
usleep(10000);
|
||||
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00);
|
||||
usleep(10000);
|
||||
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x01);
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
inline void tvp_disable_output() {
|
||||
usleep(10000);
|
||||
tvp_writereg(TVP_MISCCTRL1, 0x13);
|
||||
usleep(10000);
|
||||
tvp_writereg(TVP_MISCCTRL2, 0x03);
|
||||
usleep(10000);
|
||||
inline void tvp_disable_output()
|
||||
{
|
||||
usleep(10000);
|
||||
tvp_writereg(TVP_MISCCTRL1, 0x13);
|
||||
usleep(10000);
|
||||
tvp_writereg(TVP_MISCCTRL2, 0x03);
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
inline void tvp_enable_output() {
|
||||
usleep(10000);
|
||||
tvp_writereg(TVP_MISCCTRL1, 0x11);
|
||||
usleep(10000);
|
||||
tvp_writereg(TVP_MISCCTRL2, 0x02);
|
||||
usleep(10000);
|
||||
inline void tvp_enable_output()
|
||||
{
|
||||
usleep(10000);
|
||||
tvp_writereg(TVP_MISCCTRL1, 0x11);
|
||||
usleep(10000);
|
||||
tvp_writereg(TVP_MISCCTRL2, 0x02);
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
void tvp_init() {
|
||||
// disable output
|
||||
tvp_disable_output();
|
||||
void tvp_init()
|
||||
{
|
||||
// disable output
|
||||
tvp_disable_output();
|
||||
|
||||
//Set global defaults
|
||||
//Set global defaults
|
||||
|
||||
// Hsync input->output delay (horizontal shift)
|
||||
// Default is 13, which maintains alignment of RGB and hsync at output
|
||||
//tvp_writereg(TVP_HSOUTSTART, 0);
|
||||
// Hsync input->output delay (horizontal shift)
|
||||
// Default is 13, which maintains alignment of RGB and hsync at output
|
||||
//tvp_writereg(TVP_HSOUTSTART, 0);
|
||||
|
||||
// Hsync edge->Vsync edge delay
|
||||
tvp_writereg(TVP_VSOUTALIGN, 0);
|
||||
// Hsync edge->Vsync edge delay
|
||||
tvp_writereg(TVP_VSOUTALIGN, 0);
|
||||
|
||||
// Set default CSC coeffs.
|
||||
tvp_sel_csc(&csc_coeffs[0]);
|
||||
// Set default CSC coeffs.
|
||||
tvp_sel_csc(&csc_coeffs[0]);
|
||||
|
||||
// Set default phase
|
||||
tvp_set_hpll_phase(0x10);
|
||||
// Set default phase
|
||||
tvp_set_hpll_phase(0x10);
|
||||
|
||||
// Set min LPF
|
||||
tvp_set_lpf(0);
|
||||
tvp_set_sync_lpf(0);
|
||||
// Set min LPF
|
||||
tvp_set_lpf(0);
|
||||
tvp_set_sync_lpf(0);
|
||||
|
||||
// Increase line length tolerance
|
||||
tvp_writereg(TVP_LINELENTOL, 0x06);
|
||||
// Increase line length tolerance
|
||||
tvp_writereg(TVP_LINELENTOL, 0x06);
|
||||
|
||||
// Common sync separator threshold
|
||||
// Common sync separator threshold
|
||||
// Some arcade games need more that the default 0x40
|
||||
tvp_set_ssthold(0x44);
|
||||
tvp_set_ssthold(0x44);
|
||||
}
|
||||
|
||||
// Configure H-PLL (sampling rate, VCO gain and charge pump current)
|
||||
void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 plldivby2) {
|
||||
alt_u32 pclk_est;
|
||||
alt_u8 vco_range;
|
||||
alt_u8 cp_current;
|
||||
void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 plldivby2)
|
||||
{
|
||||
alt_u32 pclk_est;
|
||||
alt_u8 vco_range;
|
||||
alt_u8 cp_current;
|
||||
|
||||
alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0xF8;
|
||||
alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0xF8;
|
||||
|
||||
// Enable PLL post-div-by-2 with double samplerate
|
||||
if (plldivby2) {
|
||||
tvp_writereg(TVP_HPLLPHASE, status|1);
|
||||
h_samplerate = 2*h_samplerate;
|
||||
} else {
|
||||
tvp_writereg(TVP_HPLLPHASE, status);
|
||||
}
|
||||
// Enable PLL post-div-by-2 with double samplerate
|
||||
if (plldivby2) {
|
||||
tvp_writereg(TVP_HPLLPHASE, status|1);
|
||||
h_samplerate = 2*h_samplerate;
|
||||
} else {
|
||||
tvp_writereg(TVP_HPLLPHASE, status);
|
||||
}
|
||||
|
||||
tvp_writereg(TVP_HPLLDIV_MSB, (h_samplerate >> 4));
|
||||
tvp_writereg(TVP_HPLLDIV_LSB, ((h_samplerate & 0xf) << 4));
|
||||
tvp_writereg(TVP_HPLLDIV_MSB, (h_samplerate >> 4));
|
||||
tvp_writereg(TVP_HPLLDIV_LSB, ((h_samplerate & 0xf) << 4));
|
||||
|
||||
printf("Horizontal samplerate set to %u\n", h_samplerate);
|
||||
printf("Horizontal samplerate set to %u\n", h_samplerate);
|
||||
|
||||
pclk_est = ((alt_u32)h_samplerate * v_lines * hz) / 1000; //in kHz
|
||||
pclk_est = ((alt_u32)h_samplerate * v_lines * hz) / 1000; //in kHz
|
||||
|
||||
printf("Estimated PCLK: %u.%.3u MHz\n", pclk_est/1000, pclk_est%1000);
|
||||
printf("Estimated PCLK: %u.%.3u MHz\n", pclk_est/1000, pclk_est%1000);
|
||||
|
||||
if (pclk_est < 36000) {
|
||||
vco_range = 0;
|
||||
} else if (pclk_est < 70000) {
|
||||
vco_range = 1;
|
||||
} else if (pclk_est < 135000) {
|
||||
vco_range = 2;
|
||||
} else {
|
||||
vco_range = 3;
|
||||
}
|
||||
if (pclk_est < 36000) {
|
||||
vco_range = 0;
|
||||
} else if (pclk_est < 70000) {
|
||||
vco_range = 1;
|
||||
} else if (pclk_est < 135000) {
|
||||
vco_range = 2;
|
||||
} else {
|
||||
vco_range = 3;
|
||||
}
|
||||
|
||||
cp_current = (40*Kvco[vco_range]+h_samplerate/2) / h_samplerate; //"+h_samplerate/2" for fast rounding
|
||||
cp_current = (40*Kvco[vco_range]+h_samplerate/2) / h_samplerate; //"+h_samplerate/2" for fast rounding
|
||||
if (cp_current > 7)
|
||||
cp_current = 7;
|
||||
|
||||
printf("VCO range: %s\nCPC: %u\n", Kvco_str[vco_range], cp_current);
|
||||
tvp_writereg(TVP_HPLLCTRL, ((vco_range << 6) | (cp_current << 3)));
|
||||
printf("VCO range: %s\nCPC: %u\n", Kvco_str[vco_range], cp_current);
|
||||
tvp_writereg(TVP_HPLLCTRL, ((vco_range << 6) | (cp_current << 3)));
|
||||
}
|
||||
|
||||
void tvp_sel_clk(alt_u8 refclk) {
|
||||
alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0xFA;
|
||||
void tvp_sel_clk(alt_u8 refclk)
|
||||
{
|
||||
alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0xFA;
|
||||
|
||||
//TODO: set SOG and CLP LPF based on mode
|
||||
if (refclk == REFCLK_INTCLK) {
|
||||
tvp_writereg(TVP_INPMUX2, status|0x2);
|
||||
} else {
|
||||
//TODO: set SOG and CLP LPF based on mode
|
||||
if (refclk == REFCLK_INTCLK) {
|
||||
tvp_writereg(TVP_INPMUX2, status|0x2);
|
||||
} else {
|
||||
#ifdef EXTADCCLK
|
||||
tvp_writereg(TVP_INPMUX2, status|0x8);
|
||||
tvp_writereg(TVP_INPMUX2, status|0x8);
|
||||
#else
|
||||
tvp_writereg(TVP_INPMUX2, status|0xA);
|
||||
tvp_writereg(TVP_INPMUX2, status|0xA);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc) {
|
||||
tvp_writereg(TVP_CSC1HI, (csc->G_Y >> 8));
|
||||
tvp_writereg(TVP_CSC1LO, (csc->G_Y & 0xff));
|
||||
tvp_writereg(TVP_CSC2HI, (csc->G_Pb >> 8));
|
||||
tvp_writereg(TVP_CSC2LO, (csc->G_Pb & 0xff));
|
||||
tvp_writereg(TVP_CSC3HI, (csc->G_Pr >> 8));
|
||||
tvp_writereg(TVP_CSC3LO, (csc->G_Pr & 0xff));
|
||||
void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc)
|
||||
{
|
||||
tvp_writereg(TVP_CSC1HI, (csc->G_Y >> 8));
|
||||
tvp_writereg(TVP_CSC1LO, (csc->G_Y & 0xff));
|
||||
tvp_writereg(TVP_CSC2HI, (csc->G_Pb >> 8));
|
||||
tvp_writereg(TVP_CSC2LO, (csc->G_Pb & 0xff));
|
||||
tvp_writereg(TVP_CSC3HI, (csc->G_Pr >> 8));
|
||||
tvp_writereg(TVP_CSC3LO, (csc->G_Pr & 0xff));
|
||||
|
||||
tvp_writereg(TVP_CSC4HI, (csc->R_Y >> 8));
|
||||
tvp_writereg(TVP_CSC4LO, (csc->R_Y & 0xff));
|
||||
tvp_writereg(TVP_CSC5HI, (csc->R_Pb >> 8));
|
||||
tvp_writereg(TVP_CSC5LO, (csc->R_Pb & 0xff));
|
||||
tvp_writereg(TVP_CSC6HI, (csc->R_Pr >> 8));
|
||||
tvp_writereg(TVP_CSC6LO, (csc->R_Pr & 0xff));
|
||||
tvp_writereg(TVP_CSC4HI, (csc->R_Y >> 8));
|
||||
tvp_writereg(TVP_CSC4LO, (csc->R_Y & 0xff));
|
||||
tvp_writereg(TVP_CSC5HI, (csc->R_Pb >> 8));
|
||||
tvp_writereg(TVP_CSC5LO, (csc->R_Pb & 0xff));
|
||||
tvp_writereg(TVP_CSC6HI, (csc->R_Pr >> 8));
|
||||
tvp_writereg(TVP_CSC6LO, (csc->R_Pr & 0xff));
|
||||
|
||||
tvp_writereg(TVP_CSC7HI, (csc->B_Y >> 8));
|
||||
tvp_writereg(TVP_CSC7LO, (csc->B_Y & 0xff));
|
||||
tvp_writereg(TVP_CSC8HI, (csc->B_Pb >> 8));
|
||||
tvp_writereg(TVP_CSC8LO, (csc->B_Pb & 0xff));
|
||||
tvp_writereg(TVP_CSC9HI, (csc->B_Pr >> 8));
|
||||
tvp_writereg(TVP_CSC9LO, (csc->B_Pr & 0xff));
|
||||
tvp_writereg(TVP_CSC7HI, (csc->B_Y >> 8));
|
||||
tvp_writereg(TVP_CSC7LO, (csc->B_Y & 0xff));
|
||||
tvp_writereg(TVP_CSC8HI, (csc->B_Pb >> 8));
|
||||
tvp_writereg(TVP_CSC8LO, (csc->B_Pb & 0xff));
|
||||
tvp_writereg(TVP_CSC9HI, (csc->B_Pr >> 8));
|
||||
tvp_writereg(TVP_CSC9LO, (csc->B_Pr & 0xff));
|
||||
}
|
||||
|
||||
void tvp_set_lpf(alt_u8 val) {
|
||||
alt_u8 status = tvp_readreg(TVP_VIDEOBWLIM) & 0xF0;
|
||||
tvp_writereg(TVP_VIDEOBWLIM, status|val);
|
||||
printf("TVP LPF value set to 0x%x\n", val);
|
||||
void tvp_set_lpf(alt_u8 val)
|
||||
{
|
||||
alt_u8 status = tvp_readreg(TVP_VIDEOBWLIM) & 0xF0;
|
||||
tvp_writereg(TVP_VIDEOBWLIM, status|val);
|
||||
printf("TVP LPF value set to 0x%x\n", val);
|
||||
}
|
||||
|
||||
void tvp_set_sync_lpf(alt_u8 val) {
|
||||
alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0x3F;
|
||||
tvp_writereg(TVP_INPMUX2, status|((3-val)<<6));
|
||||
printf("Sync LPF value set to 0x%x\n", (3-val));
|
||||
void tvp_set_sync_lpf(alt_u8 val)
|
||||
{
|
||||
alt_u8 status = tvp_readreg(TVP_INPMUX2) & 0x3F;
|
||||
tvp_writereg(TVP_INPMUX2, status|((3-val)<<6));
|
||||
printf("Sync LPF value set to 0x%x\n", (3-val));
|
||||
}
|
||||
|
||||
void tvp_set_hpll_phase(alt_u8 val) {
|
||||
alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0x07;
|
||||
tvp_writereg(TVP_HPLLPHASE, (val<<3)|status);
|
||||
printf("Phase value set to 0x%x\n", val);
|
||||
void tvp_set_hpll_phase(alt_u8 val)
|
||||
{
|
||||
alt_u8 status = tvp_readreg(TVP_HPLLPHASE) & 0x07;
|
||||
tvp_writereg(TVP_HPLLPHASE, (val<<3)|status);
|
||||
printf("Phase value set to 0x%x\n", val);
|
||||
}
|
||||
|
||||
void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk) {
|
||||
// Configure clock settings
|
||||
tvp_sel_clk(refclk);
|
||||
|
||||
// Clamp position and ALC
|
||||
tvp_set_clamp_position(type);
|
||||
tvp_set_alc(type);
|
||||
|
||||
// Macrovision enable/disable, coast disable for RGBHV.
|
||||
// Coast needs to be enabled when HSYNC is missing during VSYNC. Valid only for RGBHV?
|
||||
// Macrovision should be enabled when serration pulses etc. present, so disable only for RGBHV.
|
||||
switch (type) {
|
||||
case VIDEO_PC:
|
||||
//tvp_writereg(TVP_MISCCTRL4, 0x04);
|
||||
tvp_writereg(TVP_MISCCTRL4, 0x0C);
|
||||
tvp_writereg(TVP_MVSWIDTH, 0x03);
|
||||
break;
|
||||
case VIDEO_HDTV:
|
||||
tvp_writereg(TVP_MISCCTRL4, 0x08);
|
||||
tvp_writereg(TVP_MVSWIDTH, 0x0E);
|
||||
break;
|
||||
case VIDEO_LDTV:
|
||||
case VIDEO_SDTV:
|
||||
case VIDEO_EDTV:
|
||||
tvp_writereg(TVP_MISCCTRL4, 0x08);
|
||||
tvp_writereg(TVP_MVSWIDTH, 0x88); // TODO: check mode
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
tvp_setup_hpll(video_modes[modeid].h_total, vlines, hz, !!(video_modes[modeid].flags & MODE_PLLDIVBY2));
|
||||
|
||||
//Long coast may lead to PLL frequency drift and sync loss (e.g. SNES)
|
||||
/*if (video_modes[modeid].v_active < 720)
|
||||
tvp_set_hpllcoast(3, 3);
|
||||
else*/
|
||||
tvp_set_hpllcoast(1, 0);
|
||||
|
||||
// Hsync output width
|
||||
tvp_writereg(TVP_HSOUTWIDTH, video_modes[modeid].h_synclen);
|
||||
void tvp_set_sog_thold(alt_u8 val)
|
||||
{
|
||||
alt_u8 status = tvp_readreg(TVP_SOGTHOLD) & 0x07;
|
||||
tvp_writereg(TVP_SOGTHOLD, (val<<3)|status);
|
||||
printf("SOG thold set to 0x%x\n", val);
|
||||
}
|
||||
|
||||
void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk) {
|
||||
alt_u8 sync_status;
|
||||
alt_u8 sog_ch;
|
||||
void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk)
|
||||
{
|
||||
// Configure clock settings
|
||||
tvp_sel_clk(refclk);
|
||||
|
||||
if ((fmt == FORMAT_RGsB) || (fmt == FORMAT_YPbPr))
|
||||
// Clamp position and ALC
|
||||
tvp_set_clamp_position(type);
|
||||
tvp_set_alc(type);
|
||||
|
||||
// Macrovision enable/disable, coast disable for RGBHV.
|
||||
// Coast needs to be enabled when HSYNC is missing during VSYNC. Valid only for RGBHV?
|
||||
// Macrovision should be enabled when serration pulses etc. present, so disable only for RGBHV.
|
||||
switch (type) {
|
||||
case VIDEO_PC:
|
||||
//tvp_writereg(TVP_MISCCTRL4, 0x04);
|
||||
tvp_writereg(TVP_MISCCTRL4, 0x0C);
|
||||
tvp_writereg(TVP_MVSWIDTH, 0x03);
|
||||
break;
|
||||
case VIDEO_HDTV:
|
||||
tvp_writereg(TVP_MISCCTRL4, 0x08);
|
||||
tvp_writereg(TVP_MVSWIDTH, 0x0E);
|
||||
break;
|
||||
case VIDEO_LDTV:
|
||||
case VIDEO_SDTV:
|
||||
case VIDEO_EDTV:
|
||||
tvp_writereg(TVP_MISCCTRL4, 0x08);
|
||||
tvp_writereg(TVP_MVSWIDTH, 0x88); // TODO: check mode
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
tvp_setup_hpll(video_modes[modeid].h_total, vlines, hz, !!(video_modes[modeid].flags & MODE_PLLDIVBY2));
|
||||
|
||||
//Long coast may lead to PLL frequency drift and sync loss (e.g. SNES)
|
||||
/*if (video_modes[modeid].v_active < 720)
|
||||
tvp_set_hpllcoast(3, 3);
|
||||
else*/
|
||||
tvp_set_hpllcoast(1, 0);
|
||||
|
||||
// Hsync output width
|
||||
tvp_writereg(TVP_HSOUTWIDTH, video_modes[modeid].h_synclen);
|
||||
}
|
||||
|
||||
void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk)
|
||||
{
|
||||
alt_u8 sync_status;
|
||||
alt_u8 sog_ch;
|
||||
|
||||
if ((fmt == FORMAT_RGsB) || (fmt == FORMAT_YPbPr))
|
||||
sog_ch = (input == TVP_INPUT3) ? 2 : 0;
|
||||
else if ((input == TVP_INPUT1) && (fmt == FORMAT_RGBS))
|
||||
sog_ch = 1;
|
||||
else
|
||||
sog_ch = 2;
|
||||
else if ((input == TVP_INPUT1) && (fmt == FORMAT_RGBS))
|
||||
sog_ch = 1;
|
||||
else
|
||||
sog_ch = 2;
|
||||
|
||||
// RGB+SOG input select
|
||||
tvp_writereg(TVP_INPMUX1, (sog_ch<<6) | (input<<4) | (input<<2) | input);
|
||||
// RGB+SOG input select
|
||||
tvp_writereg(TVP_INPMUX1, (sog_ch<<6) | (input<<4) | (input<<2) | input);
|
||||
|
||||
// Configure clock settings
|
||||
tvp_sel_clk(refclk);
|
||||
// Configure clock settings
|
||||
tvp_sel_clk(refclk);
|
||||
|
||||
// Clamp setup
|
||||
tvp_set_clamp(fmt);
|
||||
// Clamp setup
|
||||
tvp_set_clamp(fmt);
|
||||
|
||||
// HV/SOG sync select
|
||||
if ((input == TVP_INPUT3) && (fmt != FORMAT_RGsB)) {
|
||||
if (fmt == FORMAT_RGBHV)
|
||||
tvp_writereg(TVP_SYNCCTRL1, 0x52);
|
||||
else // RGBS
|
||||
tvp_writereg(TVP_SYNCCTRL1, 0x53);
|
||||
// HV/SOG sync select
|
||||
if ((input == TVP_INPUT3) && (fmt != FORMAT_RGsB)) {
|
||||
if (fmt == FORMAT_RGBHV)
|
||||
tvp_writereg(TVP_SYNCCTRL1, 0x52);
|
||||
else // RGBS
|
||||
tvp_writereg(TVP_SYNCCTRL1, 0x53);
|
||||
|
||||
sync_status = tvp_readreg(TVP_SYNCSTAT);
|
||||
if (sync_status & (1<<7))
|
||||
printf("%s detected, %s polarity\n", (sync_status & (1<<3)) ? "Csync" : "Hsync", (sync_status & (1<<5)) ? "pos" : "neg");
|
||||
if (sync_status & (1<<4))
|
||||
printf("Vsync detected, %s polarity\n", (sync_status & (1<<2)) ? "pos" : "neg");
|
||||
} else {
|
||||
tvp_writereg(TVP_SYNCCTRL1, 0x5B);
|
||||
sync_status = tvp_readreg(TVP_SYNCSTAT);
|
||||
if (sync_status & (1<<1))
|
||||
printf("SOG detected\n");
|
||||
else
|
||||
printf("SOG not detected\n");
|
||||
}
|
||||
sync_status = tvp_readreg(TVP_SYNCSTAT);
|
||||
if (sync_status & (1<<7))
|
||||
printf("%s detected, %s polarity\n", (sync_status & (1<<3)) ? "Csync" : "Hsync", (sync_status & (1<<5)) ? "pos" : "neg");
|
||||
if (sync_status & (1<<4))
|
||||
printf("Vsync detected, %s polarity\n", (sync_status & (1<<2)) ? "pos" : "neg");
|
||||
} else {
|
||||
tvp_writereg(TVP_SYNCCTRL1, 0x5B);
|
||||
sync_status = tvp_readreg(TVP_SYNCSTAT);
|
||||
if (sync_status & (1<<1))
|
||||
printf("SOG detected\n");
|
||||
else
|
||||
printf("SOG not detected\n");
|
||||
}
|
||||
|
||||
// Enable CSC for YPbPr
|
||||
if (fmt == FORMAT_YPbPr)
|
||||
tvp_writereg(TVP_MISCCTRL3, 0x10);
|
||||
else
|
||||
tvp_writereg(TVP_MISCCTRL3, 0x00);
|
||||
// Enable CSC for YPbPr
|
||||
if (fmt == FORMAT_YPbPr)
|
||||
tvp_writereg(TVP_MISCCTRL3, 0x10);
|
||||
else
|
||||
tvp_writereg(TVP_MISCCTRL3, 0x00);
|
||||
|
||||
#ifdef SYNCBYPASS
|
||||
tvp_writereg(TVP_SYNCBYPASS, 0x03);
|
||||
#else
|
||||
tvp_writereg(TVP_SYNCBYPASS, 0x00);
|
||||
#endif
|
||||
#ifdef SYNCBYPASS
|
||||
tvp_writereg(TVP_SYNCBYPASS, 0x03);
|
||||
#else
|
||||
tvp_writereg(TVP_SYNCBYPASS, 0x00);
|
||||
#endif
|
||||
|
||||
//TODO:
|
||||
//clamps
|
||||
//TVP_ADCSETUP
|
||||
//TODO:
|
||||
//clamps
|
||||
//TVP_ADCSETUP
|
||||
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
alt_u8 tvp_check_sync(tvp_input_t input) {
|
||||
alt_u8 sync_status;
|
||||
alt_u8 tvp_check_sync(tvp_input_t input)
|
||||
{
|
||||
alt_u8 sync_status;
|
||||
|
||||
sync_status = tvp_readreg(TVP_SYNCSTAT);
|
||||
sync_status = tvp_readreg(TVP_SYNCSTAT);
|
||||
|
||||
if (input == TVP_INPUT3)
|
||||
return !!((sync_status & 0x98) > 0x80);
|
||||
//return !!((sync_status & 0x90) == 0x90);
|
||||
else
|
||||
return !!(sync_status & (1<<1));
|
||||
if (input == TVP_INPUT3)
|
||||
return !!((sync_status & 0x98) > 0x80);
|
||||
//return !!((sync_status & 0x90) == 0x90);
|
||||
else
|
||||
return !!(sync_status & (1<<1));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
//
|
||||
// This file is part of Open Source Scan Converter project.
|
||||
//
|
||||
@@ -28,30 +28,30 @@
|
||||
#define I2CA_BASE I2C_OPENCORES_0_BASE
|
||||
|
||||
typedef enum {
|
||||
TVP_INPUT1 = 0,
|
||||
TVP_INPUT2 = 1,
|
||||
TVP_INPUT3 = 2
|
||||
TVP_INPUT1 = 0,
|
||||
TVP_INPUT2 = 1,
|
||||
TVP_INPUT3 = 2
|
||||
} tvp_input_t;
|
||||
|
||||
static const alt_u8 Kvco[] = {75, 85, 150, 200};
|
||||
static const char *Kvco_str[] = { "Ultra low", "Low", "Medium", "High" };
|
||||
|
||||
typedef enum {
|
||||
REFCLK_EXT27 = 0,
|
||||
REFCLK_INTCLK = 1
|
||||
REFCLK_EXT27 = 0,
|
||||
REFCLK_INTCLK = 1
|
||||
} tvp_refclk_t;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
alt_u16 R_Y;
|
||||
alt_u16 R_Pb;
|
||||
alt_u16 R_Pr;
|
||||
alt_u16 G_Y;
|
||||
alt_u16 G_Pb;
|
||||
alt_u16 G_Pr;
|
||||
alt_u16 B_Y;
|
||||
alt_u16 B_Pb;
|
||||
alt_u16 B_Pr;
|
||||
const char *name;
|
||||
alt_u16 R_Y;
|
||||
alt_u16 R_Pb;
|
||||
alt_u16 R_Pr;
|
||||
alt_u16 G_Y;
|
||||
alt_u16 G_Pb;
|
||||
alt_u16 G_Pr;
|
||||
alt_u16 B_Y;
|
||||
alt_u16 B_Pb;
|
||||
alt_u16 B_Pr;
|
||||
} ypbpr_to_rgb_csc_t;
|
||||
|
||||
static const alt_u32 clkrate[] = {27000000, 6500000}; //in MHz
|
||||
@@ -81,6 +81,8 @@ void tvp_set_sync_lpf(alt_u8 val);
|
||||
|
||||
void tvp_set_hpll_phase(alt_u8 val);
|
||||
|
||||
void tvp_set_sog_thold(alt_u8 val);
|
||||
|
||||
void tvp_source_setup(alt_8 modeid, video_type type, alt_u32 vlines, alt_u8 hz, alt_u8 refclk);
|
||||
|
||||
void tvp_source_sel(tvp_input_t input, video_format fmt, alt_u8 refclk);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
//
|
||||
// This file is part of Open Source Scan Converter project.
|
||||
//
|
||||
@@ -22,96 +22,96 @@
|
||||
|
||||
#define TVP_BASE (0xB8>>1)
|
||||
|
||||
#define TVP_CHIPREV 0x00
|
||||
#define TVP_HPLLDIV_MSB 0x01
|
||||
#define TVP_HPLLDIV_LSB 0x02
|
||||
#define TVP_HPLLCTRL 0x03
|
||||
#define TVP_HPLLPHASE 0x04
|
||||
#define TVP_CLAMPSTART 0x05
|
||||
#define TVP_CLAMPWIDTH 0x06
|
||||
#define TVP_HSOUTWIDTH 0x07
|
||||
#define TVP_B_FGAIN 0x08
|
||||
#define TVP_G_FGAIN 0x09
|
||||
#define TVP_R_FGAIN 0x0A
|
||||
#define TVP_B_FOFFSET_MSB 0x0B
|
||||
#define TVP_G_FOFFSET_MSB 0x0C
|
||||
#define TVP_R_FOFFSET_MSB 0x0D
|
||||
#define TVP_SYNCCTRL1 0x0E
|
||||
#define TVP_HPLLCTRL2 0x0F
|
||||
#define TVP_CHIPREV 0x00
|
||||
#define TVP_HPLLDIV_MSB 0x01
|
||||
#define TVP_HPLLDIV_LSB 0x02
|
||||
#define TVP_HPLLCTRL 0x03
|
||||
#define TVP_HPLLPHASE 0x04
|
||||
#define TVP_CLAMPSTART 0x05
|
||||
#define TVP_CLAMPWIDTH 0x06
|
||||
#define TVP_HSOUTWIDTH 0x07
|
||||
#define TVP_B_FGAIN 0x08
|
||||
#define TVP_G_FGAIN 0x09
|
||||
#define TVP_R_FGAIN 0x0A
|
||||
#define TVP_B_FOFFSET_MSB 0x0B
|
||||
#define TVP_G_FOFFSET_MSB 0x0C
|
||||
#define TVP_R_FOFFSET_MSB 0x0D
|
||||
#define TVP_SYNCCTRL1 0x0E
|
||||
#define TVP_HPLLCTRL2 0x0F
|
||||
|
||||
#define TVP_SOGTHOLD 0x10
|
||||
#define TVP_SSTHOLD 0x11
|
||||
#define TVP_HPLLPRECOAST 0x12
|
||||
#define TVP_HPLLPOSTCOAST 0x13
|
||||
#define TVP_SYNCSTAT 0x14
|
||||
#define TVP_OUTFORMAT 0x15
|
||||
#define TVP_MISCCTRL1 0x16
|
||||
#define TVP_MISCCTRL2 0x17
|
||||
#define TVP_MISCCTRL3 0x18
|
||||
#define TVP_INPMUX1 0x19
|
||||
#define TVP_INPMUX2 0x1A
|
||||
#define TVP_BG_CGAIN 0x1B
|
||||
#define TVP_R_CGAIN 0x1C
|
||||
#define TVP_FOFFSET_LSB 0x1D
|
||||
#define TVP_B_COFFSET 0x1E
|
||||
#define TVP_G_COFFSET 0x1F
|
||||
#define TVP_SOGTHOLD 0x10
|
||||
#define TVP_SSTHOLD 0x11
|
||||
#define TVP_HPLLPRECOAST 0x12
|
||||
#define TVP_HPLLPOSTCOAST 0x13
|
||||
#define TVP_SYNCSTAT 0x14
|
||||
#define TVP_OUTFORMAT 0x15
|
||||
#define TVP_MISCCTRL1 0x16
|
||||
#define TVP_MISCCTRL2 0x17
|
||||
#define TVP_MISCCTRL3 0x18
|
||||
#define TVP_INPMUX1 0x19
|
||||
#define TVP_INPMUX2 0x1A
|
||||
#define TVP_BG_CGAIN 0x1B
|
||||
#define TVP_R_CGAIN 0x1C
|
||||
#define TVP_FOFFSET_LSB 0x1D
|
||||
#define TVP_B_COFFSET 0x1E
|
||||
#define TVP_G_COFFSET 0x1F
|
||||
|
||||
#define TVP_R_COFFSET 0x20
|
||||
#define TVP_HSOUTSTART 0x21
|
||||
#define TVP_MISCCTRL4 0x22
|
||||
#define TVP_B_ALCOUT_LSB 0x23
|
||||
#define TVP_G_ALCOUT_LSB 0x24
|
||||
#define TVP_R_ALCOUT_LSB 0x25
|
||||
#define TVP_ALCEN 0x26
|
||||
#define TVP_ALCOUT_MSB 0x27
|
||||
#define TVP_ALCFILT 0x28
|
||||
#define TVP_FCLAMPCTRL 0x2A
|
||||
#define TVP_POWERCTRL 0x2B
|
||||
#define TVP_ADCSETUP 0x2C
|
||||
#define TVP_CCLAMPCTRL 0x2D
|
||||
#define TVP_SOGCLAMP 0x2E
|
||||
#define TVP_RGBCCLAMPCTRL 0x2F
|
||||
#define TVP_R_COFFSET 0x20
|
||||
#define TVP_HSOUTSTART 0x21
|
||||
#define TVP_MISCCTRL4 0x22
|
||||
#define TVP_B_ALCOUT_LSB 0x23
|
||||
#define TVP_G_ALCOUT_LSB 0x24
|
||||
#define TVP_R_ALCOUT_LSB 0x25
|
||||
#define TVP_ALCEN 0x26
|
||||
#define TVP_ALCOUT_MSB 0x27
|
||||
#define TVP_ALCFILT 0x28
|
||||
#define TVP_FCLAMPCTRL 0x2A
|
||||
#define TVP_POWERCTRL 0x2B
|
||||
#define TVP_ADCSETUP 0x2C
|
||||
#define TVP_CCLAMPCTRL 0x2D
|
||||
#define TVP_SOGCLAMP 0x2E
|
||||
#define TVP_RGBCCLAMPCTRL 0x2F
|
||||
|
||||
#define TVP_SOGCCLAMPCTRL 0x30
|
||||
#define TVP_ALCPLACE 0x31
|
||||
#define TVP_MVSWIDTH 0x34
|
||||
#define TVP_VSOUTALIGN 0x35
|
||||
#define TVP_SYNCBYPASS 0x36
|
||||
#define TVP_LINECNT1 0x37
|
||||
#define TVP_LINECNT2 0x38
|
||||
#define TVP_CLKCNT1 0x39
|
||||
#define TVP_CLKCNT2 0x3A
|
||||
#define TVP_HSINWIDTH 0x3B
|
||||
#define TVP_VSINWIDTH 0x3C
|
||||
#define TVP_LINELENTOL 0x3D
|
||||
#define TVP_VIDEOBWLIM 0x3F
|
||||
#define TVP_SOGCCLAMPCTRL 0x30
|
||||
#define TVP_ALCPLACE 0x31
|
||||
#define TVP_MVSWIDTH 0x34
|
||||
#define TVP_VSOUTALIGN 0x35
|
||||
#define TVP_SYNCBYPASS 0x36
|
||||
#define TVP_LINECNT1 0x37
|
||||
#define TVP_LINECNT2 0x38
|
||||
#define TVP_CLKCNT1 0x39
|
||||
#define TVP_CLKCNT2 0x3A
|
||||
#define TVP_HSINWIDTH 0x3B
|
||||
#define TVP_VSINWIDTH 0x3C
|
||||
#define TVP_LINELENTOL 0x3D
|
||||
#define TVP_VIDEOBWLIM 0x3F
|
||||
|
||||
#define TVP_AVIDSTART1 0x40
|
||||
#define TVP_AVIDSTART2 0x41
|
||||
#define TVP_AVIDSTOP1 0x42
|
||||
#define TVP_AVIDSTOP2 0x43
|
||||
#define TVP_VB0OFF 0x44
|
||||
#define TVP_VB1OFF 0x45
|
||||
#define TVP_VB0DUR 0x46
|
||||
#define TVP_VB1DUR 0x47
|
||||
#define TVP_CSC1LO 0x4A
|
||||
#define TVP_CSC1HI 0x4B
|
||||
#define TVP_CSC2LO 0x4C
|
||||
#define TVP_CSC2HI 0x4D
|
||||
#define TVP_CSC3LO 0x4E
|
||||
#define TVP_CSC3HI 0x4F
|
||||
#define TVP_AVIDSTART1 0x40
|
||||
#define TVP_AVIDSTART2 0x41
|
||||
#define TVP_AVIDSTOP1 0x42
|
||||
#define TVP_AVIDSTOP2 0x43
|
||||
#define TVP_VB0OFF 0x44
|
||||
#define TVP_VB1OFF 0x45
|
||||
#define TVP_VB0DUR 0x46
|
||||
#define TVP_VB1DUR 0x47
|
||||
#define TVP_CSC1LO 0x4A
|
||||
#define TVP_CSC1HI 0x4B
|
||||
#define TVP_CSC2LO 0x4C
|
||||
#define TVP_CSC2HI 0x4D
|
||||
#define TVP_CSC3LO 0x4E
|
||||
#define TVP_CSC3HI 0x4F
|
||||
|
||||
#define TVP_CSC4LO 0x50
|
||||
#define TVP_CSC4HI 0x51
|
||||
#define TVP_CSC5LO 0x52
|
||||
#define TVP_CSC5HI 0x53
|
||||
#define TVP_CSC6LO 0x54
|
||||
#define TVP_CSC6HI 0x55
|
||||
#define TVP_CSC7LO 0x56
|
||||
#define TVP_CSC7HI 0x57
|
||||
#define TVP_CSC8LO 0x58
|
||||
#define TVP_CSC8HI 0x59
|
||||
#define TVP_CSC9LO 0x5A
|
||||
#define TVP_CSC9HI 0x5B
|
||||
#define TVP_CSC4LO 0x50
|
||||
#define TVP_CSC4HI 0x51
|
||||
#define TVP_CSC5LO 0x52
|
||||
#define TVP_CSC5HI 0x53
|
||||
#define TVP_CSC6LO 0x54
|
||||
#define TVP_CSC6HI 0x55
|
||||
#define TVP_CSC7LO 0x56
|
||||
#define TVP_CSC7HI 0x57
|
||||
#define TVP_CSC8LO 0x58
|
||||
#define TVP_CSC8HI 0x59
|
||||
#define TVP_CSC9LO 0x5A
|
||||
#define TVP_CSC9HI 0x5B
|
||||
|
||||
#endif /* TVP7002_REGS_H_ */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
//
|
||||
// This file is part of Open Source Scan Converter project.
|
||||
//
|
||||
@@ -25,61 +25,66 @@
|
||||
#define LINECNT_MAX_TOLERANCE 30
|
||||
|
||||
const mode_data_t video_modes[] = {
|
||||
{ "240p_L3M0", 1280, 240, 6000, 1704, 262, 196, 16, 124, 3, (VIDEO_SDTV|VIDEO_PC), MODE_L3_MODE0 },
|
||||
{ "240p_L3M1", 960, 240, 6000, 1278, 262, 147, 16, 93, 3, (VIDEO_SDTV|VIDEO_PC), MODE_L3_MODE1 },
|
||||
{ "240p_L3M2", 320, 240, 6000, 426, 262, 49, 16, 31, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE2|MODE_PLLDIVBY2) },
|
||||
{ "240p_L3M3", 256, 240, 6000, 341, 262, 39, 16, 25, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE3|MODE_PLLDIVBY2) },
|
||||
{ "240p", 720, 240, 6000, 858, 262, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE) },
|
||||
{ "288p", 720, 288, 5000, 864, 312, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE) },
|
||||
{ "384p", 496, 384, 5766, 640, 423, 50, 29, 62, 3, VIDEO_EDTV, (MODE_L2ENABLE) }, //Sega Model 2
|
||||
{ "640x384", 640, 384, 5500, 800, 492, 48, 63, 96, 2, VIDEO_PC, (MODE_L2ENABLE) }, //X68k @ 24kHz
|
||||
{ "480i", 720, 240, 5994, 858, 525, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_INTERLACED) },
|
||||
{ "480p", 720, 480, 5994, 858, 525, 60, 30, 62, 6, (VIDEO_EDTV|VIDEO_PC), (MODE_DTV480P) },
|
||||
{ "640x480", 640, 480, 6000, 800, 525, 48, 33, 96, 2, (VIDEO_PC|VIDEO_EDTV), (MODE_VGA480P) },
|
||||
{ "640x512", 640, 512, 6000, 800, 568, 48, 28, 96, 2, VIDEO_PC, 0 }, //X68k @ 31kHz
|
||||
{ "576i", 720, 288, 5000, 864, 625, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_INTERLACED) },
|
||||
{ "576p", 720, 576, 5000, 864, 625, 65, 32, 60, 6, VIDEO_EDTV, 0 },
|
||||
{ "800x600", 800, 600, 6000, 1056, 628, 88, 23, 128, 4, VIDEO_PC, 0 },
|
||||
{ "720p", 1280, 720, 5994, 1650, 750, 255, 20, 40, 5, VIDEO_HDTV, 0 },
|
||||
{ "1280x720", 1280, 720, 6000, 1650, 750, 220, 20, 40, 5, VIDEO_PC, 0 },
|
||||
{ "1024x768", 1024, 768, 6000, 1344, 806, 160, 29, 136, 6, VIDEO_PC, 0 },
|
||||
{ "1280x1024", 1280, 1024, 6000, 1688, 1066, 248, 38, 112, 3, VIDEO_PC, 0 },
|
||||
{ "1080i", 1920, 1080, 5994, 2200, 1125, 148, 16, 44, 5, VIDEO_HDTV, (MODE_L2ENABLE|MODE_INTERLACED) }, //Too high freq for L2 PLL
|
||||
{ "1080p", 1920, 1080, 5994, 2200, 1125, 188, 36, 44, 5, VIDEO_HDTV, 0 },
|
||||
{ "1920x1080", 1920, 1080, 6000, 2200, 1125, 148, 36, 44, 5, VIDEO_PC, 0 },
|
||||
{ "240p_L3M0", 1280, 240, 6000, 1704, 262, 196, 16, 124, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L3_MODE0) },
|
||||
{ "240p_L3M1", 960, 240, 6000, 1278, 262, 147, 16, 93, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L3_MODE1|MODE_PLLDIVBY2) },
|
||||
{ "240p_L3M2", 320, 240, 6000, 426, 262, 49, 16, 31, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE2|MODE_PLLDIVBY2) },
|
||||
{ "240p_L3M3", 256, 240, 6000, 341, 262, 39, 16, 25, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE3|MODE_PLLDIVBY2) },
|
||||
{ "240p", 720, 240, 6000, 858, 262, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_PLLDIVBY2) },
|
||||
{ "288p_L3M0", 1280, 288, 5000, 1704, 312, 196, 16, 124, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L3_MODE0) },
|
||||
{ "288p_L3M1", 960, 288, 5000, 1278, 312, 147, 16, 93, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L3_MODE1|MODE_PLLDIVBY2) },
|
||||
{ "288p_L3M2", 320, 240, 5000, 426, 312, 49, 41, 31, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE2|MODE_PLLDIVBY2) },
|
||||
{ "288p_L3M3", 256, 240, 5000, 341, 312, 39, 41, 25, 3, (VIDEO_LDTV|VIDEO_PC), (MODE_L3_MODE3|MODE_PLLDIVBY2) },
|
||||
{ "288p", 720, 288, 5000, 864, 312, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_PLLDIVBY2) },
|
||||
{ "384p", 496, 384, 5766, 640, 423, 50, 29, 62, 3, VIDEO_EDTV, (MODE_L2ENABLE|MODE_PLLDIVBY2) }, //Sega Model 2
|
||||
{ "640x384", 640, 384, 5500, 800, 492, 48, 63, 96, 2, VIDEO_PC, (MODE_L2ENABLE) }, //X68k @ 24kHz
|
||||
{ "480i", 720, 240, 5994, 858, 525, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_PLLDIVBY2|MODE_INTERLACED) },
|
||||
{ "480p", 720, 480, 5994, 858, 525, 60, 30, 62, 6, (VIDEO_EDTV|VIDEO_PC), (MODE_DTV480P) },
|
||||
{ "640x480", 640, 480, 6000, 800, 525, 48, 33, 96, 2, (VIDEO_PC|VIDEO_EDTV), (MODE_VGA480P) },
|
||||
{ "640x512", 640, 512, 6000, 800, 568, 48, 28, 96, 2, VIDEO_PC, 0 }, //X68k @ 31kHz
|
||||
{ "576i", 720, 288, 5000, 864, 625, 65, 16, 60, 3, (VIDEO_SDTV|VIDEO_PC), (MODE_L2ENABLE|MODE_PLLDIVBY2|MODE_INTERLACED) },
|
||||
{ "576p", 720, 576, 5000, 864, 625, 65, 32, 60, 6, VIDEO_EDTV, 0 },
|
||||
{ "800x600", 800, 600, 6000, 1056, 628, 88, 23, 128, 4, VIDEO_PC, 0 },
|
||||
{ "720p", 1280, 720, 5994, 1650, 750, 255, 20, 40, 5, VIDEO_HDTV, 0 },
|
||||
{ "1280x720", 1280, 720, 6000, 1650, 750, 220, 20, 40, 5, VIDEO_PC, 0 },
|
||||
{ "1024x768", 1024, 768, 6000, 1344, 806, 160, 29, 136, 6, VIDEO_PC, 0 },
|
||||
{ "1280x1024", 1280, 1024, 6000, 1688, 1066, 248, 38, 112, 3, VIDEO_PC, 0 },
|
||||
{ "1080i", 1920, 1080, 5994, 2200, 1125, 148, 16, 44, 5, VIDEO_HDTV, (MODE_INTERLACED) }, //Too high freq for L2 PLL
|
||||
{ "1080p", 1920, 1080, 5994, 2200, 1125, 188, 36, 44, 5, VIDEO_HDTV, 0 },
|
||||
{ "1920x1080", 1920, 1080, 6000, 2200, 1125, 148, 36, 44, 5, VIDEO_PC, 0 },
|
||||
};
|
||||
|
||||
/* TODO: rewrite, check hz etc. */
|
||||
alt_8 get_mode_id(alt_u32 totlines, alt_u8 progressive, alt_u32 hz, video_type typemask, alt_u8 linemult_target, alt_u8 l3_mode, alt_u8 s480p_mode) {
|
||||
alt_8 i;
|
||||
alt_u8 num_modes = sizeof(video_modes)/sizeof(mode_data_t);
|
||||
alt_8 get_mode_id(alt_u32 totlines, alt_u8 progressive, alt_u32 hz, video_type typemask, alt_u8 linemult_target, alt_u8 l3_mode, alt_u8 s480p_mode)
|
||||
{
|
||||
alt_8 i;
|
||||
alt_u8 num_modes = sizeof(video_modes)/sizeof(mode_data_t);
|
||||
video_type mode_type;
|
||||
|
||||
// TODO: a better check
|
||||
for (i=0; i<num_modes; i++) {
|
||||
// TODO: a better check
|
||||
for (i=0; i<num_modes; i++) {
|
||||
mode_type = video_modes[i].type;
|
||||
|
||||
// disable particular 480p mode based on input and user preference
|
||||
if (video_modes[i].flags & MODE_DTV480P) {
|
||||
// disable particular 480p mode based on input and user preference
|
||||
if (video_modes[i].flags & MODE_DTV480P) {
|
||||
if (s480p_mode == 0) // auto
|
||||
mode_type &= ~VIDEO_PC;
|
||||
else if (s480p_mode == 2) // VGA 640x480
|
||||
mode_type = 0;
|
||||
} else if (video_modes[i].flags & MODE_VGA480P) {
|
||||
} else if (video_modes[i].flags & MODE_VGA480P) {
|
||||
if (s480p_mode == 0) // auto
|
||||
mode_type &= ~VIDEO_EDTV;
|
||||
else if (s480p_mode == 1) // DTV 480P
|
||||
mode_type = 0;
|
||||
}
|
||||
|
||||
if ((typemask & mode_type) && (progressive == !(video_modes[i].flags & MODE_INTERLACED)) && (totlines <= (video_modes[i].v_total+LINECNT_MAX_TOLERANCE))) {
|
||||
if (linemult_target && (video_modes[i].flags & MODE_L3ENABLE_MASK) && ((video_modes[i].flags & MODE_L3ENABLE_MASK) == (1<<l3_mode))) {
|
||||
return i;
|
||||
} else if (!(video_modes[i].flags & MODE_L3ENABLE_MASK)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((typemask & mode_type) && (progressive == !(video_modes[i].flags & MODE_INTERLACED)) && (totlines <= (video_modes[i].v_total+LINECNT_MAX_TOLERANCE))) {
|
||||
if (linemult_target && (video_modes[i].flags & MODE_L3ENABLE_MASK) && ((video_modes[i].flags & MODE_L3ENABLE_MASK) == (1<<l3_mode))) {
|
||||
return i;
|
||||
} else if (!(video_modes[i].flags & MODE_L3ENABLE_MASK)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (C) 2015 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
||||
//
|
||||
// This file is part of Open Source Scan Converter project.
|
||||
//
|
||||
@@ -24,18 +24,18 @@
|
||||
#include "sysconfig.h"
|
||||
|
||||
typedef enum {
|
||||
FORMAT_RGBS = 0,
|
||||
FORMAT_RGBHV = 1,
|
||||
FORMAT_RGsB = 2,
|
||||
FORMAT_YPbPr = 3
|
||||
FORMAT_RGBS = 0,
|
||||
FORMAT_RGBHV = 1,
|
||||
FORMAT_RGsB = 2,
|
||||
FORMAT_YPbPr = 3
|
||||
} video_format;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_LDTV = (1<<0),
|
||||
VIDEO_SDTV = (1<<1),
|
||||
VIDEO_LDTV = (1<<0),
|
||||
VIDEO_SDTV = (1<<1),
|
||||
VIDEO_EDTV = (1<<2),
|
||||
VIDEO_HDTV = (1<<3),
|
||||
VIDEO_PC = (1<<4)
|
||||
VIDEO_HDTV = (1<<3),
|
||||
VIDEO_PC = (1<<4)
|
||||
} video_type;
|
||||
|
||||
#define MODE_L3ENABLE_MASK 0xf
|
||||
@@ -45,11 +45,11 @@ typedef enum {
|
||||
MODE_L3_MODE1 = (1<<1),
|
||||
MODE_L3_MODE2 = (1<<2),
|
||||
MODE_L3_MODE3 = (1<<3),
|
||||
MODE_L2ENABLE = (1<<4),
|
||||
MODE_INTERLACED = (1<<5),
|
||||
MODE_PLLDIVBY2 = (1<<6),
|
||||
MODE_DTV480P = (1<<7),
|
||||
MODE_VGA480P = (1<<8)
|
||||
MODE_L2ENABLE = (1<<4),
|
||||
MODE_INTERLACED = (1<<5),
|
||||
MODE_PLLDIVBY2 = (1<<6),
|
||||
MODE_DTV480P = (1<<7),
|
||||
MODE_VGA480P = (1<<8)
|
||||
} mode_flags;
|
||||
|
||||
typedef struct {
|
||||
|
||||
Reference in New Issue
Block a user