DDS.c


1
#include "Header/main.h"
2
3
//The look-up-table for the sine values / phase accumulator
4
static double lut[LUT_SIZE];
5
6
//Phaseaccumulator
7
static double phase;
8
9
void DDS_init()
10
{
11
  //Fill LUT
12
  Uint8 aa = 0;
13
  for(aa = 0; aa < LUT_SIZE; aa++)
14
  {
15
    //Calculate sine samples, Int16  -32.768 to 32.767 => amplify by 32767 (2^15-1)
16
    lut[aa] = (double) sin(PI * aa / LUT_SIZE);
17
  }
18
19
  //Preset variable for the phaseaccumulator
20
  phase = 0;
21
}
22
23
/// <summary>
24
/// Direct Digital Synthesis (DDS) using Lanczos-Splines for interpolation.
25
/// It is desinged for a frequency range from 100Hz-10kHz
26
/// This method accumulates phase jumps non-quantized and returns corresponding
27
/// sine values from a look-up-table, in which only half a wave is stored.
28
/// Values between two LUT-indexes are interpolated by a Lanczos-Spline. The spline starts one index before
29
/// the arbitrary value, and ends two indexes after.
30
/// </summary>
31
/// <param name="A">Amplitude</param>
32
/// <param name="f">Frequency</param>
33
/// <returns>Array with calculated sine values</returns>
34
void DDS(Int16 *target, double A, Int16 f)
35
{
36
  //Binary tuning word (Normally multiplied by 2 but since we are using 2 Buffers ping/pong
37
  //we have to output only 25 times the ping, and 25 times the pong buffer
38
  double jumpSize = (double)f * LUT_SIZE / F_CLK;
39
40
  //Current position in the LUT
41
  Int16 index = 0;
42
43
  //Current iteration step of the accumulation
44
  Int32 iterator = 0;
45
46
  //Count variable to loop through the output buffer
47
  Uint16 aa = 0;
48
  for(aa = 0; aa < OUT_SIZE; aa++)
49
  {
50
    // Lanczos a=3 (x0' = floor(x0))
51
    // Î(x0) = L(x0-x0'-1)*lut(x0'-1) + L(x0-x0')*lut(x0') + L(x0-x0'+1)*lut(x0'+1) + L(x0-x0'+2)*lut(x0'+2)
52
53
    //Result
54
    double result = 0;
55
    Uint8 bb = 0;
56
57
    //Loop through the sum (Sigma)
58
    for(bb = 0; bb < 4; bb++)
59
    {
60
      //Set iterator
61
      iterator = (Int32)phase + bb - 1;
62
63
      //Set index for the LUT
64
      index = iterator % (2 * LUT_SIZE);
65
66
      //Get the sine value from the LUT, corresponding to the index.
67
      //Actually the LUT is a ringbuffer, if the index is negativ =>
68
      //Get the value from the end. Since we have only stored half
69
      //a sine wave, we also have to invert the value
70
      //Also calculate a step of the accumulation: L(x0-x0'-bb-1) * lut(x0'-bb-1)
71
      if(index < 0)
72
      {
73
        //If index is below the size of the lut, set to end and invert
74
        result += Lanczos(phase - iterator) * -lut[LUT_SIZE + index];
75
      }
76
      else if(index < LUT_SIZE)
77
      {
78
        //First half
79
        result += Lanczos(phase - iterator) * lut[index];
80
      }
81
      else
82
      {
83
        //If index is beyond the size of the lut => second half, set to start but invert value
84
        result += Lanczos(phase - iterator) * -lut[index - LUT_SIZE];
85
      }
86
    }
87
88
    //Amplify the result by amplitude A
89
    *(target + aa) = A * result * 32767;
90
91
    //Increment phase
92
    phase += jumpSize;
93
  }
94
95
  //Decrement phase;
96
  phase = (Int32)phase % OUT_SIZE;
97
}