Created
April 18, 2018 23:42
-
-
Save ednisley/a7279b273dfb36149349d5906417e3bb to your computer and use it in GitHub Desktop.
TeensyDuino source code: FM DDS demo on bare Teensy 3.6
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
More details on my blog at https://wp.me/poZKh-7tb