diff --git a/examples/SimpleSin/SimpleSin.ino b/examples/SimpleSin/SimpleSin.ino index ce7cc4d..f6cfd65 100644 --- a/examples/SimpleSin/SimpleSin.ino +++ b/examples/SimpleSin/SimpleSin.ino @@ -16,6 +16,7 @@ void setup() { digitalWrite(PWM_PIN, LOW); dds.start(); + dds.startPhaseAccumulator(false); dds.playWait(600, 3000); dds.on(); //dds.setAmplitude(31); @@ -38,4 +39,4 @@ ISR(ADC_vect) { } dds.clockTick(); } -#endif \ No newline at end of file +#endif diff --git a/src/DDS.cpp b/src/DDS.cpp index 9825eff..01b49c1 100644 --- a/src/DDS.cpp +++ b/src/DDS.cpp @@ -13,6 +13,7 @@ void DDS::start() { #ifdef DDS_PWM_PIN_3 TCCR2A = (TCCR2A | _BV(COM2B1)) & ~(_BV(COM2B0) | _BV(COM2A1) | _BV(COM2A0)) | _BV(WGM21) | _BV(WGM20); + //TCCR2B = (TCCR2B & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20) | _BV(WGM22); TCCR2B = (TCCR2B & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20) | _BV(WGM22); #else // Alternatively, use pin 11 @@ -33,42 +34,49 @@ void DDS::start() { OCR2A = 0; #endif -#ifdef DDS_USE_ONLY_TIMER2 - TIMSK2 |= _BV(TOIE2); -#endif + +} + +void DDS::stop() { + // TODO: Stop the timers. + if(!timer2only){ + TCCR1B = 0; + } + TCCR2B = 0; +} + +void DDS::startPhaseAccumulator(bool use_only_timer_2 = false){ + timer2only = use_only_timer_2; + + if(timer2only){ + TIMSK2 |= _BV(TOIE2); + } // Second, setup Timer1 to trigger the ADC interrupt // This lets us use decoding functions that run at the same reference // clock as the DDS. // We use ICR1 as TOP and prescale by 8 -/* TCCR1B = _BV(CS10) | _BV(WGM13) | _BV(WGM12); - TCCR1A = 0; - ICR1 = ((F_CPU / 1) / refclk) - 1; -#ifdef DDS_DEBUG_SERIAL - Serial.print(F("DDS SysClk: ")); - Serial.println(F_CPU/8); - Serial.print(F("DDS RefClk: ")); - Serial.println(refclk, DEC); - Serial.print(F("DDS ICR1: ")); - Serial.println(ICR1, DEC); -#endif + if(!timer2only){ + TCCR1B = _BV(CS10) | _BV(WGM13) | _BV(WGM12); + TCCR1A = 0; + ICR1 = ((F_CPU / 1) / refclk) - 1; + #ifdef DDS_DEBUG_SERIAL + Serial.print(F("DDS SysClk: ")); + Serial.println(F_CPU/8); + Serial.print(F("DDS RefClk: ")); + Serial.println(refclk, DEC); + Serial.print(F("DDS ICR1: ")); + Serial.println(ICR1, DEC); + #endif // Configure the ADC here to automatically run and be triggered off Timer1 - ADMUX = _BV(REFS0) | _BV(ADLAR) | 0; // Channel 0, shift result left (ADCH used) - DDRC &= ~_BV(0); - PORTC &= ~_BV(0); - DIDR0 |= _BV(0); - ADCSRB = _BV(ADTS2) | _BV(ADTS1) | _BV(ADTS0); - ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2); // | _BV(ADPS0); -*/ -} - -void DDS::stop() { - // TODO: Stop the timers. -#ifndef DDS_USE_ONLY_TIMER2 - TCCR1B = 0; -#endif - TCCR2B = 0; + ADMUX = _BV(REFS0) | _BV(ADLAR) | 0; // Channel 0, shift result left (ADCH used) + DDRC &= ~_BV(0); + PORTC &= ~_BV(0); + DIDR0 |= _BV(0); + ADCSRB = _BV(ADTS2) | _BV(ADTS1) | _BV(ADTS0); + ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2); // | _BV(ADPS0); + } } // Set our current sine wave frequency in Hz @@ -88,6 +96,8 @@ ddsAccumulator_t DDS::calcFrequency(unsigned short freq) { newStep = (1500.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS); } else if (freq == 600) { newStep = (600.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS); + } else { + newStep = pow(2,ACCUMULATOR_BITS)*freq / (refclk+refclkOffset); } } else { newStep = pow(2,ACCUMULATOR_BITS)*freq / (refclk+refclkOffset); diff --git a/src/DDS.h b/src/DDS.h index 57cf40b..ef6d193 100644 --- a/src/DDS.h +++ b/src/DDS.h @@ -10,7 +10,7 @@ // 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 +//#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. @@ -133,7 +133,7 @@ class DDS { public: DDS(): refclk(DDS_REFCLK_DEFAULT), refclkOffset(DDS_REFCLK_OFFSET), accumulator(0), running(false), - timeLimited(false), tickDuration(0), amplitude(255) + timeLimited(false), tickDuration(0), amplitude(255), timer2only(false) {}; // Start all of the timers needed @@ -142,6 +142,9 @@ public: const bool isRunning() { return running; }; // Stop the DDS timers void stop(); + // Start the phase accumulator + void startPhaseAccumulator(bool use_only_timer_2 = false); + bool isTimer2Only() { return timer2only; }; // Start and stop the PWM output void on() { @@ -214,6 +217,7 @@ public: void clockTick(); private: + volatile bool timer2only; volatile bool running; volatile unsigned long tickDuration; volatile bool timeLimited;