⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video_test.c

📁 ADSP 地层驱动
💻 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 + -