📄 video_test.c
字号:
///////////////////////////////////////////////////
// Video_test.c
//
//
///////////////////////////////////////////////////////
#include <cdefbf533.h>
#include "ccblkfn.h"
#include <sys\exception.h>
#include "Timer_ISR.h"
#include "Video_test.h"
#include <stdio.h>
#include <string.h>
// if this is defined we are setup to perform a composite video test,
// otherwise we perform a component video test
//#define COMPOSITE_TEST
int video_test = 0;
bool bDMA_Rcv_End = false;
bool bVideoTest = false; // used by timer ISR
extern SCCB_STATE sccb_state;
/****** SCCB Variables ********/
int SCCB_Variable_High_Address;
int SCCB_Control;
int SCCB_Bit_Count;
int SCCB_Word_Count;
int SCCB_Write_Read_Register;
int *pSCCB_Data_Pointer;
int SCCB_DataIn[60];
int SCCB_DataOut[60];
int SCCB_Point_of_State;
int SCCB_Read_Count;
// test the End of Transfer
void Test_EOT(void)
{
while(1)
{
if(SCCB_Read_Count == 0xab )
{
break;
}
}
}
void SCCB_Interface(void)
{
/////////////////////// SCCB Timer Interrupt Vector Init ////////////////////
//In case the timer will be used for several applications the Interrupt
//vetctor for this Interface is set here. The address of the routine to be
//executed at first is filled in the interrupt register here.
sccb_state = SCCB_Start_Cond1;
///////////////////////// SCCB GPIO init as SDA and SCL ///////////////////////
// enable PF inputs
*pFIO_INEN &= (~SCL); // serial clock is PF0
*pFIO_INEN &= (~SDA); // serial data is PF1
// The Flag PF1(SDA) and PF0(SCL) shall be high
*pFIO_FLAG_S |= SCL;
*pFIO_FLAG_S |= SDA;
// Set bit PF1(SDA) & PF0(SCL) as outputs
*pFIO_DIR |= SCL;
*pFIO_DIR |= SDA;
///////////////////////// SCCB Timer0 Init ///////////////////////
//Clear Timer Interrupt and Overflow bit
*pTIMER_STATUS = 0x0011;
// disable timer
*pTIMER_DISABLE = 0x0001;
// Setup Timer0: PWM_OUT mode, pulse hi, count to end of
// period, interrupt, sample TMR0 pin, enable pad,
// Bit configuration: 0x001D = 0000 0000 0001 1101
*pTIMER0_CONFIG = 0x001D;
// The period is set to provide a 3:1 ratio of SCL to TMR0
*pTIMER0_PERIOD = SCL_PERIOD;
// Width of provides 50% duty cycle: scl_high = 1/2 of scl_period
*pTIMER0_WIDTH = SCL_PERIOD >> 1;
///////////////////////// SCCB Timer0 Interrupt ///////////////////////
*pSIC_IAR2 = 0xfffffff4; // Timer0 -> ID4;
// assign ISRs to interrupt vectors
// register_handler(ik_ivg11, Timer0_ISR); // Timer0 ISR -> IVG 11
// enable Timer0 interrupt
*pSIC_IMASK |= IRQ_TIMER0;
//enable timer
*pTIMER_ENABLE |= 0x0001;
///////////////////////// SCCB Start Setup ///////////////////////
// prepares the variables used in this Interface
SCCB_Bit_Count = 0x8;
SCCB_Read_Count = 0x2;
pSCCB_Data_Pointer = &SCCB_DataIn[0];
SCCB_Write_Read_Register = SCCB_DataIn[0];
// This is the end of the Init program. All other subroutine will be called
// by the Timer Interrupt separately.
// *************** SCCB End of Init ****************************************
}
void config_flash(void)
{
unsigned char tempReg;
unsigned int intReg=0;
//Async Memory Bank Control Register
*pEBIU_AMBCTL0 = AMB0_TIMING;
*pEBIU_AMBCTL1 = AMB1_TIMING;
//Async Memory Global Control Register
tempReg = *pEBIU_AMGCTL;
*pEBIU_AMGCTL = tempReg | en_async_mem;
//Initialize flash A csio regs (port A)
// clear data registers
*pFlashA_Data_Out = 0x0;
ssync();
// direction control registers
*pFlashA_Data_Dir = 0xFF; // set dir=output
// de-assert ADV7171, ADV7183 reset (flashA portA bits 2 and 3)
// and configure PPI clock
tempReg = *pFlashA_Data_Out;
// de-assert encoder reset, decoder reset, use ADV7183 CLKOUT as PPI clock
*pFlashA_Data_Out = tempReg | RST_7171 | RST_7183 | PPICLK_7183;
}
void SCCB_Write_Single(int write_address,int sub_address, int data)
{
SCCB_DataIn[0] = write_address; // set device write address
SCCB_DataIn[1] = sub_address; // set device sub-address
SCCB_DataIn[2] = data; // set data to be written
SCCB_Word_Count = 3; // count
SCCB_Control = wr_cmd; // sccb write command
SCCB_Interface();
Test_EOT();
}
//////////////////////////////////////////////////////////////////////
// config the ADV7171 encoder
void config_ADV7171(void)
{
int i = 0;
// program ADV7171 to display a color bar
SCCB_Write_Single(ADV7171_WR,ADV7171_MR1, ADV7171_ColorBar );
#ifdef COMPOSITE_TEST
// program ADV7171 for composite mode
SCCB_Write_Single(ADV7171_WR,ADV7171_MR3, ADV7171_MR3_2_CVBS_Mode );
#else
// program ADV7171 for component mode
SCCB_Write_Single(ADV7171_WR,ADV7171_MR3, ADV7171_MR3_YUV_Mode );
SCCB_Write_Single(ADV7171_WR,ADV7171_MR4, ADV7171_MR4_YUV_Mode );
#endif
// give the encoder time to stabilize the color bar
for ( i = 0; i < 0x0ffffff; i++ )
{
asm("nop;");
asm("nop;");
}
}
///////////////////////////////////////////////////////////////////////
// config the ADV7183 decoder
void config_ADV7183(void)
{
#ifdef COMPOSITE_TEST
// determine input channel
int avin_select = 0;
if(video_test == AVIN1_DAC_D_A)
avin_select = ADV7183_AVIN1;
else if(video_test == AVIN4_DAC_B_A)
avin_select = ADV7183_AVIN4;
else
asm("emuexcpt;");
// program ADV7183 with desired input channel, only 1 is used (AIN1 or AIN4)
SCCB_Write_Single(ADV7183_WR,ADV7183_In_Control, avin_select );
#else
// program ADV7183 with desired input channel, all 3 are used
// Y - AIN1, U - AIN4, V - AIN5
SCCB_Write_Single(ADV7183_WR,ADV7183_In_Control, ADV7183_YUV_Mode );
#endif
// enable PF input
// only PF assigned to ADV7183 OE
*pFIO_INEN &= (~ADV7183_OE);
// set PF as an output
// only PF assigned to ADV7183 OE
*pFIO_DIR |= ADV7183_OE;
//drive ADV7182 OE low
*pFIO_FLAG_C = ADV7183_OE;
}
///////////////////////////////////////////////////////////////////////
// setup sdram
void config_sdram(void)
{
//SDRAM Refresh Rate Control Register
*pEBIU_SDRRC = 0x000001A0;
//SDRAM Memory Bank Control Register
*pEBIU_SDBCTL = 0x00000025;
//SDRAM Memory Global Control Register
*pEBIU_SDGCTL = 0x0091998d;
}
///////////////////////////////////////////////////////////////////////
// fill sdram with all zeros
void clear_sdram(void)
{
int i=0;
int *pSDRAM = SDRAM_START_ADDR;
for(i = 0; i < MEM_SIZE; i++, pSDRAM++)
{
*pSDRAM =0;
}
}
///////////////////////////////////////////////////////////////////////
// PPI DMA0 ISR
EX_INTERRUPT_HANDLER(PPI_DMA_ISR)
{
int tempReg = *pDMA0_IRQ_STATUS;
if( tempReg & 0x1)
{
*pDMA0_IRQ_STATUS |= DMA_DONE; // acknowledge DMA done
// disable PPI
*pPPI_CONTROL &= (~PORT_EN); //clear #0 bit
// disable DMA and Interrupts generated by DMA
*pDMA0_CONFIG &= (~DMAEN); //clear #0 bit
*pDMA0_CONFIG &= (~DI_EN); //clear #7 bit
// set dma end flag
bDMA_Rcv_End = 1;
}
else
{
bDMA_Rcv_End=0;
}
}
///////////////////////////////////////////////////////////////////////
// configure PPI DMA0 ISR
void config_ISR(void)
{
// configure interrupt
*pSIC_IAR1 = 0x1; // map DMA0 PPI interrupt -> IVG8
register_handler(ik_ivg8, PPI_DMA_ISR); // assign DMA0 ISR to interrupt vector 8
// enable just DMA0 PPI interrupt
*pSIC_IMASK =0x00000100;
}
///////////////////////////////////////////////////////////////////////
// configure PPI DMA0
void config_dma(void)
{
// target address of the DMA
*pDMA0_START_ADDR = SDRAM_START_ADDR;
// line length
*pDMA0_X_COUNT = PIXEL_PER_LINE;
// the modifier is set to 2 because of the 16bit transfers
*pDMA0_X_MODIFY = 0x2;
// frame length
*pDMA0_Y_COUNT = LINES_PER_FRAME;
// the modifier is set to 2 because of the 16bit transfers
*pDMA0_Y_MODIFY = 0x2;
// PPI peripheral is used
*pDMA0_PERIPHERAL_MAP = 0x0;
// DMA Config: Enable DMA | Memory write DMA | 2-D DMA | Discard DMA FIFO before start | enable assertation of interrupt | NDSIZE for stop mode | Enable STOP DMA
*pDMA0_CONFIG = DMAEN | DI_EN | WNR | WDSIZE_16| DMA2D | RESTART ;
}
///////////////////////////////////////////////////////////////////////
// configure PPI
void config_ppi(void)
{
// the PPI is set to receive 525 lines for each frame
*pPPI_FRAME = 525;
// PPI enabled, input mode, active video only, receive field 1&2,
// packing enabled, skipping disabled, 8bit data bus, nothing inverted
*pPPI_CONTROL = FLD_SEL | PACK_EN | DLEN_8; //PPI_CTRL_DMA16_FRAME;
// enable PPI
*pPPI_CONTROL |= 0x1;
}
///////////////////////////////////////////////////////////////////////
// determine average YUV values for a given bar
void get_color_info( unsigned char *Frame, int x1, int y1, int x2, int y2, int *avg_y, int *avg_u, int *avg_v )
{
// data is in UYVY
int x, y, i;
unsigned char *p;
unsigned char *p_end;
unsigned char yy1, yy2, u, v;
long long sum_y = 0;
long long sum_u = 0;
long long sum_v = 0;
int min_y = 255, min_u = 255, min_v = 255;
int max_y = 0, max_u = 0, max_v = 0;
long long num_pixels;
if( ( x1 > x2 ) || ( y1 > y2 ) ) return;
num_pixels = (y2 - y1) * (x2 - x1);
for( y = y1; y < y2; y++ )
{
for( x = x1; x < x2; x++ )
{
if( !(x & 0x01) )
{
// U
i = (unsigned char) Frame[ ( 2 * y * PIXEL_PER_LINE ) + x * 2 ];
if( i > max_u ) max_u = i;
if( i < min_u ) min_u = i;
sum_u += i;
// Y
i = (unsigned char) Frame[ ( 2 * y * PIXEL_PER_LINE ) + x * 2 + 1 ];
if( i > max_y ) max_y = i;
if( i < min_y ) min_y = i;
sum_y += i;
}
else
{
// V
i = (unsigned char) Frame[ ( 2 * y * PIXEL_PER_LINE ) + x * 2 ];
if( i > max_v ) max_v = i;
if( i < min_v ) min_v = i;
sum_v += i;
// Y
i = (unsigned char) Frame[ ( 2 * y * PIXEL_PER_LINE ) + x * 2 + 1 ];
if( i > max_y ) max_y = i;
if( i < min_y ) min_y = i;
sum_y += i;
}
}
}
*avg_y = sum_y / num_pixels;
*avg_u = sum_u / ( num_pixels >> 1 );
*avg_v = sum_v / ( num_pixels >> 1 );
}
///////////////////////////////////////////////////////////////////////
// verify that the average YUV values are within the expected range
int Verify_ColorBar(void)
{
int test_pass = 0;
int avg_y = 0, avg_u = 0, avg_v = 0;
int x1 = 6, y1 = 15, x2 = 78, y2 = 240;
int i = 0;
int column_inc = 90;
#ifdef COMPOSITE_TEST
static int tolerance = 0x10;
int color_bar[8][3] = { // y // u // v
{0xea, 0x7f, 0x7f},
{0xa7, 0x33, 0x8c},
{0x8a, 0x96, 0x33},
{0x79, 0x4b, 0x40},
{0x5f, 0xb3, 0xbe},
{0x4e, 0x67, 0xcc},
{0x32, 0xcb, 0x72},
{0x20, 0x7f, 0x7f} };
#else
static int tolerance = 0xa;
int color_bar[8][3] = { // y // u // v
{0xfa, 0x80, 0x80},
{0xac, 0x01, 0x95},
{0x8b, 0xaa, 0x01},
{0x77, 0x2c, 0x16},
{0x59, 0xd4, 0xe9},
{0x45, 0x56, 0xfe},
{0x24, 0xfe, 0x6b},
{0x10, 0x80, 0x80} };
#endif
for( i = 0; i < 8; i++ )
{
get_color_info((unsigned char*)COLORBAR_START, x1, y1, x2, y2, &avg_y, &avg_u, &avg_v );
x1+=column_inc;
x2+=column_inc;
if( ( abs( color_bar[i][0] - avg_y ) < tolerance ) &&
( abs( color_bar[i][1] - avg_u ) < tolerance ) &&
( abs( color_bar[i][2] - avg_v ) < tolerance ) )
{
// The color matches
test_pass++;
}
else
{
// test failed
}
}
// check for result
if( test_pass == 8 )
return 1;
else
return 0;
}
///////////////////////////////////////////////////////////////////////
// video test routine
int TEST_VIDEO( void )
{
// after running TEST_VIDEO(), you may view the color bar in VDSP by halting
// the Blackfin, then open the Image Viewer which is located under the
// "View->Debug Windows->Image Viewer..." menu item and set the configuration
// settings as follows:
// Source location: DSP Memory
// Source format: Raw pixel data
// Memory: BLACKFIN Memory
// Start address: 0x0
// Memory stride: 1
// Pixel format: UYVY (4:2:2)
// Width: 720
// Height: 480
int rev = 0; // silicon rev
int i = 0; // counter
bool bTimeout = true; // timeout flag
// check DSP revision;
volatile int *pREVID = (volatile int *)0xFFC00014;
rev = (((*pREVID) >> 28) & 0xFF);
if(rev<4)
{
//skip video test and mark it failed
return false;
}
#ifdef COMPOSITE_TEST
// composite tests on a single channel and we run this on 2 channels,
// component tests all 3 channels at the same time
for ( video_test = 0; video_test < 2; video_test++ )
#endif
{
SCCB_Variable_High_Address = 0;
SCCB_Control = 0;
SCCB_Bit_Count = 0;
SCCB_Word_Count = 0;
SCCB_Write_Read_Register = 0;
*pSCCB_Data_Pointer = 0;
memset(SCCB_DataIn, 0, 60);
memset(SCCB_DataOut,0,60);
SCCB_Point_of_State = 0;
SCCB_Read_Count = 0;
bDMA_Rcv_End = false;
bVideoTest = true;
bTimeout = true;
// configure all the peripherals
config_flash();
config_ADV7171();
config_ADV7183();
config_sdram();
config_ISR();
clear_sdram();
config_dma();
config_ppi();
// test for end of dma
for(i = 0; i < TIME_OUT && bTimeout; i++)
{
// if DMA completed
if(bDMA_Rcv_End==1)
{
// check color bar
if (Verify_ColorBar())
{
// we passed, break out of timeout loop
bTimeout = false;
}
else
{
bVideoTest = false; // clear flag
return false; // else we failed color bar test
}
}
}
// if we timed out we must fail
if (bTimeout)
{
bVideoTest = false; // clear flag
return false;
}
}
// we passed
bVideoTest = false;
return true;
}
///////////////////////////////////////////////////////////////////////
// main(), used if you are running video test standalone
#ifdef _STANDALONE_
void main(void)
{
int bPassed;
while(1)
{
bPassed = TEST_VIDEO();
if( 0 == bPassed )
{
break;
}
}
}
#endif //_STANDALONE_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -