From 31eb465ebfbe14edfbe07d48d850c66b3efeb28f Mon Sep 17 00:00:00 2001 From: Stephen Olesen Date: Wed, 1 Jul 2015 14:27:10 -0600 Subject: [PATCH] Allow for high idle duty cycle when output is 'off', amplitude adjustments. --- DDS.cpp | 14 +++++++++++--- DDS.h | 30 ++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/DDS.cpp b/DDS.cpp index b88b556..5b2336b 100644 --- a/DDS.cpp +++ b/DDS.cpp @@ -61,22 +61,30 @@ void DDS::clockTick() { accumulator += stepRate; if(running) { if(tickDuration == 0) { +#ifdef DDS_IDLE_HIGH + // Set the duty cycle to 50% + OCR2B = pow(2,COMPARATOR_BITS)/2; +#else + // Set duty cycle to 0, effectively off OCR2B = 0; +#endif running = false; } else { - OCR2B = getPhaseAngle(); + OCR2B = getDutyCycle(); } // Reduce our playback duration by one tick tickDuration--; } } -uint8_t DDS::getPhaseAngle() { +uint8_t DDS::getDutyCycle() { #if ACCUMULATOR_BIT_SHIFT >= 24 uint16_t phAng; #else uint8_t phAng; #endif phAng = (accumulator >> ACCUMULATOR_BIT_SHIFT); - return pgm_read_byte_near(ddsSineTable + phAng)>>(8-COMPARATOR_BITS); + uint8_t position = pgm_read_byte_near(ddsSineTable + phAng)>>(8-COMPARATOR_BITS); + // Apply scaling and return + return position >> amplitude; } diff --git a/DDS.h b/DDS.h index edb8dcf..8c17432 100644 --- a/DDS.h +++ b/DDS.h @@ -11,6 +11,10 @@ #define ACCUMULATOR_BITS 32 #endif +// 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 + #define COMPARATOR_BITS 6 #define DDS_REFCLK_DEAULT 38400 @@ -123,7 +127,7 @@ public: void on(unsigned short duration) { // Duration in ticks from milliseconds is: // t = (1/refclk) - tickDuration = duration / (1000.0/refclk); + tickDuration = (duration * refclk) / 1000; running = true; } void off() { @@ -137,8 +141,7 @@ public: } // Blocking version void playWait(unsigned short freq, unsigned short duration) { - setFrequency(freq); - on(duration); + play(freq, duration); delay(duration * 1000); } @@ -149,20 +152,27 @@ public: // Adjustable reference clock void setReferenceClock(unsigned long ref); - uint8_t getPhaseAngle(); + uint8_t getDutyCycle(); + // Set a scaling factor. To keep things quick, this is a power of 2 value. + // Set it with 0 for lowest (which will be off), 8 is highest. + void setAmplitude(unsigned char amp) { + amplitude = 8 - amp; + } + void clockTick(); private: - bool running; - unsigned long tickDuration; + volatile bool running; + volatile unsigned long tickDuration; + volatile unsigned char amplitude; #ifdef SHORT_ACCUMULATOR - unsigned short accumulator; - unsigned short stepRate; + volatile unsigned short accumulator; + volatile unsigned short stepRate; unsigned short refclk; #else - unsigned long accumulator; - unsigned long stepRate; + volatile unsigned long accumulator; + volatile unsigned long stepRate; unsigned long refclk; #endif static DDS *sDDS;