diff --git a/AFSK.cpp b/AFSK.cpp index 49ed68c..4bf18b1 100644 --- a/AFSK.cpp +++ b/AFSK.cpp @@ -121,7 +121,7 @@ bool AFSK::Encoder::start() { lastZero = 0; bitPosition = 0; bitClock = 0; - preamble = 0b11000; // 6.7ms each, 23 = 153ms + preamble = 0b110000; // 6.7ms each, 23 = 153ms done = false; hdlc = true; packet = 0x0; // No initial packet, find in the ISR diff --git a/DDS.cpp b/DDS.cpp index 86dd8ac..e4141bd 100644 --- a/DDS.cpp +++ b/DDS.cpp @@ -40,10 +40,18 @@ void DDS::start() { // Second, setup Timer1 to trigger the ADC interrupt // This lets us use decoding functions that run at the same reference // clock as the DDS. - TCCR1B = _BV(CS11) | _BV(WGM13) | _BV(WGM12); + // We use ICR1 as TOP and prescale by 8 + TCCR1B = _BV(CS10) | _BV(WGM13) | _BV(WGM12); TCCR1A = 0; - ICR1 = ((F_CPU / 8) / refclk) - 1; - //ICR1 = ((F_CPU / 8) / 9600) - 1; + 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) @@ -56,6 +64,10 @@ void DDS::start() { 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 diff --git a/DDS.h b/DDS.h index 6ce0b3b..79b23ef 100644 --- a/DDS.h +++ b/DDS.h @@ -18,10 +18,10 @@ #ifdef SHORT_ACCUMULATOR #define ACCUMULATOR_BITS 16 -typedef int16_t ddsAccumulator_t; +typedef uint16_t ddsAccumulator_t; #else #define ACCUMULATOR_BITS 32 -typedef int32_t ddsAccumulator_t; +typedef uint32_t ddsAccumulator_t; #endif // If defined, the timer will idle at 50% duty cycle @@ -60,6 +60,9 @@ typedef int32_t ddsAccumulator_t; #define DDS_REFCLK_DEFAULT (62500/4) #endif +// Output some of the calculations and information about the DDS over serial +#define DDS_DEBUG_SERIAL + // When defined, use the 1024 element sine lookup table. This improves phase // accuracy, at the cost of more flash and CPU requirements. // #define DDS_TABLE_LARGE diff --git a/examples/Crystal-Calibration/Crystal-Calibration.ino b/examples/Crystal-Calibration/Crystal-Calibration.ino new file mode 100644 index 0000000..fcebe22 --- /dev/null +++ b/examples/Crystal-Calibration/Crystal-Calibration.ino @@ -0,0 +1,152 @@ +#define DDS_REFCLK_DEFAULT 19200 +#define DDS_REFCLK_OFFSET 0 +#define DDS_DEBUG_SERIAL + +#include +#include + +HamShield radio; +DDS dds; + +void setup() { + Serial.begin(9600); + Wire.begin(); + radio.initialize(); + radio.setVHF(); + radio.setRfPower(0); + radio.setFrequency(145050); + + pinMode(2, OUTPUT); + pinMode(3, OUTPUT); + pinMode(11, INPUT); + + dds.start(); + dds.setFrequency(1200); + dds.on(); + + radio.bypassPreDeEmph(); +} + +enum Sets { + SET_REF, + SET_TONE, + SET_AMPLITUDE +} setting = SET_TONE; + +char freqBuffer[8]; +char *freqBufferPtr = freqBuffer; +uint16_t lastFreq = 1200; + +void loop() { + while(Serial.available()) { + char c = Serial.read(); + Serial.print(c); + switch(c) { + case 'h': + Serial.println(F("Commands:")); + Serial.println(F("RefClk: u = +10, U = +100, r XXXX = XXXX")); + Serial.println(F(" d = -10, D = -100")); + Serial.println(F("Radio: T = transmit, R = receive")); + Serial.println(F("Tone: t XXXX = XXXX Hz")); + Serial.println(F("Amp.: a XXX = XXX out of 255")); + Serial.println(F("DDS: o = On, O = Off")); + Serial.println(F("ie. a 31 = 32/255 amplitude, r38400 sets 38400Hz refclk")); + Serial.println("> "); + break; + case 'u': + dds.setReferenceClock(dds.getReferenceClock()+10); + dds.setFrequency(lastFreq); + dds.start(); + Serial.println(F("RefClk + 10 = ")); + Serial.println(dds.getReferenceClock()); + Serial.println("> "); + break; + case 'U': + dds.setReferenceClock(dds.getReferenceClock()+100); + dds.setFrequency(lastFreq); + dds.start(); + Serial.println(F("RefClk + 100 = ")); + Serial.println(dds.getReferenceClock()); + Serial.println("> "); + break; + case 'd': + dds.setReferenceClock(dds.getReferenceClock()-10); + dds.setFrequency(lastFreq); + dds.start(); + Serial.println(F("RefClk - 10 = ")); + Serial.println(dds.getReferenceClock()); + Serial.println("> "); + break; + case 'D': + dds.setReferenceClock(dds.getReferenceClock()-100); + dds.setFrequency(lastFreq); + dds.start(); + Serial.println(F("RefClk - 100 = ")); + Serial.println(dds.getReferenceClock()); + Serial.println("> "); + break; + case 'T': + Serial.println(F("Radio transmit")); + radio.setModeTransmit(); + Serial.println("> "); + break; + case 'R': + Serial.println(F("Radio receive")); + radio.setModeReceive(); + Serial.println("> "); + break; + case 'r': + setting = SET_REF; + break; + case 't': + setting = SET_TONE; + break; + case 'a': + setting = SET_AMPLITUDE; + break; + case 'o': + dds.on(); + Serial.println("> "); + break; + case 'O': + dds.off(); + Serial.println("> "); + break; + default: + if(c >= '0' && c <= '9') { + *freqBufferPtr = c; + freqBufferPtr++; + } + if(c == '\n' && freqBufferPtr != freqBuffer) { + *freqBufferPtr = '\0'; + freqBufferPtr = freqBuffer; + uint16_t freq = atoi(freqBuffer); + if(setting == SET_REF) { + dds.setReferenceClock(freq); + dds.setFrequency(lastFreq); + dds.start(); + Serial.print(F("New Reference Clock: ")); + Serial.println(dds.getReferenceClock()); + } else if(setting == SET_TONE) { + dds.setFrequency(freq); + lastFreq = freq; + Serial.print(F("New Tone: ")); + Serial.println(freq); + } else if(setting == SET_AMPLITUDE) { + dds.setAmplitude((uint8_t)(freq&0xFF)); + Serial.print(F("New Amplitude: ")); + Serial.println((uint8_t)(freq&0xFF)); + } + Serial.println("> "); + } + break; + } + } +} + +ISR(ADC_vect) { + TIFR1 = _BV(ICF1); + PORTD |= _BV(2); + dds.clockTick(); + PORTD &= ~_BV(2); +}