Monday 10 April 2017

BASIC Tech Group - MyNews 39 - Updated VFO with OLED display

Here’s the updated sketch for my AD9850 based VFO, to use an OLED display. The VFO tunes in 10Hz to 1MHz steps. I have in development a buffer amplifier - probably it will be based on an MMIC (ERA2-SM)maybe  to give up to +10dBm output.

Screen Shot 2017 04 11 at 17 02 50

Code

// VFO_ADS_OLED
// V1.5 9-4-17 update to U8g2lib
// output G0
// freq steps 10Hz, 100Hz, 1kHz, 10kHz, 100kHz, 1MHz
// AD9850
// W_CLK 8
// FQ_UD 9
// DATA 10
// RESET 11
// OLED 128x64
// SDA = A4
// SCL = A5
// rotary encoder pins
// DT = 2
// CLK = 3
// SW = 4


// ADS9850, OLED and Rotary Encoder, I2C libraries
#include "ADS9850.h"
#include "U8g2lib.h"
#include "Rotary.h"
#include "Wire.h"

// AD9850 pins
#define W_CLK 8
#define FQ_UD 9
#define DATA 10
#define RESET 11

// chose pin 2,3 or 3,2 for encoder
#define DT 2
//#define DT 3
#define CLK 3
//#define CLK 2
#define SW 4

// xtal calibration
#define CALIBRATE 125000000

// ads (analog-output digital synthesiser) object
ADS9850 ads;

// oled object
U8G2_SH1106_128X64_NONAME_1_HW_I2C oled(U8G2_R0, U8X8_PIN_NONE, SCL, SDA);

// Encoder object
Rotary enc = Rotary(DT, CLK);

// phase coding, 0-180 [0-5] in 11.25deg steps
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 AD9850
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(40, 0, "VFO_ADS");
dispFreq(15, 25, freqHz, freqChz, 2);
dispMsg(30, 50, "Step");
dispStep(70, 50, freqStep);

} while ( oled.nextPage() );
}

// display freq at x, y, f (Hz), cf (cHz), d)ecimal places
void dispFreq(u8g2_uint_t x, u8g2_uint_t y, double f, double cf, uint8_t d) {
double fd;
char buf[100];

// sets font, cursor position and displays freq
oled.setFont(u8g2_font_10x20_tf); // font
oled.setFontPosTop(); // origin top

fd = f + cf / 100; // calc freq

oled.setCursor(x, y);
oled.print(fd / 1000, d);
oled.print("kHz");
}

void dispStep(u8g2_uint_t x, u8g2_uint_t y, uint64_t s) {
// set font, cursor position and display step
oled.setFont(u8g2_font_7x13_tf); // font
oled.setFontPosTop();

oled.setCursor(x, y);
switch (s) // display freqStep
{
case 10:
oled.print("10Hz ");
break;
case 100:
oled.print("100Hz ");
break;
case 1000:
oled.print("1kHz ");
break;
case 10000:
oled.print("10kHz ");
break;
case 100000:
oled.print("100kHz ");
break;
case 1000000:
oled.print("1MHz ");
break;
}
}

// display message at at x), y), *m)essage
void dispMsg(u8g2_uint_t x, u8g2_uint_t y, char *m) {
// sets font, cursor position and displays message
oled.setFont(u8g2_font_7x13_tf); // font
oled.setFontPosTop();
oled.setCursor(x, y);
oled.print(m);
}

No comments: