This application note describes the basic issues that
need to be addressed in order to implement digital signal processing systems using the PIC16C74 and
provides application code modules and examples for
DTMF tone generation, a 60 Hz notch filter, and a
simple PID compensator for control systems. These
routines can also be used with other PIC16C6X and
PIC16C7XXX processors with minor modifications and
the addition of external analog I/O devices.
The use of general purpose microcontrollers for
low-end digital signal processing applications has
become more commonplace these days with the availability of higher speed processors. Since most signal
processing systems consist of a host processor and
dedicated DSP chip, the use of a single microcontroller
to perform both these functions provides a simpler and
lower cost solution. In addition, the single chip design
will consume less power which is ideal for battery
powered applications. The PIC16C74 with its on-chip
A/D, PWM module, and fast CPU is an ideal candidate
for use in these low-bandwidth signal processing
applications.
A typical signal processing system includes an A/D
converter, D/A converter, and CPU that performs the
signal processing algorithm as shown in Figure 1.
The input signal,
filter (commonly called the anti-aliasing filter) whose
function is to bandlimit the signal to below the Nyquist
rate (one half the sampling frequency) to prevent
aliasing. The signal is then digitized by the A/D
converter at a rate determined by the sample clock to
produce
system transfer function,
in the time-domain using a difference equation. The
output sample,
continuous-time signal,
output low-pass filter.
The calculation of the output signal using a difference
equation requires a multiply and accumulate (MAC)
operation. This is typically a single-cycle instruction on
DSP chips but can take many cycles to perform on a
standard microcontroller since it must be implemented
in code. Since the digitization of the signal, calculation
of the output, and output to the D/A converter all must
be completed within the sample clock period, the speed
at which this can be done determines the maximum
bandwidth that can be achieved with the system. The
relatively slow speed of most microcontrollers is the
major limitation when they are used in DSP applications but the PIC16C74’s fast instruction execution
speed (as fast as 200 ns/instruction) can provide the
performance required to implement relatively low bandwidth systems. In addition, the device’ s on-chip A/D and
PWM modules provide all the functions needed for a
single chip system. Only a few external components
are needed to use the PIC16C74 for tone generation,
filtering of transducer signals, or low bandwidth control.
x(n)
x(t)
, is first passed through an input
, the discrete-time input sequence. The
H(z)
, is typically implemented
y(n)
, is then converted back into the
y(t)
, by the D/A converter and
FIGURE 1:TYPICAL SIGNAL PROCESSING SYSTEM
X[t]
1997 Microchip Technology Inc.DS00616A-page 1
Low-pass
Filter
A/D
X[n]
H[z]
System Clock
Y[n]
D/A
Low-pass
Filter
Y[t]
AN616
CODE DEVELOPMENT TOOLS
The code for these applications was written using
Byte Craft’s MPC C compiler . The MPC compiler provides
an Integrated Development Environment (IDE) and generates highly optimized code for the entire PICmicro™
family. For new PICmicro users that are familiar with C,
this is an ideal way to quickly develop code for these
processors. In addition, the listing files can be studied in
order to learn the details of PICmicro assembly language.
The modules and examples for this application note use
C for the main program body and in-line assembly language for the time-critical routines. MPC provides interrupt support so that interrupt service routines (ISRs) can
be easily written in either C or assembly. This f eature was
used to provide a timer ISR for one of the code modules.
The compiler proved to be a valuable tool that allowed
both high level and assemb ly language routines to be written and tested quickly.
In order to provide the double precision math functions
required for this application note, a couple of existing
math functions written for the PIC16C54 (AN525,
gramming PIC16C5X Devices on Logical Devices
converted for use with MPC. The double precision multiply
and addition routines were modified by first changing all
RAM declarations done in EQU statements to C
“
unsigned char
assembly language code was preceded by “ #asm ” and
ended by “ #endasm ” preprocessor directives which tell
the compiler where the in-line assembly code starts and
ends. Finally , an y macro sections and register names that
are defined differently in MPC were changed.
The assembly language routines for tone generation and
filtering were also written as C functions using the compiler. Assembly language routines written in this way can
be called directly from other assembly language modules
or called directly from C by using the label name as a C
function. Source listings for all the modules and example
programs can be found in the appendices at the end of
this application note. These modules can be directly compiled using the MPC compiler or, alternatively, the assembly language sections can be used with MPASM with
minor modifications.
” variable declarations. The main body of
Number Representation and Math Routines
One of the challenges of using any general purpose
microcontroller for signal processing algorithms is in
implementing the finite word-length arithmetic required to
perform the calculations. As mentioned before, the speed
at which the MAC operations can be performed limits the
maximum achievab le bandwidth of the system. Theref ore,
the routines that perform the multiplication and the main
signal processing algorithms need to be optimized for
speed in order to obtain the highest possible bandwidth
when using the PIC16C74.
The selection of word size and coefficient scaling are also
important factors in the successful implementation of signal processing systems. The effects of using a fixed word
length to represent the signal and do calculations fall into
Pro-
) were
three categories: signal quantization, round-off error, and
coefficient quantization. The signal quantization due to
the A/D converter and round-off error due to the finite precision arithmetic affect the overall signal-to-noise
performance of the system. Scaling of the input signal
should be done before the A/D converter to use the full
input range and maximize the input signal-to-noise ratio.
The use of double precision math for all calculations and
storing intermediate results, even if the input and output
signals are represented as 8-bit words, will help to reduce
the round-off error noise to acceptable levels. Coefficient
quantization occurs when the calculated coefficients are
truncated or rounded off to fit within the given word length.
This has the effect of moving the system transf er function
poles and zeros which can change the system gain, critical frequencies of filters, or stability of the system. The
successful implementation of these systems requires
careful design and modeling of these effects using one of
the many software programs that are available. The code
written for this application note was first modeled using
PC MA TLAB bef ore being implemented on the PIC16C74.
The algorithms in this application note are all
implemented using fixed point two’s compliment
arithmetic. Two math libraries were used for the
examples: one 8-bit signed multiply routine that was written specifically for the tone generation algorithm, and the
modified double precision routines for the PIC16C54 that
were used in the filtering routine. All numbers are stored
in fractional two’s compliment for mat where the MSB is
the sign bit and there is an implied decimal point right after
it. This is commonly referred to as Qx format where the
number after the Q represents the number of fractional
bits in the word. For instance, 16 bit words with the decimal point after the MSB would be referred to as Q15. This
format allows numbers over the range of -1 to 0.99 to be
represented and, because the magnitude of all numbers
is less than or equal to one, has the advantage that there
can be no overflow from a multiplication operation.
Since calculations are done using two’s compliment arithmetic, values read by the PIC16C74’ s A/D con verter need
to be converted to this format. This can be easily done if
the input is set up to read values in offset binary format.
In this representation, the most negative input voltage is
assigned to the number 0, zero volts is assigned the number 128, and the most positive voltage input is assigned
255. Since the PIC16C74 has a unipolar input A/D converter, a bipolar input signal must be scaled to be between
0 and 5V. One way to accomplish this is to use an op-amp
scaling and offset circuit. The signal should be centered
at 2.5V and have a peak to peak voltage swing of
4 to 4.5V. The offset binar y number can be converted to
two’s compliment format by simply complimenting the
MSB of the word. Once the signal processing calculations
are completed, the number can be converted back to offset binary by complimenting the MSB before it is written
to the PWM module. A similar level shifting circuit can be
used at the PWM output to restore the DC level of the signal. Using this technique allows a wide range of analog
input voltages to be handled by the PIC16C74.
DS00616A-page 2
1997 Microchip Technology Inc.
AN616
A/D and D/A Conversion
The PIC16C74’s internal 8-bit A/D converter and PWM
modules can be used to implement analog I/O for the system. The A/D converter along with an external anti-aliasing filter provides the analog input for the system.
Depending on the input signal bandwidth and the sampling frequency, the filter can be a simple single pole RC
filter or a multiple pole active filter . The PWM output along
with an external output “smoothing” filter provides the D/A
output for the system. This can be a simple RC filter if the
PWM frequency is much higher (five to ten times) than the
analog signal that is being output. Alternatively, an active
filter can also be used at the PWM output . Since the use
of the A/D and PWM modules is covered in detail in the
data sheet for the part, they will not be covered here. In
addition, since the PIC16C74’s A/D conv erter is similar to
the PIC16C71 and the PWM module is the same as the
PIC16C74, the use of these is also covered in application
notes AN546, AN538, and AN539.
Appendix A contains the listing for the C module “
GIO.C
” that has the functions that read the A/D conv erter
input, initialize the PWM module, and write 8-bit values to
the PWM module. The number format (offset binary or
two’s compliment) f or the A/D and PWM v alues as well as
the PWM resolution and mode are set using “ #define ”
pragmas at the beginning of the module. The
get_sample() function takes the A/D input multiplexor
channel number as an argument and returns the measured input value. The init_PWM() function takes the
PWM period register PR2 value as an argument. The
write_PWM() function takes the output values for PWM
module1 and 2 and writes them to the appropriate registers using the specified resolution. If the second argument
to the function is 0, the registers for PWM module 2 are
unaffected. The PWM resolution is always 8-bits but the
mode used depends on the PWM frequency.
The A/D conversions need to be perf ormed at the system
sample rate which requires that some form of sample
clock be generated internally or input from an external
source. One way to generate this clock internally, in software with minimal effort, is to use the Timer2 interrupt.
Since Timer2 is used to generate the PWM period,
enabling the Timer2 interrupt and using the Timer2
postscaler can generate an interrupt at periods that are
integer divisors of the PWM period. The ISR can set a
software “sample flag” that is checked by the main routine .
Once the sample flag is asserted by the ISR, the main
routine can then clear it and perform the signal processing
operation, output the next sample, and then wait for the
sample flag to be asserted true again. Alternatively, a
separate timer/counter or external clock input can be
used for the system sample clock. The latter two methods
have the advantage that the PWM frequency can be set
independent of the sampling period. For best results, the
PWM frequency should be set for at least five times the
maximum frequency of the analog signal that is bring
reproduced. The example programs illustrate the use of
both of the methods for generating an internal sample
clock.
ANALO-
Tone Generation
For systems that need to provide audible feedback or to
provide DTMF signaling for telcom applications, the
PIC16C74’s PWM module can be used to generate these
signals. One wa y to do this is to output samples of a sin usoidal waveform to the PWM module at the system sampling rate. This method is relatively simple but is limited to
single tones and may require large amounts of memory
depending on the number of samples used per cycle of
the wavefor m and the number of tones that need to be
generated. A more efficient method of generating both
single and dual-tone signals is to use a difference equation method. This method uses a difference equation that
is derived from the z-transform of a sinusoid as follows:
thus we have a diff erence equation with coefficients
b
. Note that only two coefficients are needed to generate
a sinusoidal output sequence. These are calculated from
the relationship above and stored in memory for use by
the tone generation algorithm.
If we input an impulse to this system (x(n) = 1 at n = 0 and
is zero elsewhere) then the output of the system will be a
discrete-time sinusoidal sequence. Note that at n = 0, the
output will always be 0 and x(n) is only 1 at n = 1 so the
sequence becomes:
cosωT + z-2) = X(z)(z-1sinωT)
-1
X(z)sinωT + z-1Y(z)2cosωT - z-2Y(z)
ω
T x(n - 1) + 2cosωT y(n - 1) - y(n - 2)
a = sin ω T
and
y(0) = 0
y(1) = a
y(n) = 2b y(n - 1) - y(n - 2)
for n equal to or greater than 2
Tsin
1–
ω
Tcos–z2–+
b = cos ω T
, the equation can be
a
and
1997 Microchip Technology Inc.DS00616A-page 3
AN616
In order to further simplify the implementation of the algorithm, we can omit the first sample period. Since the output is already at 0 before starting, this will make no
difference in the final output other than the fact that it will
be time shifted by one sample. To generate dual tones,
the algorithm is executed once for each tone and the two
output samples are summed together. Since the output
must be calculated and output to the D/A each sample
period, a limitation exists on the frequency of the tone that
can be produced for a given sample rate and processor
speed. The higher the ratio of the sample clock to the tone
frequency , the better , b ut a sample rate of at least three to
four times the highest tone output should produce a sine
wave with acceptable distortion.
Appendix B contains the listing for the “ PICTONE.C ” module which uses the difference equation method to produce
variable length tones from the PWM module. Timer2 is
used to generate the PWM period as well as the sample
clock and tone duration timer. To send a tone, the coefficients and duration are written to the appropriate variables and then the tone routine is called. If the a2 and b2
coefficients are cleared, the routine will only generate a
single tone sequence. The difference equation algorithm
uses 8-bit signed math routines for the multiply operations. Using 8-bit coefficients reduces the accuracy by
which the tones can be generated but greatly reduces the
number of processor cycles needed to perform the algorithm since only single precision arithmetic is used. The
spectrum of a single tone signal generated using this routine is shown in Figure 2.
Note that the second harmonic is better than 40 dB below
the fundamental. Accuracy of this particular tone is better
than 0.5%.
An example program “ DTMFGEN.C ” illustrates the use of
the tone module to generate the 16 standard DTMF tones
used for dialing on the telephone system. A sampling rate
of 6.5 kHz was used which allows dual tones to be generated on a processor running at 10 MHz. Accuracy with
respect to the standard DTMF frequencies is better than
1% for all tones and all harmonics above the fundamental
frequency are greater than 30 dB down.
FIGURE 2:SINGLE TONE SIGNAL
0.0
-10
-20
-30
-40
-50
-60
-70
Relative Amplitude (dB)
-80
-90
-100
0.05001.0k1.5k2.0k2.5k3.0k3.5k
PIC16C74 Tone Generation Routine Output Spectrum - 770 Hz Fundamental
Frequency (Hz)
DS00616A-page 4
1997 Microchip Technology Inc.
AN616
Digital Filters
Digital filters with critical frequencies up to a kilohertz or
so can be implemented on the PIC16C74. Digital filters
fall into two classes: Finite Impulse Response (FIR) and
Infinite Impulse Response (IIR) filters. FIR filters require
more coefficients and multiplication operations to implement practical filters and are not as well suited for implementation on the PIC16C74. IIR type filters are typically
designed starting with an analog filter prototype and then
performing an analog to digital transformation to produce
the digital filter coefficients. The subject of digital filter
design is not within the scope of this application note but
there are many excellent texts that cover the theory and
design of these filters.
The implementation of a second-order IIR filter is done by
using a second-order difference equation. A
second-order infinite impulse response (IIR) filter has a
transfer function of the form:
b
+ b1z-1 + b2z
H(z) =
Where a
polynomials of the system transfer function that, when
factored, yield the system poles and zeros. The difference
equation found by taking the inverse z-transform and
applying the shift theorem is:
y(n) =
b
Since the transfer function coefficients are used directly in
the difference equation, this is often called the “Direct
Form I” implementation of a digital filter. This form has its
limitations due to numerical accuracy issues but is effective for implementing second-order systems.
Appendix C contains the listing for the general-purpose
filter routine “ IIR_FILT.C ” that can be used to implement low-pass, high-pass, bandpass, and bandstop
(notch) filters. The filter() function takes an 8-bit input
value x(n) and calculates the output value y(n) . The filter
coefficients are stored as 16-bit two’s compliment
numbers and computation of the output is done using
double precision arithmetic. Since the coefficients
generated from the filter design program will be in decimal
form, they need to be scaled to be less than 1 and then
multiplied by 32,768 to put them in Q15 format. Additional
scaling by factors of two may be required to prevent overflow of the sum during calculations. If this is done, the output must be multiplied by this scale factor to account for
this. The “ IIR_FILT.C ” module contains two other subroutines required for the filtering program. One if these is
a decimal adjust subroutine to restore the decimal place
after two 16-bit Q15 numbers are multiplied. The subroutine shifts the 32-bit result left by one to get rid of the extra
sign bit. The other routine scales the output by factors of
two and is used after the output of the filter has been
calculated to account for the scaling of the coefficients.
An example program “ NOTCH_60.C ” is provided that illustrates the implementation of a 60 Hz notch filter using the
“ IIR_FILT.C ” module. The filter was modeled and
designed using PC MATLAB before being implemented
on the PIC16C74. A sample rate of 1 kHz is used which
means that signals up to a few hundred hertz can be processed. The filter provides an attenuation of about 40 dB
at 60 Hz and can be used to remove interference from
sensor signals in a system.
Digital Control
A low bandwidth digital control system can be
implemented on the PIC16C74 using the analog I/O and
IIR filter routines. A typical digital control system is shown
below:
FIGURE 3:TYPICAL DIGITAL CONTROL
SYSTEM
r
+
The input, r , is the reference input and
continuous-time output of the system.
transfer function of the plant (controlled system) and
is the digital compensator. The error signal is calculated
by subtracting the measured output signal,
reference. The controller transfer function is essentially a
filter that is implemented in the time-domain using a difference equation. Since digital control system design is a
complex subject and the design of a suitable compensator depends on the system being controlled and the performance specifications, only the implementation issues
will be discussed.
e[n]
∑
K[z]
-
D/A
y[n]
A/D
G[s]
Plant
y(t)
G(s)
is the analog
y[t]
is the
K(z)
y(n)
, from the
1997 Microchip Technology Inc.DS00616A-page 5
AN616
One popular and well understood compensator is the Proportional-Integral-Derivative (PID) controller whose transfer function is of the form:
K
K(z) = KP +
Where
K
is the proportional gain,
,and
implemented directly or can be put in the form of a standard second-order difference equation from the modified
transfer function as shown below:
Since the numerator coefficients will be greater than one,
a gain factor
ing coefficients are less than one. In this way, the IIR filter
routine can be used to implement the controller. After the
filter routine, the output
before being output to the PWM module. Since the gain
can be high, this result needs to be checked for overflow
and limited to the maximum 8-bit value, if required. Saturating the final result prevents the system from going
unstable if overflo w in the math does occur . The gains can
also be applied externally at the D/A output. F or e xample ,
the PWM can drive a power op-amp driver that provides a
± 20 volt swing for a DC motor.
P
K
is the derivative gain. The transfer function can be
D
H(z) =
y(n) =
(KIT2 + KPT + KD) - (2KD + KPT)z-1 + KDz
(K
+ KIT +
P
2K
- (KP +
K
+
T
D
T
D
x(n - 2) - y(n - 1)
K
needs to be factored out so that the result-
I
+ KD(1 - z-1)
-1
1 - z
K
is the integral gain
I
T(1 - z-1)
K
D
)x(n)
T
)x(n - 1)
y
needs to be multiplied by
-2
RESULTS AND CONCLUSION
The results obtained using the PIC16C74 in these applications were impressive. The tone generation routines
produce very clean sinusoidal signals and DTMF tones
generated using this routine have been used to dial numbers over the telephone system with excellent results. In
addition, tones used for audible f eedback are more pleasing to the ear than those generated from a port pin as is
typically done on processors without PWM modules.
Using the PIC16C74 to generate these tones eliminates
the need for special DTMF generator IC’s thus reducing
the cost and simplifying the design. The tone routine
requires approximately 125 instruction cycles to calculate
an output sample for a single tone output and
230 instruction cycles to calculate an output sample for a
dual tone output.
The IIR filtering routines produce good results and have
been used to filter 60 Hz signals on sensor lines and also
to implement a simple PID controller system with excellent
results. The IIR routine takes approximately 1670 instruction cycles to calculate the output. Table 1 shows the performance that can be expected with the PIC16C74 for
various processor speeds.
In conclusion, the PIC16C74 provides the necessary performance to provide these simple, low bandwidth signal
processing operations. This means that products using
this device can benefit from cost and power savings by
eliminating specialized components that normally perform these tasks.
K
References
Antoniou, A. Digital Filters: Analysis and Design. NY:
McGraw-Hill Book Co., 1979.
Openheim, A.V. and Schafer, R.W. Digital Signal
Processing. Englewood Cliffs, N.J.: Prentice-Hall, Inc.,
Please check the Microchip BBS for the latest version of the source code. Microchip’s Worldwide Web Address:
www.microchip.com; Bulletin Board Support: MCHIPBBS using CompuServe
®
(CompuServe membership not
required).
APPENDIX A:ANALOG I/O MODULE
/****************************************************************************
* Analog I/O Module
*
* Written for “Digital Signal Processing with the PIC16C74” Application Note
*
* This module contains functions that read the A-D inputs, initialize the PWM
* ports, and write values to the PWM ports.
*
* D. Mostowfi 4/95
****************************************************************************/
#define active 1 /* define active as 1 */
#define LOW 0 /* define LOW as 0 */
#define HIGH 1 /* define HIGH as 1 */
#define AD_FORMAT TWOS /* define A-D format as TWOS */
#define PWM_FORMAT TWOS /* define PWM format as TWOS */
#define PWM_RES HIGH /* define PWM resolution as HIGH */
bits FLAGS; /* general purpose flags */
#define sample_flag FLAGS.1 /* define sample_flag as FLAGS.1 */
ADRES=0; /* clear ADRES */
STATUS.C=0; /* clear carry */
RLCF(channel); /* and rotate channel 3 times */
RLCF(channel); /* to put in proper position */
RLCF(channel); /* for write to ADCON0 */
ADCON0=channel; /* write channel to ADCON0 */
ADCON0.0=1; /* turn on A-D */
i=0; /* set delay loop variable to 0 */
while(i++<=5){}; /* delay (to ensure min sampling time) */
ADCON0.2=1; /* start conversion */
while(ADCON0.2){} /* wait for eoc */
ADCON0.0=0; /* turn off a-d converter */
if(AD_FORMAT==TWOS){ /* if format is two’s compliment */
ADRES.7=!ADRES.7; /* compliment MSB */
}
return ADRES; /* return value in a-d result reg */
}
/******************************************************************************
* PWM Initialization Routine - sets up PR2, sets output to mid-point, and
* starts timer 2 with interrupts disabled.
*
* usage:
1997 Microchip Technology Inc.DS00616A-page 9
AN616
* - call init_PWM(PR2 register value)
******************************************************************************/
void init_PWM(char _pr2)
{
PR2=_pr2; /* reload value for 40khz PWM period */
CCP1CON.5=0; /* set CCPxCON = 0 for 50% output */
CCP1CON.4=0;
CCP2CON.5=0;
CCP2CON.4=0;
if(PWM_RES==HIGH){ /* if resolution is high, set CCPRxH=0 and */
CCPR1H=0x00; /* CCPRxL=0x20 for 50% PWM duty cycle */
CCPR1L=0x20;
CCPR2H=0x00;
CCPR2L=0x20;
}
else{
CCPR1H=0x00; /* if resolution is low, set CCPRxH=0 and */
CCPR1L=0x80; /* CCPRxL=0x80 for 50% PWM duty cycle */
CCPR2H=0x00;
CCPR2L=0x80;
}
T2CON.TMR2ON=1; /* start timer 2 */
PIE1.TMR2IE=0; /* and disable timer 2 interrupt */
}
/*******************************************************************************
* PWM Output Routine - writes output values to PWM ports
*
* Both high resolution and low resolution modes write 8 bit values - use of
* high or low resolution depends on PWM output period.
*
* usage:
* - call write_PWM(channel 1 value, channel 2 value)
* if channel 2 value=0, PWM port 2 not written
*******************************************************************************/
void write_PWM(bits pwm_out1, bits pwm_out2)
{
if(PWM_FORMAT==TWOS){ /* if format is two’s compliment */
pwm_out1.7=!pwm_out1.7; /* compliment msb’s */
pwm_out2.7=!pwm_out1.7;
}
if(PWM_RES==HIGH){ /* if resolution is high */
STATUS.C=0; /* clear carry */
pwm_out1=RRCF(pwm_out1); /* rotate right and write two lsb’s */
CCP1CON.4=STATUS.C; /* to CCP1CON4 and CCP1CON5 */
STATUS.C=0;
pwm_out1=RRCF(pwm_out1);
CCP1CON.5=STATUS.C;
if(pwm_out2!=0){ /* if pwm_out2 not 0, do the same */
STATUS.C=0; /* for channel 2 */
pwm_out2=RRCF(pwm_out2);
CCP2CON.4=STATUS.C;
STATUS.C=0;
pwm_out2=RRCF(pwm_out2);
CCP2CON.5=STATUS.C;
}
}
CCPR1L=pwm_out1; /* write value to CCPR1L */
if(pwm_out2!=0){ /* if pwm_out2 not 0, do the same */
CCPR2L=pwm_out2; /* for CCPR2L */
}
} /* done */
DS00616A-page 10 1997 Microchip Technology Inc.
AN616
Please check the Microchip BBS for the latest version of the source code. Microchip’s Worldwide Web Address:
www.microchip.com; Bulletin Board Support: MCHIPBBS using CompuServe
®
(CompuServe membership not
required).
APPENDIX B:TONE GENERATION MODULE
/*****************************************************************************
* Tone Generation Module
*
* Written for “Digital Signal Processing with the PIC16C74” Application Note.
*
* This module contains a C callable module that generates single or dual
* tones using a difference equation method:
*
* y1(n)=a1*x(n-1)+b1*y1(n-1)-y1(n-2)
* y2(n)=a2*x(n-1)+b2*y2(n-1)-y2(n-2)
*
* The routine is written in assembly language and uses the optimized signed
* 8x8 multiply routine and scaling routine in the file 8BITMATH.C.
*
* D. Mostowfi 2/95
*****************************************************************************/
#include “\mpc\apnotes\8bitmath.c” /* 8 bit signed math routines */
#define sample_flag FLAGS.1 /* sample flag */
#define no_tone2 FLAGS,2 /* no tone 2 flag */
extern char ms_cntr; /* millisecond counter for tone loop */
char a1; /* first tone (low-group) coeeficient 1 */
char a2; /* first tone (low-group) coefficient 2 */
char b1; /* second tone (high group) coefficient 1 */
char b2; /* second tone (high group) coefficient 2 */
char duration; /* tone duration */
char y1; /* output sample y1(n) for tone 1 */
char y2; /* output sample y2(n) for tone 2 */
/******************************************************************************
* Tone function - generates single or dual tone signals out PWM port 1.
*
* usage:
* - write coefficients for tone 1 to a1 and b1
* - write coefficents for tone 2 to a2 and b2 (0 if no tone 2)
* - write duration of tone in milliseconds to duration
* - call tone() function
*******************************************************************************/
void tone(void)
{