DSP

DM642学习笔记(程序注释)

2019-07-13 17:58发布

 2010年11月初DM642学习笔记   用的是瑞泰创新的实验箱(ICETEK-DM642-IDK-M),主要是视频处理部分的程序注释及思考题思路及一些不成熟的见解~~   实验5.6-5.19 视频驱动程序应用 DM642视频驱动程序的注释: /*  *  Copyright 2003 by Texas Instruments Incorporated.  *  All rights reserved. Property of Texas Instruments Incorporated.  *  Restricted rights to use, duplicate or disclose this code are  *  granted through contract.  *   */ /* "@(#) DDK 1.10.00.23 07-02-03 (ddk-b12)" */ #include     //如果使用C语言,必须将此文件作为第一个头文件 #include   #include    #include   #include #include //使用CSL库,要用到的一些头文件,可参考CSL   #include //视频驱动头文件 #include #include #include #include #include #include       #include //芯片头文件   #include "colorbar.h"//如果显示彩 {MOD}滚动条,就必须有此头文件;否则不需要 #include "evmdm642_vcapparams.h" #include "evmdm642_vdisparams.h"     /* heap IDs defined in the BIOS configuration file */ extern Int EXTERNALHEAP;//??DSP/BIOS?????¨??   /*  * ======== main ========  */ main() {     /******************************************************/     /* open CSL DAT module for fast copy                  */     /******************************************************/     CSL_init();                                 //调用任何CSL库中的函数,必须先在此调用函数     CACHE_clean(CACHE_L2ALL, 0, 0);                             //清洗Cache模式     CACHE_setL2Mode(CACHE_256KCACHE);                         //设置Cache模式 CACHE_enableCaching(CACHE_EMIFA_CE00);                   //使能EMIFA CE0空间 CACHE_enableCaching(CACHE_EMIFA_CE01);                   //使能EMIFA CE1空间     DAT_open(DAT_CHAANY, DAT_PRI_LOW, DAT_OPEN_2D); //打开数据传输   }   /*  * ======== tskVideoLoopback ========  * video loopback function.  */ void tskVideoLoopback() {     Int i;     int m_nWork;     Int status;     FVID_Handle disChan;         //设置设备句柄     Int frames = 0;     FVID_Frame *disFrameBuf; Int numLinesDis = EVMDM642_vDisParamsChan.imgVSizeFld1; //设置显示的行数,VGA为480,PAL为576 Int numLinesCap =EVMDM642_vCapParamsChan.fldYStop1 -  //设置采集行数                                      EVMDM642_vCapParamsChan.fldYStrt1+1;         /*判断是显示区域大,还是采集区域大,取其小者*/     Int numLines = (numLinesDis > numLinesCap) ? numLinesCap : numLinesDis;   #ifdef _LOOPBACK     FVID_Handle capChan;         /*设置每行显示的像素数,PAL制为720*/     Int numPixels = EVMDM642_vCapParamsChan.fldXStop1 -        EVMDM642_vCapParamsChan.fldXStrt1+1;        FVID_Frame *capFrameBuf;         /*设置采集图像一行的总像素*/     Int capLinePitch = EVMDM642_vCapParamsChan.fldXStop1 -        EVMDM642_vCapParamsChan.fldXStrt1+1;            /*设置显示图像一行的总像素*/       Int disLinePitch = EVMDM642_vDisParamsChan.imgHSizeFld1;     #ifdef _PIP     VPORTCAP_Params EVMDM642_vCapParamsChan2 = EVMDM642_vCapParamsChan;     FVID_Handle capChan2;     FVID_Frame *capFrameBuf2;     Int yPitch = capLinePitch >> 1;     Int cPitch = ((capLinePitch >> 2) + 7) & (~ 7); #endif #endif                        numLines *= 2; /* both fields */如果输出为PAL制,前面numLinesCap不要*2,这里再*2?     /******************************************************/     /* allocate both capture and display frame buffers    */     /* in external heap memory                            */     /******************************************************/     /*分配采集和显示图像的存放缓冲区*/         EVMDM642_vCapParamsChan.segId = EXTERNALHEAP;         EVMDM642_vDisParamsChan.segId = EXTERNALHEAP;         EVMDM642_vDisParamsSAA7105.hI2C = EVMDM642_I2C_hI2C;         EVMDM642_vCapParamsSAA7115.hI2C = EVMDM642_I2C_hI2C;       /******************************************************/     /* initialization of capture driver                   */     /******************************************************/     /*建立并初始化采集设备对象*/ #ifdef _LOOPBACK     capChan = FVID_create("/VP0CAPTURE/A/0",             IOM_INPUT, &status, (Ptr)&EVMDM642_vCapParamsChan, NULL);   #ifdef _PIP     EVMDM642_vCapParamsChan2.scale = VPORT_SCALING_ENABLE;         EVMDM642_vCapParamsChan2.fldOp = VPORT_FLDOP_FLD1;                EVMDM642_vCapParamsChan2.thrld >>=1;     capChan2 = FVID_create("/VP1CAPTURE/A/1",             IOM_INPUT, &status, (Ptr)&EVMDM642_vCapParamsChan2, NULL); #endif            #endif              /******************************************************/     /* initialization of display driver                   */     /******************************************************/     /*建立并初始化显示设备对象*/     disChan = FVID_create("/VP2DISPLAY", IOM_OUTPUT,         &status, (Ptr)&EVMDM642_vDisParamsChan, NULL);           /******************************************************/     /* configure video encoder & decoder                  */     /******************************************************/     for ( m_nWork=0;m_nWork<6;m_nWork++ )//这里的循环有何用???一直没有弄清楚     {            /*为保证采集和显示设备正常工作,为其设置驱动*/            FVID_control(disChan, VPORT_CMD_EDC_BASE + EDC_CONFIG,                (Ptr)&EVMDM642_vDisParamsSAA7105); #ifdef _LOOPBACK            FVID_control(capChan, VPORT_CMD_EDC_BASE + EDC_CONFIG,                (Ptr)&EVMDM642_vCapParamsSAA7115); #ifdef _PIP            EVMDM642_vCapParamsSAA7115.aFmt = SAA7115_AFMT_COMPOSITE;            FVID_control(capChan2, VPORT_CMD_EDC_BASE+EDC_CONFIG,                (Ptr)&EVMDM642_vCapParamsSAA7115); #endif #endif        }       /******************************************************/     /* start capture & display operation                  */        /******************************************************/     /*开始采集和显示操作*/     FVID_control(disChan, VPORT_CMD_START, NULL); #ifdef _LOOPBACK     FVID_control(capChan, VPORT_CMD_START, NULL); #ifdef _PIP     FVID_control(capChan2, VPORT_CMD_START, NULL); #endif    #endif            /********************************************************/     /* request a frame buffer from display & capture driver */     /********************************************************/     /*分配采集和显示一帧图像存放的缓冲区*/     FVID_alloc(disChan, &disFrameBuf); #ifdef _LOOPBACK     FVID_alloc(capChan, &capFrameBuf); #ifdef _PIP     FVID_alloc(capChan2, &capFrameBuf2); #endif      #endif     frames ++;       while(1){/* loop forever */ #ifdef _LOOPBACK         /* copy data from capture buffer to display buffer */         /***************************************************/               /*将采集缓冲区的内容复制到显示缓冲区*/         for(i = 0; i < numLines; i ++) {             DAT_copy(capFrameBuf->frame.iFrm.y1 + i * capLinePitch,                      disFrameBuf->frame.iFrm.y1 + i * disLinePitch,                      numPixels);             DAT_copy(capFrameBuf->frame.iFrm.cb1 + i * (capLinePitch >> 1),                      disFrameBuf->frame.iFrm.cb1 + i * (disLinePitch >> 1),                      numPixels>>1);               DAT_copy(capFrameBuf->frame.iFrm.cr1 + i * (capLinePitch >> 1),                      disFrameBuf->frame.iFrm.cr1 + i * (disLinePitch >> 1),                      numPixels>>1);         } #ifdef _PIP          for(i = 0; i < (numLines>>1); i ++) {             DAT_copy(capFrameBuf2->frame.iFrm.y1 + i * yPitch,                      disFrameBuf->frame.iFrm.y1 + i * disLinePitch                      + (disLinePitch >> 1),                      (numPixels>>1));             DAT_copy(capFrameBuf2->frame.iFrm.cb1 + i * cPitch,                      disFrameBuf->frame.iFrm.cb1 + i * (disLinePitch >> 1)                      + (disLinePitch >>2 ),                      (numPixels >> 2));               DAT_copy(capFrameBuf2->frame.iFrm.cr1 + i * cPitch,                      disFrameBuf->frame.iFrm.cr1 + i * (disLinePitch >> 1)                      +(disLinePitch >> 2),                      (numPixels >> 2));         } #endif         DAT_wait(DAT_XFRID_WAITALL);         FVID_exchange(capChan, &capFrameBuf);//采集一帧图像 #ifdef _PIP         FVID_exchange(capChan2, &capFrameBuf2); #endif #else  //如果定义CAPTURE则填充图像缓冲区为8条带         fillFrmBuf(&disFrameBuf->frame.iFrm, EVMDM642_vDisParamsChan.imgHSizeFld1,           EVMDM642_vDisParamsChan.imgVSizeFld1             + EVMDM642_vDisParamsChan.imgVSizeFld2,           frames % 360); #endif         FVID_exchange(disChan, &disFrameBuf);//将显示缓冲区中一帧图像送给显示设备             frames ++;             //处理下一帧图像            } }   实验5.20 视频图像处理-取反 1.将程序改成屏幕1/4进行取反,而其他不变 在主程序中ICETEKDM642PCIImageProcessReverse()函数前加if(i<(numLines/2)),即: if(i<(numLines/2))                             ICETEKDM642PCIImageProcessReverse(); 并将ICETEKDM642PCIImageProcessReverse()函数中的循环体改为如下:        for ( i=0;i<720/2;i++ )               nMemTemp[i]=~nMemTemp[i];   2.例程中处理了亮度信号,以下是处理 {MOD}差信号: for ( i = 0; i < numLines; i ++ ) { m_nID=DAT_copy(capFrameBuf->frame.iFrm.cb1+i*(capLinePitch>>1),nMemTemp,numPixels>>1); DAT_wait(m_nID);   ICETEKDM642PCIImageProcessReverse();   DAT_copy(nMemTemp,disFrameBuf->frame.iFrm.cb1+i*(disLinePitch>>1),numPixels>>1);             for ( m_nWork=0;m_nWork>1;m_nWork++ )               nMemTemp[m_nWork]=0x080;                             DAT_copy(nMemTemp,disFrameBuf->frame.iFrm.y1+i*disLinePitch,numPixels);           DAT_copy(nMemTemp,disFrameBuf->frame.iFrm.cr1+i*(disLinePitch>>1),numPixels>>1); } 出现的问题:图像显示时右半屏有闪烁???~~~   实验5.21 视频图像处理-直方图统计 程序注释:源程序中定义的js变量不知为何用,于是就删除了~~~ #include "ICETEK-DM642-PCI.h"   //工作变量 #pragma DATA_SECTION(nMemTemp, ".INTPROCBUFF"); #pragma DATA_ALIGN(nMemTemp,128); unsigned char nMemTemp[720]; #pragma DATA_SECTION(nHisto, ".INTPROCBUFF"); #pragma DATA_ALIGN(nHisto,128); unsigned int nHisto[256]; unsigned char imgHisto[HISTOHIGH*HISTOWIDTH];//128*256 int mi,mj,m_nWork1; unsigned int m_nWork,*pWork; unsigned char *pImg,*pImg1;   void ICETEKDM642PCIBoardInit()//直方图显示区域初始化 {        for ( mi=0;mi               imgHisto[mi]=1;        for ( mi=0;mi<256;mi++ )               nHisto[mi]=0; }   #pragma CODE_SECTION(ICETEKDM642PCIStatistic,".text1") void ICETEKDM642PCIStatistic()//统计一帧图像的直方图 {        int i;        for ( i=0;i<720;i++ )        {               nHisto[nMemTemp[i]]++;        } }   #pragma CODE_SECTION(ICETEKDM642PCIHistogram,".text1") void ICETEKDM642PCIHistogram()//将统计的一帧图像的直方图显示在显示区域上 {        m_nWork=0;        for ( mi=0;mi<256;mi++ )//找出各灰度级别像素总数最大的               if ( m_nWork                      m_nWork=nHisto[mi];                             m_nWork/=(HISTOHIGH-1);//求出比例因子(即像素总数最大值/显示区域的高度)               for ( mi=0;mi<256;mi++ )//转换各灰度级,将其映射到显示区域(即:各个灰度级的像素/比例因子)        {               nHisto[mi]/=m_nWork;        }               for ( mi=0;mi               imgHisto[mi]=1;                      pImg = imgHisto; //pImg指针指向显示区域首地址        pImg += ((HISTOHIGH-1)*HISTOWIDTH); //mImg指针指向显示区域尾地址        pImg++;//???               for ( mi=1;mi<255;mi++,pImg++ )        {               for ( mj=0,pImg1=pImg;mj                      (*pImg1)=HISTOCOLOR;//对应的显示区域填充颜 {MOD},这里还是不太明白        }          for ( mi=0;mi<256;mi++ ) //清除直方图统计的数组               nHisto[mi]=0; }   实验5.22 视频图像处理-直方图均衡化增强 程序注释:直方图均衡化,其实质是图像增强的一种。 #include "math.h" #include "ICETEK-DM642-PCI.h"   //工作变量 #pragma DATA_SECTION(nMemTemp, ".INTPROCBUFF"); #pragma DATA_ALIGN(nMemTemp,128); unsigned char nMemTemp[720]; #pragma DATA_SECTION(fHisto, ".INTPROCBUFF"); #pragma DATA_ALIGN(fHisto,128); float fHisto[256];// #pragma DATA_SECTION(lut, ".INTPROCBUFF"); #pragma DATA_ALIGN(lut,128); unsigned char lut[256];//保存新的灰度级,是通过上一帧图像计算的 int mi,mj,m_nWork1; unsigned int m_nWork,*pWork,js; unsigned char *pImg,*pImg1; float m_fWork;   void ICETEKDM642PCIBoardInit() {        js=0;        for ( mi=0;mi<256;mi++ )        {               fHisto[mi]=0.0f;               lut[mi]=0;        } }   #pragma CODE_SECTION(ICETEKDM642PCIStatistic,".text1") void ICETEKDM642PCIStatistic() {        int i;        for ( i=0;i<720;i++ )        {               fHisto[nMemTemp[i]]++;//统计灰度直方图               nMemTemp[i]=lut[nMemTemp[i]];//新的灰度级映射(通过上一帧图像计算出的新灰度级,处理这一帧图像)        } }   #pragma CODE_SECTION(ICETEKDM642PCIHistogramEnhance,".text1") void ICETEKDM642PCIHistogramEnhance()// {        m_fWork=720*576; fHisto[0]/=m_fWork;               for ( mi=1;mi<256;mi++ )//灰度直方图频率        {               fHisto[mi]/=m_fWork;               fHisto[mi]+=fHisto[mi-1];        }               for ( mi=0;mi<256;mi++ )//计算新的灰度级        {               m_fWork=fHisto[mi];               m_fWork*=255;               lut[mi]=(unsigned char)m_fWork;//这就是新的灰度级        }        for ( mi=0;mi<256;mi++ )//灰度直方图数组清0               fHisto[mi]=0.0f; }   实验5.23 视频图像处理-中值滤波 中值滤波算法实质是一种图像噪声的抑制。该系统实现中值滤波算法速度极慢。   实验5.24 视频图像处理-边缘检测(Sobel算子) Sobel算子实质是图像的锐化处理,主要目的是突出图像中的细节或者增强被模糊了的细节。        但是对这个算法程序实现不是很明白。        for ( mi=0;mi        {               x3=(*pImg1); x6=(*pImg2); x9=(*pImg3);               m_nWork1=x7+x8+x8-x2-x2-x3;               m_nWork2=x3+x6+x6-x4-x4-x7;                             if ( m_nWork1                      m_nWork1=m_nWork2;                             m_nWork2=m_nWork1+x9-x1;                             if ( m_nWork2>255 )    m_nWork2=255;               else if ( m_nWork2<0 )  m_nWork2=0;                             nMemTemp[mi+180]=m_nWork2;                             x1=x2; x2=x3;               x4=x5; x5=x6;               x7=x8; x8=x9;        }   实验5.25 视频图像处理-傅立叶变换        对傅立叶变换的知识比较空白。压根没看懂~~~
 
实验5.26 视频图像处理- {MOD}彩空间变换 程序注释: void ICETEKDM642PCIYUVRGB() {        int i,j;        int r,g,b,y,u,v;        unsigned char *py,*pu,*pv,*pr,*pg,*pb;               py=m_dbFrameY; pu=m_dbFrameU; pv=m_dbFrameV;        pr=m_dbTargetImageR; pg=m_dbTargetImageG; pb=m_dbTargetImageB;        for ( i=0;i        {                for ( j=0;j               {                      u=(*pu); v=(*pv); y=(*py);                      u-=128; v-=128;                      r=y+1.402*u;                      g=y-0.34414*u-0.71414*v;                      b=y+1.772*v;                      if ( r>255 )     r=255;                      else if ( r<0 )  r=0;                      if ( g>255 )    g=255;                      else if ( g<0 )  g=0;                      if ( b>255 )    b=255;                      else if ( b<0 )  b=0;                                           (*pr)=r; pr++;                      (*pg)=g; pg++;                      (*pb)=b; pb++;                      py++; y=(*py);                      r=y+1.402*u;                      g=y-0.34414*u-0.71414*v;                      b=y+1.772*v;                      if ( r>255 )     r=255;                      else if ( r<0 )  r=0;                      if ( g>255 )    g=255;                      else if ( g<0 )  g=0;                      if ( b>255 )    b=255;                      else if ( b<0 )  b=0;                                           (*pr)=r; pr++;                      (*pg)=g; pg++;                      (*pb)=b; pb++;                      py++; pu++; pv++;               }     } } ////在计算机中,用RGB方式描述一个像素需要R、G、B共3个字节。而用YUV方式描述,则对于每2个像素,Y用2个字节,U取相同的值,用一个字节,V取相同的值, ////用一个字节,平均每个像素2个字节。理解了这一点,对于上面的程序就理解了~~~