- Products
- Download
- What's New
- Support
- FAQs
- technical support
- Installation
- Application Notes
- Device List
- Hints and Tips
- Product-specific Notes
- Resources
- Articles on embedded topics
- An introduction to USB and C, with sample code.
- A way to prove C compilers can match and beat macro assembly
- Embedded programming, C standards, and our contribution.
- Exceptional Programming
- Fixed-point event driven sine wave generation
- Fuzzy Logic adds new design options for embedded programming.
- Linking C functions to eTPU channel functions
- Moving from C6805 to C6808
- Something SPECIAL
- Touch sensitive switch

- C Language Resources
- eTPU_C Glossary
- Glossary of Embedded Systems Terminology
- Product-Specific Resources

- Articles on embedded topics
- CODSupport

- product registration
- Distributors and resellers
- About Us
- Fixed Point
- Fuzzy Logic
- Publishing
- FAE/Client Login
- more information

# Fixed-point types event driven 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;

#pragma thread PWM() INTERRUPT (MTIMSC.TOF);

void PWM(void)

{

if(on_duty)

{

OUTPUT = 1;

MTIMMOD = duty; //reset TOF

}

else

{

OUTPUT = 0;

MTIMMOD = 255 - duty; //reset TOF

}

on_duty = ~on_duty;

}

#pragma thread sine_wave() INTERRUPT (SRTISC.RTIF);

#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;

#pragma thread PWM() INTERRUPT (MTIMSC.TOF);

void PWM(void)

{

if(on_duty)

{

OUTPUT = 1;

MTIMMOD = duty; //reset TOF

}

else

{

OUTPUT = 0;

MTIMMOD = 255 - duty; //reset TOF

}

on_duty = ~on_duty;

}

#pragma thread sine_wave() INTERRUPT (SRTISC.RTIF);

//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();

}