# Fixed point types and sine wave generation

We've found that the variety of data types offered by the compiler is
of paramount importance to the ease and effectiveness of embedded
programming. Having lots of data types makes implementing your
programming solution easier. It also removes a big source of error:
the hand-optimization needed to encode data in assembly programs.

Starting in 2007 we're offering a large variety of fixed point data
types in new releases of our compilers. Fixed point data types handle
fractional values ("Fractional" types) and occasionally types with
fractional and small integer components ("Accumulator" types).

These are the relevant types:

Type Description
fixed168 16 bits integer, 8 bits fraction
fixed1616 16 bits integer, 16 bits fraction
_Fract 16 bits fraction
fract8 8 bits fraction
fract16 16 bits fraction
fract24 24 bits fraction
_Accum 8 bits integer, 16 bits fraction
accum88 8 bits integer, 8 bits fraction
accum816 8 bits integer, 16 bits fraction
accum824 8 bits integer, 24 bits fraction

If you're tempted to use floating-point math in your application,
consider fixed-point instead. The processing is substantially easier
and less memory-intensive, and the underlying math is easier to
verify.

When your programming challenge deals with fractional values, you can
describe them naturally and combine them with integers with ease. You
don't have to remember to perform conversions or use translated number
systems: the compiler performs data promotion automatically.

## Catch the wave

One good use of fractional values is in sine wave generation. It helps
to keep the sine wave values as fractional when dealing with a
variable magnitude described as an integer.

There are two ways to generate accurate sine waves: using the
transcendental function and using "rectangle rule integration".

## Sine wave using fixed point transcendentals

Byte Craft Limited offers a fixed point transcendental library
suitable for use with our fixed point data types. It is retargetable:
you can change the underlying data type (just redefine "real" and the
real fixed-point suffix) to the smallest necessary resolution and
recompile.

This is a program that emits a PWM sinewave:

```#pragma option f 0;
#include <9RS08KA2.h>

/* This is a sine wave function generator for RS08.
It will generate a PWM function on an output pin
suitable to pass through an RC network.

It makes use of the two timers on the RS08:
the slower 32kHz RTI graphs the sine wave,
and the faster MTIM switches the output.

This software uses threads to manage the
event-driven work of generating the signal.

*/

//define real accum88
//define matching _rs real suffix to match real,
//for use with constants
#define real accum88
#define _rs hk

#include >FIX_math.h<

#define OUTPUT (PORTA.0)

/* PWM uses the modulo overflow to change from on duty to off duty. */

_Bool on_duty;
unsigned int8 duty;

void PWM(void)
{
if(on_duty)
{
OUTPUT = 1;
MTIMMOD = duty; //reset TOF
}
else
{
OUTPUT = 0;
MTIMMOD = 255 - duty; //reset TOF
}

on_duty = ~on_duty;
}

#define TWOPI (__fix_pi * 2)
//put a 1 in the LS fract bit of an accum88
#define MINFRACT ((real)0x0001)

unsigned real position;

void sine_wave(void)
{
//update the duty cycle
duty = 128 + (int8)(127.0 /* _rs */
* fix_sin(position));
//advance to next position in waveform
position = (position + MINFRACT);
//loop
if (position > TWOPI) position = 0;
SRTISC.RTIACK = 1;
}

void main(void)
{
on_duty = 0;
duty = 128;

position = 0.0r;

//start the RTI
SRTISC.CLKS = 0;     //1 kHz oscillator
SRTISC.RTIS = 0b001; //8ms period
SRTISC.RTIACK = 1;   //reset any stray interrupt
SRTISC.RTIE = 1;     //enable

//start the PWM
MTIMCLK.CLKS = 0b01; //fixed-frequency clock
MTIMCLK.PS = 0;      //no prescaling
MTIMMOD = duty;      //initial reset of TOF
MTIMSC.TOIE = 1;     //interrupt enable
MTIMSC.TSTP = 0;     //enable

while(1)
__DISPATCH();

}

#include <FIX_math.c>
```

## Sine wave using rectangle-rule integration

This is a different method of generating both sine and cosine
waves. It generates less code but does not use radian measurements or
keep its results within the range -1..1.

```#pragma option f 0;
#include <9RS08KA2.h>

/* This is a sine wave function generator for RS08.
It will generate a PWM function on an output pin
suitable to pass through an RC network.

It makes use of the two timers on the RS08:
the slower 32kHz RTI graphs the sine wave,
and the faster MTIM switches the output.

This software uses threads to manage the
event-driven work of generating the signal.

*/

//prototype
void __DISPATCH(void);

//define real accum88
//define matching _rs real suffix to match real,
//for use with constants
#define real accum88
#define _rs hk

#define OUTPUT (PORTA.0)

/* PWM uses the modulo overflow to change from on duty to off duty. */

_Bool on_duty;
unsigned int8 duty;

void PWM(void)
{
if(on_duty)
{
OUTPUT = 1;
MTIMMOD = duty; //reset TOF
}
else
{
OUTPUT = 0;
MTIMMOD = 255 - duty; //reset TOF
}

on_duty = ~on_duty;
}

//accumulators for sine and cosine waveforms.
real sv, cv;
//temporary
real temp;

//8ms time interval
#define t_int (8/1000)

void sine_wave(void)
{
//store sine value before alteration.
temp = sv;
sv = cv * t_int;
cv = temp * t_int; //sv

//use the sine value
duty = 128 + (int8)(sv);

SRTISC.RTIACK = 1;
}

void main(void)
{
on_duty = 0;
duty = 128;

//initialize
sv = 127;
cv = 0;

//start the RTI
SRTISC.CLKS = 0;     //1 kHz oscillator
SRTISC.RTIS = 0b001; //8ms period
SRTISC.RTIACK = 1;   //reset any stray interrupt
SRTISC.RTIE = 1;     //enable

//start the PWM
MTIMCLK.CLKS = 0b01; //fixed-frequency clock
MTIMCLK.PS = 0;      //no prescaling
MTIMMOD = duty;      //initial reset of TOF
MTIMSC.TOIE = 1;     //interrupt enable
MTIMSC.TSTP = 0;     //enable

while(1)
__DISPATCH();

}

```