📄 dsk_app.c
字号:
/*
* Copyright 2003 by Spectrum Digital Incorporated.
* All rights reserved. Property of Spectrum Digital Incorporated.
*/
/*
* ======== dsk_app.c ========
*
* Version 1.00
*
* This example digitally processes audio data from the line input on the
* AIC23 codec and plays the result on the line output. It uses the McBSP
* and EDMA to efficiently handle the data transfer without intervention from
* the DSP.
*
* Data transfer
*
* Audio data is transferred back and forth from the codec through McBSP2,
* a bidirectional serial port. The EDMA is configured to take every 16-bit
* signed audio sample arriving on McBSP1 and store it in a buffer in memory
* until it can be processed. Once it has been processed, the EDMA
* controller sends the data back to McBSP1 for transmission.
*
* A second serial port, McBSP0 is used to control/configure the AIC23. The
* codec receives serial commands through McBSP0 that set configuration
* parameters such as volume, sample rate and data format.
*
* In addition to basic EDMA transfers, this example uses 2 special
* techniques to make audio processing more convenient and efficient:
*
* 1) Ping-pong data buffering in memory
* 2) Linked EDMA transfers
*
* Applications with single buffers for receive and transmit data are
* very tricky and timing dependent because new data constantly overwrites
* the data being transmitted. Ping-pong buffering is a technique where two
* buffers (referred to as the PING buffer and the PONG buffer) are used for
* a data transfer instead of only one. The EDMA is configured to fill the
* PING buffer first, then the PONG buffer. While the PONG buffer is being
* filled, the PING buffer can be processed with the knowledge that the
* current EDMA transfer won't overwrite it. This example uses ping-pong
* buffers on both transmit and receive ends for a total of four buffers.
*
* The EDMA controller must be configured slightly differently for each
* buffer. When a buffer is filled, the EDMA controller generates an
* interrupt. The interrupt handler must reload the configuration
* for the next buffer before the next audio sample arrives. An EDMA
* feature called linked transfers is used to make this event less time
* critical. Each configuration is created in advance and the EDMA
* controller automatically links to the next configuration when the
* current configuration is finished. An interrupt is still generated,
* but it serves only to signal the DSP that it can process the data.
* The only time constraint is that all the audio data must be processed
* before the the active buffer fills up, which is much longer than the
* time between audio samples. It is much easier to satisfy real-time
* constraints with this implementation.
*
* Program flow
*
* When the program is run, the individual DSP/BIOS modules are initialized
* as configured in dsk_app.cdb with the DSP/BIOS configuration tool. The
* main() function is then called as the main user thread. In this example
* main() performs application initialization and starts the EDMA data
* transfers. When main exits, control passes back entirely to DSP/BIOS
* which services any interrupts or threads on an as-needed basis.
*
* The edmaHwi() interrupt service routine is called when a buffer has been
* filled. It contains a state variable named pingOrPong that indicates
* whether the buffer is a PING or PONG buffer. dmaHwi switches the buffer
* state to the opposite buffer and calls the SWI thread processBuffer to
* process the audio data.
*
* Other Functions
*
* The example includes a few other functions that are executed in the
* background as examples of the multitasking that DSP/BIOS is capable of:
*
* 1) blinkLED() toggles LED #0 every 500ms if DIP switch #0 is depressed.
* It is a periodic thread with a period of 500 ticks.
*
* 2) load() simulates a 20-25% dummy load if DIP switch #1 is depressed.
* It represents other computation that may need to be done. It is a
* periodic thread with a period of 10ms.
*
* Please see the 6713 DSK help file under Software/Examples for more
* detailed information on this example.
*/
/*
* DSP/BIOS is configured using the DSP/BIOS configuration tool. Settings
* for this example are stored in a configuration file called dsk_app.cdb.
* At compile time, Code Composer will auto-generate DSP/BIOS related files
* based on these settings. A header file called dsk_appcfg.h contains the
* results of the autogeneration and must be included for proper operation.
* The name of the file is taken from dsk_app.cdb and adding cfg.h.
*/
#include "dsk_appcfg.h"
/*
* These are include files that support interfaces to BIOS and CSL modules
* used by the program.
*/
#include <std.h>
#include <swi.h>
#include <log.h>
#include <c6x.h>
#include <csl.h>
#include <csl_edma.h>
#include <csl_irq.h>
#include <csl_mcbsp.h>
/*
* The 6713 DSK Board Support Library is divided into several modules, each
* of which has its own include file. The file dsk6713.h must be included
* in every program that uses the BSL. This example also uses the
* DIP, LED and AIC23 modules.
*/
#include "dsk6713.h"
#include "dsk6713_led.h"
#include "dsk6713_dip.h"
#include "aic23.h"
/* Function prototypes */
void initIrq(void);
void initMcbsp(void);
void initEdma(void);
void copyData(Int16 *inbuf, Int16 *outbuf, Int16 length);
void processBuffer(void);
void edmaHwi(void);
/* Constants for the buffered ping-pong transfer */
#define BUFFSIZE 1000
#define PING 0
#define PONG 1
/*
* Data buffer declarations - the program uses four logical buffers of size
* BUFFSIZE, one ping and one pong buffer on both receive and transmit sides.
*/
Int16 gBufferXmtPing[BUFFSIZE]; // Transmit PING buffer
Int16 gBufferXmtPong[BUFFSIZE]; // Transmit PONG buffer
Int16 gBufferRcvPing[BUFFSIZE]; // Receive PING buffer
Int16 gBufferRcvPong[BUFFSIZE]; // Receive PONG buffer
EDMA_Handle hEdmaXmt; // EDMA channel handles
EDMA_Handle hEdmaReloadXmtPing;
EDMA_Handle hEdmaReloadXmtPong;
EDMA_Handle hEdmaRcv;
EDMA_Handle hEdmaReloadRcvPing;
EDMA_Handle hEdmaReloadRcvPong;
MCBSP_Handle hMcbsp1; // McBSP1 (codec data) handle
Int16 gXmtChan; // TCC codes (see initEDMA())
Int16 gRcvChan;
/*
* EDMA Config data structure
*/
/* Transmit side EDMA configuration */
EDMA_Config gEdmaConfigXmt = {
EDMA_FMKS(OPT, PRI, HIGH) | // Priority
EDMA_FMKS(OPT, ESIZE, 16BIT) | // Element size
EDMA_FMKS(OPT, 2DS, NO) | // 2 dimensional source?
EDMA_FMKS(OPT, SUM, INC) | // Src update mode
EDMA_FMKS(OPT, 2DD, NO) | // 2 dimensional dest
EDMA_FMKS(OPT, DUM, NONE) | // Dest update mode
EDMA_FMKS(OPT, TCINT, YES) | // Cause EDMA interrupt?
EDMA_FMKS(OPT, TCC, OF(0)) | // Transfer complete code
EDMA_FMKS(OPT, LINK, YES) | // Enable link parameters?
EDMA_FMKS(OPT, FS, NO), // Use frame sync?
(Uint32)&gBufferXmtPing, // Src address
EDMA_FMK (CNT, FRMCNT, NULL) | // Frame count
EDMA_FMK (CNT, ELECNT, BUFFSIZE), // Element count
EDMA_FMKS(DST, DST, OF(0)), // Dest address
EDMA_FMKS(IDX, FRMIDX, DEFAULT) | // Frame index value
EDMA_FMKS(IDX, ELEIDX, DEFAULT), // Element index value
EDMA_FMK (RLD, ELERLD, NULL) | // Reload element
EDMA_FMK (RLD, LINK, NULL) // Reload link
};
/* Receive side EDMA configuration */
EDMA_Config gEdmaConfigRcv = {
EDMA_FMKS(OPT, PRI, HIGH) | // Priority
EDMA_FMKS(OPT, ESIZE, 16BIT) | // Element size
EDMA_FMKS(OPT, 2DS, NO) | // 2 dimensional source?
EDMA_FMKS(OPT, SUM, NONE) | // Src update mode
EDMA_FMKS(OPT, 2DD, NO) | // 2 dimensional dest
EDMA_FMKS(OPT, DUM, INC) | // Dest update mode
EDMA_FMKS(OPT, TCINT, YES) | // Cause EDMA interrupt?
EDMA_FMKS(OPT, TCC, OF(0)) | // Transfer complete code
EDMA_FMKS(OPT, LINK, YES) | // Enable link parameters?
EDMA_FMKS(OPT, FS, NO), // Use frame sync?
EDMA_FMKS(SRC, SRC, OF(0)), // Src address
EDMA_FMK (CNT, FRMCNT, NULL) | // Frame count
EDMA_FMK (CNT, ELECNT, BUFFSIZE), // Element count
(Uint32)&gBufferRcvPing, // Dest address
EDMA_FMKS(IDX, FRMIDX, DEFAULT) | // Frame index value
EDMA_FMKS(IDX, ELEIDX, DEFAULT), // Element index value
EDMA_FMK (RLD, ELERLD, NULL) | // Reload element
EDMA_FMK (RLD, LINK, NULL) // Reload link
};
/* McBSP codec data channel configuration */
static MCBSP_Config mcbspCfg1 = {
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) |
MCBSP_FMKS(SPCR, XSYNCERR, NO) |
MCBSP_FMKS(SPCR, XRST, YES) |
MCBSP_FMKS(SPCR, DLB, OFF) |
MCBSP_FMKS(SPCR, RJUST, RZF) |
MCBSP_FMKS(SPCR, CLKSTP, DISABLE) |
MCBSP_FMKS(SPCR, DXENA, OFF) |
MCBSP_FMKS(SPCR, RINTM, RRDY) |
MCBSP_FMKS(SPCR, RSYNCERR, NO) |
MCBSP_FMKS(SPCR, RRST, YES),
MCBSP_FMKS(RCR, RPHASE, SINGLE) |
MCBSP_FMKS(RCR, RFRLEN2, DEFAULT) |
MCBSP_FMKS(RCR, RWDLEN2, DEFAULT) |
MCBSP_FMKS(RCR, RCOMPAND, MSB) |
MCBSP_FMKS(RCR, RFIG, NO) |
MCBSP_FMKS(RCR, RDATDLY, 0BIT) |
MCBSP_FMKS(RCR, RFRLEN1, OF(1)) |
MCBSP_FMKS(RCR, RWDLEN1, 16BIT) |
MCBSP_FMKS(RCR, RWDREVRS, DISABLE),
MCBSP_FMKS(XCR, XPHASE, SINGLE) |
MCBSP_FMKS(XCR, XFRLEN2, DEFAULT) |
MCBSP_FMKS(XCR, XWDLEN2, DEFAULT) |
MCBSP_FMKS(XCR, XCOMPAND, MSB) |
MCBSP_FMKS(XCR, XFIG, NO) |
MCBSP_FMKS(XCR, XDATDLY, 0BIT) |
MCBSP_FMKS(XCR, XFRLEN1, OF(1)) |
MCBSP_FMKS(XCR, XWDLEN1, 16BIT) |
MCBSP_FMKS(XCR, XWDREVRS, DISABLE),
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_MCR_DEFAULT,
MCBSP_RCER_DEFAULT,
MCBSP_XCER_DEFAULT,
MCBSP_FMKS(PCR, XIOEN, SP) |
MCBSP_FMKS(PCR, RIOEN, SP) |
MCBSP_FMKS(PCR, FSXM, EXTERNAL) |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -