EmbeddedRelated.com
Forums

sine routines

Started by CAFxX January 14, 2004
"CAFxX" <cafxx@n-side.it> wrote in message
news:bu634c$7g9$1@lacerta.tiscalinet.it...
> what i need to do is to generate a custom-frequency sine wave to be > outputted at CD-quality frequency (44100 samples/second) to a DAC.
If that is all you have to do, take a look at Analog Device's DDS chips. Meindert
CAFxX <cafxx@n-side.it> wrote:
> what i need to do is to generate a custom-frequency sine wave to be > outputted at CD-quality frequency (44100 samples/second) to a DAC. > If possible i'd prefer working with 16 bit integers since float needs > cpu-time-expensive libraries.
Setting aside the recommendable option of replacing the whole kaboodle you're planning now with a special-purpose chip (a digitally controlled oscillator), there's still no reason to actually evaluate a sine function for this. A table should be perfectly adequate --- subsample it in steps through the table whose size is governed by the quotient of your target frequency and the frequency of the tabulated signal. E.g. if you have a sine table of (effectively) 44100 samples for a 1 Hz wave, a 1 kHz wave would use every 1000th sample from that table, and wrap around at the 45th iteration to 45*1000 - 44100 = 900. You'll want to handle non-integer step sizes, too --- either using fixed-point fractional arithmetic, or by Bresenham's algorithm. The actual table should of course store only one quadrant of the wave (0 .. 90 degrees, typically), to keep it short. -- Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de) Even if all the snow were burnt, ashes would remain.
"CAFxX" <cafxx@n-side.it> wrote in message
news:bu49k1$125$1@lacerta.tiscalinet.it...
> does anybody know where to find some FAST sine routines to be run on an > 8052? sdcc's math.h is just an empty file... just an #error directive!
thank
> you in advance. >
This is a very fast but quite imprecise method of generating a sine-like wave. I guess whether it is suitable depends what you want to use for. I used it years ago on a PIC in conjunction with a software PWM and decay function to generate a pleasing bell-like tone. I tried it out just now on C++Builder, so I'll just paste the code and let you play with it to see if it works for you. I seem to remember it may decay over time by itself due to rounding errors: void __fastcall TForm1::FormCreate(TObject *Sender) { int s=Image1->Height/4; int c=0; for( int x=0; x<Image1->Width; x++ ) { c = c+s/16; s = s-c/16; Image1->Canvas->Pixels[x][s+Image1->Height/2] =(TColor)0x00FF0000; } } Peter.
44100 samples / sec = 22,676 microseconds per sample.

Are you sure the 8051 is fast enough to handle that ?

Using a lookup table may help.
Doing 16-bit calculations seems impossible.
Calculating a floating point sine IS impossible.

It depends on the derivative you use.
A standard 8051 will certainly not be able to do the job.

grtnx
/jan




CAFxX <cafxx@n-side.it> schrieb in im Newsbeitrag:
bu634c$7g9$1@lacerta.tiscalinet.it...
> what i need to do is to generate a custom-frequency sine wave to be > outputted at CD-quality frequency (44100 samples/second) to a DAC. > If possible i'd prefer working with 16 bit integers since float needs > cpu-time-expensive libraries. > thanks to all of you for your replies. > "Jack Klein" <jackklein@spamcop.net> ha scritto nel messaggio > news:bc0c00tijn9u6i0h5trab1kiuj5m9c58op@4ax.com... > > On Wed, 14 Jan 2004 21:43:20 +0100, "CAFxX" <cafxx@n-side.it> wrote in > > comp.arch.embedded: > > > > > does anybody know where to find some FAST sine routines to be run on
an
> > > 8052? sdcc's math.h is just an empty file... just an #error directive! > thank > > > you in advance. > > > > There are no FAST routines for calculating sine with the 8051 > > instruction set, and probably no fast ones either. How much accuracy > > and precision do you need? The fastest approach would be a look-up > > table. > > > > -- > > Jack Klein > > Home: http://JK-Technology.Com > > FAQs for > > comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html > > comp.lang.c++ http://www.parashift.com/c++-faq-lite/ > > alt.comp.lang.learn.c-c++ > > http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html > >
On Thu, 15 Jan 2004 15:43:00 +0100, the renowned "Jan Homuth"
<jandothomuth@altium.com> wrote:

>44100 samples / sec = 22,676 microseconds per sample.
That's less than 23 usec, just to make it clear.
>Are you sure the 8051 is fast enough to handle that ? > >Using a lookup table may help. >Doing 16-bit calculations seems impossible. >Calculating a floating point sine IS impossible. > >It depends on the derivative you use. >A standard 8051 will certainly not be able to do the job.
A phase accumulator with a LUT ought be able to do it, using a faster ("very" faster..) variant of the 8051 such as the Cygnal parts. Best to write and simulate the short (assembler!) code now and see how long it will take to execute, including the interrupt and timer reload overhead.. at 50 so-called MIPS there are ~1150 cycles between interrupts. If you can jig the frequency a bit to fit into an integral number of sample periods you can simplify it and reduce the size of the LUT. Best regards, Spehro Pefhany -- "it's the network..." "The Journey is the reward" speff@interlog.com Info for manufacturers: http://www.trexon.com Embedded software/hardware/analog Info for designers: http://www.speff.com
CAFxX wrote:
> > what i need to do is to generate a custom-frequency sine wave to be > outputted at CD-quality frequency (44100 samples/second) to a DAC. > If possible i'd prefer working with 16 bit integers since float needs > cpu-time-expensive libraries.
Because it causes confusion. Why is topposting evil and rude. It would have been simpler if you had stated your real requirements originally. Hans Broeker and Morris Dovey have the right idea. You can limit your table to the range 0..45 degrees and use (1 - sin(90-x)) for 45 to 90. Similarly -sin(-x) for -90..0. Etc. It is probably easiest if you keep the table as signed integers to be divided by 32768 for the actual result. Not 65535 or 32767. -- Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net) Available for consulting/temporary embedded and systems. <http://cbfalconer.home.att.net> USE worldnet address!
On Thu, 15 Jan 2004 14:04:53 +0100, "CAFxX" <cafxx@n-side.it> wrote:

>what i need to do is to generate a custom-frequency sine wave to be >outputted at CD-quality frequency (44100 samples/second) to a DAC. >If possible i'd prefer working with 16 bit integers since float needs >cpu-time-expensive libraries.
Sine? Not quite... You can generate a square function - not a square wave but an x^2 function. Imagine x^2 between 0 and 1. It looks a bit like a quarter cycle of sine. You can generate an arbitrary amplitude and frequency wave in real time by stringing together four such sections with appropriate manipulation. The result is slightly 'fatter' than a sinusoid to look at on a 'scope, but the difference can only really be seen with a direct comparison. I've used this for controlling hydraulic machinery from almost 0 to 100Hz with great success - it really depends on your application. I don't know if your processor is up to it, but it's much easier than a real sine and more flexible than a LUT. Unless of course your application allows you to pre-calculte a LUT before sending it to the DAC. -- Syd
ok i understood that i have to use a lookup table. before asking some more
question i just want to explain what i am really trying to do.
it will simply be a sort of musical keyboard (a synth). it takes the input
of 24 keys (using 3 of the four raw i/o ports of the 8052) and sends 16 bit
samples to the dac (even if it accepts only 24 bits samples - i simply leave
the LS 8 all low).
what i'm wondering here is how to implement the lookup table (actually the
problem is that the sine function generate variable frequency sine waves)
i mean:

short sine (unsigned short frequency) {
    return sin[(counter % frequency) / frequency];
}

(note that long is 4 byte in sdcc) to make sure of having a *decent*
resolution without using long and float (int and short are the same) values
in the calculation what can i do?
i thought of something like
    return sin[((counter % frequency) << 10) / frequency];
(at least 10) but i think this will mess up everything. or not?

"Hans-Bernhard Broeker" <broeker@physik.rwth-aachen.de> ha scritto nel
messaggio news:bu65lp$1ls$1@nets3.rz.RWTH-Aachen.DE...
> CAFxX <cafxx@n-side.it> wrote: > > what i need to do is to generate a custom-frequency sine wave to be > > outputted at CD-quality frequency (44100 samples/second) to a DAC. > > If possible i'd prefer working with 16 bit integers since float needs > > cpu-time-expensive libraries. > > Setting aside the recommendable option of replacing the whole kaboodle > you're planning now with a special-purpose chip (a digitally > controlled oscillator), there's still no reason to actually evaluate a > sine function for this. > > A table should be perfectly adequate --- subsample it in steps through > the table whose size is governed by the quotient of your target > frequency and the frequency of the tabulated signal. E.g. if you have > a sine table of (effectively) 44100 samples for a 1 Hz wave, a 1 kHz > wave would use every 1000th sample from that table, and wrap around at > the 45th iteration to 45*1000 - 44100 = 900. You'll want to handle > non-integer step sizes, too --- either using fixed-point fractional > arithmetic, or by Bresenham's algorithm. > > The actual table should of course store only one quadrant of the wave > (0 .. 90 degrees, typically), to keep it short. > > -- > Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de) > Even if all the snow were burnt, ashes would remain.
> short sine (unsigned short frequency) { > return sin[(counter % frequency) / frequency]; > }
i meant (real world math): sin(mod(counter, frequency) * pi * 2 / frequency) counter simply is the sample counter. "CAFxX" <cafxx@n-side.it> ha scritto nel messaggio news:bu6k2g$s4s$1@lacerta.tiscalinet.it...
> ok i understood that i have to use a lookup table. before asking some more > question i just want to explain what i am really trying to do. > it will simply be a sort of musical keyboard (a synth). it takes the input > of 24 keys (using 3 of the four raw i/o ports of the 8052) and sends 16
bit
> samples to the dac (even if it accepts only 24 bits samples - i simply
leave
> the LS 8 all low). > what i'm wondering here is how to implement the lookup table (actually the > problem is that the sine function generate variable frequency sine waves) > i mean: > > > (note that long is 4 byte in sdcc) to make sure of having a *decent* > resolution without using long and float (int and short are the same)
values
> in the calculation what can i do? > i thought of something like > return sin[((counter % frequency) << 10) / frequency]; > (at least 10) but i think this will mess up everything. or not? > > "Hans-Bernhard Broeker" <broeker@physik.rwth-aachen.de> ha scritto nel > messaggio news:bu65lp$1ls$1@nets3.rz.RWTH-Aachen.DE... > > CAFxX <cafxx@n-side.it> wrote: > > > what i need to do is to generate a custom-frequency sine wave to be > > > outputted at CD-quality frequency (44100 samples/second) to a DAC. > > > If possible i'd prefer working with 16 bit integers since float needs > > > cpu-time-expensive libraries. > > > > Setting aside the recommendable option of replacing the whole kaboodle > > you're planning now with a special-purpose chip (a digitally > > controlled oscillator), there's still no reason to actually evaluate a > > sine function for this. > > > > A table should be perfectly adequate --- subsample it in steps through > > the table whose size is governed by the quotient of your target > > frequency and the frequency of the tabulated signal. E.g. if you have > > a sine table of (effectively) 44100 samples for a 1 Hz wave, a 1 kHz > > wave would use every 1000th sample from that table, and wrap around at > > the 45th iteration to 45*1000 - 44100 = 900. You'll want to handle > > non-integer step sizes, too --- either using fixed-point fractional > > arithmetic, or by Bresenham's algorithm. > > > > The actual table should of course store only one quadrant of the wave > > (0 .. 90 degrees, typically), to keep it short. > > > > -- > > Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de) > > Even if all the snow were burnt, ashes would remain. > >
On Thu, 15 Jan 2004 14:04:53 +0100, "CAFxX" <cafxx@n-side.it> wrote:

>what i need to do is to generate a custom-frequency sine wave to be >outputted at CD-quality frequency (44100 samples/second) to a DAC.
You should have stated this in your first posting. You might get away with a phase accumulator and a look-up-table even without interpolation between the steps. The truncation errors will on some output frequencies contribute with wide band noise at the DAC output, while on other frequency settings all the noise power is concentrated in discrete sidebands. Depending your requirements for the signal to noise ratio and the maximum level allowed for discrete tones, the size of the LUT can be determined. Also the situation is simpler if all the generated frequencies are well below the sampling frequencies. Most literature about numeric controlled oscillators (NCO) also evaluates the size of the phase accumulator vs. steps size, the number of address bits into the sin(x) table and the number of DAC bits and the spurious levels. If a simple table look up is not accurate enough, some very simple interpolation with shifts and one or two adds should do the trick. Use a spreadsheet to evaluate the error between the interpolated value and the "exact" 64 bit double precision value and select your table size and interpolation strategy to minimise the number of clock cycles required for the calculations. Paul