• AVR Freaks

Si3000 working through the DCI module with DMA

Author
rain
New Member
  • Total Posts : 29
  • Reward points : 0
  • Joined: 2006/08/17 23:29:44
  • Location: 0
  • Status: offline
2006/08/30 19:56:33 (permalink)
0

Si3000 working through the DCI module with DMA

HI,
 
May i know what is the different between the DCI module with DMA and SPI module? I'm currently doing a project on Speech with Digital Signal Processing, whereby i need to input some of speech signal, and do some processing to eliminate the noise or echo, and output to the speaker.
I am using dsPIC 33FJ 256 GP710 and Si3000. Any recommendation on the module that i should use and the related register?
 
Thanks in advance!
#1

12 Replies Related Threads

    jetcode
    Super Member
    • Total Posts : 886
    • Reward points : 0
    • Joined: 2004/06/19 09:45:59
    • Location: San Geronimo Valley
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/08/30 20:10:58 (permalink)
    0
    ORIGINAL: rain

    HI,

    May i know what is the different between the DCI module with DMA and SPI module? I'm currently doing a project on Speech with Digital Signal Processing, whereby i need to input some of speech signal, and do some processing to eliminate the noise or echo, and output to the speaker.
    I am using dsPIC 33FJ 256 GP710 and Si3000. Any recommendation on the module that i should use and the related register?

    Thanks in advance!

     
    You don't need DMA to operate the Si3000. You will need the DCI.
    #2
    Oznog
    Super Member
    • Total Posts : 1011
    • Reward points : 0
    • Joined: 2004/10/14 21:54:10
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/08/30 21:03:40 (permalink)
    0
    If you're doing any speech project, the Si3000 is definitely the way to go.

    The Si3000 can be connected either through one of the 2 Framed SPI modules OR the DCI module.  For either case, it is VERY beneficial to use the DMA controller (best part of the 33F series!) to read and write the registers without frequent processor interrupts.  This is especially true if you use the SPI module because the SPI module only buffers a single word (whereas the DCI buffers 4) so module-based interrupts would have to be serviced 4x more frequently than the DCI module would if you chose not to use the DMA controller.

    The important thing to know is that most examples of the Si3000 try to put it in Slave mode, which is a totally unnecessary train wreck of a setup.  You want to let the Si3000 generate the Frame Sync and dsPIC looks for it, it's crazy to mess with a frame counter in the DCI module to try to sync up with what the Si3000's frame counter is doing.
    post edited by Oznog - 2006/08/30 21:11:03
    #3
    rain
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2006/08/17 23:29:44
    • Location: 0
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/08/30 23:22:55 (permalink)
    0
    Hi,
     
    Thank you for all the replies. Appreciate it a lot.
    Now i'm running a sample code from the moetronix.com, however i found that some of the variable for example: DCI_BUFF_LEN_4,DCI_INT_ON, DCI_INT_PRI_6 and etc (all relates to the DCI) are not declared. * error after built *
     
    Are these from the library or we need to define ourself?
     
    Thanks a million for ur help.
    #4
    Oznog
    Super Member
    • Total Posts : 1011
    • Reward points : 0
    • Joined: 2004/10/14 21:54:10
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/08/31 11:15:26 (permalink)
    0
    Moe's code is one that puts the SI3K in Slave mode.  It's inappropriate.  Also very difficult to understand because SI3K's doc doesn't even describe its Slave mode in any useful degree of detail.  I did email SiLabs and they sent me some more data on Slave mode.

    The Si3000's mode is set a forced value on SDO (dsPIC's SDI) and SCLK on the first rising edge of MCLK after RESET goes low.

    void Timer1_Init( void )
    {
        //Designed for 40MIPS
        T2CON = 0;
        T2CONbits.TCKPS = 0;
        PR2=8;
         IEC0bits.T2IE = 0;
         IFS0bits.T2IF = 0;
        T2CONbits.TON = 1;
    }


    void resetSI3K(){
        unsigned long i;

        //We need to have SCK=0 & SDI (SI3K SDO)=1
        //On the "First rising edge of MCLK after RESET_N goes LOW
        //It is ok to force the value from the dsPIC rather than the
        //pullup/pulldown resistors in Si3K's doc

        TRIS_SI3K_SCK=1;  
        TRIS_SI3K_SDI=1;
        TRIS_SI3K_SDO=1;
        TRIS_SI3K_FS =1;

        TRIS_SI3K_RST_N    =0;    
        TRIS_SI3K_MCLK     =0;

        PIN_SI3K_SCK=0;
        PIN_SI3K_SDI=1;

        PIN_SI3K_MCLK=1;

        PIN_SI3K_RST_N=0; //Reset

        Nop();Nop();Nop();Nop();

        TRIS_SI3K_SCK=0;
        TRIS_SI3K_SDI=0;
        PIN_SI3K_SCK=0;
        PIN_SI3K_SDI=1;

        for(i=0;i<400000;++i){
            ClrWdt();
        }    

        //3.967MHz, 54.8% duty
        //MCLK should be hooked up to OC8
        Timer1_Init();
        OC8CON=0b110;
        OC8RS=5;

        for(i=0;i<400000;++i){
            ClrWdt();
        }    

        PIN_SI3K_RST_N=1;  

        TRIS_SI3K_SDI=1;
        TRIS_SI3K_SCK=1;
        TRIS_SI3K_SDO=0;
        PIN_SI3K_SDO=0;
    }


    void initDCI(){
        DCICON1= (0b00000101 << 8) | 0b10000000;
        DCICON2= (0b00000000 << 8) | 0b00001111; //Only one word buffer with DMA
        DCICON3= (0b00000000 << 8) | 0b00000000; //nothing
        TXBUF0=0x0000;
        RXBUF0=0x0000;
        _DCIIP=6;
        _DCIIF=0;
        _DCIIE=0; //If we use DMA do not use this interrupt
        _DCIEN=1;
    }
    post edited by Oznog - 2006/09/01 02:01:14
    #5
    Mocharz
    New Member
    • Total Posts : 4
    • Reward points : 0
    • Joined: 2006/08/31 22:27:54
    • Location: 0
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/08/31 22:33:56 (permalink)
    0
    I am trying to use this two devices too.
    My plan is to let dsPIC33F be the master and Si3000 be the slave.
    Frame synchronisation should be Si3000 be the master, isn't it?
     
    Do you think both lines SCLK and SDO should be pulled up to 10ohm or the suggested 50ohm.
    Previous experience is 10ohm for other microchips.
     
    Thanks
    #6
    Oznog
    Super Member
    • Total Posts : 1011
    • Reward points : 0
    • Joined: 2004/10/14 21:54:10
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/09/01 01:57:58 (permalink)
    0
    ORIGINAL: Mocharz\
    My plan is to let dsPIC33F be the master and Si3000 be the slave.
    Frame synchronisation should be Si3000 be the master, isn't it?

    Do you think both lines SCLK and SDO should be pulled up to 10ohm or the suggested 50ohm.
    Previous experience is 10ohm for other microchips.

    Thanks


    Yes let Si3000 generate the FS signal (Master Mode).  Si3000 documents two Master modes.  I was unable to get Mode 0- the Master mode where FS is a level- to work at all.  Mode 1 is the Master mode where FS makes a pulse and it works fine!  To select Mode 1 you need to pull SCLK LOW and pull Si3000's SDO (dsPIC's SDI) HIGH during the first rising edge of MCLK after reset is pulled low.  If your MCLK is free-running (like mine) I would say it's a good idea to be safe and retain these values during any other rising edges of MCLK while reset is low too.

    Do NOT bother using pullup resistors, they're completely unnecessary!  Just drive the levels you need with the PIC during reset, toggle the clock (or start your clock PWM), immediately release reset and tristate the SCLK and dsPIC SDI pin because these become Si3000 outputs (dsPIC inputs) once you release reset.

    Actually I made an error in the code I posted, I'm editing the post now so you may want to cut-and-paste it again.

    Also some of dsPICDem's code required you to use very specific hardware for the xtal/osc and it led to people assuming that this is necessary.  It's complete BS, really.  What happened is Microchip's code inexplicably hard-coded in the Si3000 initialization sequences in some places and with no way to change that it meant you could only xtal freq for the whole system, also inexplicable, they chose a very odd xtal for that requirement IIRC. 

    The truth is the Si3000 has a clock multiplier/divisor and can generate ANY sample rate from a very wide range of arbitrary MCLK frequencies.  Not to mention if you use the OCx PWM to generate the MCLK you can of course generate any Si3000 clock you want that way too.

    BTW, 10 ohm pullups?  What are you thinking??  There's no point to outrageously powerful pullups, in fact the dsPIC doesn't even have enough drive current to override that pullup resistance.  Did you mean 10k or something?
    post edited by Oznog - 2006/09/01 02:15:30
    #7
    Mocharz
    New Member
    • Total Posts : 4
    • Reward points : 0
    • Joined: 2006/08/31 22:27:54
    • Location: 0
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/09/03 23:19:42 (permalink)
    0
    Opps, sorry. It should be 10k ohm.
    The suggested value was 50k ohm though.
    #8
    rain
    New Member
    • Total Posts : 29
    • Reward points : 0
    • Joined: 2006/08/17 23:29:44
    • Location: 0
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/09/20 20:42:30 (permalink)
    0
    Hi,
     
    Just like wat Jetcode said, "You don't need DMA to operate the Si3000. You will need the DCI." in the previous post...
     
    If my application require continuous signal receive and transmit, while the processing of the signal(DSP) is carry on without interrupt, do i need DMA to store my data?
     
    Thanks
    #9
    Oznog
    Super Member
    • Total Posts : 1011
    • Reward points : 0
    • Joined: 2004/10/14 21:54:10
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2006/09/20 22:51:37 (permalink)
    0
    No, there is no specific requirement.  The 30F talks to the Si3000 just fine through the DCI, and the 33F has all the capabilities of the 30F.  The DCI module can buffer 4 frames by itself (however the SPI has only 1 I/O buffer), so DCI interrupts need only occur 2000 per sec for an Fs=8KHz.  If you have an ISR which needs 50 cycles to interrupt, save context, copy the data to a buffer, manage the pointer, save the context, and return, it's still only 0.1MIPs on a part capable of 40MIPs.  And 50 cycles is probably a fairly inefficient ISR coding.

    The savings are more significant when you're running at a lower MIPs,  a module without so much buffering,  more frequent interrupts, or you will be replacing several ISRs with several DMA channels.

    It may also be more important if you are doing some time-critical bit-banging operation that does not like to be interrupted. 
    post edited by Oznog - 2006/09/20 23:27:42
    #10
    seb_franke
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2007/04/12 04:29:59
    • Location: 0
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2007/07/02 02:43:04 (permalink)
    0
    I'm about to port my dsPIC30F6014 code to dsPIC33FJ128GP306 and experience problems with the Speech codec,
    the decoder seams to work but I get no framesdone.
    I think the DCI doesn't work correctly, because I get no dci interrupt.
    I've found that the interrupt flag was moved from IFS2 to IFS3, maybe there are also other changes ..
    Did someone use the SI3000 with DCI correctly with the "old" libs on a dsPIC33 ?
     
    I also get some warnings  ..  (paths shortend)

    Warning: object Com_lsp_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCAL
    Warning: object Com_lsp_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCBL
    Warning: object Com_lsp_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register CORCON
    Warning: object Com_lsp_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCAH
    Warning: object Com_math_approx_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register CORCON
    Warning: object Com_math_approx_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCAL
    Warning: object Com_math_approx_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCBL
    Warning: object Com_math_approx_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCBH
    Warning: object Com_filters_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register CORCON
    Warning: object Com_filters_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register MODCON
    Warning: object Com_filters_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register YMODSRT
    Warning: object Com_filters_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register YMODEND
    Warning: object Com_filters_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCBL
    Warning: object Com_filters_annex.o from library...\libspxdecoderlib.a was created for the 30F6014 and references register ACCBU
    Warning: object Com_filters_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCAL
    Warning: object Com_filters_annex.o from library ...\libspxdecoderlib.a was created for the 30F6014 and references register ACCAH


    post edited by seb_franke - 2007/07/02 07:30:56
    #11
    superlou
    New Member
    • Total Posts : 30
    • Reward points : 0
    • Joined: 2008/09/26 16:20:42
    • Location: 0
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2009/04/15 12:54:30 (permalink)
    0
    Hi everyone,

    I'm also trying to interface an Si3000 to a dsPIC33F over DCI (no DMA for now).  I have also used output compare from the DSP to generate the MCLK signal for CODEC at 4 MHz.  I am using the following code to initialize/reset the Si3000:


    void initSI3K()
    {
        // Wait until the frame is transmitted
        // This ensures the first primary and secondary frame use current data
        while (DCISTATbits.TMPTY == 0);
       
        // Write to PLL1 Divide N1 Register
        TXBUF0 = PLUS_ONE_WITH_SECONDARY;
        TXBUF1 = WRITE_PLL1_DIVIDE_N1 | PLL1_DIVIDE_N1_VAL;
       
        // Wait until the frame is transmitted
        while (DCISTATbits.TMPTY == 0);
       
        // Write to PLL1 MULTIPLY M1 Register
        TXBUF0=PLUS_ONE_WITH_SECONDARY;
        TXBUF1=WRITE_PLL1_MULTIPLY_M1 | PLL1_MULTIPLY_M1_VAL;
        while(DCISTATbits.TMPTY==0);

        // Write to RX Gain Control 1 Register
        TXBUF0=PLUS_ONE_WITH_SECONDARY;
        TXBUF1=WRITE_RX_GAIN_CONTROL_1 |RX_GAIN_CONTROL_1_VAL ;
        while(DCISTATbits.TMPTY==0);

        // Write to ADC Volume Control Register
        TXBUF0=PLUS_ONE_WITH_SECONDARY;
        TXBUF1=WRITE_ADC_VOLUME_CONTROL | ADC_VOLUME_CONTROL_VAL;
        while(DCISTATbits.TMPTY==0);

        // Write to DAC Volume Control Register
        TXBUF0=PLUS_ONE_WITH_SECONDARY;
        TXBUF1=WRITE_DAC_VOLUME_CONTROL | DAC_VOLUME_CONTROL_VAL;
        while(DCISTATbits.TMPTY==0);
       
        // Write to Analog Attenuation Register
        TXBUF0=PLUS_ONE_WITH_SECONDARY;
        TXBUF1=WRITE_ANALOG_ATTENUATION | ANALOG_ATTENUATION_VAL;
        while(DCISTATbits.TMPTY==0);
       
        // Write to Control Register 1
        TXBUF0=PLUS_ONE_WITH_SECONDARY;
        TXBUF1=WRITE_CONTROL_1 | CONTROL_1_VAL;
        while(DCISTATbits.TMPTY==0);
    }   


    void resetSI3K()
    {
        unsigned long i;
       
        TRIS_SI3K_SCK = 1;
        TRIS_SI3K_SDI = 1;
        TRIS_SI3K_SDO = 1;
        TRIS_SI3K_FSYNC = 1;
       
        TRIS_SI3K_RST = 0;        // Set reset pin as output
        TRIS_SI3K_MCLK = 0;        // Set mclk pin as output
       
        LAT_SI3K_SCK = 0;        // ?? Don't know why these are set here! ??
        LAT_SI3K_SDO = 1;

        LAT_SI3K_MCLK = 1;

        LAT_SI3K_RST = 0;    // Put SI3K in reset
        Nop(); Nop(); Nop(); Nop();   
       
        // Need to have SCK = 0 and CSDI (SI3K SDO) = 1
        // Sets SI3K mode so FSYNC pulse starts data frame
        // While the data sheet uses pull-ups/downs, we will
        // drive from the DSP
        TRIS_SI3K_SCK = 0;
        TRIS_SI3K_SDO = 0;

        LAT_SI3K_SCK = 0;
        LAT_SI3K_SDO = 1;
       
        for (i=0; i<400000;i++)
            ClrWdt();
       
        initMCLK();                    // Prep OC1 to generate a 4MHz waveform
        startMCLK();                // Start the OC1 running
       
        for (i=0; i<400000;i++)
            ClrWdt();
           
        LAT_SI3K_RST = 1;            // Bring SI3K out of reset
    }

    void initMCLK()
    {
        // Configure a 4 MHz 50% PWM waveform on Output Compare 1 using Timer2
        // Timer 2 has a rollover every 5 instruction cycles (8 MHz)
        T2CONbits.TON = 0;            // Disable Timer2
        T2CONbits.TCS = 0;            // Select internal instruction cycle clock
        T2CONbits.TGATE = 0;        // Disable gated timer mode
        T2CONbits.TCKPS = 0b00;        // Select 1:1 prescaler
        TMR2 = 0x00;                // Clear timer register
        PR2 = 4;                    // Load the period value (count: 0,1,2,3,4,0,1,...)
        _T2IE = 0;                    // Disable Timer2 interrupt
        T2CONbits.TON = 1;            // Enable Timer2
       
        OC1CONbits.OCM = 0b000;        // Disable OC1 module
        OC1CONbits.OCM = 0b001;        // Define initial state for OC1 pin (low)
        OC1CONbits.OCM = 0b000;        // Disable OC1 module
        OC1CONbits.OCTSEL = 0;        // Select Timer2 as output compare time base
        OC1R = 4;                    // Load the OC1 compare register value
        _OC1IE = 0;                    // Disable OC1 interrupt

        _RP12R = 0b10010;            // P10 - Map Output Compare 1 to RP12 for Si3000 MCLK
        // Ready to go, just need a call to startMCLK() to start OC1 toggling
    }


    void startMCLK()
    {
        TMR2 = 0x00;
        OC1CONbits.OCM = 0b011;        // Set OC1 for toggle mode   
    }


    To initialize the DCI, I am using:


    void initDCI()
    {
        // Clear DCI control registers
        DCICON1 = 0x0000;
        DCICON2 = 0x0000;
        DCICON3 = 0x0000;
       
        // Set receive slot 0 and 8 enable
        //RSCON = 0x00;
        RSCONbits.RSE8 = 1;
        RSCONbits.RSE0 = 1;
       
        // Set transmit slot 0 and 8 enable
        //TSCON = 0x00;
        TSCONbits.TSE8 = 1;
        TSCONbits.TSE0 = 1;
       
        // DCI Control Register DCICON1 Initialization
        DCICON1bits.COFSM = 0;        // Multichannel Frame Sync mode
        DCICON1bits.DJST = 0;        // Data TX/RX is begun one serial clock cycle after frame sync pulse
        DCICON1bits.CSCKE = 0;        // Data changes on rising edge sampled on falling edge of CSCK
        DCICON1bits.COFSD = 1;         // Frame sync driven by Si3000
        DCICON1bits.CSCKD = 1;        // Clock is input to DCI from Si3000
       
        // DCI Control Register DCICON2 Initialization
        DCICON2bits.BLEN = 1;        // 2 data words will be buffered between interrupts   
        DCICON2bits.COFSG = 15;        // Data frame has 16 words 
        DCICON2bits.WS = 15;        // Data word size is 16 bits

        // DCI Control Register DCICON3 Initialization
        DCICON3 = 0;                // Ensure bit clock count = 0
       
        // Disable DCI Interrupt and Enable DCI module
        IPC15bits.DCIIP=6;
        IFS3bits.DCIIF=0;
        IEC3bits.DCIIE=0;
       
        // Enable DCI Module
        _DCIEN = 1;
    }


    I apologize for the length of code.  I've tried to keep it more readible at the expense of size.  I have the codec as master, supplying the Frame Sync and clock signals.

    If I understand the Si3000 datasheet correctly, the sampling rate Fs = (M1/N1) * MCLK / (5*1024), which comes out to 781.25 Hz when M1 and N1 are in their defaults (1).  The frame rate for the Si3000 is Fs and on the scope I see the Frame Sync pulse has a frequency of 781 Hz which makes sense.  Also, the datasheet says the SCLK frequency = 256 * Fs = 200 KHz which matches the output I see from the SCLK pin of the Si3000.  I also see some data coming from the SDO of the Si3000 near the start of each frame.  However, I see no signals coming from the CSDO on the DSP.  My measurement point seems ok since I can manually toggle the CSDO pin (before it's assigned to the DCI peripheral) and see a pulse.

    Does anyone have experience with this kind of behavior?  I'd appreciate any comments or suggestions.

    #12
    superlou
    New Member
    • Total Posts : 30
    • Reward points : 0
    • Joined: 2008/09/26 16:20:42
    • Location: 0
    • Status: offline
    RE: Si3000 working through the DCI module with DMA 2009/04/15 13:31:36 (permalink)
    0
    So, I said to myself, Lou, you've checked to make sure you're not making that mistake of not disabling ADC on the peripheral select pins since they might be multiplexed there.  And then I said, already checked that, aren't I clever:


        _PCFG9 = 1;
        _PCFG10 = 1;


    But then 4.5 hours later I say, Lou, did you check the register value of ADC1PFGL, and I said, no, not yet.  I'm busy looking at complicated code, I don't have time for shennanigans.  And Lou said, you really should.  So I did to make him happy, and lo and behold ADC1PFGL = 0x00FF.  After a quick:


        AD1PCFGL = 0xFFFF;


    ... all is right in the world.  For now.  Sorry to waste everyone's time.
    #13
    Jump to:
    © 2019 APG vNext Commercial Version 4.5