DSPRelated.com
Forums

I2S sign extension

Started by andor_bariska June 24, 2003
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



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.




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



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



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



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.



> 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


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


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).
>




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/