Skip to content

Instantly share code, notes, and snippets.

@ednisley ednisley/FMDDS.ino
Created Apr 18, 2018

Embed
What would you like to do?
TeensyDuino source code: FM DDS demo on bare Teensy 3.6
// FM DDS
// Ed Nisley - KE4ZNU
// 2017-04-19 Demo 1
#include <IntervalTimer.h>
#include <ADC.h>
#include <SPI.h>
#define HEART_PIN 14
#define TIMER_PIN 15
#define ANALOG_PIN 16
#define GLITCH_PIN 17
#define AUDIO_PIN A9
#define DDS_FQUD_PIN 10
// data to DDS MOSI0 11
// no data from DDS MISO0 12
// DDS clock on SCK0 13 -- also LED
#define BUILTIN_LED 13
//---------------------
// Useful constants
int SamplePeriod = 25; // microseconds per analog sample
//---------------------
// Globals
ADC *adc = new ADC();
IntervalTimer timer;
volatile unsigned int AnalogSample;
typedef struct {
uint8_t Phase;
uint8_t Bits31_24;
uint8_t Bits23_16;
uint8_t Bits15_8;
uint8_t Bits7_0;
} DDS;
DDS DDSBuffer = {0x01,0x02,0x04,0x08,0x10};
double DDSFreq, EpsilonFreq, DDSStepFreq;
double CenterFreq, TestFreq;
//---------------------
// Handy routines
void FlipPin(int pin) {
digitalWriteFast(pin,!digitalRead(pin));
}
void PulsePin(int p) {
FlipPin(p);
FlipPin(p);
}
//---------------------
// Timer handler
void timer_callback(void) {
digitalWriteFast(TIMER_PIN,HIGH);
digitalWriteFast(DDS_FQUD_PIN,HIGH); // latch previously shifted bits
adc->startSingleRead(AUDIO_PIN, ADC_0); // start ADC conversion
analogWriteDAC0(AnalogSample); // show previous audio sample
digitalWriteFast(TIMER_PIN,LOW);
}
//---------------------
// Analog read handler
void adc0_isr(void) {
digitalWriteFast(ANALOG_PIN,HIGH);
AnalogSample = adc->readSingle(); // fetch just-finished sample
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
digitalWriteFast(DDS_FQUD_PIN, LOW);
SPI.transfer(DDSBuffer.Phase); // interleave with FM calculations
SPI.transfer(DDSBuffer.Bits31_24);
SPI.transfer(DDSBuffer.Bits23_16);
SPI.transfer(DDSBuffer.Bits15_8);
SPI.transfer(DDSBuffer.Bits7_0);
SPI.endTransaction(); // do not raise FQ_UD until next timer tick!
digitalWriteFast(ANALOG_PIN,LOW);
}
//---------------------
// Hardware setup
void setup(void) {
pinMode(BUILTIN_LED,OUTPUT); // will eventually become SCK0
pinMode(HEART_PIN, OUTPUT); // show we arrived
digitalWrite(HEART_PIN,LOW);
PulsePin(HEART_PIN);
PulsePin(HEART_PIN);
pinMode(TIMER_PIN,OUTPUT);
digitalWrite(TIMER_PIN,LOW);
pinMode(GLITCH_PIN,OUTPUT);
digitalWrite(GLITCH_PIN,LOW);
pinMode(ANALOG_PIN,OUTPUT);
digitalWrite(ANALOG_PIN,LOW);
pinMode(AUDIO_PIN,INPUT);
pinMode(DDS_FQUD_PIN,OUTPUT);
digitalWriteFast(DDS_FQUD_PIN,HIGH);
Serial.begin(115200);
int waited = 0;
while (!Serial && waited < 3000) { // fall out after a few seconds
delay(1);
waited++;
if (! (waited % 50))
FlipPin(BUILTIN_LED);
}
Serial.printf("FM Modulated DDS\nEd Nisley KE4ZNU\n");
Serial.printf(" serial wait: %d ms\n\n",waited);
SPI.begin();
SPI.usingInterrupt(255); // attached through analog IRQs
adc->setAveraging(0);
adc->setResolution(12);
adc->setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED);
adc->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED);
adc->enableInterrupts(ADC_0);
if (!timer.begin(timer_callback, SamplePeriod)) {
Serial.printf("Timer start failed\n");
while (true) {
FlipPin(BUILTIN_LED);
delay(50);
}
}
DDSFreq = 180.0e6;
EpsilonFreq = 1.0e-5;
DDSStepFreq = DDSFreq / (1LL << 32);
Serial.printf("DDS frequency: %18.7f Hz\n",DDSFreq);
Serial.printf(" epsilon: %18.7f Hz\n",EpsilonFreq);
Serial.printf(" step: %18.7f Hz\n\n",DDSStepFreq);
CenterFreq = 146520000.0;
TestFreq = CenterFreq;
Serial.printf("Center frequency: %18.7f Hz\n",CenterFreq);
Serial.printf("Setup done\n");
}
//---------------------
// Do things forever
void loop(void) {
digitalWrite(HEART_PIN,HIGH);
if (TestFreq < (CenterFreq + 100*EpsilonFreq))
TestFreq += EpsilonFreq;
else
TestFreq += DDSStepFreq;
Serial.printf(" %18.7f Hz\n",TestFreq);
digitalWrite(HEART_PIN,LOW);
delay(500);
}
@ednisley

This comment has been minimized.

Copy link
Owner Author

commented Apr 18, 2018

More details on my blog at https://wp.me/poZKh-7tb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.