This code has been updated - see later posting!!
Here's the code for a VFO using the AD9851, up to 70MHz. The AD9851 code is here
// VFO_ADS51_OLED
// V1.0 16-4-17 VFO for the AD9851, 30MHz external xtal, x6 180MHz internal clock
// freq steps 10Hz, 100Hz, 1kHz, 10kHz, 100kHz, 1MHz
// AD9851
// RESET 8
// DATA 9
// FQ_UD 10
// W_CLK 11
// OLED 128x64
// SDA = A4
// SCL = A5
// rotary encoder pins
// CLK = 2
// DT = 3
// SW = 4
// OLED, AD9851, Rotary Encoder & I2C libraries
#include "Oled_128X64_I2C.h"
#include "ADS9851.h"
#include "Rotary.h"
// AD9851 pins
#define RESET 8
#define DATA 9
#define FQ_UD 10
#define W_CLK 11
// xtal calibration (30MHz external x6 REFCLK = 180MHz internal
#define CALIBRATE 180002300 // cal against SDR (cal at 7070 against CORRA)
// encoder
#define CLK 2
#define DT 3
#define SW 4
// ads (analog-output digital synthesiser) object
ADS9851 ads;
// Encoder object
Rotary enc = Rotary(DT, CLK);
// phase coding, 0-180 [0-5]
uint8_t ph[] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x10};
// initial settings
volatile double freqHz = 7100000; // (Hz) start frequency 7.1MHz
volatile double freqChz = 0; // (cHz) additional 0cHz
volatile double freqStep = 10; // (Hz) init 10Hz freqStep
uint8_t phase = ph[0]; // init phase
// freq change flag
volatile bool freqChange;
void setup() {
// encoder, button pins
pinMode(DT, INPUT_PULLUP);
pinMode(CLK, INPUT_PULLUP);
pinMode(SW, INPUT_PULLUP);
// setup interrupts from DT or CLK for tuning
attachInterrupt(digitalPinToInterrupt(DT), freqTune, CHANGE);
attachInterrupt(digitalPinToInterrupt(CLK), freqTune, CHANGE);
interrupts(); // enable
// oled init, sets I2C addr to 0x3C
oled.begin();
// init ads, executes down() to flush buffers
ads.begin(W_CLK, FQ_UD, DATA, RESET);
// calibrate to xtal actual frequency
ads.calibrate(CALIBRATE);
ads.setFreq(freqHz, freqChz, phase);
freqChange = false;
dispUpdate();
}
// check button & freq tune, update display
void loop() {
if (button()) {
dispUpdate();
}
if (freqChange) {
// freq updated
ads.setFreq(freqHz, freqChz, phase);
freqChange = false;
dispUpdate();
}
}
// ISR - encoder interrupt service routine
void freqTune() {
unsigned char result;
result = enc.process();
if (result == DIR_CW ) {
freqHz += freqStep;
freqChange = true;
}
else if (result == DIR_CCW) {
freqHz -= freqStep;
freqChange = true;
}
}
// change freqStep, 10Hz to 1MHz
bool button() {
if (digitalRead(SW) == LOW) { // button pressed?
while (!digitalRead(SW)); // wait for release
if (freqStep == 1000000) freqStep = 10; // back to 10Hz
else freqStep = freqStep * 10; // or increase by x10
return true;
}
else {
return false;
}
}
// picture loop, display init data
void dispUpdate() {
oled.firstPage();
do {
dispMsg(50, 0, "VFO");
dispFreq(15, 25, freqHz, freqChz, 2);
dispMsg(15, 50, "<--");
dispStep(45, 50, freqStep);
dispMsg(95, 50, "-->");
} while ( oled.nextPage() );
}
No comments:
Post a Comment