Skip to content

Instantly share code, notes, and snippets.

@la3pna
Created July 23, 2015 16:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save la3pna/263276cd933f5c100454 to your computer and use it in GitHub Desktop.
Save la3pna/263276cd933f5c100454 to your computer and use it in GitHub Desktop.
/*
VFO program for Si5351
Using I2C LCD from:
http://www.amazon.com/Huhushop-TM-Serial-Display-Arduino/dp/B00JM88A94/
Si5351 library from NT7S.
Uses the updated version of the library (master).
Updated with the format_freq routine from Tom AK2B
Display library is avaible from:
https://code.google.com/p/u8glib/
UNO and 328 boards: Encoder on pin 2 and 3. Center pin to GND.
Leonardo: Encoder on pin 0 and 1. Center pin to GND.
100nF from each of the encoder pins to gnd is used to debounce
The pushbutton goes to pin 6 to set the tuning rate.
Pin 7 is the RX/TX pin. Put this pin LOW for RX, open or high for TX.
Single transistor switch to +RX will work.
VFO will NOT tune in TX.
In serial monitor, you can send "F"+frequency to set frequency. Ex: "F7063000"
IF frequency is positive for sum product (IF = RF + LO) and negative for diff (IF = RF - LO)
VFO signal output on CLK0, BFO signal on CLK2
TODO:
* Write own OLED i2c library with optimizing for text to reduce size of compiled program.
*Add variable tuning resolution
*/
volatile unsigned long frequency = 144400000; // This will be the frequency it always starts on.
long freqstep[] = {50, 100, 500, 1000, 5000, 10000}; // set this to your wanted tuning rate in Hz.
int corr = 120; // this is the correction factor for the Si5351, use calibration sketch to find value.
long iffreq = 0; // set the IF frequency in Hz.
#include "U8glib.h"
//U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // I2C / TWI
U8GLIB_SSD1306_128X64 u8g(10, 9, 12, 11, 13); // SW SPI Com: SCK = 10, MOSI = 9, CS = 12, D0 = 11, RESET = 13
String str;
char b[8];
int inData;
String displayFreq;
boolean A_set = false;
boolean B_set = false;
unsigned int lastReportedPos = 1; // change management
static boolean rotating = false; // debounce management
#include <si5351.h>
#include "Wire.h"
Si5351 si5351;
// int encoderPinA ;
//int encoderPinB;
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
int encoderPinA = 0;
int encoderPinB = 1;
#endif
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
int encoderPinA = 2;
int encoderPinB = 3;
#endif
bool tx;
int txpin = 7;
int freqsteps = 1;
int bandbutton = 6;
#define arraylength (sizeof(freqstep) / sizeof(freqstep[0]))
void setup()
{
// set the encoder to inputs
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
pinMode(txpin, INPUT);
pinMode(bandbutton, INPUT);
// turn on pullup resistors
digitalWrite(encoderPinA, HIGH);
digitalWrite(encoderPinB, HIGH);
digitalWrite(txpin, HIGH);
digitalWrite(bandbutton, HIGH );
u8g.setFont(u8g_font_courB12);
Serial.begin(9600);
// Initialize the Si5351
// Change the 2nd parameter in init if using a ref osc other
// than 25 MHz
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0);
si5351.set_correction(corr);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_4MA);
si5351.drive_strength(SI5351_CLK2, SI5351_DRIVE_4MA);
// assign default color value
if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
u8g.setColorIndex(255); // white
}
else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
u8g.setColorIndex(3); // max intensity
}
else if ( u8g.getMode() == U8G_MODE_BW ) {
u8g.setColorIndex(1); // pixel on
}
else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
u8g.setHiColorByRGB(255, 255, 255);
}
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
encoderPinA = 0;
encoderPinB = 1;
//Code in here will only be compiled if an Arduino Leonardo is used.
// encoder pin on interrupt 2 (pin 0)
attachInterrupt(2, doEncoderA, CHANGE);
// encoder pin on interrupt 3 (pin 1)
attachInterrupt(3, doEncoderB, CHANGE);
#endif
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
encoderPinA = 2;
encoderPinB = 3;
//Code in here will only be compiled if an Arduino Uno (or older) is used.
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 1)
attachInterrupt(1, doEncoderB, CHANGE);
#endif
}
void loop()
{
tx = digitalRead(txpin);
rotating = true; // reset the debouncer
if ( lastReportedPos != frequency) {
lastReportedPos = frequency;
// Serial.print(frequency); // unncomment this to output frequency on change.
si5351.set_freq((frequency + iffreq) * 100ULL, 0, SI5351_CLK0);
}
if (digitalRead(bandbutton) == LOW ) {
delay(150); // delay to debounce
if (digitalRead(bandbutton) == LOW ) {
freqsteps = freqsteps + 1;
Serial.print(freqstep[freqsteps - 1]);
Serial.print(" ");
Serial.print(freqsteps);
Serial.print(" ");
Serial.println(sizeof(freqstep));
if (freqsteps > arraylength - 1 ) {
freqsteps = 0;
}
delay(1000); //delay to avoid many steps at one
}
}
format_freq();
// rebuild the picture after some delay
delay(50);
if (Serial.available() > 0) // see if incoming serial data:
{
inData = Serial.read(); // read oldest byte in serial buffer:
}
if (inData == 'F') {
frequency = Serial.parseInt();
inData = 0;
}
}
// Interrupt on A changing state
void doEncoderA() {
// debounce
if ( rotating ) delay (1); // wait a little until the bouncing is done
// Test transition, did things really change?
if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set ) {
if (!tx) {
frequency += freqstep[freqsteps]; // hehre is the amount to increase the freq
}
rotating = false; // no more debouncing until loop() hits again
}
}
}
// Interrupt on B changing state, same as A above
void doEncoderB() {
if ( rotating ) delay (1);
if ( digitalRead(encoderPinB) != B_set ) {
B_set = !B_set;
// adjust counter - 1 if B leads A
if ( B_set && !A_set ) {
if (!tx) {
frequency -= freqstep[freqsteps]; // here is the amount to decrease the freq
}
rotating = false;
}
}
}
void format_freq() {
u8g.firstPage();
do {
u8g.setPrintPos(0,15);
uint16_t f, g;
f = frequency / 1000000;
if (f < 10)
u8g.print(' ');
u8g.print(f);
u8g.print('.');
f = (frequency % 1000000) / 1000;
if (f < 100)
u8g.print('0');
if (f < 10)
u8g.print('0');
u8g.print(f);
u8g.print('.');
f = frequency % 1000;
if (f < 100)
u8g.print('0');
if (f < 10)
u8g.print('0');
u8g.print(f);
u8g.setPrintPos(80,32);
u8g.println(freqstep[freqsteps]);
if (tx)
{
u8g.drawStr( 110, 15, "TX" );
}
//draw();
} while ( u8g.nextPage() );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment