- Fixed a few problems with Arduino Zero support

- Added a 10-bit sine table, probably wasteful considering its stored in 16-bit integers.
- Added "DDS_MAX_COMPARATOR" and "DDS_MAX_ACCUMULATOR" macros to hide some math and imrpove readability.
- Simplified calcFrequency and made it work for arbirary frequencies (with/without default refclk)
- Simplified getDutyCycle().  I think its more understandable now, and works for various combinations of accumulator size and lookup table size.

Tested on both an Arduino Zero and an Arduino UNO.  Seems to work, but YMMV.
This commit is contained in:
Jake-B 2015-08-17 17:26:33 -04:00
parent fdaa602401
commit a581404e04
2 changed files with 173 additions and 73 deletions

96
DDS.cpp
View File

@ -24,10 +24,12 @@ void DDS::start() {
Serial.print(F("DDS SysClk: "));
Serial.println(F_CPU/8);
Serial.print(F("DDS RefClk: "));
Serial.println(refclk, DEC);
Serial.println(refclk, DEC);
#endif
#ifdef __SAMD21G18A__
// SAMD21, like Ardino Zero
// Enable the Generic Clock Generator 0 and configure for TC4 and TC5.
// We only need TC5, but they are configured together
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)) ;
@ -55,9 +57,20 @@ void DDS::start() {
TC_WAIT();
//Configure the DAC
#if COMPARATOR_BITS==6
// Not sure why you'd use 6-bit, other than debugging.
// Reduced amplitude: clockTick() and getDutyCycle() do not scale the 6 up to 8-bits
analogWriteResolution(8);
analogWrite(A0, 0);
#elif COMPARATOR_BITS == 8 || COMPARATOR_BITS == 10
analogWriteResolution(COMPARATOR_BITS);
#else
#error Unsupported resoltuion for DAC (expected 8 or 10)
#endif
analogWrite(A0, 0);
#else
// For AVRs
// Use the clkIO clock rate
ASSR &= ~(_BV(EXCLK) | _BV(AS2));
@ -81,7 +94,7 @@ void DDS::start() {
// Setting Comparator Bits smaller will allow for higher frequency PWM,
// with the loss of resolution.
#ifdef DDS_PWM_PIN_3
OCR2A = pow(2,COMPARATOR_BITS)-1;
OCR2A = DDS_MAX_COMPARATOR-1;
OCR2B = 0;
#else
OCR2A = 0;
@ -132,33 +145,32 @@ void DDS::stop() {
ddsAccumulator_t DDS::calcFrequency(unsigned short freq) {
// Fo = (M*Fc)/2^N
// M = (Fo/Fc)*2^N
ddsAccumulator_t newStep;
if(refclk == DDS_REFCLK_DEFAULT) {
// Try to use precalculated values if possible
if(freq == 2200) {
newStep = (2200.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS);
return (2200.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * DDS_MAX_ACCUMULATOR;
} else if (freq == 1200) {
newStep = (1200.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS);
return (1200.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * DDS_MAX_ACCUMULATOR;
} else if(freq == 2400) {
newStep = (2400.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS);
return (2400.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * DDS_MAX_ACCUMULATOR;
} else if (freq == 1500) {
newStep = (1500.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS);
return (1500.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * DDS_MAX_ACCUMULATOR;
} else if (freq == 600) {
newStep = (600.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS);
return (600.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * DDS_MAX_ACCUMULATOR;
}
} else {
//TODO: This doesn't work with the SAM21D... yet
newStep = pow(2,ACCUMULATOR_BITS)*freq / (refclk+refclkOffset);
}
return newStep;
}
// Not a pre-calc frequency OR not using default REFCLK
return DDS_MAX_ACCUMULATOR * freq / (refclk+refclkOffset);
}
// Degrees should be between -360 and +360 (others don't make much sense)
void DDS::setPhaseDeg(int16_t degrees) {
accumulator = degrees * (pow(2,ACCUMULATOR_BITS)/360.0);
accumulator = degrees * (DDS_MAX_ACCUMULATOR/360.0);
}
void DDS::changePhaseDeg(int16_t degrees) {
accumulator += degrees * (pow(2,ACCUMULATOR_BITS)/360.0);
accumulator += degrees * (DDS_MAX_ACCUMULATOR/360.0);
}
// TODO: Clean this up a bit..
@ -173,7 +185,7 @@ void DDS::clockTick() {
if(timeLimited && tickDuration == 0) {
#ifdef __SAMD21G18A__
#ifdef DDS_IDLE_HIGH
analogWrite(A0, pow(2,COMPARATOR_BITS)/2);
analogWrite(A0, DDS_MAX_COMPARATOR/2);
#else
analogWrite(A0, 0);
#endif
@ -183,7 +195,7 @@ void DDS::clockTick() {
#else
#ifdef DDS_IDLE_HIGH
// Set the duty cycle to 50%
OCR2B = pow(2,COMPARATOR_BITS)/2;
OCR2B = DDS_MAX_COMPARATOR/2;
#else
// Set duty cycle to 0, effectively off
OCR2B = 0;
@ -208,7 +220,7 @@ void DDS::clockTick() {
} else {
#ifdef __SAMD21G18A__
#ifdef DDS_IDLE_HIGH
analogWrite(A0, pow(2,COMPARATOR_BITS)/2);
analogWrite(A0, DDS_MAX_COMPARATOR/2);
#else
analogWrite(A0, 0);
#endif
@ -219,7 +231,7 @@ void DDS::clockTick() {
#else
#ifdef DDS_IDLE_HIGH
// Set the duty cycle to 50%
OCR2B = pow(2,COMPARATOR_BITS)/2;
OCR2B = DDS_MAX_COMPARATOR/2;
#else
// Set duty cycle to 0, effectively off
OCR2B = 0;
@ -229,27 +241,49 @@ void DDS::clockTick() {
}
}
//TODO: rename this function as it is more than just dutyCycle?
//now it powers both a PWM dutyCycle as well as a DAC value on the Zero
ddsComparitor_t DDS::getDutyCycle() {
#if ACCUMULATOR_BIT_SHIFT >= 24
#if ACCUMULATOR_BITS - ACCUMULATOR_BIT_SHIFT > 8
// For larger sineTables which need more thn 8 bits.
uint16_t phAng;
#else
// For standard sineTables which need 8 bits.
uint8_t phAng;
#endif
if(amplitude == 0) // Shortcut out on no amplitude
return 128>>(8-COMPARATOR_BITS);
return DDS_MAX_COMPARATOR/2;
// Lookup the value from the sin table.
phAng = (accumulator >> ACCUMULATOR_BIT_SHIFT);
int8_t position = pgm_read_byte_near(ddsSineTable + phAng); //>>(8-COMPARATOR_BITS);
// Apply scaling and return
#if DDS_LOOKUPVALUE_BITS > 8
// 16-bit lookup
int16_t position = pgm_read_word_near(ddsSineTable + phAng); //>>(8-COMPARATOR_BITS);
int32_t scaled = position;
#else
// 8-bit lookup
int8_t position = pgm_read_byte_near(ddsSineTable + phAng); //>>(8-COMPARATOR_BITS);
int16_t scaled = position;
// output = ((duty * amplitude) / 256) + 128
// This keeps amplitudes centered around 50% duty
#endif
// If there's an amplitude, scale it
if(amplitude != 255) { // Amplitude is reduced, so do the full math
scaled *= amplitude;
scaled >>= 8+(8-COMPARATOR_BITS);
} else { // Otherwise, only shift for the comparator bits
scaled >>= (8-COMPARATOR_BITS);
scaled *= amplitude; // multiply by the amplitude, max 255 or an 8-bit shift
scaled >>= 8; // bring it back 8 bits devide
}
scaled += 128>>(8-COMPARATOR_BITS);
// Scale to the number of bits available
#if COMPARATOR_BITS > DDS_LOOKUPVALUE_BITS
scaled <<= (COMPARATOR_BITS - DDS_LOOKUPVALUE_BITS);
#elif COMPARATOR_BITS < DDS_LOOKUPVALUE_BITS
scaled >>= (DDS_LOOKUPVALUE_BITS-COMPARATOR_BITS);
#else
// COMARATOR_BITS == DDS_LOOKUPVALUE_BITS -- no math needed.
#endif
//Move the sinewave up 1/2 scale into the positive range.
scaled += DDS_MAX_COMPARATOR/2;
return scaled;
}

150
DDS.h
View File

@ -3,27 +3,25 @@
#include <Arduino.h>
#include <avr/pgmspace.h>
// Just a little reminder
// Just a little (useless?) reminder; #warnings are not displayed in Arduino IDE.
#ifndef __SAMD21G18A__
#warning Experimental support for ArduinoZero. Not yet complete
#warning Experimental support for ArduinoZero. Not yet complete.
#endif
// For AVRs:
// Use pin 3 for PWM? If not defined, use pin 11
// Quality on pin 3 is higher than on 11, as it can be clocked faster
// when the COMPARATOR_BITS value is less than 8
#ifndef __SAMD21G18A__
#define DDS_PWM_PIN_3
#endif
// #define DDS_PWM_PIN_3
// For AVRs:
// Normally, we turn on timer2 and timer1, and have ADC sampling as our clock
// Define this to only use Timer2, and not start the ADC clock
// #define DDS_USE_ONLY_TIMER2
// Use a short (16 bit) accumulator. Phase accuracy is reduced, but speed
// is increased, along with a reduction in memory use.
#ifndef __SAMD21G18A__
// is increased, along with a reduction in memory use._
#define SHORT_ACCUMULATOR
#endif
#ifdef SHORT_ACCUMULATOR
#define ACCUMULATOR_BITS 16
@ -33,10 +31,15 @@ typedef uint16_t ddsAccumulator_t;
typedef uint32_t ddsAccumulator_t;
#endif
// The maximum value of the accumulator based on the number of bits
// Macro for code readability.
#define DDS_MAX_ACCUMULATOR (pow(2,ACCUMULATOR_BITS))
// If defined, the timer will idle at 50% duty cycle
// This leaves it floating in the centre of the PWM/DAC voltage range
#define DDS_IDLE_HIGH
// For AVRs:
// Select how fast the PWM is, at the expense of level accuracy.
// A faster PWM rate will make for easier filtering of the output wave,
// while a slower one will allow for more accurate voltage level outputs,
@ -44,23 +47,28 @@ typedef uint32_t ddsAccumulator_t;
// 8 = 62.5kHz PWM
// 7 = 125kHz PWM
// 6 = 250kHz PWM
// For SAMD21's -- the resolution of the DAC.
#ifdef __SAMD21G18A__
//TODO: 10 bit resolution for the Zero's DAC.
//Doesn't work just yet, so keep 8-bit for now.
#define COMPARATOR_BITS 8
typedef uint8_t ddsComparitor_t;
#define COMPARATOR_BITS 10
typedef uint16_t ddsComparitor_t;
#elif defined(DDS_PWM_PIN_3)
#define COMPARATOR_BITS 6
typedef uint8_t ddsComparitor_t;
#define COMPARATOR_BITS 6
typedef uint8_t ddsComparitor_t;
#else // When using pin 11, we always want 8 bits
#define COMPARATOR_BITS 8
typedef uint8_t ddsComparitor_t;
#define COMPARATOR_BITS 8
typedef uint8_t ddsComparitor_t;
#endif
// The maximum value of the comparitor based on the number of bits
// Macro for code readability.
#define DDS_MAX_COMPARATOR pow(2,COMPARATOR_BITS)
// This is how often we'll perform a phase advance, as well as ADC sampling
// rate. The higher this value, the smoother the output wave will be, at the
// expense of CPU time. It maxes out around 62000 (TBD)
// May be overridden in the sketch to improve performance
// expense of CPU time.
// For AVRs: It maxes out around 62000 (TBD) May be overridden in the sketch
// to improve performance
#ifndef DDS_REFCLK_DEFAULT
#ifdef __SAMD21G18A__
#define DDS_REFCLK_DEFAULT 44100
@ -88,9 +96,71 @@ typedef uint8_t ddsComparitor_t;
// accuracy, at the cost of more flash and CPU requirements.
// #define DDS_TABLE_LARGE
#ifdef DDS_TABLE_LARGE
// How many bits to keep from the accumulator to look up in this table
// When defined, use a 10-bit table of short integers. This is wasteful of
// flash space as there are 6 bits of each value that are unused.
// May improve resolution. When set, "DDS_TABLE_LARGE" is ignored.
// #define DDS_TABLE_10BIT
#ifdef DDS_TABLE_10BIT
// 10-bit Large SineTable, 1024 values +/-511
// Generated using http://www.meraman.com/htmls/en/sinTable.html
#define ACCUMULATOR_BIT_SHIFT (ACCUMULATOR_BITS-10)
#define DDS_LOOKUPVALUE_BITS 10
static const int16_t ddsSineTable[1024] PROGMEM = {0, 3, 6, 9, 13, 16, 19, 22, 25, 28, 31, 34, 38, 41, 44, 47, 50, 53,
56, 59, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127, 130, 133, 136,
139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178, 181, 184, 187, 190, 193, 196, 198, 201, 204, 207,
210, 213, 216, 218, 221, 224, 227, 230, 233, 235, 238, 241, 244, 246, 249, 252, 255, 257, 260, 263, 265, 268, 271, 273,
276, 279, 281, 284, 286, 289, 292, 294, 297, 299, 302, 304, 307, 309, 312, 314, 317, 319, 322, 324, 327, 329, 331, 334,
336, 338, 341, 343, 345, 348, 350, 352, 355, 357, 359, 361, 364, 366, 368, 370, 372, 374, 377, 379, 381, 383, 385, 387,
389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 410, 412, 414, 416, 418, 420, 421, 423, 425, 427, 428, 430, 432,
433, 435, 437, 438, 440, 441, 443, 445, 446, 448, 449, 451, 452, 454, 455, 456, 458, 459, 461, 462, 463, 465, 466, 467,
468, 470, 471, 472, 473, 474, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 492,
493, 494, 495, 496, 496, 497, 498, 499, 499, 500, 501, 501, 502, 502, 503, 503, 504, 505, 505, 505, 506, 506, 507, 507,
508, 508, 508, 509, 509, 509, 509, 510, 510, 510, 510, 510, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, 511,
511, 511, 511, 510, 510, 510, 510, 510, 509, 509, 509, 509, 508, 508, 508, 507, 507, 506, 506, 505, 505, 505, 504, 503,
503, 502, 502, 501, 501, 500, 499, 499, 498, 497, 496, 496, 495, 494, 493, 492, 492, 491, 490, 489, 488, 487, 486, 485,
484, 483, 482, 481, 480, 479, 478, 477, 476, 474, 473, 472, 471, 470, 468, 467, 466, 465, 463, 462, 461, 459, 458, 456,
455, 454, 452, 451, 449, 448, 446, 445, 443, 441, 440, 438, 437, 435, 433, 432, 430, 428, 427, 425, 423, 421, 420, 418,
416, 414, 412, 410, 409, 407, 405, 403, 401, 399, 397, 395, 393, 391, 389, 387, 385, 383, 381, 379, 377, 374, 372, 370,
368, 366, 364, 361, 359, 357, 355, 352, 350, 348, 345, 343, 341, 338, 336, 334, 331, 329, 327, 324, 322, 319, 317, 314,
312, 309, 307, 304, 302, 299, 297, 294, 292, 289, 286, 284, 281, 279, 276, 273, 271, 268, 265, 263, 260, 257, 255, 252,
249, 246, 244, 241, 238, 235, 233, 230, 227, 224, 221, 218, 216, 213, 210, 207, 204, 201, 198, 196, 193, 190, 187, 184,
181, 178, 175, 172, 169, 166, 163, 160, 157, 154, 151, 148, 145, 142, 139, 136, 133, 130, 127, 124, 121, 118, 115, 112,
109, 106, 103, 100, 97, 94, 90, 87, 84, 81, 78, 75, 72, 69, 66, 63, 59, 56, 53, 50, 47, 44, 41, 38, 34, 31, 28, 25, 22,
19, 16, 13, 9, 6, 3, 0, -3, -6, -9, -13, -16, -19, -22, -25, -28, -31, -34, -38, -41, -44, -47, -50, -53, -56, -59, -63,
-66, -69, -72, -75, -78, -81, -84, -87, -90, -94, -97, -100, -103, -106, -109, -112, -115, -118, -121, -124, -127, -130,
-133, -136, -139, -142, -145, -148, -151, -154, -157, -160, -163, -166, -169, -172, -175, -178, -181, -184, -187, -190,
-193, -196, -198, -201, -204, -207, -210, -213, -216, -218, -221, -224, -227, -230, -233, -235, -238, -241, -244, -246,
-249, -252, -255, -257, -260, -263, -265, -268, -271, -273, -276, -279, -281, -284, -286, -289, -292, -294, -297, -299,
-302, -304, -307, -309, -312, -314, -317, -319, -322, -324, -327, -329, -331, -334, -336, -338, -341, -343, -345, -348,
-350, -352, -355, -357, -359, -361, -364, -366, -368, -370, -372, -374, -377, -379, -381, -383, -385, -387, -389, -391,
-393, -395, -397, -399, -401, -403, -405, -407, -409, -410, -412, -414, -416, -418, -420, -421, -423, -425, -427, -428,
-430, -432, -433, -435, -437, -438, -440, -441, -443, -445, -446, -448, -449, -451, -452, -454, -455, -456, -458, -459,
-461, -462, -463, -465, -466, -467, -468, -470, -471, -472, -473, -474, -476, -477, -478, -479, -480, -481, -482, -483,
-484, -485, -486, -487, -488, -489, -490, -491, -492, -492, -493, -494, -495, -496, -496, -497, -498, -499, -499, -500,
-501, -501, -502, -502, -503, -503, -504, -505, -505, -505, -506, -506, -507, -507, -508, -508, -508, -509, -509, -509,
-509, -510, -510, -510, -510, -510, -511, -511, -511, -511, -511, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-511, -510, -510, -510, -510, -510, -509, -509, -509, -509, -508, -508, -508, -507, -507, -506, -506, -505, -505, -505,
-504, -503, -503, -502, -502, -501, -501, -500, -499, -499, -498, -497, -496, -496, -495, -494, -493, -492, -492, -491,
-490, -489, -488, -487, -486, -485, -484, -483, -482, -481, -480, -479, -478, -477, -476, -474, -473, -472, -471, -470,
-468, -467, -466, -465, -463, -462, -461, -459, -458, -456, -455, -454, -452, -451, -449, -448, -446, -445, -443, -441,
-440, -438, -437, -435, -433, -432, -430, -428, -427, -425, -423, -421, -420, -418, -416, -414, -412, -410, -409, -407,
-405, -403, -401, -399, -397, -395, -393, -391, -389, -387, -385, -383, -381, -379, -377, -374, -372, -370, -368, -366,
-364, -361, -359, -357, -355, -352, -350, -348, -345, -343, -341, -338, -336, -334, -331, -329, -327, -324, -322, -319,
-317, -314, -312, -309, -307, -304, -302, -299, -297, -294, -292, -289, -286, -284, -281, -279, -276, -273, -271, -268,
-265, -263, -260, -257, -255, -252, -249, -246, -244, -241, -238, -235, -233, -230, -227, -224, -221, -218, -216, -213,
-210, -207, -204, -201, -198, -196, -193, -190, -187, -184, -181, -178, -175, -172, -169, -166, -163, -160, -157, -154,
-151, -148, -145, -142, -139, -136, -133, -130, -127, -124, -121, -118, -115, -112, -109, -106, -103, -100, -97, -94,
-90, -87, -84, -81, -78, -75, -72, -69, -66, -63, -59, -56, -53, -50, -47, -44, -41, -38, -34, -31, -28, -25, -22, -19,
-16, -13, -9, -6, -3
};
#elif defined(DDS_TABLE_LARGE)
// Large SineTable, 1024 values +/-127
#define ACCUMULATOR_BIT_SHIFT (ACCUMULATOR_BITS-10) // How many bits to keep from the accumulator to look up in this table
#define DDS_LOOKUPVALUE_BITS 8
static const int8_t ddsSineTable[1024] PROGMEM = {
0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 13, 13, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 23, 24,
24, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 39, 39, 40, 41, 42, 42, 43, 44, 44, 45, 46, 47, 47,
@ -125,30 +195,26 @@ static const int8_t ddsSineTable[1024] PROGMEM = {
-48, -47, -47, -46, -45, -44, -44, -43, -42, -42, -41, -40, -39, -39, -38, -37, -36, -36, -35, -34, -33, -33, -32, -31, -30, -30, -29, -28, -27, -27, -26, -25,
-24, -24, -23, -22, -21, -20, -20, -19, -18, -17, -17, -16, -15, -14, -13, -13, -12, -11, -10, -10, -9, -8, -7, -7, -6, -5, -4, -3, -3, -2, -1, 0
};
#else
// Standard SineTable, 256 values +/-127
#define ACCUMULATOR_BIT_SHIFT (ACCUMULATOR_BITS-8)
static const int8_t ddsSineTable[256] PROGMEM = {
0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49,
51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88, 90,
92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113, 115,
116, 117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126,
126, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 125, 125,
124, 123, 122, 122, 121, 120, 118, 117, 116, 115, 113, 112, 111,
109, 107, 106, 104, 102, 100, 98, 96, 94, 92, 90, 88, 85, 83, 81,
78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51, 49, 46, 43, 40, 37,
34, 31, 28, 25, 22, 19, 16, 12, 9, 6, 3, 0, -3, -6, -9, -12, -16,
-19, -22, -25, -28, -31, -34, -37, -40, -43, -46, -49, -51, -54,
-57, -60, -63, -65, -68, -71, -73, -76, -78, -81, -83, -85, -88,
-90, -92, -94, -96, -98, -100, -102, -104, -106, -107, -109, -111,
-112, -113, -115, -116, -117, -118, -120, -121, -122, -122, -123,
-124, -125, -125, -126, -126, -126, -127, -127, -127, -127, -127,
-127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122,
-121, -120, -118, -117, -116, -115, -113, -112, -111, -109, -107,
-106, -104, -102, -100, -98, -96, -94, -92, -90, -88, -85, -83,
-81, -78, -76, -73, -71, -68, -65, -63, -60, -57, -54, -51, -49,
-46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3
};
#endif /* DDS_TABLE_LARGE */
#define DDS_LOOKUPVALUE_BITS 8
static const int8_t ddsSineTable[256] PROGMEM = {0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 51, 54,
57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113,
115, 116, 117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 126, 126,
126, 125, 125, 124, 123, 122, 122, 121, 120, 118, 117, 116, 115, 113, 112, 111, 109, 107, 106, 104, 102, 100, 98, 96,
94, 92, 90, 88, 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51, 49, 46, 43, 40, 37, 34, 31, 28, 25, 22, 19, 16,
12, 9, 6, 3, 0, -3, -6, -9, -12, -16, -19, -22, -25, -28, -31, -34, -37, -40, -43, -46, -49, -51, -54, -57, -60, -63,
-65, -68, -71, -73, -76, -78, -81, -83, -85, -88, -90, -92, -94, -96, -98, -100, -102, -104, -106, -107, -109, -111,
-112, -113, -115, -116, -117, -118, -120, -121, -122, -122, -123, -124, -125, -125, -126, -126, -126, -127, -127, -127,
-127, -127, -127, -127, -126, -126, -126, -125, -125, -124, -123, -122, -122, -121, -120, -118, -117, -116, -115, -113,
-112, -111, -109, -107, -106, -104, -102, -100, -98, -96, -94, -92, -90, -88, -85, -83, -81, -78, -76, -73, -71, -68,
-65, -63, -60, -57, -54, -51, -49, -46, -43, -40, -37, -34, -31, -28, -25, -22, -19, -16, -12, -9, -6, -3
};
#endif /* DDS_TABLE_LARGE, DDS_TABLE_10BIT */
class DDS {
public: