# sine routines

Started by 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
>

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.

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.

```
```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

```