Init new project with variations on KK9JEF's code.
This commit is contained in:
commit
b2345cf54e
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"cmake.configureOnOpen": false
|
||||
}
|
2
README.md
Normal file
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# DDS_VFO
|
||||
Code for the arduino-controlled VFO based on the Si5351 chip
|
BIN
Vfo Wiring.fzz
Normal file
BIN
Vfo Wiring.fzz
Normal file
Binary file not shown.
39
include/README
Normal file
39
include/README
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
lib/README
Normal file
46
lib/README
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
17
platformio.ini
Normal file
17
platformio.ini
Normal file
|
@ -0,0 +1,17 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:metro]
|
||||
platform = atmelavr
|
||||
board = metro
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
etherkit/Etherkit Si5351@^2.1.4
|
||||
paulstoffregen/Encoder@^1.4.4
|
395
src/main.cpp
Normal file
395
src/main.cpp
Normal file
|
@ -0,0 +1,395 @@
|
|||
//----------- History ---------------
|
||||
/*
|
||||
/* This code has been modified from that written by Jeff Glass (KK9JEF) and documented in the following locations:
|
||||
/* - https://kk9jef.wordpress.com/2015/11/09/40m-direction-conversion-receiver-in-the-polyakov-style/
|
||||
/* - https://github.com/JeffersGlass/DDS_VFO
|
||||
/*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Encoder.h>
|
||||
#include <Wire.h>
|
||||
//#include <LiquidCrystal.h>
|
||||
#include <si5351.h>
|
||||
|
||||
|
||||
//----------- Variables & Declarations ---------------
|
||||
/*
|
||||
* The current and desired LISTENING FREQUENCY, which is not always the frequency being output by the Si5351.
|
||||
* In 'testing' and 'basic' modes, the output freqeuncy is equal to currFreq
|
||||
* In 'polyakov' mode, the output frequency is half of curFreq
|
||||
* In BFO mode, .........
|
||||
* These adjustments are mode in the setFrequency_5351 function depending on the current mode held in currMode
|
||||
*/
|
||||
|
||||
long currFreq = 1800000; //in HZ
|
||||
long ifFreq = 8865000; //in HZ
|
||||
|
||||
//-----Enumerations of frequency steps and their labels for each mode----//
|
||||
|
||||
enum modes{mode_testing = 0, mode_basic, mode_polyakov, mode_bfo, mode_if};
|
||||
const int NUM_MODES = 5;
|
||||
int currMode = mode_basic;
|
||||
|
||||
const char* modeNames[NUM_MODES] = {"TEST", "VFO", "POLYA", "BFO", "IF"};
|
||||
|
||||
long steps[][10] = { //don't forget to update the MAX_STEPS_INDEX array below
|
||||
{10000000, 5000000, 1000000, 500000, 100000, 10000, 1000, 10, 1}, //testing
|
||||
{10000, 1000, 100, 10}, //basic
|
||||
{1000, 100, 10, 1}, //polyakov
|
||||
{1000, 100, 10, 1}, //bfo
|
||||
{1000, 100, 10, 1} //IF Mode
|
||||
};
|
||||
|
||||
const int NUM_STEP_OPTIONS[NUM_MODES] = {
|
||||
10, //testing
|
||||
4, //basic
|
||||
4, //polyakov
|
||||
4, //bfo
|
||||
4 //if
|
||||
};
|
||||
const char* stepNames[][10] = {
|
||||
{" 10MHz", " 5MHz", " 1MHz", "500Khz", "100KHz", " 10KHz", " 1KHz", " 100Hz", " 10Hz", " 1 Hz"}, //basic
|
||||
{" 10KHz", " 1KHz", " 100 Hz", " 10 Hz"}, //basic
|
||||
{" 1KHz", " 100 Hz", " 10 Hz", " 1 Hz"}, //polyakov
|
||||
{" 1KHz", " 100 Hz", " 10 Hz", " 1 Hz"}, //BFO
|
||||
{" 1KHz", " 100 Hz", " 10 Hz", " 1 Hz"} //IF
|
||||
};
|
||||
|
||||
int stepIndex = 0; // holds the index of the currently selected step value
|
||||
|
||||
//-----AMATEUR BAND DEFININTIONS----------------//
|
||||
//See function "getCurrentBand" below as well
|
||||
const int NUM_BANDS = 9;
|
||||
const char* bandNames[NUM_BANDS] = {"160m", "80m", "40m", "30m", "20m", "17m", "15m", "12m", "10m"};
|
||||
const char* OUT_OF_BAND_LABEL = "OOB";
|
||||
|
||||
long bandEdges[NUM_BANDS][2] = {
|
||||
{1800000, 2000000}, //160m
|
||||
{3500000, 4000000}, //80m
|
||||
{7000000, 7300000}, //40m
|
||||
{10100000, 10150000}, //30m
|
||||
{14000000, 14350000}, //20m
|
||||
{18068000, 18168000}, //17m
|
||||
{21000000, 21450000}, //15m
|
||||
{24890000, 24990000}, //12m
|
||||
{28000000, 29700000} //10m
|
||||
};
|
||||
|
||||
/*
|
||||
* Holds the last-seen frequency within each band. The list below is also the default location at bootup.
|
||||
* This array is updated when the BAND button is used to change between bands.
|
||||
* If the used has scrolled outside of a defined band and then presses the BAND button, they will
|
||||
* still be advanced to the next band, but the band-return location will not be updated
|
||||
*/
|
||||
|
||||
long lastBandFreq[NUM_BANDS] = {
|
||||
1800000, //160m
|
||||
3500000, //80m
|
||||
7000000, //40m
|
||||
10100000, //30m
|
||||
14000000, //20m
|
||||
18068000, //17m
|
||||
21000000, //15m
|
||||
24890000, //12m
|
||||
28000000 //10m
|
||||
};
|
||||
|
||||
/*Information on bandplan permissions and recommended communication modes is contained in the
|
||||
* methods getPermission and getBandplanModes below
|
||||
*/
|
||||
|
||||
//---------------------------------------------
|
||||
|
||||
long lastButtonPress[] = {0,0,0,0,0,0,0}; //holds the last timestamp, from millis(), that a pin changed state. Directly references the arduino output pin numbers, length may need to be increased
|
||||
boolean buttonActive[] = {false, false, false, false, false, false, false};
|
||||
|
||||
long encoderPosition = 0;
|
||||
boolean displayNeedsUpdate;
|
||||
|
||||
const long MIN_FREQ = 8500;
|
||||
const long MAX_FREQ = 150000000;
|
||||
|
||||
//---------LCD SETUP-------//
|
||||
// int PIN_RS = 7;
|
||||
// int PIN_EN = 8;
|
||||
// int PIN_DB4 = 9;
|
||||
// int PIN_DB5 = 10;
|
||||
// int PIN_DB6 = 11;
|
||||
// int PIN_DB7 = 12;
|
||||
//LiquidCrystal lcd(PIN_RS, PIN_EN, PIN_DB4, PIN_DB5, PIN_DB6, PIN_DB7);
|
||||
|
||||
//--------Si5351 Declaration---------------//
|
||||
|
||||
Si5351 si5351;
|
||||
//SDA is on pin A4 for Arduino Uno
|
||||
//SCL is on pin A5 for Arduino Uno
|
||||
|
||||
//--------Tuning Knob Interrupt Pins-------//
|
||||
//Encoder knob(2, 3), pushbutton on 1
|
||||
|
||||
Encoder encoder(2, 3);
|
||||
const int PIN_BUTTON_ENCODER = 1;
|
||||
|
||||
//Button Pins//
|
||||
const int PIN_BUTTON_MODE = 4;
|
||||
const int PIN_BUTTON_BAND = 0;
|
||||
const int BUTTON_DEBOUNCE_TIME = 10; //milliseconds
|
||||
|
||||
//SWR Sensor Pins
|
||||
const int PIN_SWR_FORWARD = A1;
|
||||
const int PIN_SWR_REVERSE = A0;
|
||||
|
||||
|
||||
|
||||
// void displayInfo(){
|
||||
// lcd.clear();
|
||||
|
||||
// // frequency information be centeredw within 11 spaces on the second line:
|
||||
// if (currFreq >= 100000000) lcd.setCursor(3, 0);
|
||||
// else if (currFreq > 10000000) lcd.setCursor(4, 0);
|
||||
// else lcd.setCursor(5, 0);
|
||||
// int mhz = int(currFreq/ 1000000);
|
||||
// int khz = int((currFreq - (mhz*1000000)) / 1000);
|
||||
// int hz = int(currFreq % 1000);
|
||||
|
||||
// int khzPad = 0;
|
||||
// if (khz < 100) khzPad++;
|
||||
// if (khz < 10) khzPad++;
|
||||
|
||||
// int hzPad = 0;
|
||||
// if (hz < 100) hzPad++;
|
||||
// if (hz < 10) hzPad++;
|
||||
|
||||
// lcd.print(mhz);
|
||||
// lcd.print(".");
|
||||
// for (int i = 0; i < khzPad; i++) lcd.print("0");
|
||||
// lcd.print(khz);
|
||||
// lcd.print(".");
|
||||
// for (int i = 0; i < hzPad; i++) lcd.print("0");
|
||||
// lcd.print(hz);
|
||||
|
||||
// //The current amateur band is printed in the top-right corner
|
||||
// int currBand = getCurrentBand();
|
||||
// if (currBand >= 0){
|
||||
// char* currBandName = bandNames[currBand];
|
||||
// lcd.setCursor(20-strlen(currBandName), 0);
|
||||
// lcd.print(currBandName);
|
||||
// }
|
||||
// else{
|
||||
// lcd.setCursor(20-strlen(OUT_OF_BAND_LABEL), 0);
|
||||
// lcd.print(OUT_OF_BAND_LABEL);
|
||||
// }
|
||||
|
||||
// //The license needed to operate on this frequency (ARRL, USA ONLY) is printed just below the band label
|
||||
// lcd.setCursor (19, 1);
|
||||
// lcd.print(getPermission());
|
||||
|
||||
// //Step Information should take the middle 11 spaces on the 3nd line
|
||||
// //The first 5 symbols are "STEP:", leaving 6 chars for step info.
|
||||
// lcd.setCursor(4, 2);
|
||||
// lcd.print("STEP:");
|
||||
// lcd.print(stepNames[currMode][stepIndex]);
|
||||
|
||||
// //Callsign is printed at the beginning of the 4th line
|
||||
// lcd.setCursor(0, 3);
|
||||
// lcd.print("KK9JEF");
|
||||
|
||||
// //The mode is printed on the 4th line with no label
|
||||
// //lcd.setCursor(6, 3);
|
||||
// lcd.setCursor(20-strlen(modeNames[currMode]), 3);
|
||||
// lcd.print(modeNames[currMode]);
|
||||
|
||||
// //DEBUG
|
||||
// //lcd.setCursor(0,0);
|
||||
// //lcd.print(getCurrentBand());
|
||||
|
||||
// /*float fwd = analogRead(PIN_SWR_FORWARD);
|
||||
// float rev = analogRead(PIN_SWR_REVERSE);
|
||||
// float gamma = rev/fwd;
|
||||
// float swr = (1 + abs(gamma)) / (1 - abs(gamma));
|
||||
|
||||
// lcd.setCursor(0, 1);
|
||||
// lcd.print(int(fwd));
|
||||
// lcd.setCursor(4, 1);
|
||||
// lcd.print(int(rev));
|
||||
// lcd.setCursor(8, 1);
|
||||
// lcd.print(gamma);
|
||||
// lcd.setCursor(14, 1);
|
||||
// lcd.print(swr);*/
|
||||
|
||||
// }
|
||||
|
||||
boolean checkButtonPress(int pin){
|
||||
long time = millis();
|
||||
if (buttonActive[pin] && digitalRead(pin) == HIGH){
|
||||
buttonActive[pin] = false;
|
||||
lastButtonPress[pin] = time;
|
||||
}
|
||||
else if (digitalRead(pin) == LOW && !buttonActive[pin] && time > lastButtonPress[pin] + BUTTON_DEBOUNCE_TIME){
|
||||
buttonActive[pin] = true;
|
||||
lastButtonPress[pin] = time;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setFrequency_5351(long newFreq){
|
||||
switch (currMode){
|
||||
case mode_testing:
|
||||
si5351.set_freq(newFreq * 100ULL, SI5351_CLK0);
|
||||
break;
|
||||
case mode_basic:
|
||||
si5351.set_freq(newFreq * 100ULL, SI5351_CLK0);
|
||||
break;
|
||||
case mode_polyakov:
|
||||
si5351.set_freq((newFreq / 2) * 100ULL, SI5351_CLK0);
|
||||
break;
|
||||
case mode_bfo:
|
||||
si5351.set_freq(newFreq * 100ULL, SI5351_CLK0);
|
||||
break;
|
||||
case mode_if:
|
||||
si5351.set_freq((newFreq + ifFreq) * 100UL, SI5351_CLK0); //VFO+IF
|
||||
//VFO-IF
|
||||
//IF-VFO
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Returns the index of the current amateur radio band based on currFreq. Does not include the 60m band
|
||||
//Returns -1 if out of band, but within the HF amateur turning range
|
||||
//returns -2 if out of band and lower than the lowest defined band
|
||||
//returns -3 if out of band and higher than the highest defined band
|
||||
int getCurrentBand(){
|
||||
if (currFreq < bandEdges[0][0]) return -2; //we are lower than the lower edge of the lowest defined band
|
||||
if (currFreq > bandEdges[NUM_BANDS-1][1]) return -3; //We are higher than the upper edge of the highest defined band
|
||||
for (int i = 0; i < NUM_BANDS; i++){
|
||||
if (currFreq >= bandEdges[i][0] && currFreq <= bandEdges[i][1]){return i;} //We are within a band
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char getPermission(){
|
||||
if (getCurrentBand() < 0) return ' ';
|
||||
|
||||
//160m
|
||||
if (currFreq >= 1800000 && currFreq <= 2000000) return 'G';
|
||||
|
||||
//80m
|
||||
if (currFreq >= 3525000 && currFreq <= 3600000) return 'T';
|
||||
if ((currFreq >= 3525000 && currFreq <= 3600000) || (currFreq >= 3800000 && currFreq <= 4000000)) return 'G';
|
||||
if ((currFreq >= 3525000 && currFreq <= 3600000) || (currFreq >= 3700000 && currFreq <= 4000000)) return 'A';
|
||||
if (currFreq >= 3500000 && currFreq <= 4000000) return 'E';
|
||||
|
||||
//40m
|
||||
if (currFreq >= 7025000 && currFreq <= 7125000) return 'T';
|
||||
if ((currFreq >= 7025000 && currFreq <= 7125000) || (currFreq >= 7175000 && currFreq <= 7300000)) return 'G';
|
||||
if (currFreq >= 7025000 && currFreq <= 7300000) return 'A';
|
||||
if (currFreq >= 7000000 && currFreq <= 7300000) return 'E';
|
||||
|
||||
//30m
|
||||
if (currFreq >= 10100000 && currFreq <= 10150000) return 'G';
|
||||
|
||||
//20m
|
||||
if ((currFreq >= 14025000 && currFreq <= 14150000) || (currFreq >= 14225000 && currFreq <= 14350000)) return 'G';
|
||||
if ((currFreq >= 14025000 && currFreq <= 14150000) || (currFreq >= 14175000 && currFreq <= 14350000)) return 'A';
|
||||
if (currFreq >= 14000000 && currFreq <= 14350000) return 'E';
|
||||
|
||||
//17m
|
||||
if (currFreq >= 18068000 && currFreq <= 18168000) return 'G';
|
||||
|
||||
//15m
|
||||
if (currFreq >= 21025000 && currFreq <= 21200000) return 'T';
|
||||
if ((currFreq >= 21025000 && currFreq <= 21200000) || (currFreq >= 21275000 && currFreq <= 21450000)) return 'G';
|
||||
if ((currFreq >= 21025000 && currFreq <= 21200000) || (currFreq >= 21225000 && currFreq <= 21450000)) return 'A';
|
||||
if (currFreq >= 21000000 && currFreq <= 21450000) return 'E';
|
||||
|
||||
//12m
|
||||
if (currFreq >= 24890000 && currFreq <= 24990000) return 'G';
|
||||
|
||||
//10m
|
||||
if (currFreq >= 28000000 && currFreq <= 28500000) return 'T';
|
||||
if (currFreq >= 28000000 && currFreq <= 29700000) return 'G';
|
||||
|
||||
return 'X';
|
||||
}
|
||||
|
||||
void setup(){
|
||||
// inialize LCD, display welcome message
|
||||
//lcd.begin(20, 4);
|
||||
//delay(250);
|
||||
//lcd.setCursor(4, 1);
|
||||
//lcd.print("VFO STARTING");
|
||||
|
||||
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
|
||||
si5351.set_freq(currFreq * 100ULL, SI5351_CLK0);
|
||||
si5351.output_enable(SI5351_CLK0, 1);
|
||||
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA);
|
||||
|
||||
si5351.output_enable(SI5351_CLK1, 0);
|
||||
si5351.output_enable(SI5351_CLK2, 0);
|
||||
delay(750);
|
||||
|
||||
//knob.write(0);
|
||||
pinMode(PIN_BUTTON_ENCODER, INPUT);
|
||||
digitalWrite(PIN_BUTTON_ENCODER, HIGH);
|
||||
|
||||
pinMode(PIN_BUTTON_MODE, INPUT);
|
||||
digitalWrite(PIN_BUTTON_MODE, HIGH);
|
||||
pinMode(PIN_BUTTON_BAND, INPUT);
|
||||
digitalWrite(PIN_BUTTON_BAND, HIGH);
|
||||
|
||||
pinMode(PIN_SWR_FORWARD, INPUT);
|
||||
pinMode(PIN_SWR_REVERSE, INPUT);
|
||||
|
||||
//lcd.clear();
|
||||
//lcd.setCursor(2, 7);
|
||||
//lcd.print("WELCOME!");
|
||||
//delay(500);
|
||||
//displayInfo();
|
||||
}
|
||||
|
||||
void loop(){
|
||||
//if (displayNeedsUpdate) {displayInfo();}
|
||||
//delay(80);
|
||||
|
||||
//detect whether encoder has changed position
|
||||
long reading = encoder.read();
|
||||
long encoderChange = reading - encoderPosition;
|
||||
encoderPosition = reading;
|
||||
|
||||
displayNeedsUpdate = false;
|
||||
|
||||
//step up or down or change step size, for either button presses or encoder turns
|
||||
if ((encoderChange > 0)){currFreq += steps[currMode][stepIndex]; currFreq = min(currFreq, MAX_FREQ); setFrequency_5351(currFreq); displayNeedsUpdate = true;}
|
||||
if ((encoderChange < 0)){currFreq -= steps[currMode][stepIndex]; currFreq = max(currFreq, MIN_FREQ); setFrequency_5351(currFreq); displayNeedsUpdate = true;}
|
||||
|
||||
//pressing the encoder button increments through the possible step sizes for each mode
|
||||
if (checkButtonPress(PIN_BUTTON_ENCODER)){stepIndex = (stepIndex + 1) % (NUM_STEP_OPTIONS[currMode]); displayNeedsUpdate = true;}
|
||||
|
||||
//pressing the mode button cycles through the available modes
|
||||
if (checkButtonPress(PIN_BUTTON_MODE)){currMode = (currMode+1) % NUM_MODES; stepIndex = 0; setFrequency_5351(currFreq); displayNeedsUpdate = true;}
|
||||
|
||||
/*The mode button: if currFreq is inside an amateur band, save that frequency as the one to return to when
|
||||
* the user returns to this band, and jump to the return frequency for the next higher band. Otherwise,
|
||||
* just jump to the next higher band
|
||||
*/
|
||||
if (checkButtonPress(PIN_BUTTON_BAND)){
|
||||
int currBand = getCurrentBand();
|
||||
if (currBand >= 0){
|
||||
lastBandFreq[currBand] = currFreq;
|
||||
currFreq = lastBandFreq[(getCurrentBand() + 1) % NUM_BANDS];
|
||||
setFrequency_5351(currFreq);
|
||||
}
|
||||
else if (currBand == -2 || currBand == -3){
|
||||
currFreq = lastBandFreq[0];
|
||||
setFrequency_5351(currFreq);
|
||||
}
|
||||
else if (currBand == -1){
|
||||
for (int i = 0; i < NUM_BANDS; i++){
|
||||
if (currFreq < lastBandFreq[i]){currFreq = lastBandFreq[i]; setFrequency_5351(currFreq); break;}
|
||||
}
|
||||
}
|
||||
displayNeedsUpdate = true;
|
||||
}
|
||||
}
|
11
test/README
Normal file
11
test/README
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
8
vfo_oled.code-workspace
Normal file
8
vfo_oled.code-workspace
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
Loading…
Reference in New Issue
Block a user