I found this page which was helpful in figuring out which pins to wire to communicate with the DDS. http://webshed.org/wiki/AD9850_Arduino
I learned that Reset on my board is “REST”. The init sketch (bottom of page) had that line tied to pin 11 whereas the SNA Jr II sketch has it moved to A2.
Pin 10 in the init sketch is Data which is “D7” on my DDS and that goes to A3 in the SNA Jr II sketch. Pin 9 is Load or “FQUP” which goes to A4. Finally there is pin 8 which is Clock or “WCLK” and that goes to A5.
/*********************************************************************
Simple SNA for the HF amateur bands
portions of this software are covered by the GNU General Public License ,
BEERWARE, or other open source licenses
DuWayne KV4QB
----------------------------------------------------------------------------
"THE BEER-WARE LICENSE" (Revision 42):
<duwayne@kv4qb.us> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy me a beer in return. DuWayne
----------------------------------------------------------------------------
Libraries used Adafruit LCD and Graphics Libraries
rotary.h from AD7C
*************/
#include <SPI.h>
#include <rotary.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h> // Hardware-specific library
// pins used by TFT Display
#define TFT_CS 6
#define TFT_DC 10
#define TFT_RST 7
#define Backlight 9 // Analog output pin that the LED is attached to
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
Adafruit_ST7735 display = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// AD9850 info
#define W_CLK A5 // connect to AD9850 module word load clock pin (CLK)
#define FQ_UD A4 // connect to freq update pin (FQ)
#define DATA A3 // connect to serial data load pin (DATA)
#define DDS_RESET A2 //- connect to reset pin (RST)
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
#define AD8307_POWER_CALIBERATION (-872) // value is determained by checking reading against known input value
// start with 840 ad8307 log intgerccedpt * 10
#define FreqCorr 0.2897435 // frequency correction difference in value from 1 and 40 Mhz / 39
//Global variables
// used by sweep and PC input
long int frq;
double Fstart_MHz = 1000000; // Start Frequency for sweep
double Fstop_MHz = 40000000; // Stop Frequency for sweep
double current_freq_MHz; // Temp variable used during sweep
double Fstep_MHz = 10000; //size of Sweep step
double VFOstep_Khz = 100000; //size of VFO step
int num_steps = 160; // Number of steps to use in the sweep change for screen size
// used in gain loss calculation
double db; // db gain loss ref to v out
double dbPoint[160]; //sweep points db*10
// lookup table for converfting return loss to swr * 10
int SWRPoint[46] = {375, 375, 375, 375, 337, 301, 262, 232, 220, 208,
198, 187, 178, 160, 150, 143, 138, 133, 129, 125,
120, 117, 115, 113, 112, 111, 109, 108, 107, 107,
106, 105, 105, 104, 104, 103, 103, 103, 102, 102,
101, 101, 101, 100, 100, 100
};
double max_db; // used to normalize data
float powerdB = 0.00; // Calculated power in dBm
float last_db = 0.00;
float Peak_db = 0.00;
// used by encoder and pushbutton control
int buttonstate = 0;
double encoder;
//used by various display procedures
int c_pos;
int p;
double f1;
double f2;
double dbValue;
int RunOnce = 1; // for anything I want to run once at startup
float SupplyVoltage = (0); // Power supply voltage
int backlightTimer = 5000; // counts the cycles without input (turn off backlight after about 5 seconds of no rf)
// Setup for rotary encoder with push button
Rotary r = Rotary(2, 3); // sets the pins the rotary encoder uses. Must be interrupt pins.
#define EncoderBtn 4
// Analog input for battery monitor
#define vin_BAT A6
#define R1 (12) // from GND to vin_BAT, express in 100R (10 = 1000 Ohm)
#define R2 (33) // from + power supply to vin_BAT, express in 100R (47 = 4700 Ohm)
#define VoltSupplyMini (550) // minimum battery voltage expressed in 100mV (if lower, alarm is generated)
#define LOG_AMP A1
// system modalities
#define mSWEEP 0
#define mNORM 1
#define mFAST 2
#define mVFO 3
#define mDIP 4
#define mSWR 5
#define mWATT 6
int modality = mSWEEP ;
// display modes either sweep or settings
#define dmSWEEP 0
#define dmSETTING 1
//int dMODE = dmSWEEP ;
int dMODE = dmSETTING ;
// settings
#define sSTART 2
#define sEND 3
#define sSTEP 4
#define sMODE 1
int sITEM = sMODE ;
void setup() {
// Serial.begin(57600); // connect to the serial port only for testing comment out for final build
// Serial.println("KV4QB SNA Jr.");
// initialize interrupts
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
// set up encoder and pushbutton pins
pinMode(2, INPUT);
digitalWrite(2, HIGH);
pinMode(3, INPUT);
digitalWrite(3, HIGH);
pinMode(EncoderBtn, INPUT);
digitalWrite(EncoderBtn, HIGH);
//
// setup inputs for reading RF_out RF_in and battery
pinMode (LOG_AMP, INPUT);
pinMode(vin_BAT, INPUT);
// Use this initializer if you're using a 128x160 TFT
display.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab
display.setRotation(1); // set orientation of display
analogWrite(Backlight, 120);
// Control is done with a state machine
// start out in settings and select mode
dMODE = dmSETTING;
sITEM = sMODE ;
// setup AD9850 module pins and initialze
pinMode(FQ_UD, OUTPUT);
digitalWrite(FQ_UD, LOW);
pinMode(W_CLK, OUTPUT);
digitalWrite(W_CLK, LOW);
pinMode(DATA, OUTPUT);
digitalWrite(DATA, LOW);
pinMode(DDS_RESET, OUTPUT);
pulseHigh(DDS_RESET);
pulseHigh(W_CLK);
pulseHigh(FQ_UD); // this pulse enables serial mode on the AD9850
}
//
// END of Setup
//
// Main program loop
void loop()
{
//check battery
measuresupplyvolt(); // show Splash screen only do once
SplashScreen();
RunOnce = 0;
// process pushbutton
buttonstate = digitalRead(EncoderBtn);
if (buttonstate == LOW) {
delay(800);
buttonstate = digitalRead(EncoderBtn); //held over .8 second then toggle sweep screen or settings
if (buttonstate == LOW) {
if (dMODE == dmSWEEP) {
dMODE = dmSETTING;
display.fillScreen(BLUE);
dispSettingScreen();
}
else {
dMODE = dmSWEEP;
display.fillScreen(BLUE);
if (modality == mVFO) {
dispVFOScreen();
VFO_VM();
}
else
dispScanScreen();
}
delay(100);
}
// Got correct display mode from long press now process short push
// first take care of settings
// Note you have to press button to enable settings change or go to display screen
else if (dMODE == dmSETTING) { // process changes to settings
if (sITEM == sSTART) {
setStartFreq();
sITEM = sEND ;
}
else if (sITEM == sEND) {
setEndFreq();
sITEM = sSTEP;
}
else if (sITEM == sSTEP) {
setStepSize();
sITEM = sMODE;
}
else if (sITEM == sMODE) {
setModality();
sITEM = sSTART;
}
}
// Not a settings change
// start data acquisition
if (dMODE == dmSWEEP) {
display.fillScreen(BLUE);
if (modality == mVFO)
VFO_VM();
else if (modality == mDIP)
find_dip();
else if (modality == mFAST)
Fast_Sweep();
else if (modality == mWATT)
WattMeter();
else if (modality == mSWR) {
SWRScan();
display.fillScreen(BLUE);
}
else
Perform_sweep();
// dispScanScreen();
drawSweep();
sITEM = sMODE;
}
}
// button press processed now use rotary
// to scroll through acquired data
if (dMODE == dmSWEEP)
scrollSweep();
}
//
// end of loop
//
// ******* Functions ************
//
// interrupt service routine for encoder
ISR(PCINT2_vect) {
unsigned char result = r.process();
if (result) {
if (result == DIR_CW) {
encoder--;
}
else {
encoder++;
}
}
}
//
// Do a scan of band compute gain loss for each point store to array and display sweep
//
void Perform_sweep() {
int x;
int x1 = 0;
int y;
int y1 ;
// show screen for selected modality
if ((modality == mSWEEP) || (modality == mNORM))
dispScanScreen();
// else if (modality == mNORM)
// dispScanScreen();
// Find step size for sweep
Fstep_MHz = (Fstop_MHz - Fstart_MHz) / num_steps;
// Start scan loop
max_db = -120; // set peak finder for possible normalize of data
for (int i = 0; i <= num_steps; i++) {
// Calculate frequency for each step in scan
current_freq_MHz = Fstart_MHz + (i * Fstep_MHz);
sendFrequency(current_freq_MHz);
delay(4); // Wait a little for settling
read_DB();
dbPoint[i] = powerdB + (FreqCorr * (current_freq_MHz / 100000)); // store data add frequency correction
if (max_db < dbPoint[i]) max_db = dbPoint[i];
}
if (modality == mNORM) {
for (int i = 0; i <= num_steps; i++) {
dbPoint[i] = (dbPoint[i] - (max_db)) ;
}
}
// dispScanScreen();
// drawSweep();
}
//scroll through sweep
void scrollSweep() {
if (encoder != 0) {
// clear old values from screen
display.fillRect(1, 1, 159, 16, BLUE);
display.drawLine(c_pos , 20, c_pos , 127, BLUE);
c_pos = (encoder + c_pos);
encoder = 0;
if (c_pos >= (num_steps - 1)) {
c_pos = num_steps - 1 ; //Upper scan limit
}
if (c_pos <= 1) {
c_pos = 1; // Lower scan limit
}
p = c_pos;
f1 = ( Fstart_MHz + ( c_pos * Fstep_MHz ));
display.setCursor(2, 6);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print((f1 / 1000000), 4);
display.setCursor(112, 6);
dbValue = (dbPoint[p] / 10);
display.print(dbValue, 1);
display.print("db");
drawSweep();
drawGrid();
display.drawLine(c_pos , 20, c_pos , 127, RED);
}
}
//
// Draw the sweep waveform divide by 50 gives approximate 10 db per divisions in Sweep mode
//
void drawSweep() {
int x;
int x1 = 0; int y;
int y1 = 26 - ((dbPoint[0] - 150) / 10) ;
for (int i = 0; i <= num_steps; i++) {
y = 26 - ( (dbPoint[i] - 150) / 10) ;
display.drawLine(x1, y1, i, y, YELLOW);
x1 = i;
y1 = y;
}
}
//
// set output frequency to AD9850
// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
//
void sendFrequency(double frequency) {
int32_t freq = frequency * 4295067295 / 125000000; // note 125 MHz clock on 9850. You can make 'slight' tuning variations here by adjusting the clock frequency.
for (int b = 0; b < 4; b++, freq >>= 8) {
tfr_byte(freq & 0xFF);
}
tfr_byte(0x000); // Final control byte, all 0 for 9850 chip
pulseHigh(FQ_UD); // Done! Should see output
}
// transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line
void tfr_byte(byte data) {
for (int i = 0; i < 8; i++, data >>= 1) {
digitalWrite(DATA, data & 0x01);
pulseHigh(W_CLK); //after each bit sent, CLK is pulsed high
}
}
//
// display Scan screen with frequency range
//
void dispScanScreen() {
// display start and stop frequencies on top of display
//display.fillScreen(BLUE);
display.setTextSize(1);
display.setTextColor(YELLOW);
display.setCursor(2, 6);
display.print((Fstart_MHz / 1000000), 3);
display.setCursor(112, 6);
display.print((Fstop_MHz / 1000000), 3);
drawGrid();
}
//
// Draw the scan grid modify for each frequency band width
//
void drawGrid() {
int xinc;
display.setTextColor(CYAN);
xinc = num_steps / 6; // scale for screen
for (int i = 0; i <= 7; i++)
display.drawLine((i * xinc) + 1, 20, (i * xinc) + 1, 125, CYAN);
// these values give approximatly 20 db level markings
for (int i = 1; i <= 6; i++)
if (i == 2)
display.drawLine(2, (i * 21) - 1, num_steps - 2, (i * 21) - 1, MAGENTA); // 0 DB LINE
else
display.drawLine(2, (i * 21) - 1, num_steps - 2, (i * 21) - 1, CYAN);
}
//
// Power SupplyVoltage measure voltage and test for low volts
//display low voltage
//
void measuresupplyvolt () {
// Read power supply voltage
SupplyVoltage = analogRead(vin_BAT);
SupplyVoltage = map(SupplyVoltage, 0, 1023, 0, (500 * (float R2 + float R1) / float R1)); // compute battery voltage using voltage divider values
//SupplyVoltage = SupplyVoltage + diode ; if you have a reverse voltage diode add the voltage drop
if (SupplyVoltage <= 500) return; // not running on batteries !
if (SupplyVoltage <= VoltSupplyMini) {
//display.fillScreen(BLUE);
display.setCursor(40, 10);
display.print("LOW BATTERY !");
display.setCursor(40, 10);
delay (500);
display.setTextColor(BLUE);
display.print("LOW BATTERY !");
display.setTextColor(YELLOW);
}
}
//
// Splash screen with battery voltage
//
void SplashScreen() {
if (RunOnce == 1) {
display.setTextColor(YELLOW);
display.fillScreen(BLUE);
display.setCursor(24, 35);
display.setTextSize(3);
display.println("KV4QB");
display.setTextSize(2);
display.setCursor(5, 70);
display.print(" SNA Jr");
display.setCursor(25, 7);
display.setTextSize(1);
display.setCursor(30, 100);
display.print("Batt =");
display.print((SupplyVoltage / 100));
display.print("v");
delay(2500);
RunOnce = 0;
display.fillScreen(BLUE);
dispSettingScreen();
}
}
//
// Functions related to settings
//
//
// display settings screen
void dispSettingScreen() {
display.setTextSize(1);
if (sITEM == sSTART) // active setting in yellow
display.setTextColor(YELLOW); // inactiove settings in cyan
else
display.setTextColor(CYAN);
display.setCursor(2, 4);
display.print("Start Frequency Mhz.");
display.setCursor(12, 16);
display.setTextSize(2);
display.print((Fstart_MHz / 1000000), 3);
if (sITEM == sEND)
display.setTextColor(YELLOW);
else
display.setTextColor(CYAN);
display.setTextSize(1);
display.setCursor(2, 36);
display.print("Stop Frequency Mhz.");
display.setTextSize(2);
display.setCursor(12, 48);
display.print((Fstop_MHz / 1000000), 3);
display.setTextSize(1);
if (sITEM == sSTEP)
display.setTextColor(YELLOW);
else
display.setTextColor(CYAN);
display.setCursor(2, 66);
display.print("Step Khz.");
display.setTextSize(2);
display.setCursor(12, 76);
display.print((VFOstep_Khz / 1000), 0);
display.setTextSize(1);
if (sITEM == sMODE)
display.setTextColor(YELLOW);
else
display.setTextColor(CYAN);
display.setCursor(2, 94);
display.print("Mode");
display.setTextSize(2);
display.setCursor(12, 106);
if (modality == 0)
display.print("SWEEP.R");
else if (modality == 1)
display.print("SWEEP.N");
else if (modality == 2)
display.print("SWEEP.FAST");
else if (modality == 3)
display.print("SIG GEN");
else if (modality == 4)
display.print("DIP METER");
else if (modality == 5)
display.print("SWR SCAN");
else if (modality == 6)
display.print("WATT METER");
}
//
// change settings functions
//
// set start frequency
void setStartFreq() {
dispSettingScreen(); // mark other settings inactive
display.setTextColor(YELLOW);
display.setCursor(2, 16);
display.setTextSize(2);
while (1) {
if (encoder != 0) {
delay(10);
Fstart_MHz = Fstart_MHz + (encoder * VFOstep_Khz);
if (Fstart_MHz > 40000000) Fstart_MHz = 40000000;
if (Fstart_MHz < 1000000) Fstart_MHz = 1000000;
encoder = 0;
display.fillRect(1, 16, 127, 16, BLUE);
display.setCursor(12, 16);
display.print((Fstart_MHz / 1000000), 3);
}
buttonstate = digitalRead(EncoderBtn);
if (buttonstate == LOW)
return;
}
}
// setEndfrequency
void setEndFreq() {
dispSettingScreen();
display.setTextColor(YELLOW);
display.setTextSize(2);
while (1) { // use encoder to set frequency press button to exit
if (encoder != 0) {
delay(10);
Fstop_MHz = Fstop_MHz + (encoder * VFOstep_Khz);
if (Fstop_MHz > 40000000) Fstop_MHz = 40000000;
if (Fstop_MHz < 1000000) Fstop_MHz = 1000000;
encoder = 0;
display.fillRect(1, 48, 127, 16, BLUE);
display.setCursor(12, 48);
display.print((Fstop_MHz / 1000000), 3);
}
buttonstate = digitalRead(EncoderBtn);
if (buttonstate == LOW)
return;
}
}
// set Step Size
void setStepSize() {
dispSettingScreen();
display.setTextColor(YELLOW);
display.setTextSize(2);
while (1) { // use encoder to set frequency press button to exit
if (encoder != 0) {
delay(10);
VFOstep_Khz = VFOstep_Khz * 10;
if (VFOstep_Khz > 1000000) VFOstep_Khz = 1000;
encoder = 0;
display.fillRect(1, 76, 127, 16, BLUE);
display.setCursor(12, 76);
display.print(( VFOstep_Khz / 1000), 0);
}
buttonstate = digitalRead(EncoderBtn);
if (buttonstate == LOW)
return;
}
}
// Set Modality
void setModality() {
dispSettingScreen();
display.setTextColor(YELLOW);
display.setTextSize(2);
while (1) {
if (encoder != 0) {
modality++;
if (modality > 6)
modality = 0;
encoder = 0;
display.fillRect(1, 106, 160, 16, BLUE);
display.setCursor(12, 106);
if (modality == 0)
display.print("SWEEP.R");
else if (modality == 1)
display.print("SWEEP.N");
else if (modality == 2)
display.print("SWEEP.FAST");
else if (modality == 3)
display.print("SIG GEN");
else if (modality == 4)
display.print("DIP METER");
else if (modality == 5)
display.print("SWR SCAN");
else
display.print("WATT METER");
}
buttonstate = digitalRead(EncoderBtn);
if (buttonstate == LOW)
return;
}
}
// VFO function with simple rf voltmeter
void dispVFOScreen() {
current_freq_MHz = Fstart_MHz;
display.setTextSize(1);
display.setTextColor(YELLOW); // inactiove settings in cyan
display.setCursor(2, 8);
display.print(" VFO Frequency Mhz.");
display.setCursor(12, 20);
display.setTextSize(2);
display.print( (current_freq_MHz / 1000000), 6);
display.setTextSize(1);
display.setCursor(12, 40);
display.print("Step Khz.");
display.setTextSize(2);
display.setCursor(12, 52);
display.print((VFOstep_Khz / 1000), 3);
display.setTextSize(1);
display.setTextSize(1);
display.setCursor(12, 74);
display.print(" RF Level");
display.setTextSize(2);
display.setCursor(12, 86);
// display.print(db, 1);
display.fillRect(1, 102, 159, 16, YELLOW);
}
// Sig Gen Power meter
void VFO_VM() {
int last_db;
float scale ;
current_freq_MHz = Fstart_MHz;
sendFrequency(current_freq_MHz);
dispVFOScreen();
while (1) {
buttonstate = digitalRead(EncoderBtn); // check for button press
if (buttonstate == LOW) {
delay(250);
buttonstate = digitalRead(EncoderBtn); // then check for long press and exit
if (buttonstate == LOW) return;
else { // short press change step size
display.fillRect(1, 52, num_steps, 16, BLUE);
VFOstep_Khz = VFOstep_Khz * 10;
if (VFOstep_Khz > 1000000) VFOstep_Khz = 10;
display.setCursor(12, 52);
display.print((VFOstep_Khz / 1000), 3);
}
}
if (encoder != 0) { // look for frequency change from encoder
delay(10);
current_freq_MHz = current_freq_MHz + (encoder * VFOstep_Khz);
if (current_freq_MHz > 40000000) current_freq_MHz = 40000000;
if (current_freq_MHz < 1000000) current_freq_MHz = 1000000;
encoder = 0;
display.fillRect(1, 18, 127, 16, BLUE);
display.setCursor(12, 18);
display.print((current_freq_MHz / 1000000), 5); // display frequency
display.print("0"); // min step is 10 hz. so add a zero to display
sendFrequency(current_freq_MHz);
}
read_DB(); // Power meter display
if (int( powerdB ) != last_db) { // only update if changed from last reading
display.setTextSize(2);
display.fillRect(1, 86, 127, 16, BLUE); // clear previous readings
display.fillRect(1, 102, 127, 16, YELLOW);
scale = abs((powerdB / 10) - 10) * .8; // display bargraph
display.fillRect(10, 104, 100 - int (scale), 12, BLACK);
display.setCursor(12, 86); // display value in dBm
display.print(powerdB / 10 , 1);
display.print(" dB ");
last_db = powerdB;
delay(50);
}
}
}
// Find dip frequency
void find_dip() {
double dip_freq;
double min_db;
// Start and End frequency full range
Fstart_MHz = 1000000;
Fstop_MHz = 40000000;
Fstep_MHz = 25000; // stgep 50Khz
min_db = 100; // inital value for peak detector
display.fillScreen(BLUE);
display.setTextSize(2);
display.setTextColor(YELLOW);
display.setCursor(12, 2);
display.print("Finding Dip");
display.setCursor(1, 8);
for (int i = 0; i <= 1559; i++) {
// Calculate frequency for each step in scan
current_freq_MHz = Fstart_MHz + (i * Fstep_MHz);
sendFrequency(current_freq_MHz);
delay(1); // Wait a little for settling
read_DB();
if (min_db > powerdB) { // look for dip
min_db = powerdB;
dip_freq = current_freq_MHz;
}
}
Fstart_MHz = dip_freq - 1000000;
Fstop_MHz = dip_freq + 1000000;
display.fillScreen(BLUE);
c_pos = 80;
dispScanScreen();
Perform_sweep();
drawSweep();
}
// Fast cpntinusous sweep for aliogiing filters
//
void Fast_Sweep() {
// int x;
// int x1 = 0;
int y;
int y1 ;
// show screen for selected modality
display.fillScreen(BLUE);
dispScanScreen();
// Find step size for sweep
Fstep_MHz = (Fstop_MHz - Fstart_MHz) / num_steps;
// Start scan loop
buttonstate = digitalRead(EncoderBtn);
while (buttonstate == HIGH) {
for (int i = 0; i <= num_steps; i++) {
// Calculate frequency for each step in scan
current_freq_MHz = Fstart_MHz + (i * Fstep_MHz);
sendFrequency(current_freq_MHz);
delay(1); // Wait a little for settling
y = 26 - ((dbPoint[i] / 10) - 150 / 10) ;
y1 = 26 - ((dbPoint[i + 1] / 10) - 150 / 10) ;
display.drawLine(i, y, i + 1, y1, BLUE);
read_DB();
dbPoint[i] = powerdB + (FreqCorr * (current_freq_MHz / 100000)) ;
y = 26 - ((dbPoint[i] / 10) - 150 / 10) ;
y1 = 26 - ((dbPoint[i - 1] / 10) - 150 / 10) ;
display.drawLine(i - 1, y1, i , y, YELLOW);
// Check for button pressed during a sweep
buttonstate = digitalRead(EncoderBtn);
// if button pressed during sweep exit while loop
}
drawGrid(); // refresh grid at end of sweep
}
sITEM = sMODE;
// scanning stopped redraw screen wait for another short press to restart sweep or long press to exit
dispScanScreen();
drawSweep();
}
void read_DB() {
int RF_in = 0;
float power_caliberation = AD8307_POWER_CALIBERATION;
// Read the forawrd power , repeat to help elminate noise and increase voltage for conversion
RF_in = analogRead(LOG_AMP);
RF_in = RF_in + analogRead(LOG_AMP);
powerdB = RF_in + (power_caliberation ); // convert logamp reading to dB * 10
// if (abs(new_reading - powerdB) > 2) // only update if reading has changed
// powerdB = new_reading ; // value is power in dbm * 10
}
// Power meter display
// Wattmeter function
void WattMeter() {
float scale ;
double RFPower;
double lastRFPower;
double PeakRFPower = 0;
float db40;
display.fillScreen(RED);
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(30, 30);
display.print(" Must use 40dB.");
display.setCursor(30, 45);
display.print(" TAP for proper");
display.setCursor(30, 60);
display.print(" Reading !");
delay(2000);
display.fillScreen(BLUE);
while (1) {
buttonstate = digitalRead(EncoderBtn); // check for button press
if (buttonstate == LOW) {
delay(250);
buttonstate = digitalRead(EncoderBtn); // then check for long press and exit
sITEM = sMODE;
if (buttonstate == LOW) {
sITEM = sMODE;
return;
}
}
read_DB(); // check for RF
if ( powerdB / 10 <= -20) { // No RF sp clear screen and flash Message
if (PeakRFPower != 0) // if previous RF hold display for 2 seconds
delay(2000);
display.fillScreen(BLUE);
display.setTextSize(3);
display.setTextColor(WHITE);
display.setCursor(20, 46);
display.print("No RF !");
delay(100);
display.setTextColor(YELLOW);
PeakRFPower = 0; // Reset peak
}
else { // got RF so display values
db40 = powerdB + 400; // add 40 dB to correct for Tap
if (int( powerdB ) != last_db) { // only update if changed from last reading
display.setTextSize(2);
display.fillScreen(BLUE); // clear previous readings
display.setCursor(20, 8); // display value in dBm
display.print(db40 / 10 , 1);
display.setTextSize(1);
display.print(" dBm. ");
RFPower = pow(10, db40 / 100);
if (RFPower > PeakRFPower)
PeakRFPower = RFPower ;
display.setCursor(8, 46); // display value in watts
if (RFPower <= 2000) {
display.setTextSize(2);
display.print(RFPower , 1);
display.setTextSize(1);
display.print(" mWatt ");
}
else {
display.setTextSize(2);
display.print(RFPower / 1000 , 1);
display.setTextSize(1);
display.print(" Watt");
}
display.setCursor(8, 86);
if (PeakRFPower <= 2000) {
display.setTextSize(2);
display.print(PeakRFPower , 1);
display.setTextSize(1);
display.print(" mWatt Peak");
}
else {
display.setTextSize(2);
display.print(PeakRFPower / 1000 , 1);
display.setTextSize(1);
display.print(" Watt Peak");
}
last_db = powerdB;
delay(100);
}
}
}
}
void SWRScan() {
Perform_sweep();
drawSWRGrid();
display.setTextSize(1);
display.setTextColor(YELLOW);
display.setCursor(2, 6);
display.print((Fstart_MHz / 1000000), 3);
display.setCursor(112, 6);
display.print((Fstop_MHz / 1000000), 3);
drawSWRSweep();
while (1) {
scrollSWR();
// drawSWRSweep();
buttonstate = digitalRead(EncoderBtn); // check for button press
if (buttonstate == LOW) {
delay(350);
buttonstate = digitalRead(EncoderBtn); // then check for long press and exit
if (buttonstate == LOW) {
display.fillScreen(BLUE);
sITEM = sMODE;
return;
}
}
}
}
void drawSWRSweep() {
int x;
int x1 = 0; int y;
int y1;
x = abs(dbPoint[0] + 150) / 10;
y1 = 149 - (SWRPoint[x] / 3 ) ;
for (int i = 0; i <= num_steps; i++) {
x = abs(dbPoint[i] + 150) / 10;
y = 149 - (SWRPoint[x] / 3 ) ;
display.drawLine(x1, y1, i, y, YELLOW);
x1 = i;
y1 = y;
}
}
//scroll through sweep look up swr from table
void scrollSWR() {
int x;
float swr;
if (encoder != 0) {
// clear old values from screen
display.fillRect(1, 1, 159, 16, BLUE);
display.drawLine(c_pos , 20, c_pos , 127, BLUE);
c_pos = (encoder + c_pos);
encoder = 0;
if (c_pos >= (num_steps - 1)) {
c_pos = num_steps - 1 ; //Upper scan limit
}
if (c_pos <= 1) { // Lower scan limit
c_pos = 1;
}
p = c_pos;
f1 = ( Fstart_MHz + ( c_pos * Fstep_MHz ));
display.setCursor(2, 6);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print((f1 / 1000000), 3);
display.setCursor(90, 6);
display.print("SWR ");
x = abs(dbPoint[p] + 150) / 10;
swr = float (SWRPoint[x]);
if (swr > 375)swr = 375;
if (swr < 100 )swr = 100;
display.print(swr / 100, 2);
display.print(":1");
drawSWRSweep();
drawSWRGrid();
display.drawLine(c_pos , 20, c_pos , 120, RED);
}
}
void drawSWRGrid() {
int xinc;
display.setTextColor(CYAN);
xinc = num_steps / 6; // scale for screen
for (int i = 0; i <= 7; i++)
display.drawLine((i * xinc) + 1, 21, (i * xinc) + 1, 117, CYAN);
// these values give approximatly 1 SWR level markings
for (int i = 0; i <= 4; i++)
display.drawLine(2, (i * 32) - 11, num_steps - 2, (i * 32) - 11, CYAN);
}