BF533 使用DMA方式传输ITU-656格式图像例程中,图片分成两个的解决方案

ADSP5.0中 video input(c) 例程拍摄得出的图片是两层的图片,效果如下图

上面的图片只是一部分,原图还要更高一点,但是我现在只能找到这张了。有时候上下两部分中间还有20~30像素高的黑条。

出现这个情况的原因,是该例程视频输入采用ITU-656模式,在这种模式下视频输入数据分为filed1和filed2两个场,filed1中放的是奇数行的数据,filed2中放的是偶数行的数据。比较简单的办法是另外申请一块内存,将奇数行数据和偶数行数据交叉放置就可以了。但是一方面这样花费了额外的处理时间,另一方面当出现上面说的黑条时,这样处理后的图片也会出现黑条,这个我也不清楚为什么会出现。

ITU-656 输入模式

在该例程中,使用的是active video only sent模式,即输入数据完全是图像数据,没有任何描述信息和冗余信息。如果将数据一次读进来,结果就是上面的样子,我希望可以将图像用两次读进来,第一次读field1,第二次读field2,并且在读入数据时就将它们存入正确的位置。解决方案是采用交叉传送(好像是叫这个名字)。

在例程里面拍照是通过调用Init_DMA();Init_PPI();两个函数实现的,前者是配置DMA,主要是数据宽度、偏移量、数据量等信息,后者配置数据的行数并且启动传输。实现交叉传送的关键就在于配置DMA的偏移量,具体来说是设置行偏移寄存器DMA0_Y_MODIFY。它的功能是设置当传输完一行数据一行,数据目的指针增加的字节数,在例程里面是0x2,因为图像数据是16位的,占两个字节。比如用下面的数组存储图像

Short datas[100][300];

那么图像的宽度是300,高度是100datas[0][299]是第一行的最后一个像素,datas[1][0]是第二行的第一个像素,这两个元素的地址相差一个short的大小,即0x2 

现在我要达到的效果是,第一行数据传输完以后,下一行数据从datas[2][0]开始存储,跳过datas[1],那么只需要将DMA0_Y_MODIFY加上一行数据的字节数,即300*2,则DMA0_Y_MODIFY的值为2+300*2=602 

同时由于一张图片传送两次,那么每次的数据量减半,DMA0_Y_COUNT的值变为原来的一半。两次传送的起始地址是不一样的,为了不改变接口,添加了一个全局变量来标识。

char frame_1=1;

Init_DMA()函数中判断frame_1的值来决定是否偏移数据首地址。

修改后的代码如下

#define Line_Length 720
#define Frame_Length 576

char frame_1=1;

void Init_DMA(unsigned char *pAdd)
{
	//Target address of the DMA
	if(frame_1)
		*pDMA0_START_ADDR = pAdd;
	else
		*pDMA0_START_ADDR = pAdd+ Line_Length*2;

	//Line_Length 16bit transfers will be executed
	*pDMA0_X_COUNT = Line_Length;

	//The modifier is set to 2 because of the 16bit transfers
	*pDMA0_X_MODIFY = 0x2;	
														
	//Frame_Length 16bit transfers will be executed
	//*pDMA0_Y_COUNT = Frame_Length;
	*pDMA0_Y_COUNT = Frame_Length/2;

	//The modifier is set to 2 because of the 16bit transfers
	//*pDMA0_Y_MODIFY = 0x2;	
	*pDMA0_Y_MODIFY = Line_Length+2;	

	//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 | DI_EN;	
}//end Init_DMA
void Init_PPI(void)
{
	//The PPI is set to receive 525 lines for each frame
	//*pPPI_FRAME = 576;	
	*pPPI_FRAME = 288;	

	//PPI enabled, input mode, active video only, receive field 1&2, 
	//packing enabled, skipping disabled, 8bit data bus, nothing inverted
	*pPPI_CONTROL = PORT_EN | FLD_SEL | PACK_EN | DLEN_8 ;
}//end Init_PPI

注释掉的代码是例程中原来的代码。

在主函数中连续采集图像,即相当于拍摄视频的代码如下

frame_1=1;
n=-1;
while(n==-1)
{
	camera=1;
	Init_DMA((void *) VideoFrame);
	Init_PPI();
	while(camera);
	frame_1=!frame_1;
	if(frame_1)
		send_packet((char*)VideoFrame+80,614400,1,1440);  //这个+80是什么我不记得了
}

其中camera变量在DMA0_PPI_ISR中断中被复位,表明DMA传送完成。

你可能感兴趣的:(dsp)