DSPRelated.com
Forums

external ADC on McBSP

Started by Sven Jaborek February 23, 2006
Hello McBSP'lers

i need to sample a signal with 150khz bandwith, i found ad7663 to do the
job.
I am running the ADC in a serial master mode, with read after convert.

I have three signals connected to the McBSP
ADC,sdout -> DR1
ADC,sclk -> RCLK
ADC,sync -> FSR1

If i look at this signals on the scope its like this:

SCLK  |__C C C C C C C C C C C C C C C C________________C C C...

SYNC  |__###############################________________####...

SDOUT |__X X X X X X X X X X X X X X X X________________X X X...

hmm, doesnt look perfect.
there are 16 clock ticks matching a bit on sdout, no delay
there is a sync signal high, as long as bits are send.

Then there is the conv. delay until, and the next 16 bit are pushed out.
Pretty simple system.

I cant find a working configuration for my McBSP since 2 Days. Iam
almost a
beginner with DSPs and TI Stuff, so any idea or suggestion is
appreciated.

Here is the test-code, derived from the pingpong example:

#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>
#include <stdlib.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"

/* Function prototypes */
void initIrq(void);
void initMcbsp(void);
void initEdma(void);
void processBuffer(void);
void edmaHwi(void);                                    

// trace object connection
#ifdef _6x_
extern far LOG_Obj trace;
#else
extern LOG_Obj trace;
#endif
	#include <stdio.h> 

/* Constants for the buffered ping-pong transfer */
#define BUFFSIZE (1280)
#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.
 */

/*Allocate buffer in external RAM, too big for internal memory*/
#pragma DATA_SECTION ("SDRAM");
Int16 gBufferRcvPing[BUFFSIZE];  // Receive PING buffer
#pragma DATA_SECTION ("SDRAM");
Int16 gBufferRcvPong[BUFFSIZE];  // Receive PONG buffer

/*EDMA_Handle hEdmaXmt;         
EDMA_Handle hEdmaReloadXmtPing;
EDMA_Handle hEdmaReloadXmtPong;*/
EDMA_Handle hEdmaRcv;
EDMA_Handle hEdmaReloadRcvPing;
EDMA_Handle hEdmaReloadRcvPong;

MCBSP_Handle hMcbsp1;
                        
Int16 gRcvChan;
	/*
 *  EDMA Config data structure 
 */
  
/* 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*/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 mcbspCfg_adc = {
        MCBSP_FMKS(SPCR, FREE, NO)              |
        MCBSP_FMKS(SPCR, SOFT, NO)              |
        MCBSP_FMKS(SPCR, FRST, NO)              |
        MCBSP_FMKS(SPCR, GRST, NO)              |
        MCBSP_FMKS(SPCR, XINTM, FRM)        	| /*XRDY|EOS|FRM|XSYNCERR*/
        MCBSP_FMKS(SPCR, XSYNCERR, NO)          |
        MCBSP_FMKS(SPCR, XRST, YES)             |
        MCBSP_FMKS(SPCR, DLB, OFF)              |
        MCBSP_FMKS(SPCR, RJUST, RZF)            | /*RZF|RSE|LZF*/
        MCBSP_FMKS(SPCR, CLKSTP, DISABLE)       | /*DISABLE|NODELAY|
DELAY*/
        MCBSP_FMKS(SPCR, DXENA, OFF)            |
        MCBSP_FMKS(SPCR, RINTM, FRM)           	| /*RRDY|EOS|FRM|
XSYNCERR */
        MCBSP_FMKS(SPCR, RSYNCERR, NO),          /*YES|NO*/
        
        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)              | /*YES/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, YES)               |
        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, FREE)        	| /*FREE|SYNC */
        MCBSP_FMKS(SRGR, CLKSP, RISING)        | /*RISING|FALLING*/
        MCBSP_FMKS(SRGR, CLKSM, CLKS)        	| /*CLKS|INTERNAL*/
        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, DEFAULT)         |
        MCBSP_FMKS(PCR, RIOEN, DEFAULT)         |
        MCBSP_FMKS(PCR, FSXM, DEFAULT)          |
        MCBSP_FMKS(PCR, FSRM, EXTERNAL)         |
        MCBSP_FMKS(PCR, CLKXM, DEFAULT)         |
        MCBSP_FMKS(PCR, CLKRM, INPUT)           |
        MCBSP_FMKS(PCR, CLKSSTAT, DEFAULT)      |
        MCBSP_FMKS(PCR, DXSTAT, DEFAULT)        |
        MCBSP_FMKS(PCR, FSXP, DEFAULT)          |
        MCBSP_FMKS(PCR, FSRP, ACTIVEHIGH)       |  /*ACTIVEHIGH|
ACTIVElow*/
        MCBSP_FMKS(PCR, CLKXP, DEFAULT)         |
        MCBSP_FMKS(PCR, CLKRP, RISING)
};
              
/* --------------------------- main() function
-------------------------- */
/*
 *  main() - The main user task.  Performs application initialization
and
 *           starts the data transfer.
 */
int main()
{
	short imux=0x00;
    /* Initialize Board Support Library */
    DSK6713_init();

    /* Initialize LEDs and DIP switches */
    DSK6713_LED_init();
    DSK6713_DIP_init();
	/* make sure LED 0 and 1 is off */    
	DSK6713_LED_off(0);
	DSK6713_LED_off(1);
    
    /*
     * when the software is started, check DIP Switches 0 and 1
     * Show their Position on LED 0 and 1
     * DIP Switch 0 represents the CPLD MUX Register f McBSP 0
     * DIP Switch 1 represents the CPLD MUX Register f McBSP 1
     * If the switch is pulled down MUX connects McBSP to AIC,
     * otherwise it connects the McBSP Port to the J3 connector
     * 
     */
    if(DSK6713_DIP_get(0) == 1){
		imux+=0x01;
		DSK6713_LED_on(0);    	
    }
    if(DSK6713_DIP_get(1) == 1){
		imux+=0x02;
		DSK6713_LED_on(1);
	}    
    DSK6713_rset(DSK6713_MISC, imux);
    LOG_printf(&trace, "MUX set");
    
    initMcbsp();               // Initialize McBSP1
    IRQ_globalDisable();       // Disable global interrupts during setup
    initEdma();                // Initialize the EDMA controller
    initIrq();                 // Initialize interrupts
    IRQ_globalEnable();        // Re-enable global interrupts
    LOG_printf(&trace, "main finished");    
}
	/* ------------------------Helper Functions
----------------------------- */
	/*
 *  initMcbsp() - Initialize the McBSP for codec data transfers using
the
 *                configuration define at the top of this file.
 */
void initMcbsp()
{
    /* Open the McBSP */
    hMcbsp1 = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);

    /* Configure the codec */
    MCBSP_config(hMcbsp1, &mcbspCfg_adc);

    /* Start the McBSP running */
    MCBSP_start(hMcbsp1, MCBSP_RCV_START,
0x00003000);                      
  
    // no idea what 0x00003000 means, find it on dsprelated ;-)
}
	/*
 *  initIrq() - Initialize and enable the DMA receive interrupt using
the
CSL.
 *              The interrupt service routine for this interrupt is
edmaHwi.
 */
void initIrq(void)
{
    /* Enable EDMA interrupts to the CPU */
    IRQ_clear(IRQ_EVT_EDMAINT);    // Clear any pending EDMA interrupts
    IRQ_enable(IRQ_EVT_EDMAINT);   // Enable EDMA interrupt
}
	/*
 *  initEdma() - Initialize the DMA controller.  Use linked transfers
to 
 *               automatically transition from ping to pong and
visa-versa.
 */
void initEdma(void)
{  
    /* Configure receive channel */
    hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET);  // get
hEdmaRcv
handle and reset channel
    hEdmaReloadRcvPing = EDMA_allocTable(-1);               // get
hEdmaReloadRcvPing handle
    hEdmaReloadRcvPong = EDMA_allocTable(-1);               // get
hEdmaReloadRcvPong handle
	        
    gEdmaConfigRcv.src = MCBSP_getRcvAddr(hMcbsp1);	// and the
desination
address to McBSP1 DXR
        
    gRcvChan = EDMA_intAlloc(-1);                           // get an
open
TCC
    gEdmaConfigRcv.opt |= EDMA_FMK(OPT,TCC,gRcvChan);       // set TCC
to
gRcvChan

    EDMA_config(hEdmaRcv, &gEdmaConfigRcv);                 // then
configure the registers
    EDMA_config(hEdmaReloadRcvPing, &gEdmaConfigRcv);       // and the
reload for Ping
    
    gEdmaConfigRcv.dst = EDMA_DST_OF(gBufferRcvPong);       // change
the
structure to have a destination of Pong
    EDMA_config(hEdmaReloadRcvPong, &gEdmaConfigRcv);       // and
configure
the reload for Pong
    
    EDMA_link(hEdmaRcv,hEdmaReloadRcvPong);                 // link the
regs
to Pong
    EDMA_link(hEdmaReloadRcvPong,hEdmaReloadRcvPing);       // link Pong
to
Ping
    EDMA_link(hEdmaReloadRcvPing,hEdmaReloadRcvPong);       // and link
Ping
to Pong
        
    /* Enable interrupts in the EDMA controller */ 
    EDMA_intClear(gRcvChan);                                // clear any
possible spurious interrupts
                               
    EDMA_intEnable(gRcvChan);                               // enable
EDMA
interrupts (CIER)
                                                                     
    EDMA_enableChannel(hEdmaRcv);                           // enable
EDMA
channel
                                                
}

/* ---------------------- Interrupt Service Routines
-------------------- */

/*
 *  edmaHwi() - Interrupt service routine for the DMA transfer.  It is
 *              triggered when a complete DMA receive frame has been
 *              transferred.   The edmaHwi ISR is inserted into the
interrupt
 *              vector table at compile time through a setting in the
DSP/BIOS
 *              configuration under Scheduling --> HWI --> HWI_INT8. 
edmaHwi
 *              uses the DSP/BIOS Dispatcher to save register state and
make
 *              sure the ISR co-exists with other DSP/BIOS functions.
 */
void edmaHwi(void)
{
    static Uint32 pingOrPong = PING;  // Ping-pong state variable
    static Int16 rcvdone = 0;
    
    if (EDMA_intTest(gRcvChan))
    {                           
        EDMA_intClear(gRcvChan);
        rcvdone = 1;
    }

    if (rcvdone)
    {
        if (pingOrPong==PING)
        {
            SWI_or(&processBufferSwi, PING);
            pingOrPong = PONG;
        } else
        {
            SWI_or(&processBufferSwi, PONG);
            pingOrPong = PING;
        }
        rcvdone = 0; 
    }
}
	/* ------------------------------- Threads
------------------------------ */

/*
 *  processBuffer() - Process audio data once it has been
received.         
  
 */
void processBuffer(void)
{
    Uint32 pingPong;
    //LOG_printf(&trace, "Int");
    
    /* Get contents of mailbox posted by edmaHwi */
    pingPong =  SWI_getmbox();

    /* receive, could process audio here */
    if (pingPong == PING) { 
        /* Toggle LED #3 as a visual cue */
        DSK6713_LED_toggle(3);
                             
    } else {
        /* Toggle LED #2 as a visual cue */
        DSK6713_LED_toggle(2);                       
    }
}