DSPRelated.com
Forums

Zero input yields flipping samples

Started by orwellish October 9, 2006
Hi guys!

Sorry about the cryptic Subject-line. This might be a newbie
question with a very obvious answer. I'm looking at my input samples
to my 6713dsk. The samples are delivered as a 32 bit word with the
MSB 16 bits representing the right channel and the LSB 16 bits
representing the left channel. I split this word up using the
follwing code:

int manipulate(int dataIn){

int left=0;
int right=0;
int leftmask=0x0000ffff;
int rightmask=0xffff0000;

//extract left and right sample from 32 bit input
left = dataIn & leftmask;
right = dataIn & rightmask;
right = right >> 16;
right = right & leftmask;
//some more code
}

When I investigate these channels (left & right) with no input to
the 6713dsk, the samples look something like this:

Right: 0
Left: 1
Right: 0
Left: 0
Right: FFFF
Left: 0
Right: 0
Left: 0
Right: FFFE
Left: 0
Right: 0
Left: FFFF
Right: 0
Left: 1
Right: 0
Left: 0
Right: 0
Left: 1
Right: FFFF
Left: FFFF

I.e, the sample values roughly flips between 0 and FFFF. I suspect
this has something to do with the sign of the sample but I can't
figure it out! Anyone out there that can point me in the right
direction?

Best regards,
/Nils
Nils-

> Sorry about the cryptic Subject-line. This might be a newbie
> question with a very obvious answer. I'm looking at my input samples
> to my 6713dsk. The samples are delivered as a 32 bit word with the
> MSB 16 bits representing the right channel and the LSB 16 bits
> representing the left channel. I split this word up using the
> follwing code:

Don't mask right channel samples with 0xffff, and you should have:

Ch Hex Bipolar Val
-- --- -----------
R 0 0
L 1 1
R 0 0
L 0 0
R FFFFFFFF -1
L 0 0
R 0 0
L 0 0
R FFFFFFFE -2
L 0 0

which is correct as the AIC23B codec provides bipolar data, not unipolar.

-Jeff

>
> int manipulate(int dataIn){
>
> int left=0;
> int right=0;
> int leftmask=0x0000ffff;
> int rightmask=0xffff0000;
>
> //extract left and right sample from 32 bit input
> left = dataIn & leftmask;
> right = dataIn & rightmask;
> right = right >> 16;
> right = right & leftmask;
> //some more code
> }
>
> When I investigate these channels (left & right) with no input to
> the 6713dsk, the samples look something like this:
>
> Right: 0
> Left: 1
> Right: 0
> Left: 0
> Right: FFFF
> Left: 0
> Right: 0
> Left: 0
> Right: FFFE
> Left: 0
> Right: 0
> Left: FFFF
> Right: 0
> Left: 1
> Right: 0
> Left: 0
> Right: 0
> Left: 1
> Right: FFFF
> Left: FFFF
>
> I.e, the sample values roughly flips between 0 and FFFF. I suspect
> this has something to do with the sign of the sample but I can't
> figure it out! Anyone out there that can point me in the right
> direction?
>
> Best regards,
> /Nils
Your problem definitely has to do with the type of the variable used.

When a signed integer is shifted right, the value is sign extended hence the 0xFFFF. Change the data type for right to unsigned int and you should see the correct values.

Cheers.
Dinesh
>> Your problem definitely has to do with the type of the variable used.
>>
>> When a signed integer is shifted right, the value is sign extended
>> hence the 0xFFFF. Change the data type for right to unsigned int and
>> you should see the correct values.
>
>That is not correct. Values from the AIC23B are signed. Nils' only issue is
>that he
>masked the sample with 0xffff *after* right-shifting. After arithmetic
>right-shift,
>no further manipulation is needed.
>
>-Jeff

I would like to point out that the C standard does not guarantee that >>
will sign extended. Compilers are free to either sign extend or just shift
in 0's. If you don't ever have to use a new compiler (possibly even a newer
version of your existing compiler) you don't have to worry about this...
I'm tring to laugh my way out of this mess :) Can't get it to work!
Not even the simplest filtering. I've attached some code below. I'm
just trying to do a basic FIR filtering of the signal. Even though I
clearly can see that - if I disable the filtering - the 32 bit input
sample is properly divided into two 16 bit left/right sample and
then re-assembled again. It sounds ok, not audible distortion. But
when I invoke the FIR filter, it simply doesnt work. I'm probably
missing something very basic, which confuses me. If this would have
been a private project, I would have given up already... :-D

****************************************************
****************************************************

#include
#include
#include "Config1cfg.h"
#include "dsk6713_aic23.h"//support file for codec,DSK

#define FILTERLENGTH 4

short rightFilterBuffer[FILTERLENGTH]={0};
short leftFilterBuffer[FILTERLENGTH]={0};

float coeffs[FILTERLENGTH]={ -0.25, 0.25, -0.25, 0.25 };

short firFilter(short *filtbuffer, float *coeffs)
{

int k=0;
short output=0;

for(k=0;k output=output+coeffs[k]*filtbuffer[k];
}
return(output);
}

void shiftBuffer(short inSample, short *buffer)
{
int k=0;

for(k=FILTERLENGTH-1;k>0;k--) {
buffer[k]=buffer[k-1];
}
buffer[0]=inSample;
}

interrupt void c_int11(){ //interrupt
service routine
//This interrupt is called when a sample
//is sent to the MCBSP

return;
//return from interrupt
}

interrupt void c_int10(){ //interrupt
service routine

/* sample=input_sample();
//read from MCBSP
output_sample(sample*gain);
//write to MCBSP
*/
output_sample(manipulate(input_sample()));

return;
//return from interrupt
}
int manipulate(int dataIn){

short left=0;
short right=0;
short leftOut=0;
short rightOut=0;
int dataOut=0;

//extract left and right sample from 32 bit input
left = dataIn;
right = dataIn >> 16;

/*
printf("dataIn: %X \n",dataIn);
printf("Right: %X \n",right);
printf("Left: %X \n",left);
printf("dataOut: %X \n",dataOut);
printf("*****************************************\n");
*/

//do some processing of samples here

shiftBuffer(right,rightFilterBuffer);
shiftBuffer(left,leftFilterBuffer);

rightOut = firFilter(rightFilterBuffer,coeffs);
leftOut = firFilter(leftFilterBuffer,coeffs);

dataOut = (rightOut << 16) + leftOut;

return(dataOut);
}
void main(){

comm_intr();
//init DSK, codec, McBSP

while(1);
//infinite loop
}

****************************************************
****************************************************
--- In c..., Jeff Brower wrote:
>
> Dinesh-
>
> > Your problem definitely has to do with the type of the variable
used.
> >
> > When a signed integer is shifted right, the value is sign
extended
> > hence the 0xFFFF. Change the data type for right to unsigned
int and
> > you should see the correct values.
>
> That is not correct. Values from the AIC23B are signed. Nils'
only issue is that he
> masked the sample with 0xffff *after* right-shifting. After
arithmetic right-shift,
> no further manipulation is needed.
>
> -Jeff
>
Nils-

> I'm tring to laugh my way out of this mess :) Can't get it to work!
> Not even the simplest filtering. I've attached some code below. I'm
> just trying to do a basic FIR filtering of the signal. Even though I
> clearly can see that - if I disable the filtering - the 32 bit input
> sample is properly divided into two 16 bit left/right sample and
> then re-assembled again. It sounds ok, not audible distortion. But
> when I invoke the FIR filter, it simply doesnt work. I'm probably
> missing something very basic, which confuses me.

First, your firFilter() routine wouldn't work on a PC either. Hints: a) your FIR
filter coefficients are not symmetric, b) you're adding floats to a short (more on
that below).

Second, didn't people on the group (including me) tell you how to mask/shift AIC23
input samples? So you changed everything to short and forgot about masking? Why?
You had it right before, just one extra mask that needed to be deleted. Your new
code below:

> short left=0;
> short right=0;
> short leftOut=0;
> short rightOut=0;
> int dataOut=0;
>
> //extract left and right sample from 32 bit input
> left = dataIn;
> right = dataIn >> 16;

forces you to watch for 16-bit overflow in any subsequent processing. As a good
example of the trap you made for yourself, consider this line:

dataOut = (rightOut << 16) + leftOut;

What happens to a short when you shift it left 16 bits?

> If this would have
> been a private project, I would have given up already... :-D

That better be a joke, otherwise you shouldn't be in engineering. Your problems are
self-made -- one of them is having a hard time to follow instructions. Another is
recognizing that debug takes careful step-by-step analysis -- a lot of work and
persistence.

-Jeff
> ****************************************************
> ****************************************************
>
> #include
> #include
> #include "Config1cfg.h"
> #include "dsk6713_aic23.h"//support file for codec,DSK
>
> #define FILTERLENGTH 4
>
> short rightFilterBuffer[FILTERLENGTH]={0};
> short leftFilterBuffer[FILTERLENGTH]={0};
>
> float coeffs[FILTERLENGTH]={ -0.25, 0.25, -0.25, 0.25 };
>
> short firFilter(short *filtbuffer, float *coeffs)
> {
>
> int k=0;
> short output=0;
>
> for(k=0;k > output=output+coeffs[k]*filtbuffer[k];
> }
> return(output);
> }
>
> void shiftBuffer(short inSample, short *buffer)
> {
> int k=0;
>
> for(k=FILTERLENGTH-1;k>0;k--) {
> buffer[k]=buffer[k-1];
> }
> buffer[0]=inSample;
> }
>
> interrupt void c_int11(){ //interrupt
> service routine
> //This interrupt is called when a sample
> //is sent to the MCBSP
>
> return;
> //return from interrupt
> }
>
> interrupt void c_int10(){ //interrupt
> service routine
>
> /* sample=input_sample();
> //read from MCBSP
> output_sample(sample*gain);
> //write to MCBSP
> */
> output_sample(manipulate(input_sample()));
>
> return;
> //return from interrupt
> }
>
> int manipulate(int dataIn){
>
> short left=0;
> short right=0;
> short leftOut=0;
> short rightOut=0;
> int dataOut=0;
>
> //extract left and right sample from 32 bit input
> left = dataIn;
> right = dataIn >> 16;
>
> /*
> printf("dataIn: %X \n",dataIn);
> printf("Right: %X \n",right);
> printf("Left: %X \n",left);
> printf("dataOut: %X \n",dataOut);
> printf("*****************************************\n");
> */
>
> //do some processing of samples here
>
> shiftBuffer(right,rightFilterBuffer);
> shiftBuffer(left,leftFilterBuffer);
>
> rightOut = firFilter(rightFilterBuffer,coeffs);
> leftOut = firFilter(leftFilterBuffer,coeffs);
>
> dataOut = (rightOut << 16) + leftOut;
>
> return(dataOut);
> }
>
> void main(){
>
> comm_intr();
> //init DSK, codec, McBSP
>
> while(1);
> //infinite loop
> }
>
> ****************************************************
> ****************************************************
>
> --- In c..., Jeff Brower wrote:
> >
> > Dinesh-
> >
> > > Your problem definitely has to do with the type of the variable
> used.
> > >
> > > When a signed integer is shifted right, the value is sign
> extended
> > > hence the 0xFFFF. Change the data type for right to unsigned
> int and
> > > you should see the correct values.
> >
> > That is not correct. Values from the AIC23B are signed. Nils'
> only issue is that he
> > masked the sample with 0xffff *after* right-shifting. After
> arithmetic right-shift,
> > no further manipulation is needed.
> >
> > -Jeff
> Re: Zero input yields flipping samples
> Posted by: "orwellish" n...@gmail.com orwellish
> Date: Thu Oct 12, 2006 9:51 am (PDT)
>
> But when I invoke the FIR filter, it simply doesnt work.

Nils,

Below I am attaching my modifications to the posted code. I did not
attempt to complile or actually test it, so the modifications are
only for an example purpose.

A few comments:

Hard to comment the above quoted statement. Perhaps the code works, but
not as expected?

Jeff, my opinion is that the FIR (if considered as a dot product)
would never overflow, as the dot product is absolutely bounded
by 1 (or rather by 0x7FFF in fixed point).
It is the gain value that might scale the product to
a possible overflow.

The filter coefficints suggest (although I have not checked
the impulse responce) that the lower band is probably filtered
out; hence it might be an HPF? If were changed to all 1/4s,
that would definitely be an LPF.

I explicitly prototyped all the defined functions, and would
recommend to always prototype functions.

I removed the multiplication (sample * gain) as it is a real
mistake, since the sample holds both channels. The gain
has been moved to be applied to the individual channels.

The processing has been moved out from the ISR. The ISR now
does nothing except copying new data to a global variable
and raising a semaphore, signaling that the new samples have
been received. I would also recommend to do nothing on the
interrupt level, except servicing the i/o device, copying
data and setting the corresponding flags (or semaphores).

Instead, the processing is being done at the "normal mode"
(or the task level?). Again, this is also my suggestion to
always perform math/processing at the task level.

The second mistake was initialization of the filter data
buffers. Just a single zero seem not enough, only the
zeroth entries are initialized, the rest three are junk
values, since cl6x does not implicitly initialize globals.

Can't say anything about INT 11 ISR. It does nothing, may be
it needs to clear some fields in the MCBSP control regs?
And the INT 10 ISR as well?

Anyway, these are just my thoughts. Hope they'd help to get
things working. The code is below.

Regards,

Andrew

P.S. Forgot to mention the circular buffers: there's of course
no need to physically move data! A play with the array index
value will do the job much faster; for large buffers that might
be much faster.

> ****************************************************
>
> #include
> #include
> #include "Config1cfg.h"
> #include "dsk6713_aic23.h" // support file for codec,DSK
>
> #define FILTERLENGTH 4
> #define GAIN 1 // gain is set to identity
>
> // global arrays
>
> short rightFilterBuffer[FILTERLENGTH] = {0,0,0,0};
> short leftFilterBuffer[FILTERLENGTH] = {0,0,0,0};
> float coeffs[FILTERLENGTH] = {-0.25, 0.25, -0.25, 0.25};
>
> // global variables
>
> volatile int sample = 0; // new sample from MCBSP
> volatile int flag = 0; // rased when a new sample was received
>
> // function declarations
>
> short input_sample (void);
> void output_sample (int);
> short firFilter (short *, float *);
> void shiftBuffer (short, short *);
> int manipulate (int);
> void main (void);
>
> short firFilter (short *filtbuffer, float *coeffs)
> {
>
> int k = 0;
> short output = 0;
>
> for(k = 0; k < FILTERLENGTH; k++)
> {
> // a small comment is needed here:
> // the filterbuffer entries will first
> // be converted to floats. the product
> // is calculated and the float result is
> // converted back to a short value that
> // is finally added to the short lvalue.
> output += coeffs[k] * filtbuffer[k];
> }
>
> return (output);
> }
>
> void shiftBuffer (short inSample, short *buffer)
> {
> int k = 0;
>
> for(k = FILTERLENGTH-1; k>0; k--)
> {
> buffer[k] = buffer[k-1];
> }
>
> buffer[0] = inSample;
> }
>
> // INT 11 ISR
> // This interrupt is asserted when a sample
> // is sent to the MCBSP
> interrupt void c_int11 (void)
> {
> return; // from interrupt
> }
>
> // INT 10 ISR
> interrupt void c_int10()
> {
> sample = input_sample (); // read from MCBSP
> flag = 1; // assert flag
> return; // from interrupt
> }
>
> int manipulate (int dataIn)
> {
> short left=0;
> short right=0;
> short leftOut=0;
> short rightOut=0;
> int dataOut=0;
>
> // extract left and right sample from 32 bit input
>
> left = dataIn;
> right = dataIn >> 16;
>
> /*
> printf("dataIn: %X \n",dataIn);
> printf("Right: %X \n",right);
> printf("Left: %X \n",left);
> printf("dataOut: %X \n",dataOut);
> printf("*****************************************\n");
> */
>
> // do some processing of samples here
> // apply gain
>
> shiftBuffer (right * GAIN, rightFilterBuffer);
> shiftBuffer (left * GAIN, leftFilterBuffer);
>
> rightOut = firFilter (rightFilterBuffer, coeffs);
> leftOut = firFilter (leftFilterBuffer, coeffs);
>
> dataOut = (rightOut << 16) + leftOut;
>
> return (dataOut);
> }
> void main (void)
> {
> comm_intr(); // init DSK, codec, McBSP
>
> for ( ; ; ) // infinite loop
> {
> if (flag == 1)
> {
> // clear flag
> flag = 0;
> // write to MCBSP
> /* output_sample (sample); */ // passthrough mode
> output_sample(manipulate (sample));
> }
> }
> }
>
> ****************************************************
Hi Jeff,

[I said]
> > Jeff, my opinion is that the FIR (if considered as a dot product)
> > would never overflow, as the dot product is absolutely bounded
> > by 1 (or rather by 0x7FFF in fixed point).
> > It is the gain value that might scale the product to
> > a possible overflow.

[Jeff commented]
> Yes that is text-book correct. But this is a debug issue. At Nils' stage
> of DSP learning he should keep overflow off the list of things he has to
> worry about and use 32-bit values to store results. Many different errors
> in his code could cause overflow -- filter coefficients not correct,
> masking/shifting errors on AIC32B I/O, even basic C code handling the
> filter. With a 32-bit result, at least he can see a non-wrapped answer --
> for example zero would really be zero. That might help him debug and not
> add to the confusion.

Yes, I certainly do agree. Following these rules, the code should have been
rewritten persistently using ints in all instances of shorts.

> Nils, if Andrew has fixed your filter code, I would point out that the
> code below still has at least one obvious error:
>
> dataOut = (rightOut << 16) + leftOut;
>
> as rightOut is a short.

In fact, I vaguley could recall the default type conversion conventions
in the C standard, I was not even sure in all the quoted code below, and
unfortunately was unable to dig out my copy of K&R 2nd ed,

>>> short left=0;
>>> short right=0;
>>> short leftOut=0;
>>> short rightOut=0;
>>> int dataOut=0;
>>>
>>> left = dataIn;
>>> right = dataIn >> 16;
>>>
>>> . . .
>>>
>>> dataOut = (rightOut << 16) + leftOut;

so I compiled the code (by the way, I have totally overlooked the prototype
of the "void comm_intr (void)" function, thus the compiler complained!) and
fortunately for my dying memory, my first shoot was not so bad: it missed
my leg :)

The options were: full optimization, no debug, no bad aliasing, int
threshold 1, far everything, chip model 6710, little endian.

The first two lines have compiled to

|| SHR .S1 A3,16,A4 ; |102| right = dataIn >> 16

and in the different EP:

|| EXT .S1 A3,16,16,A4 ; |103| left = dataIn

So the result was as it had been expected.

The last line under question has compiled to:

SHL .S1 A6,16,A0 ; |110| rightOut << 16
ADD .D1 A4,A0,A4 ; |110| + leftOut

which means that the compiler has taken into account the fact that the result
lvalue is an int, and promoted the type of the rightOut variable, exactly as I
"had felt" it would :)

Contrary to Pascal, C sometimes proves to have very practical default
type conversion rules. The only thing I really disliked (and that has
already gone!) was promotion of floats in floating point expressions;
it used to be a permanent source of errors and long standing misconceptions
about floating point calculations.

Last but not the least; there is a situation possible where the C compiler
might be fooled, and that might also be the reason the code Nils had posted
"does not work":

Let's say that a C coded ISR has been relocated to an address more than 8M
apart from the corresponding ISFP. That means that the 23 bit displacement
branch cannot be used in the ISFP: B or CALL _ISR_C_CODED cannot be used.
Instead, the branch should use a full 32 bit address stored in a register,
e.g.:

_int_tbl_k_entry:

MVKL _ISR_C_CODED, REG_K
MVKH _ISR_C_CODED, REG_K
B REG_K

This is not good, as the contents of REG_K is lost forever. Then the
solution might be to save REG_K on the stack first, then init it with
the ISR entry address and perform the branch. This also leads to the same
situation, the register contents is lost, since the C writted ISR

interrupt void ISR_C_CODED (void) { ...

wold first push on the stack the *modified* REG_K, if it is used
internally and pop the *modified* value on the return. Thus
immediately after return from interrupt, REG_K holds the address
of the ISR instead of its original and correct value.

This error might be very difficult to catch, as the value of REG_K
may not be immediately used, if it is going to be overwritten by
a valid value.

I was thinking for a while on a workaround to this sad situation,
and eventually came to a conclusion that the ISR is to be written
in assembly, or at least its entry and exit sequences are, with
an interim call to a regular C function that does interrupt
processing.

I am curious of how costly from the hardware point of view would
have been to set a file of e.g. 32 memory mapped registers, 32 bit wide,
that would have been initialized with ISRs' 32 bit addresses and
whenever an interrupt has occured the CPU would jumped to one of
these addresses. Such a table is not necesarily bounded to the
peripheral bus, it might be relocated to a ram using the ISTP,
and would have easily served up to 32 interrurpt sources. It might
be extended up to 512 bytes in size, or 128 different addresses and
therefore 128 interrupt sources, before it is equal in size to the
interrupt table that is actually implemented in the C6000 architecture.

Rgds,

Andrew
Andrew-

> > Nils, if Andrew has fixed your filter code, I would point out that the
> > code below still has at least one obvious error:
> >
> > dataOut = (rightOut << 16) + leftOut;
> >
> > as rightOut is a short.
>
> In fact, I vaguley could recall the default type conversion conventions
> in the C standard, I was not even sure in all the quoted code below, and
> unfortunately was unable to dig out my copy of K&R 2nd ed,

Andrew you're too careful, so now I'm backtracking and I agree the line should work.
I would though note differences in K&R and ANSI C on how type promotion occurs, plus
mention that C rules discuss int and long int, whereas 67xx has short (16 bits), int
(32 bits), and long (40 bits). It's not something as consistent between coding
environments as it should be.

For a student or entry-level engineer learning real-time DSP coding, I would suggest
they write:

int dataOut;
short rightOut;

dataOut = ((int)rightOut << 16) + leftOut;

and in general be very explicit about what's going on, at least until they get their
code working and they can rule out the many other things that can cause embedded
system code to fail. Debug is the major skill that new engineers lack; throwing
".NET correct" code at the DSP and assuming it works the same way can make that debug
even harder.

-Jeff
> >>> short left=0;
> >>> short right=0;
> >>> short leftOut=0;
> >>> short rightOut=0;
> >>> int dataOut=0;
> >>>
> >>> left = dataIn;
> >>> right = dataIn >> 16;
> >>>
> >>> . . .
> >>>
> >>> dataOut = (rightOut << 16) + leftOut;
>
> so I compiled the code (by the way, I have totally overlooked the prototype
> of the "void comm_intr (void)" function, thus the compiler complained!) and
> fortunately for my dying memory, my first shoot was not so bad: it missed
> my leg :)
>
> The options were: full optimization, no debug, no bad aliasing, int
> threshold 1, far everything, chip model 6710, little endian.
>
> The first two lines have compiled to
>
> || SHR .S1 A3,16,A4 ; |102| right = dataIn >> 16
>
> and in the different EP:
>
> || EXT .S1 A3,16,16,A4 ; |103| left = dataIn
>
> So the result was as it had been expected.
>
> The last line under question has compiled to:
>
> SHL .S1 A6,16,A0 ; |110| rightOut << 16
> ADD .D1 A4,A0,A4 ; |110| + leftOut
>
> which means that the compiler has taken into account the fact that the result
> lvalue is an int, and promoted the type of the rightOut variable, exactly as I
> "had felt" it would :)
>
> Contrary to Pascal, C sometimes proves to have very practical default
> type conversion rules. The only thing I really disliked (and that has
> already gone!) was promotion of floats in floating point expressions;
> it used to be a permanent source of errors and long standing misconceptions
> about floating point calculations.
>
> Last but not the least; there is a situation possible where the C compiler
> might be fooled, and that might also be the reason the code Nils had posted
> "does not work":
>
> Let's say that a C coded ISR has been relocated to an address more than 8M
> apart from the corresponding ISFP. That means that the 23 bit displacement
> branch cannot be used in the ISFP: B or CALL _ISR_C_CODED cannot be used.
> Instead, the branch should use a full 32 bit address stored in a register,
> e.g.:
>
> _int_tbl_k_entry:
>
> MVKL _ISR_C_CODED, REG_K
> MVKH _ISR_C_CODED, REG_K
> B REG_K
>
> This is not good, as the contents of REG_K is lost forever. Then the
> solution might be to save REG_K on the stack first, then init it with
> the ISR entry address and perform the branch. This also leads to the same
> situation, the register contents is lost, since the C writted ISR
>
> interrupt void ISR_C_CODED (void) { ...
>
> wold first push on the stack the *modified* REG_K, if it is used
> internally and pop the *modified* value on the return. Thus
> immediately after return from interrupt, REG_K holds the address
> of the ISR instead of its original and correct value.
>
> This error might be very difficult to catch, as the value of REG_K
> may not be immediately used, if it is going to be overwritten by
> a valid value.
>
> I was thinking for a while on a workaround to this sad situation,
> and eventually came to a conclusion that the ISR is to be written
> in assembly, or at least its entry and exit sequences are, with
> an interim call to a regular C function that does interrupt
> processing.
>
> I am curious of how costly from the hardware point of view would
> have been to set a file of e.g. 32 memory mapped registers, 32 bit wide,
> that would have been initialized with ISRs' 32 bit addresses and
> whenever an interrupt has occured the CPU would jumped to one of
> these addresses. Such a table is not necesarily bounded to the
> peripheral bus, it might be relocated to a ram using the ISTP,
> and would have easily served up to 32 interrurpt sources. It might
> be extended up to 512 bytes in size, or 128 different addresses and
> therefore 128 interrupt sources, before it is equal in size to the
> interrupt table that is actually implemented in the C6000 architecture.
>
> Rgds,
>
> Andrew
Andrew-

>> Re: Zero input yields flipping samples
>> Posted by: "orwellish" n...@gmail.com orwellish
>> Date: Thu Oct 12, 2006 9:51 am (PDT)
>>
>> But when I invoke the FIR filter, it simply doesnt work.
>
> Nils,
>
> Below I am attaching my modifications to the posted code. I did not
> attempt to complile or actually test it, so the modifications are
> only for an example purpose.
>
> A few comments:
>
> Hard to comment the above quoted statement. Perhaps the code works, but
> not as expected?
>
> Jeff, my opinion is that the FIR (if considered as a dot product)
> would never overflow, as the dot product is absolutely bounded
> by 1 (or rather by 0x7FFF in fixed point).
> It is the gain value that might scale the product to
> a possible overflow.

Yes that is text-book correct. But this is a debug issue. At Nils' stage
of DSP learning he should keep overflow off the list of things he has to
worry about and use 32-bit values to store results. Many different errors
in his code could cause overflow -- filter coefficients not correct,
masking/shifting errors on AIC32B I/O, even basic C code handling the
filter. With a 32-bit result, at least he can see a non-wrapped answer --
for example zero would really be zero. That might help him debug and not
add to the confusion.

Nils, if Andrew has fixed your filter code, I would point out that the
code below still has at least one obvious error:

dataOut = (rightOut << 16) + leftOut;

as rightOut is a short.

-Jeff

> The filter coefficints suggest (although I have not checked
> the impulse responce) that the lower band is probably filtered
> out; hence it might be an HPF? If were changed to all 1/4s,
> that would definitely be an LPF.
>
> I explicitly prototyped all the defined functions, and would
> recommend to always prototype functions.
>
> I removed the multiplication (sample * gain) as it is a real
> mistake, since the sample holds both channels. The gain
> has been moved to be applied to the individual channels.
>
> The processing has been moved out from the ISR. The ISR now
> does nothing except copying new data to a global variable
> and raising a semaphore, signaling that the new samples have
> been received. I would also recommend to do nothing on the
> interrupt level, except servicing the i/o device, copying
> data and setting the corresponding flags (or semaphores).
>
> Instead, the processing is being done at the "normal mode"
> (or the task level?). Again, this is also my suggestion to
> always perform math/processing at the task level.
>
> The second mistake was initialization of the filter data
> buffers. Just a single zero seem not enough, only the
> zeroth entries are initialized, the rest three are junk
> values, since cl6x does not implicitly initialize globals.
>
> Can't say anything about INT 11 ISR. It does nothing, may be
> it needs to clear some fields in the MCBSP control regs?
> And the INT 10 ISR as well?
>
> Anyway, these are just my thoughts. Hope they'd help to get
> things working. The code is below.
>
> Regards,
>
> Andrew
>
> P.S. Forgot to mention the circular buffers: there's of course
> no need to physically move data! A play with the array index
> value will do the job much faster; for large buffers that might
> be much faster.
>
>> ****************************************************
>>
>> #include
>> #include
>> #include "Config1cfg.h"
>> #include "dsk6713_aic23.h" // support file for codec,DSK
>>
>> #define FILTERLENGTH 4
>> #define GAIN 1 // gain is set to identity
>>
>> // global arrays
>>
>> short rightFilterBuffer[FILTERLENGTH] = {0,0,0,0};
>> short leftFilterBuffer[FILTERLENGTH] = {0,0,0,0};
>> float coeffs[FILTERLENGTH] = {-0.25, 0.25, -0.25, 0.25};
>>
>> // global variables
>>
>> volatile int sample = 0; // new sample from MCBSP
>> volatile int flag = 0; // rased when a new sample was received
>>
>> // function declarations
>>
>> short input_sample (void);
>> void output_sample (int);
>> short firFilter (short *, float *);
>> void shiftBuffer (short, short *);
>> int manipulate (int);
>> void main (void);
>>
>> short firFilter (short *filtbuffer, float *coeffs)
>> {
>>
>> int k = 0;
>> short output = 0;
>>
>> for(k = 0; k < FILTERLENGTH; k++)
>> {
>> // a small comment is needed here:
>> // the filterbuffer entries will first
>> // be converted to floats. the product
>> // is calculated and the float result is
>> // converted back to a short value that
>> // is finally added to the short lvalue.
>> output += coeffs[k] * filtbuffer[k];
>> }
>>
>> return (output);
>> }
>>
>> void shiftBuffer (short inSample, short *buffer)
>> {
>> int k = 0;
>>
>> for(k = FILTERLENGTH-1; k>0; k--)
>> {
>> buffer[k] = buffer[k-1];
>> }
>>
>> buffer[0] = inSample;
>> }
>>
>> // INT 11 ISR
>> // This interrupt is asserted when a sample
>> // is sent to the MCBSP
>> interrupt void c_int11 (void)
>> {
>> return; // from interrupt
>> }
>>
>> // INT 10 ISR
>> interrupt void c_int10()
>> {
>> sample = input_sample (); // read from MCBSP
>> flag = 1; // assert flag
>> return; // from interrupt
>> }
>>
>> int manipulate (int dataIn)
>> {
>> short left=0;
>> short right=0;
>> short leftOut=0;
>> short rightOut=0;
>> int dataOut=0;
>>
>> // extract left and right sample from 32 bit input
>>
>> left = dataIn;
>> right = dataIn >> 16;
>>
>> /*
>> printf("dataIn: %X \n",dataIn);
>> printf("Right: %X \n",right);
>> printf("Left: %X \n",left);
>> printf("dataOut: %X \n",dataOut);
>> printf("*****************************************\n");
>> */
>>
>> // do some processing of samples here
>> // apply gain
>>
>> shiftBuffer (right * GAIN, rightFilterBuffer);
>> shiftBuffer (left * GAIN, leftFilterBuffer);
>>
>> rightOut = firFilter (rightFilterBuffer, coeffs);
>> leftOut = firFilter (leftFilterBuffer, coeffs);
>>
>> dataOut = (rightOut << 16) + leftOut;
>>
>> return (dataOut);
>> }
>> void main (void)
>> {
>> comm_intr(); // init DSK, codec, McBSP
>>
>> for ( ; ; ) // infinite loop
>> {
>> if (flag == 1)
>> {
>> // clear flag
>> flag = 0;
>> // write to MCBSP
>> /* output_sample (sample); */ // passthrough mode
>> output_sample(manipulate (sample));
>> }
>> }
>> }
>>
>> ****************************************************