|
Hi, is it true that when I read 24bit I2S audio (from an AES/EBU codec for example) into my 65L, I manually have to sign-extend the 24bit value (which arrives right-justified in the memory via serial port DMA) to get a signed two's complement 32bit integer? If so, isn't that kind of stupid? With non-I2S mode (ADI calls this "DSP serial mode") I have the option of sign-extending the input from the serial port - why not for the I2S mode? Regards, Andor |
|
|
I2S sign extension
Started by ●June 24, 2003
Reply by ●June 25, 20032003-06-25
|
Sign extenstion is a real problem for me. In my software I have to sign extend the adc data which is stored in a 12 bit hardware FIFO. As I am using a FOR loop for that, it takes 0.8msec. Its a very long period to me. How could I reduce this time. Is there any hardware solution for that. Using assembly language is a solution, but as the whole application is written in C, I feel it difficult to transfer buffer from C to assembly for sign ext and then tranfer it back to C. Is there any easy method. Regards Liyju ____________________________________________ Things are difficult before it becomes easy. |
|
|
Reply by ●June 25, 20032003-06-25
|
Please be more precise in your question! What is your destination variable length 16 or 32 bit? Here a short example how to sign extend a 12 bit value in a 16bit register or variable. signed short val = MyAdcValue; val<<=4; // shift so that sign is in sign bit val>>=4; // shift in old place, there you are In many application you can leave the second part away. Be aware the not all ADC send signed results. In such case sub the MSB first. Jens |
|
|
Reply by ●June 25, 20032003-06-25
|
On Tue, 24 Jun 2003, Liyju Janardhan wrote: > Sign extenstion is a real problem for me. > In my software I have to sign extend the adc data > which is stored in a 12 bit hardware FIFO. > As I am using a FOR loop for that, it takes 0.8msec. > Its a very long period to me. > > How could I reduce this time. Is there any hardware > solution for that. > Using assembly language is a solution, but as the > whole application is written in C, I feel it > difficult to transfer buffer from C to assembly for > sign ext and then tranfer it back to C. > Is there any easy method. Hardware wise, yes there is. Make the 12 bits go into the most significant bit positions. So when you read the raw data, it's already sign correct. If you want, mask off the last 4 bits (if you read 16) or 20 if you read 32. Then it takes zero time to fix the problem, because the problem doesn't exist! Patience, persistence, truth, Dr. mike |
|
|
Reply by ●June 25, 20032003-06-25
|
Jens Michaelsen wrote: ... > Here a short example how to sign extend > a 12 bit value in a 16bit register or variable. > > signed short val = MyAdcValue; > val<<=4; // shift so that sign is in sign bit > val>>=4; // shift in old place, there you are How does the C/C++ compiler translate >> and << ? There are two assembly shift computes, ashift and lshift (arithemtic and logic). Perhaps there is a way to specify to the compiler which shift is used (because both are useful). If the logic shift is used, the above sequence won't sign extend, in fact, in won't do anything. Regards, Andor |
|
|
Reply by ●June 25, 20032003-06-25
|
I am using an ADSP-21161N DSP and would like to buffer data in a circular buffer using the circular buffer routines in the DSP. The following is the pertinent sections of code I've tried but not had any success with : -------------------------- IntHandler.cpp //-------------- \/ Circular Buffer \/ -------------- SFLOAT Left_Channel_Buf_In0_0 [ BufSize_16ksps ] ; //-------------- /\ Circular Buffer /\ -------------- void Process_Samples( int sig_int) { Receive_Samples(); // retrieve samples ast 48000sps asm("dm(i7,m0)=r15;"); // load in M long buffer Transmit_Samples(); // send out samples for scope at 8000sps } -------------------------- ADDS_21161_EzKit.cpp void Setup_ADSP21161N() { /* *** Enable circular buffering in MODE1 Register for revision 0.x silicon. Important when porting 2106x code!!! */ asm("bit set MODE1 CBUFEN;"); /* flag 0-3 are inputs from pushbutton switches */ asm("bit clr MODE2 FLG0O | FLG1O | FLG2O | FLG3O;"); /* irqx edge sensitive */ asm("bit set mode2 IRQ2E | IRQ0E | IRQ1E;"); //-------------- \/ Circular Buffer \/ -------------- asm("m0=1; b7=_Left_Channel_Buf_In0_0; l7=@_Left_Channel_Buf_In0_0;"); // input buffer //-------------- /\ Circular Buffer /\ -------------- } -------------------------- InputCircBuf.cpp void InputCircBufInt( int sig_int) { asm("#include <def21161.h>"); // This instruction is added to include header file include header file asm("bit clr stky CB7S;"); // clear sticky bit to prevent re-interrupt } -------------------------- main.cpp void main( void ) { /* Setup Interrupt edges and flag I/O directions */ Setup_ADSP21161N(); /* Setup SDRAM Controller */ Setup_SDRAM(); Setup_AD1836(); Init_AD1852_DACs(); Program_SPORT02_TDM_Registers(); Program_SPORT02_DMA_Channels(); interruptf( SIG_SP0I, Process_Samples); //-------------- \/ Circular Buffer \/ -------------- interruptf( SIG_CB7, InputCircBufInt); //-------------- /\ Circular Buffer /\ -------------- *(int *) SP02MCTL |= MCE; for ( int i = 0; i != 1;) { asm("idle;"); } } Thanks for your help. |
|
|
Reply by ●June 26, 20032003-06-26
|
> How does the C/C++ compiler translate >> and << ? There are
two > assembly shift computes, ashift and lshift (arithemtic and logic). > Perhaps there is a way to specify to the compiler which shift is used > (because both are useful). signed short sig = MyAdcValue; sig<<=4; // don't care sig>>=4; // ashift arithemtic unsigned short usig = MyAdcValue; usig<<=4; // don't care usig>>=4; // lshift logic > If the logic shift is used, the above sequence won't sign extend, in > fact, in won't do anything. Thats why I use signed values to sign extend ;-) Jens |
Reply by ●June 27, 20032003-06-27
|
Hi all, i have some about the connecting the 12 bits of the FIFO to the higher bit position of the data bus. If it is short word data (16bit), it is same as shifting 4 bit position, i.e scaled by 2^4. So the output is the scaled version of the input. This is same for the 32bit data, here the scaling factor is 2^20. Pls note that in ADSP Sharc compiler, the short integer also represented by 32 bit. So the effective shifting is 20 bit in that case. In order to get the original data back, either we have to divide the data by 2^20 (pls note also that division will take more cycles - the other solution is shift right back.) or use "FLOAT Rx by Ry" instruction in assembly ( i am not sure the corresponding instruction in C). I think in general it is better to use assembly for bit wise operation rather than go for C. in line assembly is also a solution. The other solution is use shift left and then right back with out change any hardware, as Jens showed. Jens, I am not understand why you adds this lines "In many application you can leave the second part away." after the shifting operation "signed short val = MyAdcValue; val<<=4; // shift so that sign is in sign bit val>>=4; // shift in old place, there you are In many application you can leave the second part away. " Is it no need of shifting right back after the shift left operation in the above mentioned problem? Then the data become a scaled one, no? Is there any case where this kind of situation arises? For the full hardware solution I think it is better option is what Friedrich mentioned. I am quoting his lines "you can shift your fifo connection to lower bits as you like; you just have to connect all free higher bits of the data bus to the MSB of your fifo output.-- Check your fifo output driver capability..." rgds ajith --- In , "Jens Michaelsen" <jens.michaelsen@w...> wrote: > Please be more precise in your question! > > What is your destination variable length 16 or 32 bit? > > Here a short example how to sign extend > a 12 bit value in a 16bit register or variable. > > signed short val = MyAdcValue; > val<<=4; // shift so that sign is in sign bit > val>>=4; // shift in old place, there you are > > In many application you can leave the second part away. > > Be aware the not all ADC send signed results. > In such case sub the MSB first. > > Jens |
Reply by ●June 27, 20032003-06-27
|
Hi Jens, this is solution 2 since you restriced compiler access to core resources. Performance is ok -- nice idea to use a USTAT register as transfer buffer. If m0 is initialized to 1 and constant you can use m6 instead which is initialized to 1 by the compiler, thus freeing m0 for compiler use. But: How do you use the data in your circular buffer? Is any code polling on I0 (or even doing idle())? Since you are using a serial port to receive your data, you may want to evaluate a version using the SPort DMA -- this depends on your signal processing. So long Friedrich -----Ursprgliche Nachricht----- Von: Jens Michaelsen [mailto:] Gesendet: Freitag, 27. Juni 2003 08:39 An: 'Steve Holle'; ; Burgwedel, Friedrich Betreff: Re: AW: [adsp] Using the overflow interrupt. I'm not shure if I implemented best or second best solution. What I did so far: - reserve USTAT and a DAG register set from the compiler - have the following ISR code handle each sample event ___lib_SPR0I: USTAT1 = DM(RX0_A); DM(I0, M0) = USTAT1; rti; rti; Is there any better way to handle it? Jens ----- Original Message ----- >From: "Burgwedel, Friedrich" <> >To: "'Steve Holle'" <>; <> >Sent: Thursday, June 26, 2003 7:02 PM >Subject: AW: AW: [adsp] Using the overflow interrupt. > >Best solution: > >Implement in assembler code; drawback: guessing from your posted code >segment, there will be some learning involved (no offence intended). > |
Reply by ●June 27, 20032003-06-27
|
Hi Ajith, I don't think that there is something like short word memory adress space for external memory -- I'm not 100% sure about this without looking into the manuals, but if I'm right your fifo will allways be accessed as 32 bit word. > In order to get the original data back, either we have to divide the > data by 2^20 (pls note also that division will take more cycles - the > other solution is shift right back.) 'real programmers never divide by a power of two'. > or use "FLOAT Rx by Ry" instruction in assembly If you do your signal processing in floating point format anyway this would be the way to go. (use inline assembler if neccessary). > Is it no need of shifting right back after the shift left operation > in the above mentioned problem? Then the data become a scaled one, > no? Is there any case where this kind of situation arises? You may want to use the ADC value in fractional fixed point format - that is, the nominal range of your samples is assumed to be [-1,1[ represented in a way that all bit are just the fractions 2^(-1), 2^(-2),...2^(-32). This is a very conveniant representation for fixed point signal data (sometimes you can achive lower noise by using fixed point filtering) and is supported by the core. I would try to avoid the 'full hardware solution' if your fifo output cannot drive multiple data bus lines at the specified speed since the data bus driver would involve addition cost that has to be multiplied with your production lot size... So long Friedrich -----Ursprgliche Nachricht----- Von: ajith_pc [mailto:] Gesendet: Freitag, 27. Juni 2003 07:35 An: Betreff: [adsp] Re: sign extension in C Hi all, i have some about the connecting the 12 bits of the FIFO to the higher bit position of the data bus. If it is short word data (16bit), it is same as shifting 4 bit position, i.e scaled by 2^4. So the output is the scaled version of the input. This is same for the 32bit data, here the scaling factor is 2^20. Pls note that in ADSP Sharc compiler, the short integer also represented by 32 bit. So the effective shifting is 20 bit in that case. In order to get the original data back, either we have to divide the data by 2^20 (pls note also that division will take more cycles - the other solution is shift right back.) or use "FLOAT Rx by Ry" instruction in assembly ( i am not sure the corresponding instruction in C). I think in general it is better to use assembly for bit wise operation rather than go for C. in line assembly is also a solution. The other solution is use shift left and then right back with out change any hardware, as Jens showed. Jens, I am not understand why you adds this lines "In many application you can leave the second part away." after the shifting operation "signed short val = MyAdcValue; val<<=4; // shift so that sign is in sign bit val>>=4; // shift in old place, there you are In many application you can leave the second part away. " Is it no need of shifting right back after the shift left operation in the above mentioned problem? Then the data become a scaled one, no? Is there any case where this kind of situation arises? For the full hardware solution I think it is better option is what Friedrich mentioned. I am quoting his lines "you can shift your fifo connection to lower bits as you like; you just have to connect all free higher bits of the data bus to the MSB of your fifo output.-- Check your fifo output driver capability..." rgds ajith --- In , "Jens Michaelsen" <jens.michaelsen@w...> wrote: > Please be more precise in your question! > > What is your destination variable length 16 or 32 bit? > > Here a short example how to sign extend > a 12 bit value in a 16bit register or variable. > > signed short val = MyAdcValue; > val<<=4; // shift so that sign is in sign bit > val>>=4; // shift in old place, there you are > > In many application you can leave the second part away. > > Be aware the not all ADC send signed results. > In such case sub the MSB first. > > Jens _____________________________________ Note: If you do a simple "reply" with your email client, only the author of this message will receive your answer. You need to do a "reply all" if you want your answer to be distributed to the entire group. _____________________________________ About this discussion group: To Join: Send an email to To Post: Send an email to To Leave: Send an email to Archives: http://groups.yahoo.com/group/adsp Other Groups: http://www.dsprelated.com/groups.php3 ">http://docs.yahoo.com/info/terms/ |
|
|






