www.pudn.com > sdr.rar > DSK_APP.C


/**********************************************************/ 
/*                                                        */ 
/*     中频软件无线电接收机子系统数字信号处理部分主程序   */ 
/*                                                        */ 
/*                   dsk_app.c                            */ 
/*                                                        */ 
/**********************************************************/ 
 
#include "dsk_appcfg.h" 
 
/*   
 * 这些包含文件支持程序中使用的BIOS和CSL模块接口  
*/ 
#include  
#include  
#include  
#include  
#include  
#include   
#include  
#include  
 
 
/*   
 * 该包含文件引入数学函数fastrts67x.lib,其中包括乘方,开方, 
 * 正、余弦,反正切,对数运算,指数运算等汇编函数 
*/ 
 
#include  
 
/* 
 * TMS320C6713 开发板支持库分为几个模块,每个模块都有各自的包含文件 
 * 每一个应用程序要使用开发板支持库就必须包含头文件dsk6713.h  
 *  本应用程序中还使用了DIP, LED模块 
 */ 
#include "dsk6713.h" 
#include "dsk6713_led.h" 
#include "dsk6713_dip.h" 
 
/* 函数原型 */ 
void initIrq(void);//初始化中断 
void initMcbsp(void);//初始化Mcbsp 
void initEdma(void);//初始化Edma 
void demodulateAM(INT16 *inBuf,Uint32 *outBuf,INT16 Length)//AM信号解调程序 
void processBuffer(void);//处理缓冲区数据 
void edmaHwi(void);//Edma中断线程 
 
 
/* 为ping-pong缓冲传输定义常量 */ 
#define BUFFSIZE 1024 
#define PING 0 
#define PONG 1 
 
/* 
 * 数据缓冲区声名  
 * 程序中使用四个BUFFSIZE大小的逻辑缓冲区 
 * 一个PING接收缓冲区,一个PONG接收缓冲区 
 * 一个存储PING缓冲区解调后数据,一个存储PONG缓冲区解调后数据 
  
 */ 
Int16 gBufferRcvPing[BUFFSIZE];  // PING接收缓冲区 
Int16 gBufferRcvPong[BUFFSIZE];  // PONG接收缓冲区 
 
Uint32 gBufferXmtPing[BUFFSIZE/2];  // 存储PING缓冲区解调后数据 
Uint32 gBufferXmtPong[BUFFSIZE/2];  // 存储PONG缓冲区解调后数据 
 
 
EDMA_Handle hEdmaRcv;//EDMA句柄 
EDMA_Handle hEdmaReloadRcvPing;//EDMA接收PING缓冲区数据自加载句柄 
EDMA_Handle hEdmaReloadRcvPong;//EDMA接收PONG缓冲区数据自加载句柄 
 
MCBSP_Handle hMcbsp1;                 // McBSP1 句柄 
                     
Int16 gRcvChan;                       // EDMA传输结束代码 
 
 
/* 
 *  EDMA 配置数据结构  
 */ 
 /*接收部分EDMA 配置 */ 
EDMA_Config gEdmaConfigRcv = {   
    EDMA_FMKS(OPT, PRI, HIGH)          |  // 优先级高 
    EDMA_FMKS(OPT, ESIZE, 16BIT)       |  // 数据单元大小16bit 
    EDMA_FMKS(OPT, 2DS, NO)            |  // 源地址非两纬传输 
    EDMA_FMKS(OPT, SUM, NONE)          |  // 源地址不变 
    EDMA_FMKS(OPT, 2DD, NO)            |  // 目的地址非两纬传输 
    EDMA_FMKS(OPT, DUM, INC)           |  // 目的地址自动增加 
    EDMA_FMKS(OPT, TCINT, YES)         |  // 使能EDMA中断 
    EDMA_FMKS(OPT, TCC, OF(0))         |  // 传输结束代码 
    EDMA_FMKS(OPT, LINK, YES)          |  // 使能链接地址 
    EDMA_FMKS(OPT, FS, NO),               // 不使用帧同步 
     
    EDMA_FMKS(SRC, SRC, OF(0)),           // 源地址 
  
    EDMA_FMK (CNT, FRMCNT, NULL)       |  // 帧计数  
    EDMA_FMK (CNT, ELECNT, BUFFSIZE),     // 数据单元计数 
     
    (Uint32)&gBufferRcvPing,              // 目的地址 
           
    EDMA_FMKS(IDX, FRMIDX, DEFAULT)    |  // 帧索引值 
    EDMA_FMKS(IDX, ELEIDX, DEFAULT),      // 数据单元索引值 
 
    EDMA_FMK (RLD, ELERLD, NULL)       |  // 重新加载数据单元 
    EDMA_FMK (RLD, LINK, NULL)            // 重新加载链接地址 
}; 
 
/* McBSP 配置数据结构 */ 
static MCBSP_Config mcbspCfg1 = { 
/* 配置McBSP 串行口控制寄存器 */ 
        MCBSP_FMKS(SPCR, FREE, NO)              |//禁止串行时钟自由运行模式 
        MCBSP_FMKS(SPCR, SOFT, NO)              |//仿真停止,串行口时钟立即停止 
        MCBSP_FMKS(SPCR, FRST, YES)             |//帧同步发生器复位 
        MCBSP_FMKS(SPCR, GRST, YES)             |//采样率发生器复位 
        MCBSP_FMKS(SPCR, XINTM, XRDY)           |//传输中断由事件XRDY驱动 
        MCBSP_FMKS(SPCR, XSYNCERR, NO)          |//无帧同步发送错误 
        MCBSP_FMKS(SPCR, XRST, YES)             |//使能串行口发送 
        MCBSP_FMKS(SPCR, DLB, OFF)              |//禁止数字链路回馈模式 
        MCBSP_FMKS(SPCR, RJUST, RZF)            |//接收数据无符号扩展,右对其,高位补0 
        MCBSP_FMKS(SPCR, CLKSTP, DISABLE)       |//禁止时钟停止模式 
        MCBSP_FMKS(SPCR, DXENA, OFF)            |//禁止DX管脚使能 
        MCBSP_FMKS(SPCR, RINTM, RRDY)           |//接收中断右事件RRDY驱动 
        MCBSP_FMKS(SPCR, RSYNCERR, NO)          |//无帧同步接收错误 
        MCBSP_FMKS(SPCR, RRST, YES),             //使能串行口接收 
         
/* 配置McBSP接收控制寄存器 */ 
        MCBSP_FMKS(RCR, RPHASE, SINGLE)         |//接收一相 
        MCBSP_FMKS(RCR, RFRLEN2, DEFAULT)       |//第二相接收帧长度 
        MCBSP_FMKS(RCR, RWDLEN2, DEFAULT)       |//第二相接收帧中数据单元长度 
        MCBSP_FMKS(RCR, RCOMPAND, MSB)          |//接收时无压缩扩展,由最高位开始传输 
        MCBSP_FMKS(RCR, RFIG, YES)              |//忽略突发接收帧同步信号 
        MCBSP_FMKS(RCR, RDATDLY, 2BIT)          |//接收时数据延迟2位 
        MCBSP_FMKS(RCR, RFRLEN1, OF(1))         |//第一相接收帧长度每相两个字长 
        MCBSP_FMKS(RCR, RWDLEN1, 16BIT)         |//第一相接收单元长度16bit 
        MCBSP_FMKS(RCR, RWDREVRS, DISABLE),      //禁止32bit接收单元位颠倒 
         
/* 配置McBSP 发送控制寄存器 */ 
        MCBSP_FMKS(XCR, XPHASE, DEFAULT)          | 
        MCBSP_FMKS(XCR, XFRLEN2, DEFAULT)         | 
        MCBSP_FMKS(XCR, XWDLEN2, DEFAULT)         | 
        MCBSP_FMKS(XCR, XCOMPAND,DEFAULT)         | 
        MCBSP_FMKS(XCR, XFIG, DEFAULT)            | 
        MCBSP_FMKS(XCR, XDATDLY, DEFAULT)         | 
        MCBSP_FMKS(XCR, XFRLEN1, DEFAULT)         | 
        MCBSP_FMKS(XCR, XWDLEN1, DEFAULT)         | 
        MCBSP_FMKS(XCR, XWDREVRS, DEFAULT),       
         
/* 配置McBSP 采样率产生寄存器 */         
        MCBSP_FMKS(SRGR, GSYNC, DEFAULT)        | 
        MCBSP_FMKS(SRGR, CLKSP, DEFAULT)        | 
        MCBSP_FMKS(SRGR, CLKSM, DEFAULT)        | 
        MCBSP_FMKS(SRGR, FSGM, DEFAULT)         | 
        MCBSP_FMKS(SRGR, FPER, DEFAULT)         | 
        MCBSP_FMKS(SRGR, FWID, DEFAULT)         | 
        MCBSP_FMKS(SRGR, CLKGDV, DEFAULT),        
         
/* 配置McBSP 多通道控制寄存器 */ 
        MCBSP_MCR_DEFAULT,  
           
/* 配置McBSP 接收通道使能寄存器 */                             
        MCBSP_RCER_DEFAULT,  
           
/* 配置McBSP 发送通道使能寄存器 */                            
        MCBSP_XCER_DEFAULT,                       
         
/* 配置McBSP引脚控制寄存器 */ 
        MCBSP_FMKS(PCR, XIOEN, SP)              |//串行发送模式 
        MCBSP_FMKS(PCR, RIOEN, SP)              |//串行接收模式 
        MCBSP_FMKS(PCR, FSXM, INTERNAL)         |//内部帧同步发送 
        MCBSP_FMKS(PCR, FSRM, EXTERNAL)         |//外部帧同步接收 
        MCBSP_FMKS(PCR, CLKXM, OUTPUT)          |//CLKX输出发送时钟 
        MCBSP_FMKS(PCR, CLKRM, INPUT)           |//CLKR输入接收时钟 
        MCBSP_FMKS(PCR, CLKSSTAT, DEFAULT)      |//CLKS管脚状态 
        MCBSP_FMKS(PCR, DXSTAT, DEFAULT)        |//DX管脚状态 
        MCBSP_FMKS(PCR, FSXP, ACTIVEHIGH)       |//发送帧同步信号高电平有效 
        MCBSP_FMKS(PCR, FSRP, ACTIVEHIGH)       |//接收帧同步信号高电平有效 
        MCBSP_FMKS(PCR, CLKXP, RISING)          |//发送时钟上升沿触发数据发送 
        MCBSP_FMKS(PCR, CLKRP, FALLING)          //接收时钟下降沿触发数据接收 
}; 
 
 
/* --------------------------- main() 函数 ------------------------ */ 
/* 
 *   main()函数 - 应用程序主线程 
 *  应用程序初始化,启动McBSP传输   
 */ 
void main() 
{ 
    /* 初始化开发板支持库 */ 
    DSK6713_init(); 
 
    /* 初始化 LEDs指示灯 和 DIP开关 */ 
    DSK6713_LED_init(); 
    DSK6713_DIP_init(); 
     
    /* 清除缓冲区 */ 
    memset((void *)gBufferXmtPing, 0, BUFFSIZE * 4 * 2); 
     
    initMcbsp();               // 初始化 McBSP1 接收AD6620串行输出的数据 
 
    IRQ_globalDisable();       // 初始化设置时禁止全局中断 
 
    initEdma();                // 初始化 EDMA 控制器 
    initIrq();                 // 初始化中断 
     
    DSK6713_rset(6,2);         // 设置TMS320C6713 McBSP1连接开发板上外部扩展端口     
     
    IRQ_globalEnable();        // 重新使能全局中断 
    
} 
 
 
/* ------------------------函数代码 ----------------------------- */  
 
/* 
 *               initMcbsp()  
 *   使用前面定义的McBSP结构配置初始化McBSP   
 */ 
void initMcbsp() 
{ 
    /* 打开McBSP1*/ 
     hMcbsp1 = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET); 
     
    /* 配置McBSP1 */ 
    MCBSP_config(hMcbsp1, &mcbspCfg1); 
    
     /* 启动McBSP */ 
    MCBSP_start(hMcbsp1, MCBSP_XMIT_START | MCBSP_RCV_START | 
        MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC, 220); 
    MCBSP_start(hMcbsp0, MCBSP_XMIT_START | MCBSP_RCV_START | 
        MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC, 220); 
} 
 
 
/* 
 *             initIrq()  
 *  使用芯片支持库初始化、使能DMA接收中断     
 *        该中断的中断服务例程是edmaHwi(). 
 */ 
void initIrq(void) 
{ 
    /* CPU使能 EDMA 中断  */ 
    IRQ_clear(IRQ_EVT_EDMAINT);    // 清除挂起的 EDMA 中断 
    IRQ_enable(IRQ_EVT_EDMAINT);   // 使能EDMA中断 
} 
 
 
/* 
 *                     initEdma()   
 *                   初始化EDMA控制器   
 *  使用连接地址传输,自动在PING、PONG缓冲区间交互传输 
 */ 
void initEdma(void) 
{ 
    /* 配置接收通道 */ 
    hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET);  // 获得 hEdmaRcv 句柄、复位通道  
    hEdmaReloadRcvPing = EDMA_allocTable(-1);               // 获得 hEdmaReloadRcvPing 句柄 
    hEdmaReloadRcvPong = EDMA_allocTable(-1);               // 获得 hEdmaReloadRcvPong 句柄 
     
    gEdmaConfigRcv.src = MCBSP_getRcvAddr(hMcbsp1);         // 设置EDMA传输的源地址是 McBSP1 数据接收寄存器 
         
    gRcvChan = EDMA_intAlloc(-1);                           // 获得一个传输结束代码 
    gEdmaConfigRcv.opt |= EDMA_FMK(OPT,TCC,gRcvChan);       // 设置传输结束代码给 gRcvChan 
 
    EDMA_config(hEdmaRcv, &gEdmaConfigRcv);                 // 配置寄存器 
    EDMA_config(hEdmaReloadRcvPing, &gEdmaConfigRcv);       // Ping重新加载 
     
    gEdmaConfigRcv.dst = EDMA_DST_OF(gBufferRcvPong);       //改变EDMA配置的目的地址为Pong 
    EDMA_config(hEdmaReloadRcvPong, &gEdmaConfigRcv);       // 重新加载Pong 
     
    EDMA_link(hEdmaRcv,hEdmaReloadRcvPong);                 // 连接寄存器 Pong 
    EDMA_link(hEdmaReloadRcvPong,hEdmaReloadRcvPing);       // 连接地址 Pong 到 Ping 
    EDMA_link(hEdmaReloadRcvPing,hEdmaReloadRcvPong);       // 连接地址 Ping 到 Pong 
         
    /* EDMA 控制器使能中断  */ 
   
    EDMA_intClear(gRcvChan);                                // 清除任何可能的伪中断 
 
    
    EDMA_intEnable(gRcvChan);                               // 使能EDMA 中断 (CIER) 
 
    EDMA_enableChannel(hEdmaRcv);                           // 使能 EDMA 通道 
     
    /* 通过Mcbsp写的伪操作产生第一个  McBSP 传输事件 */ 
    MCBSP_write(hMcbsp1, 0); 
 
} 
 
 
 
/* ---------------------- 中断服务例程 ----------------------- */ 
 
/* 
 *                   edmaHwi()  
 *             EDMA 传输中断服务例程 
 *      当一个完整的EDMA接收帧传输结束时触发  
  *               通过在DSP/BIOS中配置 
 *             Scheduling --> HWI --> HWI_INT8.    
 *     在编译时edmaHwi()中断服务例程 插入中断向量表 
 *        edmaHwi() 使用 DSP/BIOS Dispatcher发报机  
 *  保存寄存器状态、确定中断服务例程和其它DSP/BIOS 函数并存 
 */ 
void edmaHwi(void) 
{ 
    static Int16 rcvdone = 0;//定义局部变量rcvdone 
    static Uint32 pingOrPong = PING;  // 定义局部变量pingOrPong,指示PING、PONG缓冲区 
     
         
    if (EDMA_intTest(gRcvChan))//通道gRcvChan接收传输完成中断 
    { 
        EDMA_intClear(gRcvChan);//清楚通道gRcvChan传输完成标志 
        rcvdone = 1;//传输完成标志变量置1 
    } 
         
    /* 如果传输结束, 将处理软件中断 processBufferSwi  */ 
    if (rcvdone)//传输完成 
    { 
        if (pingOrPong==PING)//当前是PING缓冲区 
        { 
            SWI_or(&processBufferSwi, PING);//启动软件中断processBufferSwi 
                                            //向mailbox 发送PING=0 
            pingOrPong = PONG;//缓冲区状态赋值PONG 
        } else 
        { 
            SWI_or(&processBufferSwi, PONG);//启动软件中断processBufferSwi 
                                            //向mailbox 发送PONG=1 
            pingOrPong = PING;//缓冲区状态赋值PING 
        } 
        rcvdone = 0;//传输完成标志变量清零 
    } 
} 
 
 
/* ------------------------------- 线程 ------------------------------ */ 
/* 
 *            demodulateAM()  
 *            AM信号解调程序 
 * 将一个缓冲区(inBuf)中的数据(I、Q信号)解调算法处理 
 *            处理后数据存(outBuf) 
 */ 
 
/*   
 * AM解调程序 
 * 程序中调用了函数库fastrts67x.lib中  
 * 乘方汇编函数powsp(),开方汇编函数sqrtsp() 
*/ 
/* inBuf存取I、Q信号缓冲区,16位,缓冲区大小1024 */ 
/*outBuf存取解调后数据缓冲区,32位,缓冲区大小512*/ 
void demodulateAM(INT16 *inBuf,Uint32 *outBuf,INT16 Length) 
{ 
	INT16 i; 
	Uint32 TempBuf; 
	for(i=0;i<=Length;i+2) 
	{ 
		TempBuf=powsp(inBuf[i],2); 
		TempBuf=+powsp(inBuf[i+1],2); 
		*outBuf[i/2]=sqrtsp(TempBuf); 
	} 
} 
 
 
/* 
 *              processBuffer()  
 *       软件中断processBufferSwi的线程   
 *  处理接收缓冲区gBufferRcvPing、gBufferRcvPong数据           
 */ 
void processBuffer(void) 
{ 
    Uint32 pingPong; 
     
    /* 读取mailbox中由edmaHwi()中断发送的内容 */ 
    pingPong =  SWI_getmbox(); 
 
    /*处理接收缓冲区gBufferRcvPing、gBufferRcvPong数据  */ 
    if (pingPong == PING) //处理PING缓冲区中数据 
    	{ /* 指示灯LED #3 闪烁 */ 
        DSK6713_LED_toggle(3); 
         
        /* 处理PING 缓冲区数据 */ 
        demodulateAM(gBufferRcvPing, gBufferXmtPing, BUFFSIZE); 
    	}  
    else {//处理PONG缓冲区中数据 
        /* 指示灯LED #2 闪烁 */ 
        DSK6713_LED_toggle(2); 
         
        /* 处理POING 缓冲区数据 */ 
        demodulateAM(gBufferRcvPong, gBufferXmtPong, BUFFSIZE); 
    } 
} 
 
/* 
 *                     周期性线程blinkLED()  
 *   当DIP 开关 #0 按下时 ,指示灯LED #0每500毫秒闪亮一次 
 *                    该线程在DSP/BIOS中配置   
 *               Scheduling -->PRD --> PRD_blinkLed. 
 */ 
void blinkLED(void) 
{ 
    /* 如果DIP 开关 #0 按下,指示灯 LED #0闪亮 */ 
    if (!DSK6713_DIP_get(0)) 
        DSK6713_LED_toggle(0); 
} 
 
 
/* 
 *                      周期性线程load() 
 *   当DIP开关switch #1按下时,该线程仿真给225MHz 6713 20-25%虚负荷 
 *                    该线程在DSP/BIOS中配置  
 *                 Scheduling --> PRD-->PRD_load.  
 *                      该线程1毫秒执行一次 
 */ 
void load(void) 
{ 
    volatile Uint32 i;   
 
    /* 如果DIP 开关 #1 按下,CPU执行一个for循环 */ 
    if (!DSK6713_DIP_get(1)) 
        for (i = 0; i < 30000; i++); 
}