## Wednesday, 3 April 2013

### Sinewave Generator with the DAC of the ARM SAM3X -The Code

```   /* Discrete Computational Methods */

/* Generating/Sample discrete sinusoid */

/* Direct digital synthesis is a common technique for generating
waveforms digitally. The principles of the technique are simple and
widely applicable. You can build a DDS oscillator in hardware or in
software.
A DDS oscillator is sometimes also known as a Numerically-Controlled
Oscillator (NCO). Usually we use a Circular buffer or FIFO.
The NCO function contains a sine look-up tables (LUTs) that perform
the following functions:
sin(n) = sin(2πn/N)
where:
n = Address input to the LUT
N = Number of samples in the LUT
sin(n) = Amplitude of sine wave at (2πn/N)

Incrementing n from 0 to N causes the LUT to output one complete
cycle of amplitude values for the sine  function. The value 2πn/N
represents a fractional phase angle between 0 and 2π. The time (t)
required to increment n from 0 to N is the period of the sine
waveforms produced by the NCO function.

The LUT address is incremented once each system clock cycle by an
amount equal to the phase input. The phase angle data is accumulated
and stored in the phase accumulator register. The output of the
phase accumulator register is used to address the LUTs.
The frequency (f) of the system clock (fCLK) is fixed. Therefore,
the frequency of the sine waves is:
f = 1/t = fCLK × phase/2π. */
/*  Table Lookup */
/*The table look-up method precomputes the unique samples of every
output sinusoid at the start of the simulation, and recalls the
samples from memory as needed. Because a table of finite length
can only be constructedif all output sequences repeat, the method
requires that the period ofevery sinusoid in the output be evenly
divisible by the sample period. That is, 1/(fiTs) = ki must be
an integer value for every channel i = 1, 2, ..., N.
The table that is constructed for each channel contains ki elements.
For long output sequences, the table look-up method requires
far fewer floating-point operations than any of the other methods,
but may demand considerably more memory, especially for high
sample rates (long tables). This is the recommended method
for models that are intended to emulate or generate code for DSP
hardware, and that therefore need to be optimized for execution speed.*/
/*  Differential */
/* The differential method uses an incremental (differential) algorithm
rather than one based on absolute time.
This mode offers reduced computational load, but is subject to drift
over time due to cumulative quantization error.
Because the method is not contingent on an absolute time value,
there is no danger of discontinuity during extended operations (when
an absolute time variable might overflow). */
/* Trigonometric Function */
/*  If the period of every sinusoid in the output is evenly divisible
by the sample  period, meaning that
1/(fiTs) = ki is an integer for every output yi, then the sinusoidal
output in the ith channel is a repeating sequence with a period of
ki samples. At each sample time, the block evaluates the sine function
at the appropriate time value within the first cycle of the sinusoid.
By constraining trigonometric evaluations to the first cycle of each
sinusoid, the block avoids the imprecision of computing the sine of
very large numbers, and eliminates the possibility of discontinuity
during extended operations (when an absolute time variable might
overflow). This method therefore avoids the memory demands of the table
look-up method at the expense of many more floating-point operations. */
/*  - THE CODE -  */
/*Used the proverbial timer interrupt example code, and
the old techniques on Direct digital synthesis available at
places like
http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/
or
http://rcarduino.blogspot.co.uk/2012/12/arduino-due-dds-part-1-sinewaves-and.html
*/

// variables accessed by the interrupt
volatile byte out_sign;
volatile boolean l;

float pi = 3.141592;
float w ;    // ψ
float yi ;
float phase;
int D = 1024;
byte sign_samp;
byte sin_data;  // sine LUT Array
int icounter;
int counter2;
int testPin = 13;      // debugging pin digital pin 13
int testPin2 = 12;      // debugging pin digital pin 12
int testPin3 = 11;      // debugging pin digital pin 11
int testPin4 = 10;      // debugging pin digital pin 11
float a;
float b;

void setup()
{
fill_sinewave();       // load memory with sine table
pinMode(testPin,OUTPUT);
pinMode(testPin2,OUTPUT);
pinMode(testPin3,OUTPUT);
pinMode(testPin4,OUTPUT);
startTimer(TC1, 0, TC3_IRQn, 0x8000); //TC1 channel 0, the IRQ
// for that channel and the desired frequency - 32768 -see somewhere
// else for the reason why
analogWrite(DAC0,0);  //Duane B// this is a cheat - enable the DAC
}

void loop()
{
counter2++;           //
if (counter2 >= 0x400)
{
digitalWrite(13, l = !l); // toggle debugging pin on pin 13
counter2=0;
fill_sinewave();
}
if(b<=511)
{
b=b*pi/128;
}
else if (b>=512)
{
b=b/16;
}
{
a=2;
}
{
a=4;
}
{
a=6;
}
{
a=8;
}
digitalWrite(12, l = !l);     // toggle debugging pin on pin 12
}
/*
* Here is the table of parameters: *
ISR/IRQ TC      Channel Due   pins
TC0 TC0 0 2,      13
TC1 TC0 1 60,     61
TC2 TC0 2 58
TC3 TC1 0 none  <- this line in the example above
TC4 TC1 1 none
TC5 TC1 2 none
TC6 TC2 0 4, 5
TC7 TC2 1 3, 10
TC8 TC2 2 11, 12
*/

void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency) {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
uint32_t rc = VARIANT_MCK/8/frequency; //8 because we selected TIMER_CLOCK1 above
TC_SetRA(tc, channel, rc/2); //50% high, 50% low
TC_SetRC(tc, channel, rc);
TC_Start(tc, channel);
tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
NVIC_EnableIRQ(irq);
}
// TC1 ch 0
void TC3_Handler()
{
digitalWrite(10, l = !l);    // toggle debugging pin on pin 10
TC_GetStatus(TC1, 0);
icounter++;                  // increment index
//icounter=icounter + b;         // Variable frequency with potentiometer
icounter = icounter & 0x3ff;         // limit index 0..1023
if( icounter==0x400)
{
icounter=0;
}
out_sign=sin_data[icounter];
dacc_write_conversion_data(DACC_INTERFACE, out_sign);
}

/*  Plotting Complex Sinusoids as Circular Motion  */
/*             */
/* Euler's relation graphically as it applies to sinusoids. A point
traveling with uniform velocity around a circle with radius 1 may
be represented by  */
/* eiφ = cos(φ) + i*sin(φ) */
/*   eψt=eψft    */
/* in the complex plane, where:
t is time and  is the number of revolutions per second.
e is Euler's number, the base of natural logarithms,
i is the imaginary unit, which satisfies i2 = −1, and
π is pi, the ratio of the circumference of a circle to its diameter.
(1) http://en.wikipedia.org/wiki/Sound
(2) http://en.wikipedia.org/wiki/Sound_frequency
(3) http://en.wikipedia.org/wiki/Sine_wave
(4) https://ccrma.stanford.edu/~jos/Welcome.html
(5) http://lionel.cordesses.free.fr/gpages/DDS1.pdf
*/
void fill_sinewave()
{
digitalWrite(11, l = !l);  // toggle debugging pin on pin 11
w= a*pi;
w= w/512;  // sine LUT Array D= ox8000(fs)@32Hz. at  use 512 ```
`   //The shape of the stored waveform is 64Hz`
```  // arbitrary, and can be a sinusoid, a square, sawtooth, etc
// fill the 1024 byte circular ring buffer array
for (D = 0; D <= 0x3ff; D++)
{
yi= 0x7f*sin(phase);   // try yi= 0x7f*sin(phase)-(2*cos(phase));
//  increase to 3 ? yi= A*sin(phase)- cos(phase)- cos(phase)- cos(phase);
phase=phase+w;         // 0 to 2xpi - 1/1024 increments
sign_samp=0x7f+yi;     // dc offset
sign_samp+= b;         // Add adc value; Keep it at zero for pure sine
sin_data[D]=sign_samp; // write value into array
/*
*/
}
digitalWrite(11, l = !l);  // toggle debugging pin on pin 11
} Chec my related post with a slightly refined code template

http://dubworks.blogspot.co.uk/2013/09/simple-sine-wave-generator-template-in-c.html

http://dubworks.blogspot.co.uk/p/blog-page.html

```