Compare commits

...

12 Commits

Author SHA1 Message Date
Morgan Redfield ec1fccf424
Merge pull request #6 from per1234/keywords-separator
Use correct field separator in keywords.txt
2018-08-04 18:13:20 -07:00
Morgan Redfield c2feff6816 update library keywords and properties 2018-08-04 18:12:16 -07:00
Morgan Redfield 95c808bb7f update keywords tabs 2018-08-04 13:39:06 -07:00
per1234 b66c2088b9
Use correct field separator in keywords.txt
The Arduino IDE requires the use of a single true tab separator between the keyword name and identifier. When spaces are used rather than a true tab the keyword is not highlighted.

Reference:
https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords
2018-07-15 22:26:20 -07:00
Morgan Redfield bcd6d7e6b3
Merge pull request #5 from per1234/remove-redundant-default-argument
Remove default argument from function definition
2018-03-07 21:41:25 -08:00
Nigel VH 0e8d42699a
Merge pull request #4 from per1234/arduino_h
#include Arduino.h dependency
2018-03-07 21:34:12 -08:00
per1234 3d476bf1c2
Remove default argument from function definition
Default arguments should only be specified in function prototypes, not in the function definition. This caused compilation of the library to fail for Arduino AVR Boards 1.6.11 or earlier. It does not cause compilation to fail for Arduino AVR Boards 1.6.12 and newer only because the -fpermissive compiler flag was added, which downgrades this to an error. It has been stated that flag may be removed in the future:
06868f4cd3
So this change is necessary for both backwards and forwards compatibility. Even with current versions it fixes a warning, which is always wise to do.
2018-03-07 21:32:24 -08:00
per1234 f9322214a9
#include Arduino.h dependency
Previously the library relied on the Arduino IDE doing the automatic insertion of #include <Arduino.h> in the sketch before #include <DDS.h>. In some IDE versions that does not happen and there is no guarantee of that behavior in future IDE versions thus for backwards and forwards compatibility it's best to simply add an #include directive to DDS.h.
2018-03-07 21:27:02 -08:00
nick6x 6726836631 Fix example 2017-07-30 12:07:00 -07:00
nick6x 7ebe201f96 Determine ISR on #define 2017-07-30 11:53:55 -07:00
nick6x c4daa7941b Fix examples isr 2017-07-28 16:16:10 -07:00
nick6x 6f4d8a93c5 Change 'Use Timer 2 Only' from compile option to software option 2017-07-28 10:52:11 -07:00
5 changed files with 86 additions and 50 deletions

View File

@ -9,6 +9,9 @@
#define PWM_PIN 3 #define PWM_PIN 3
#define DDS_USE_ONLY_TIMER2 true
#define TIMER2_PHASE_ADVANCE 24
DDS dds; DDS dds;
void setup() { void setup() {
@ -16,6 +19,7 @@ void setup() {
digitalWrite(PWM_PIN, LOW); digitalWrite(PWM_PIN, LOW);
dds.start(); dds.start();
dds.startPhaseAccumulator(DDS_USE_ONLY_TIMER2);
dds.playWait(600, 3000); dds.playWait(600, 3000);
dds.on(); dds.on();
//dds.setAmplitude(31); //dds.setAmplitude(31);
@ -25,9 +29,14 @@ void loop() {
dds.setFrequency(2200); dds.setFrequency(2200);
} }
#ifdef DDS_USE_ONLY_TIMER2
#if DDS_USE_ONLY_TIMER2
ISR(TIMER2_OVF_vect) { ISR(TIMER2_OVF_vect) {
dds.clockTick(); static unsigned char tcnt = 0;
if(++tcnt == TIMER2_PHASE_ADVANCE) {
tcnt = 0;
dds.clockTick();
}
} }
#else // Use the ADC timer instead #else // Use the ADC timer instead
ISR(ADC_vect) { ISR(ADC_vect) {

View File

@ -6,24 +6,36 @@
# Datatypes (KEYWORD1) # Datatypes (KEYWORD1)
####################################### #######################################
DDS KEYWORD1 DDS KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
####################################### #######################################
#begin KEYWORD2
#exists KEYWORD2 start KEYWORD2
#mkdir KEYWORD2 isRunning KEYWORD2
#remove KEYWORD2 stop KEYWORD2
#rmdir KEYWORD2 startPhaseAccumulator KEYWORD2
#open KEYWORD2 isTimer2Only KEYWORD2
#close KEYWORD2 on KEYWORD2
#seek KEYWORD2 off KEYWORD2
#position KEYWORD2 play KEYWORD2
#size KEYWORD2 playWait KEYWORD2
calcFrequency KEYWORD2
getPhaseAdvance KEYWORD2
setFrequency KEYWORD2
setPrecalcFrequency KEYWORD2
setPhaseDeg KEYWORD2
setAmplitude KEYWORD2
changePhaseDeg KEYWORD2
setReferenceClock KEYWORD2
getReferenceClock KEYWORD2
setReferenceOffset KEYWORD2
getReferenceOffset KEYWORD2
getDutyCycle KEYWORD2
clockTick KEYWORD2
####################################### #######################################
# Constants (LITERAL1) # Constants (LITERAL1)
####################################### #######################################
#FILE_READ LITERAL1
#FILE_WRITE LITERAL1

View File

@ -1,10 +1,10 @@
name=DDS name=DDS
version=1.0.2 version=1.0.3
author=Morgan Redfield <morgan@enhancedradio.com>, Casey Halverson <casey@enhancedradio.com> author=Morgan Redfield <morgan@enhancedradio.com>, Casey Halverson <casey@enhancedradio.com>
maintainer=Morgan Redfield <morgan@enhancedradio.com> maintainer=Morgan Redfield <morgan@enhancedradio.com>
sentence=A library for use with HamShield by Enhanced Radio Devices. sentence=Generate sinusoids on AVR-based Arduinos at varying frequencies. Requires an analog low-pass filter.
paragraph= paragraph=
category=Device Control category=Signal Input/Output
url=http://www.hamshield.com url=http://www.hamshield.com
architectures=* architectures=avr
includes=DDS.h includes=DDS.h

View File

@ -13,6 +13,7 @@ void DDS::start() {
#ifdef DDS_PWM_PIN_3 #ifdef DDS_PWM_PIN_3
TCCR2A = (TCCR2A | _BV(COM2B1)) & ~(_BV(COM2B0) | _BV(COM2A1) | _BV(COM2A0)) | TCCR2A = (TCCR2A | _BV(COM2B1)) & ~(_BV(COM2B0) | _BV(COM2A1) | _BV(COM2A0)) |
_BV(WGM21) | _BV(WGM20); _BV(WGM21) | _BV(WGM20);
//TCCR2B = (TCCR2B & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20) | _BV(WGM22);
TCCR2B = (TCCR2B & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20) | _BV(WGM22); TCCR2B = (TCCR2B & ~(_BV(CS22) | _BV(CS21))) | _BV(CS20) | _BV(WGM22);
#else #else
// Alternatively, use pin 11 // Alternatively, use pin 11
@ -33,42 +34,49 @@ void DDS::start() {
OCR2A = 0; OCR2A = 0;
#endif #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){
timer2only = use_only_timer_2;
if(timer2only){
TIMSK2 |= _BV(TOIE2);
}
// Second, setup Timer1 to trigger the ADC interrupt // Second, setup Timer1 to trigger the ADC interrupt
// This lets us use decoding functions that run at the same reference // This lets us use decoding functions that run at the same reference
// clock as the DDS. // clock as the DDS.
// We use ICR1 as TOP and prescale by 8 // We use ICR1 as TOP and prescale by 8
/* TCCR1B = _BV(CS10) | _BV(WGM13) | _BV(WGM12); if(!timer2only){
TCCR1A = 0; TCCR1B = _BV(CS10) | _BV(WGM13) | _BV(WGM12);
ICR1 = ((F_CPU / 1) / refclk) - 1; TCCR1A = 0;
#ifdef DDS_DEBUG_SERIAL ICR1 = ((F_CPU / 1) / refclk) - 1;
Serial.print(F("DDS SysClk: ")); #ifdef DDS_DEBUG_SERIAL
Serial.println(F_CPU/8); Serial.print(F("DDS SysClk: "));
Serial.print(F("DDS RefClk: ")); Serial.println(F_CPU/8);
Serial.println(refclk, DEC); Serial.print(F("DDS RefClk: "));
Serial.print(F("DDS ICR1: ")); Serial.println(refclk, DEC);
Serial.println(ICR1, DEC); Serial.print(F("DDS ICR1: "));
#endif Serial.println(ICR1, DEC);
#endif
// Configure the ADC here to automatically run and be triggered off Timer1 // 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) ADMUX = _BV(REFS0) | _BV(ADLAR) | 0; // Channel 0, shift result left (ADCH used)
DDRC &= ~_BV(0); DDRC &= ~_BV(0);
PORTC &= ~_BV(0); PORTC &= ~_BV(0);
DIDR0 |= _BV(0); DIDR0 |= _BV(0);
ADCSRB = _BV(ADTS2) | _BV(ADTS1) | _BV(ADTS0); ADCSRB = _BV(ADTS2) | _BV(ADTS1) | _BV(ADTS0);
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2); // | _BV(ADPS0); 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;
} }
// Set our current sine wave frequency in Hz // 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); newStep = (1500.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS);
} else if (freq == 600) { } else if (freq == 600) {
newStep = (600.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS); newStep = (600.0 / (DDS_REFCLK_DEFAULT+DDS_REFCLK_OFFSET)) * pow(2,ACCUMULATOR_BITS);
} else {
newStep = pow(2,ACCUMULATOR_BITS)*freq / (refclk+refclkOffset);
} }
} else { } else {
newStep = pow(2,ACCUMULATOR_BITS)*freq / (refclk+refclkOffset); newStep = pow(2,ACCUMULATOR_BITS)*freq / (refclk+refclkOffset);

View File

@ -1,6 +1,7 @@
#ifndef _DDS_H_ #ifndef _DDS_H_
#define _DDS_H_ #define _DDS_H_
#include <Arduino.h>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
// Use pin 3 for PWM? If not defined, use pin 11 // Use pin 3 for PWM? If not defined, use pin 11
@ -10,7 +11,7 @@
// Normally, we turn on timer2 and timer1, and have ADC sampling as our clock // 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 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 // Use a short (16 bit) accumulator. Phase accuracy is reduced, but speed
// is increased, along with a reduction in memory use. // is increased, along with a reduction in memory use.
@ -133,7 +134,7 @@ class DDS {
public: public:
DDS(): refclk(DDS_REFCLK_DEFAULT), refclkOffset(DDS_REFCLK_OFFSET), DDS(): refclk(DDS_REFCLK_DEFAULT), refclkOffset(DDS_REFCLK_OFFSET),
accumulator(0), running(false), accumulator(0), running(false),
timeLimited(false), tickDuration(0), amplitude(255) timeLimited(false), tickDuration(0), amplitude(255), timer2only(false)
{}; {};
// Start all of the timers needed // Start all of the timers needed
@ -142,6 +143,9 @@ public:
const bool isRunning() { return running; }; const bool isRunning() { return running; };
// Stop the DDS timers // Stop the DDS timers
void stop(); void stop();
// Start the phase accumulator
void startPhaseAccumulator(bool use_only_timer_2 = false);
bool isTimer2Only() { return timer2only; };
// Start and stop the PWM output // Start and stop the PWM output
void on() { void on() {
@ -214,6 +218,7 @@ public:
void clockTick(); void clockTick();
private: private:
volatile bool timer2only;
volatile bool running; volatile bool running;
volatile unsigned long tickDuration; volatile unsigned long tickDuration;
volatile bool timeLimited; volatile bool timeLimited;