mirror of
https://codeberg.org/mclemens/ubitxv6.git
synced 2024-09-10 18:24:15 -04:00
Merge pull request #2 from reedbn/one_stop_settings
Merging one stop settings branch
This commit is contained in:
commit
7b2057eabb
152
keyer.cpp
152
keyer.cpp
@ -1,4 +1,5 @@
|
||||
#include <Arduino.h>
|
||||
#include "settings.h"
|
||||
#include "ubitx.h"
|
||||
|
||||
/**
|
||||
@ -28,72 +29,27 @@
|
||||
*/
|
||||
|
||||
//CW ADC Range
|
||||
int cwAdcSTFrom = 0;
|
||||
int cwAdcSTTo = 50;
|
||||
int cwAdcBothFrom = 51;
|
||||
int cwAdcBothTo = 300;
|
||||
int cwAdcDotFrom = 301;
|
||||
int cwAdcDotTo = 600;
|
||||
int cwAdcDashFrom = 601;
|
||||
int cwAdcDashTo = 800;
|
||||
//byte cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
||||
static const unsigned int cwAdcSTFrom = 0;
|
||||
static const unsigned int cwAdcSTTo = 50;
|
||||
static const unsigned int cwAdcBothFrom = cwAdcSTTo + 1;
|
||||
static const unsigned int cwAdcBothTo = 300;
|
||||
static const unsigned int cwAdcDotFrom = cwAdcBothTo + 1;
|
||||
static const unsigned int cwAdcDotTo = 600;
|
||||
static const unsigned int cwAdcDashFrom = cwAdcDotTo + 1;
|
||||
static const unsigned int cwAdcDashTo = 800;
|
||||
|
||||
byte delayBeforeCWStartTime = 50;
|
||||
static const unsigned int delayBeforeCWStartTime = 50;
|
||||
|
||||
|
||||
|
||||
|
||||
// in milliseconds, this is the parameter that determines how long the tx will hold between cw key downs
|
||||
//#define CW_TIMEOUT (600l) //Change to CW Delaytime for value save to eeprom
|
||||
#define PADDLE_DOT 1
|
||||
#define PADDLE_DASH 2
|
||||
#define PADDLE_BOTH 3
|
||||
#define PADDLE_STRAIGHT 4
|
||||
|
||||
//we store the last padde's character
|
||||
//to alternatively send dots and dashes
|
||||
//when both are simultaneously pressed
|
||||
char lastPaddle = 0;
|
||||
|
||||
/*
|
||||
//reads the analog keyer pin and reports the paddle
|
||||
byte getPaddle(){
|
||||
int paddle = analogRead(ANALOG_KEYER);
|
||||
//handle the ptt as the straight key
|
||||
|
||||
if (digitalRead(PTT) == 0)
|
||||
return PADDLE_STRAIGHT;
|
||||
|
||||
if (paddle > 800) // above 4v is up
|
||||
return 0;
|
||||
|
||||
if (!Iambic_Key)
|
||||
return PADDLE_STRAIGHT;
|
||||
|
||||
if (paddle > 600) // 4-3v is dot
|
||||
return PADDLE_DASH;
|
||||
else if (paddle > 300) //1-2v is dash
|
||||
return PADDLE_DOT;
|
||||
else if (paddle > 50)
|
||||
return PADDLE_BOTH; //both are between 1 and 2v
|
||||
else
|
||||
return PADDLE_STRAIGHT; //less than 1v is the straight key
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* Starts transmitting the carrier with the sidetone
|
||||
* It assumes that we have called cwTxStart and not called cwTxStop
|
||||
* each time it is called, the cwTimeOut is pushed further into the future
|
||||
*/
|
||||
void cwKeydown(){
|
||||
|
||||
keyDown = 1; //tracks the CW_KEY
|
||||
tone(CW_TONE, (int)sideTone);
|
||||
tone(CW_TONE, globalSettings.cwSideToneFreq);
|
||||
digitalWrite(CW_KEY, 1);
|
||||
|
||||
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
||||
//cwTimeout = millis() + CW_TIMEOUT;
|
||||
cwTimeout = millis() + cwDelayTime * 10;
|
||||
globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,13 +57,10 @@ void cwKeydown(){
|
||||
* Pushes the cwTimeout further into the future
|
||||
*/
|
||||
void cwKeyUp(){
|
||||
keyDown = 0; //tracks the CW_KEY
|
||||
noTone(CW_TONE);
|
||||
digitalWrite(CW_KEY, 0);
|
||||
|
||||
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
||||
//cwTimeout = millis() + CW_TIMEOUT;
|
||||
cwTimeout = millis() + cwDelayTime * 10;
|
||||
globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs;
|
||||
}
|
||||
|
||||
//Variables for Ron's new logic
|
||||
@ -119,16 +72,14 @@ void cwKeyUp(){
|
||||
enum KSTYPE {IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT };
|
||||
static unsigned long ktimer;
|
||||
unsigned char keyerState = IDLE;
|
||||
uint8_t keyerControl = 0;
|
||||
|
||||
//Below is a test to reduce the keying error. do not delete lines
|
||||
//create by KD8CEC for compatible with new CW Logic
|
||||
char update_PaddleLatch(byte isUpdateKeyState) {
|
||||
char update_PaddleLatch(bool isUpdateKeyState) {
|
||||
unsigned char tmpKeyerControl = 0;
|
||||
|
||||
int paddle = analogRead(ANALOG_KEYER);
|
||||
//diagnostic, VU2ESE
|
||||
//itoa(paddle, b, 10);
|
||||
//printLine2(b);
|
||||
|
||||
//use the PTT as the key for tune up, quick QSOs
|
||||
if (digitalRead(PTT) == 0)
|
||||
@ -139,9 +90,8 @@ char update_PaddleLatch(byte isUpdateKeyState) {
|
||||
tmpKeyerControl |= DIT_L;
|
||||
else if (paddle >= cwAdcBothFrom && paddle <= cwAdcBothTo)
|
||||
tmpKeyerControl |= (DAH_L | DIT_L) ;
|
||||
else
|
||||
{
|
||||
if (Iambic_Key)
|
||||
else{
|
||||
if (KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode)
|
||||
tmpKeyerControl = 0 ;
|
||||
else if (paddle >= cwAdcSTFrom && paddle <= cwAdcSTTo)
|
||||
tmpKeyerControl = DIT_L ;
|
||||
@ -149,7 +99,7 @@ char update_PaddleLatch(byte isUpdateKeyState) {
|
||||
tmpKeyerControl = 0 ;
|
||||
}
|
||||
|
||||
if (isUpdateKeyState == 1)
|
||||
if (isUpdateKeyState)
|
||||
keyerControl |= tmpKeyerControl;
|
||||
|
||||
return tmpKeyerControl;
|
||||
@ -160,22 +110,24 @@ char update_PaddleLatch(byte isUpdateKeyState) {
|
||||
// modified by KD8CEC
|
||||
******************************************************************************/
|
||||
void cwKeyer(void){
|
||||
lastPaddle = 0;
|
||||
bool continue_loop = true;
|
||||
unsigned tmpKeyControl = 0;
|
||||
|
||||
if( Iambic_Key ) {
|
||||
while(continue_loop) {
|
||||
switch (keyerState) {
|
||||
if(KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode){
|
||||
while(continue_loop){
|
||||
switch(keyerState){
|
||||
case IDLE:
|
||||
tmpKeyControl = update_PaddleLatch(0);
|
||||
if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L ||
|
||||
tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) {
|
||||
update_PaddleLatch(1);
|
||||
if((tmpKeyControl == DAH_L)//Currently dah
|
||||
||(tmpKeyControl == DIT_L)//Currently dit
|
||||
||(tmpKeyControl == (DAH_L | DIT_L))//Currently both
|
||||
||( keyerControl & (DAH_L | DIT_L))){//Resolving either
|
||||
update_PaddleLatch(true);
|
||||
keyerState = CHK_DIT;
|
||||
}else{
|
||||
if (0 < cwTimeout && cwTimeout < millis()){
|
||||
cwTimeout = 0;
|
||||
}
|
||||
else{
|
||||
if (0 < globalSettings.cwExpirationTimeMs && globalSettings.cwExpirationTimeMs < millis()){
|
||||
globalSettings.cwExpirationTimeMs = 0;
|
||||
stopTx();
|
||||
}
|
||||
continue_loop = false;
|
||||
@ -185,7 +137,7 @@ void cwKeyer(void){
|
||||
case CHK_DIT:
|
||||
if (keyerControl & DIT_L) {
|
||||
keyerControl |= DIT_PROC;
|
||||
ktimer = cwSpeed;
|
||||
ktimer = globalSettings.cwDitDurationMs;
|
||||
keyerState = KEYED_PREP;
|
||||
}else{
|
||||
keyerState = CHK_DAH;
|
||||
@ -194,7 +146,7 @@ void cwKeyer(void){
|
||||
|
||||
case CHK_DAH:
|
||||
if (keyerControl & DAH_L) {
|
||||
ktimer = cwSpeed*3;
|
||||
ktimer = 3*globalSettings.cwDitDurationMs;
|
||||
keyerState = KEYED_PREP;
|
||||
}else{
|
||||
keyerState = IDLE;
|
||||
@ -203,13 +155,11 @@ void cwKeyer(void){
|
||||
|
||||
case KEYED_PREP:
|
||||
//modified KD8CEC
|
||||
if (!inTx){
|
||||
if (!globalSettings.txActive){
|
||||
//DelayTime Option
|
||||
active_delay(delayBeforeCWStartTime * 2);
|
||||
|
||||
keyDown = 0;
|
||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||
startTx(TX_CW);
|
||||
globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs;
|
||||
startTx(TuningMode_e::TUNE_CW);
|
||||
}
|
||||
ktimer += millis(); // set ktimer to interval end time
|
||||
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||
@ -220,10 +170,11 @@ void cwKeyer(void){
|
||||
|
||||
case KEYED:
|
||||
if (millis() > ktimer) { // are we at end of key down ?
|
||||
cwKeyUp();
|
||||
ktimer = millis() + cwSpeed; // inter-element time
|
||||
cwKeyUp();
|
||||
ktimer = millis() + (globalSettings.cwDitDurationMs / 10); // inter-element time
|
||||
keyerState = INTER_ELEMENT; // next state
|
||||
}else if (keyerControl & IAMBICB) {
|
||||
}
|
||||
else if(KeyerMode_e::KEYER_IAMBIC_B == globalSettings.keyerMode){
|
||||
update_PaddleLatch(1); // early paddle latch in Iambic B mode
|
||||
}
|
||||
break;
|
||||
@ -246,20 +197,19 @@ void cwKeyer(void){
|
||||
checkCAT();
|
||||
} //end of while
|
||||
}
|
||||
else{
|
||||
else{//KEYER_STRAIGHT
|
||||
while(1){
|
||||
char state = update_PaddleLatch(0);
|
||||
// Serial.println((int)state);
|
||||
if (state == DIT_L) {
|
||||
// if we are here, it is only because the key is pressed
|
||||
if (!inTx){
|
||||
startTx(TX_CW);
|
||||
if (!globalSettings.txActive){
|
||||
startTx(TuningMode_e::TUNE_CW);
|
||||
|
||||
//DelayTime Option
|
||||
active_delay(delayBeforeCWStartTime * 2);
|
||||
|
||||
keyDown = 0;
|
||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
||||
globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwDitDurationMs;
|
||||
}
|
||||
cwKeydown();
|
||||
|
||||
@ -269,24 +219,16 @@ void cwKeyer(void){
|
||||
cwKeyUp();
|
||||
}
|
||||
else{
|
||||
if (0 < cwTimeout && cwTimeout < millis()){
|
||||
cwTimeout = 0;
|
||||
keyDown = 0;
|
||||
if (0 < globalSettings.cwExpirationTimeMs && globalSettings.cwExpirationTimeMs < millis()){
|
||||
globalSettings.cwExpirationTimeMs = 0;
|
||||
stopTx();
|
||||
}
|
||||
//if (!cwTimeout) //removed by KD8CEC
|
||||
// return;
|
||||
// got back to the beginning of the loop, if no further activity happens on straight key
|
||||
// we will time out, and return out of this routine
|
||||
//delay(5);
|
||||
//delay_background(5, 3); //removed by KD8CEC
|
||||
//continue; //removed by KD8CEC
|
||||
return; //Tx stop control by Main Loop
|
||||
return;//Tx stop control by Main Loop
|
||||
}
|
||||
|
||||
checkCAT();
|
||||
} //end of while
|
||||
} //end of elese
|
||||
}//end of else KEYER_STRAIGHT
|
||||
}
|
||||
|
||||
|
||||
|
37
morse.cpp
37
morse.cpp
@ -1,19 +1,19 @@
|
||||
#include <Arduino.h>
|
||||
#include "ubitx.h"
|
||||
#include "settings.h"
|
||||
#include "morse.h"
|
||||
|
||||
struct Morse {
|
||||
char letter;
|
||||
unsigned char code;
|
||||
};
|
||||
|
||||
/*
|
||||
* Each byte of the morse table stores one letter.
|
||||
* The 0 is a dot, a 1 is a dash
|
||||
* From the Most significant byte onwards, the letter is padded with 1s.
|
||||
* The first zero after the 1s indicates the start of the letter, it MUST be discarded
|
||||
*/
|
||||
|
||||
extern int cwSpeed;
|
||||
struct Morse {
|
||||
char letter;
|
||||
unsigned char code;
|
||||
};
|
||||
|
||||
static const PROGMEM struct Morse morse_table[] = {
|
||||
{'a', 0xf9}, // 11111001
|
||||
{'b', 0xe8}, // 11101000
|
||||
@ -51,9 +51,9 @@ static const PROGMEM struct Morse morse_table[] = {
|
||||
{'8', 0xdc}, // 11011100
|
||||
{'9', 0xde}, // 11011110
|
||||
{'0', 0xdf}, // 11011111
|
||||
{'.', 0xd5}, // 110010101
|
||||
{',', 0xd3}, // 110110011 //AD7U 20191217
|
||||
{'?', 0xcc}, // 11001100 //AD7U 20191217 - Added
|
||||
{'.', 0x95}, // 10010101
|
||||
{',', 0xb3}, // 10110011
|
||||
{'?', 0x8c}, // 10001100
|
||||
};
|
||||
|
||||
static void morseLetter(char c){
|
||||
@ -61,8 +61,8 @@ static void morseLetter(char c){
|
||||
|
||||
//handle space character as three dashes
|
||||
if (c == ' '){
|
||||
active_delay(cwSpeed * 9);
|
||||
Serial.print(' ');
|
||||
active_delay(9 * globalSettings.cwDitDurationMs);
|
||||
//Serial.print(' ');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -79,22 +79,23 @@ static void morseLetter(char c){
|
||||
//now we are at the first zero, skip and carry on
|
||||
mask = mask >> 1;
|
||||
while(mask){
|
||||
tone(CW_TONE, sideTone,10000);
|
||||
tone(CW_TONE, globalSettings.cwSideToneFreq,10000);
|
||||
if (mask & code){
|
||||
delay(3 * (int)cwSpeed);
|
||||
delay(3 * globalSettings.cwDitDurationMs);
|
||||
//Serial.print('-');
|
||||
}
|
||||
else{
|
||||
delay((int)cwSpeed);
|
||||
delay(globalSettings.cwDitDurationMs);
|
||||
//Serial.print('.');
|
||||
}
|
||||
//Serial.print('#');
|
||||
noTone(CW_TONE);
|
||||
delay((int)cwSpeed); // space between dots and dashes
|
||||
delay(globalSettings.cwDitDurationMs); // space between dots and dashes
|
||||
mask = mask >> 1;
|
||||
}
|
||||
//Serial.println('@');
|
||||
delay(200); // space between letters is a dash (3 dots), one dot's space has already been sent
|
||||
delay(2*globalSettings.cwDitDurationMs); // space between letters is a dash (3 dots), one dot's space has already been sent
|
||||
break;//We've played the letter, so don't bother checking the rest of the list
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,7 +108,7 @@ void morseText(char *text){
|
||||
delay(1000);
|
||||
// }
|
||||
|
||||
Serial.println(sideTone);
|
||||
//Serial.println(globalSettings.cwSideToneFreq);
|
||||
while(*text){
|
||||
morseLetter(*text++);
|
||||
}
|
||||
|
78
nano_gui.cpp
78
nano_gui.cpp
@ -1,5 +1,5 @@
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
#include "settings.h"
|
||||
#include "ubitx.h"
|
||||
#include "nano_gui.h"
|
||||
|
||||
@ -8,30 +8,45 @@
|
||||
|
||||
struct Point ts_point;
|
||||
|
||||
//filled from a test run of calibration routine
|
||||
int slope_x=104, slope_y=137, offset_x=28, offset_y=29;
|
||||
/*
|
||||
* This formats the frequency given in f
|
||||
*/
|
||||
void formatFreq(uint32_t freq, char* buff, uint16_t buff_size) {
|
||||
memset(buff, 0, buff_size);
|
||||
|
||||
ultoa(freq, buff, DEC);
|
||||
uint8_t num_digits = strlen(buff);
|
||||
const uint8_t num_spacers = (num_digits-1) / 3;
|
||||
const uint8_t num_leading_digits_raw = num_digits % 3;
|
||||
const uint8_t num_leading_digits = (0 == num_leading_digits_raw) ? 3 : num_leading_digits_raw;
|
||||
|
||||
if(0 == num_spacers){
|
||||
return;
|
||||
}
|
||||
|
||||
buff += num_leading_digits;
|
||||
num_digits -= num_leading_digits;
|
||||
for(int i = num_digits-1; i >= 0; --i){
|
||||
buff[i + (i/3 + 1)] = buff[i];
|
||||
}
|
||||
for(unsigned int i = 0; i < num_spacers; ++i){
|
||||
memcpy_P(buff,F("."),1);
|
||||
buff += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void readTouchCalibration(){
|
||||
EEPROM.get(SLOPE_X, slope_x);
|
||||
EEPROM.get(SLOPE_Y, slope_y);
|
||||
EEPROM.get(OFFSET_X, offset_x);
|
||||
EEPROM.get(OFFSET_Y, offset_y);
|
||||
|
||||
/*
|
||||
//for debugging
|
||||
Serial.print(slope_x); Serial.print(' ');
|
||||
Serial.print(slope_y); Serial.print(' ');
|
||||
Serial.print(offset_x); Serial.print(' ');
|
||||
Serial.println(offset_y); Serial.println(' ');
|
||||
*/
|
||||
|
||||
LoadSettingsFromEeprom();
|
||||
/* for debugging
|
||||
Serial.print(globalSettings.touchSlopeX); Serial.print(' ');
|
||||
Serial.print(globalSettings.touchSlopeY); Serial.print(' ');
|
||||
Serial.print(globalSettings.touchOffsetX); Serial.print(' ');
|
||||
Serial.println(globalSettings.touchOffsetY); Serial.println(' ');
|
||||
//*/
|
||||
}
|
||||
|
||||
void writeTouchCalibration(){
|
||||
EEPROM.put(SLOPE_X, slope_x);
|
||||
EEPROM.put(SLOPE_Y, slope_y);
|
||||
EEPROM.put(OFFSET_X, offset_x);
|
||||
EEPROM.put(OFFSET_Y, offset_y);
|
||||
SaveSettingsToEeprom();
|
||||
}
|
||||
|
||||
#define Z_THRESHOLD 400
|
||||
@ -118,7 +133,7 @@ static void touch_update(){
|
||||
}
|
||||
|
||||
|
||||
boolean readTouch(){
|
||||
bool readTouch(){
|
||||
touch_update();
|
||||
if (zraw >= Z_THRESHOLD) {
|
||||
ts_point.x = xraw;
|
||||
@ -130,8 +145,8 @@ boolean readTouch(){
|
||||
}
|
||||
|
||||
void scaleTouch(struct Point *p){
|
||||
p->x = ((long)(p->x - offset_x) * 10l)/ (long)slope_x;
|
||||
p->y = ((long)(p->y - offset_y) * 10l)/ (long)slope_y;
|
||||
p->x = ((long)(p->x - globalSettings.touchOffsetX) * 10L)/ (long)globalSettings.touchSlopeX;
|
||||
p->y = ((long)(p->y - globalSettings.touchOffsetY) * 10L)/ (long)globalSettings.touchSlopeY;
|
||||
|
||||
//Serial.print(p->x); Serial.print(",");Serial.println(p->y);
|
||||
}
|
||||
@ -169,7 +184,6 @@ void displayInit(void){
|
||||
tft.setRotation(1);
|
||||
|
||||
xpt2046_Init();
|
||||
readTouchCalibration();
|
||||
}
|
||||
|
||||
void displayPixel(unsigned int x, unsigned int y, unsigned int c){
|
||||
@ -291,14 +305,14 @@ void setupTouch(){
|
||||
// we average two readings and divide them by half and store them as scaled integers 10 times their actual, fractional value
|
||||
//the x points are located at 20 and 300 on x axis, hence, the delta x is 280, we take 28 instead, to preserve fractional value,
|
||||
//there are two readings (x1,x2) and (x3, x4). Hence, we have to divide by 28 * 2 = 56
|
||||
slope_x = ((x4 - x3) + (x2 - x1))/56;
|
||||
globalSettings.touchSlopeX = ((x4 - x3) + (x2 - x1))/56;
|
||||
//the y points are located at 20 and 220 on the y axis, hence, the delta is 200. we take it as 20 instead, to preserve the fraction value
|
||||
//there are two readings (y1, y2) and (y3, y4). Hence we have to divide by 20 * 2 = 40
|
||||
slope_y = ((y3 - y1) + (y4 - y2))/40;
|
||||
globalSettings.touchSlopeY = ((y3 - y1) + (y4 - y2))/40;
|
||||
|
||||
//x1, y1 is at 20 pixels
|
||||
offset_x = x1 + -((20 * slope_x)/10);
|
||||
offset_y = y1 + -((20 * slope_y)/10);
|
||||
globalSettings.touchOffsetX = x1 + -((20 * globalSettings.touchSlopeX)/10);
|
||||
globalSettings.touchOffsetY = y1 + -((20 * globalSettings.touchSlopeY)/10);
|
||||
|
||||
/*
|
||||
Serial.print(x1);Serial.print(':');Serial.println(y1);
|
||||
@ -307,10 +321,10 @@ void setupTouch(){
|
||||
Serial.print(x4);Serial.print(':');Serial.println(y4);
|
||||
|
||||
//for debugging
|
||||
Serial.print(slope_x); Serial.print(' ');
|
||||
Serial.print(slope_y); Serial.print(' ');
|
||||
Serial.print(offset_x); Serial.print(' ');
|
||||
Serial.println(offset_y); Serial.println(' ');
|
||||
Serial.print(globalSettings.touchSlopeX); Serial.print(' ');
|
||||
Serial.print(globalSettings.touchSlopeY); Serial.print(' ');
|
||||
Serial.print(globalSettings.touchOffsetX); Serial.print(' ');
|
||||
Serial.println(globalSettings.touchOffsetY); Serial.println(' ');
|
||||
*/
|
||||
writeTouchCalibration();
|
||||
displayClear(DISPLAY_BLACK);
|
||||
|
@ -18,6 +18,8 @@ void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t
|
||||
void displayRawText(char *text, int x1, int y1, int color, int background);
|
||||
void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border);
|
||||
|
||||
void formatFreq(uint32_t freq, char* buff, uint16_t buff_size);
|
||||
|
||||
/* touch functions */
|
||||
boolean readTouch();
|
||||
|
||||
|
168
settings.cpp
Normal file
168
settings.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#include <string.h>//memset
|
||||
#include <stdint.h>
|
||||
#include <EEPROM.h>
|
||||
#include <Arduino.h>//only needed for debugging's Serial.print stuff
|
||||
#include "settings.h"
|
||||
#include "ubitx.h"//redrawVFOs() function
|
||||
|
||||
/**
|
||||
* These are the "magic" indices where these user changable settinngs are stored in the EEPROM
|
||||
*/
|
||||
static const uint16_t EEPROM_ADDR_MASTER_CAL = 0;//int32_t
|
||||
//4 is currently unused, but may have been LSB_CAL on other versions
|
||||
static const uint16_t EEPROM_ADDR_USB_CAL = 8;//uint32_t
|
||||
//12 is currently unused, but may have been CW_SIDETONE on other versions?
|
||||
static const uint16_t EEPROM_ADDR_VFO_A_FREQ = 16;//uint32_t
|
||||
static const uint16_t EEPROM_ADDR_VFO_B_FREQ = 20;//uint32_t
|
||||
static const uint16_t EEPROM_ADDR_CW_SIDETONE = 24;//uint32_t
|
||||
static const uint16_t EEPROM_ADDR_CW_DIT_TIME = 28;//uint32_t
|
||||
static const uint16_t EEPROM_ADDR_TOUCH_SLOPE_X = 32;//int16_t
|
||||
static const uint16_t EEPROM_ADDR_TOUCH_SLOPE_Y = 36;//int16_t
|
||||
static const uint16_t EEPROM_ADDR_TOUCH_OFFSET_X = 40;//int16_t
|
||||
static const uint16_t EEPROM_ADDR_TOUCH_OFFSET_Y = 44;//int16_t
|
||||
static const uint16_t EEPROM_ADDR_CW_DELAYTIME = 48;
|
||||
static const uint16_t EEPROM_ADDR_VFO_A_MODE = 256;
|
||||
static const uint16_t EEPROM_ADDR_VFO_B_MODE = 257;
|
||||
static const uint16_t EEPROM_ADDR_CW_KEY_TYPE = 358;
|
||||
|
||||
template<typename T>
|
||||
bool LoadSane(T& dest,uint16_t addr, T min, T max)
|
||||
{
|
||||
T read_value;
|
||||
EEPROM.get(addr,read_value);
|
||||
if((min <= read_value) && (read_value <= max)){
|
||||
dest = read_value;
|
||||
//Serial.print(addr);
|
||||
//Serial.print(F(":"));
|
||||
//Serial.println(dest);
|
||||
return true;
|
||||
}
|
||||
//Serial.print(addr);
|
||||
//Serial.print(F(": Not valid: "));
|
||||
//Serial.print(read_value);
|
||||
//Serial.print(F(" Leaving value at "));
|
||||
//Serial.println(dest);
|
||||
return false;
|
||||
}
|
||||
|
||||
//This is the non-extern version that actually gets built
|
||||
SettingsRam globalSettings;
|
||||
|
||||
void LoadDefaultSettings()
|
||||
{
|
||||
memset(&globalSettings,0x00,sizeof(globalSettings));
|
||||
|
||||
globalSettings.oscillatorCal = 0L;
|
||||
globalSettings.usbCarrierFreq = 11052000UL;
|
||||
|
||||
globalSettings.activeVfo = Vfo_e::VFO_A;
|
||||
globalSettings.vfoA.frequency = 7150000UL;
|
||||
globalSettings.vfoA.mode = VFO_MODE_LSB;
|
||||
globalSettings.vfoB.frequency = 14150000UL;
|
||||
globalSettings.vfoB.mode = VFO_MODE_USB;
|
||||
|
||||
globalSettings.keyerMode = KEYER_STRAIGHT;
|
||||
globalSettings.cwSideToneFreq = 800;
|
||||
globalSettings.cwDitDurationMs = 100;
|
||||
globalSettings.cwActiveTimeoutMs = 50;
|
||||
|
||||
globalSettings.touchSlopeX = 104;
|
||||
globalSettings.touchSlopeY = 137;
|
||||
globalSettings.touchOffsetX = 28;
|
||||
globalSettings.touchOffsetY = 29;
|
||||
|
||||
globalSettings.ritOn = false;
|
||||
globalSettings.ritFrequency = globalSettings.vfoA.frequency;
|
||||
|
||||
globalSettings.tuningMode = TuningMode_e::TUNE_SSB;
|
||||
|
||||
globalSettings.splitOn = false;
|
||||
|
||||
globalSettings.txActive = false;
|
||||
globalSettings.txCatActive = false;
|
||||
globalSettings.cwExpirationTimeMs = 0;
|
||||
}
|
||||
|
||||
void LoadSettingsFromEeprom()
|
||||
{
|
||||
LoadSane(globalSettings.usbCarrierFreq,EEPROM_ADDR_USB_CAL,11048000UL,11060000UL);
|
||||
LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,500000UL+1,109000000UL-1);//Allow all freq supported by si5351 driver
|
||||
LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,500000UL+1,109000000UL-1);//Allow all freq supported by si5351 driver
|
||||
LoadSane(globalSettings.cwSideToneFreq,EEPROM_ADDR_CW_SIDETONE,100UL,2000UL);
|
||||
LoadSane(globalSettings.cwDitDurationMs,EEPROM_ADDR_CW_DIT_TIME,10U,1000U);
|
||||
if(LoadSane(globalSettings.cwActiveTimeoutMs,EEPROM_ADDR_CW_DELAYTIME,10U,100U)){
|
||||
globalSettings.cwActiveTimeoutMs *= 10;//scale by 10 for legacy reasons
|
||||
}
|
||||
LoadSane(globalSettings.vfoA.mode,EEPROM_ADDR_VFO_A_MODE,VFO_MODE_LSB,VFO_MODE_USB);
|
||||
LoadSane(globalSettings.vfoB.mode,EEPROM_ADDR_VFO_B_MODE,VFO_MODE_LSB,VFO_MODE_USB);
|
||||
LoadSane(globalSettings.keyerMode,EEPROM_ADDR_CW_KEY_TYPE,KEYER_STRAIGHT,KEYER_IAMBIC_B);
|
||||
|
||||
//No sanity check on these - cal your heart out
|
||||
EEPROM.get(EEPROM_ADDR_MASTER_CAL,globalSettings.oscillatorCal);
|
||||
EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_X,globalSettings.touchSlopeX);
|
||||
EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_Y,globalSettings.touchSlopeY);
|
||||
EEPROM.get(EEPROM_ADDR_TOUCH_OFFSET_X,globalSettings.touchOffsetX);
|
||||
EEPROM.get(EEPROM_ADDR_TOUCH_OFFSET_Y,globalSettings.touchOffsetY);
|
||||
}
|
||||
|
||||
void SaveSettingsToEeprom()
|
||||
{
|
||||
//Serial.println(F("Saving..."));
|
||||
EEPROM.put(EEPROM_ADDR_MASTER_CAL,globalSettings.oscillatorCal);
|
||||
EEPROM.put(EEPROM_ADDR_USB_CAL,globalSettings.usbCarrierFreq);
|
||||
EEPROM.put(EEPROM_ADDR_VFO_A_FREQ,globalSettings.vfoA.frequency);
|
||||
EEPROM.put(EEPROM_ADDR_VFO_B_FREQ,globalSettings.vfoB.frequency);
|
||||
EEPROM.put(EEPROM_ADDR_CW_SIDETONE,globalSettings.cwSideToneFreq);
|
||||
EEPROM.put(EEPROM_ADDR_CW_DIT_TIME,globalSettings.cwDitDurationMs);
|
||||
EEPROM.put(EEPROM_ADDR_TOUCH_SLOPE_X,globalSettings.touchSlopeX);
|
||||
EEPROM.put(EEPROM_ADDR_TOUCH_SLOPE_Y,globalSettings.touchSlopeY);
|
||||
EEPROM.put(EEPROM_ADDR_TOUCH_OFFSET_X,globalSettings.touchOffsetX);
|
||||
EEPROM.put(EEPROM_ADDR_TOUCH_OFFSET_Y,globalSettings.touchOffsetY);
|
||||
EEPROM.put(EEPROM_ADDR_CW_DELAYTIME,globalSettings.cwActiveTimeoutMs/10);//scale by 10 for legacy reasons
|
||||
EEPROM.put(EEPROM_ADDR_VFO_A_MODE,globalSettings.vfoA.mode);
|
||||
EEPROM.put(EEPROM_ADDR_VFO_B_MODE,globalSettings.vfoB.mode);
|
||||
EEPROM.put(EEPROM_ADDR_CW_KEY_TYPE,globalSettings.keyerMode);
|
||||
}
|
||||
|
||||
uint32_t GetActiveVfoFreq()
|
||||
{
|
||||
if(VFO_A == globalSettings.activeVfo){
|
||||
return globalSettings.vfoA.frequency;
|
||||
}
|
||||
else{
|
||||
return globalSettings.vfoB.frequency;
|
||||
}
|
||||
}
|
||||
|
||||
void SetActiveVfoFreq(uint32_t frequency)
|
||||
{
|
||||
if(VFO_A == globalSettings.activeVfo)
|
||||
{
|
||||
globalSettings.vfoA.frequency = frequency;
|
||||
}
|
||||
else{
|
||||
globalSettings.vfoB.frequency = frequency;
|
||||
}
|
||||
}
|
||||
|
||||
VfoMode_e GetActiveVfoMode()
|
||||
{
|
||||
if(VFO_A == globalSettings.activeVfo){
|
||||
return globalSettings.vfoA.mode;
|
||||
}
|
||||
else{
|
||||
return globalSettings.vfoB.mode;
|
||||
}
|
||||
}
|
||||
|
||||
void SetActiveVfoMode(VfoMode_e mode)
|
||||
{
|
||||
if(VFO_A == globalSettings.activeVfo)
|
||||
{
|
||||
globalSettings.vfoA.mode = mode;
|
||||
}
|
||||
else{
|
||||
globalSettings.vfoB.mode = mode;
|
||||
}
|
||||
redrawVFOs();
|
||||
}
|
109
settings.h
Normal file
109
settings.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This class deals with all of the radio settings,
|
||||
* so that other areas of the code doesn't have to
|
||||
*
|
||||
* Example usage:
|
||||
* LoadSettingsFromEeprom();
|
||||
* Serial.println(globalSettings.vfoAFreq);
|
||||
* globalSettings.vfoAFreq = 12345678;
|
||||
* SaveSettingsToEeprom();
|
||||
* Serial.println(globalSettings.vfoAFreq);
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Loads default values for all settings
|
||||
*/
|
||||
void LoadDefaultSettings();
|
||||
|
||||
/*
|
||||
* Loads all persistent settings from the EEPROM
|
||||
*/
|
||||
void LoadSettingsFromEeprom();
|
||||
|
||||
/*
|
||||
* Saves all persistent settings to the EEPROM
|
||||
*
|
||||
* It's a little CPU-cycle-wasteful to save EVERYTHING
|
||||
* each time, but keeps things simple
|
||||
*/
|
||||
void SaveSettingsToEeprom();
|
||||
|
||||
/*
|
||||
* These are all of the settings
|
||||
* Note that not all settings are saved to the EEPROM
|
||||
*/
|
||||
enum Vfo_e : uint8_t
|
||||
{
|
||||
VFO_A,
|
||||
VFO_B
|
||||
};
|
||||
|
||||
enum VfoMode_e : uint8_t
|
||||
{
|
||||
VFO_MODE_LSB = 2,
|
||||
VFO_MODE_USB = 3
|
||||
};
|
||||
|
||||
struct VfoSettings_t
|
||||
{
|
||||
uint32_t frequency;
|
||||
VfoMode_e mode;
|
||||
};
|
||||
|
||||
enum TuningMode_e : uint8_t
|
||||
{
|
||||
TUNE_SSB,
|
||||
TUNE_CW
|
||||
};
|
||||
|
||||
enum KeyerMode_e : uint8_t
|
||||
{
|
||||
KEYER_STRAIGHT,
|
||||
KEYER_IAMBIC_A,
|
||||
KEYER_IAMBIC_B
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the definition of the settings/state variables
|
||||
*/
|
||||
struct SettingsRam
|
||||
{
|
||||
uint32_t oscillatorCal;
|
||||
uint32_t usbCarrierFreq;
|
||||
|
||||
Vfo_e activeVfo;
|
||||
VfoSettings_t vfoA;
|
||||
VfoSettings_t vfoB;
|
||||
|
||||
KeyerMode_e keyerMode;
|
||||
uint32_t cwSideToneFreq;
|
||||
uint16_t cwDitDurationMs;
|
||||
uint16_t cwActiveTimeoutMs;
|
||||
|
||||
int16_t touchSlopeX;
|
||||
int16_t touchSlopeY;
|
||||
int16_t touchOffsetX;
|
||||
int16_t touchOffsetY;
|
||||
|
||||
bool ritOn;
|
||||
uint32_t ritFrequency;
|
||||
|
||||
TuningMode_e tuningMode;
|
||||
|
||||
bool splitOn;
|
||||
|
||||
bool txActive;
|
||||
bool txCatActive;
|
||||
uint32_t cwExpirationTimeMs;
|
||||
};
|
||||
|
||||
//This is the shared declaration
|
||||
extern SettingsRam globalSettings;
|
||||
|
||||
//Some convenience functions
|
||||
uint32_t GetActiveVfoFreq();
|
||||
void SetActiveVfoFreq(uint32_t frequency);
|
||||
VfoMode_e GetActiveVfoMode();
|
||||
void SetActiveVfoMode(VfoMode_e mode);
|
164
setup.cpp
164
setup.cpp
@ -1,6 +1,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
#include "morse.h"
|
||||
#include "settings.h"
|
||||
#include "ubitx.h"
|
||||
#include "nano_gui.h"
|
||||
|
||||
@ -22,7 +23,6 @@ void setupExit(){
|
||||
}
|
||||
|
||||
//this is used by the si5351 routines in the ubitx_5351 file
|
||||
extern int32_t calibration;
|
||||
extern uint32_t si5351bx_vcoa;
|
||||
|
||||
static const unsigned int COLOR_TEXT = DISPLAY_WHITE;
|
||||
@ -73,73 +73,61 @@ void displayDialog(const __FlashStringHelper* title, const __FlashStringHelper*
|
||||
displayText(c, LAYOUT_INSTRUCTION_TEXT_X, LAYOUT_INSTRUCTION_TEXT_Y, LAYOUT_INSTRUCTION_TEXT_WIDTH, LAYOUT_INSTRUCTION_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
void printCarrierFreq(unsigned long freq){
|
||||
|
||||
memset(c, 0, sizeof(c));
|
||||
memset(b, 0, sizeof(b));
|
||||
|
||||
ultoa(freq, b, DEC);
|
||||
|
||||
strncat(c, b, 2);
|
||||
strcat_P(c,(const char*)F("."));
|
||||
strncat(c, &b[2], 3);
|
||||
strcat(c,(const char*)F("."));
|
||||
strncat(c, &b[5], 1);
|
||||
void printCarrierFreq(unsigned long freq)
|
||||
{
|
||||
formatFreq(freq,c,sizeof(c));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
void setupFreq(){
|
||||
int knob = 0;
|
||||
int32_t prev_calibration;
|
||||
|
||||
displayDialog(F("Set Frequency"),F("Push TUNE to Save"));
|
||||
|
||||
//round off the the nearest khz
|
||||
frequency = (frequency/1000l)* 1000l;
|
||||
setFrequency(frequency);
|
||||
{
|
||||
uint32_t freq = GetActiveVfoFreq();
|
||||
freq = (freq/1000l)* 1000l;
|
||||
setFrequency(freq);
|
||||
}
|
||||
|
||||
strcpy_P(c,(const char*)F("You should have a"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
strcpy_P(c,(const char*)F("signal exactly at"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 1*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
ltoa(frequency/1000l, c, 10);
|
||||
ltoa(GetActiveVfoFreq()/1000L, c, 10);
|
||||
strcat_P(c,(const char*)F(" KHz"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 2*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
strcpy_P(c,(const char*)F("Rotate to zerobeat"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 4*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
|
||||
ltoa(calibration, b, 10);
|
||||
ltoa(globalSettings.oscillatorCal, b, 10);
|
||||
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND);
|
||||
//keep clear of any previous button press
|
||||
while (btnDown())
|
||||
active_delay(100);
|
||||
active_delay(100);
|
||||
|
||||
prev_calibration = calibration;
|
||||
calibration = 0;
|
||||
|
||||
while (!btnDown())
|
||||
{
|
||||
knob = enc_read();
|
||||
if (knob != 0)
|
||||
calibration += knob * 875;
|
||||
/* else if (knob < 0)
|
||||
calibration -= 875; */
|
||||
else
|
||||
int knob = enc_read();
|
||||
if(knob != 0){
|
||||
globalSettings.oscillatorCal += knob * 875;
|
||||
}
|
||||
else{
|
||||
continue; //don't update the frequency or the display
|
||||
}
|
||||
|
||||
si5351bx_setfreq(0, usbCarrier); //set back the cardrier oscillator anyway, cw tx switches it off
|
||||
si5351_set_calibration(calibration);
|
||||
setFrequency(frequency);
|
||||
si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator anyway, cw tx switches it off
|
||||
si5351_set_calibration(globalSettings.oscillatorCal);
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
|
||||
ltoa(calibration, b, 10);
|
||||
ltoa(globalSettings.oscillatorCal, b, 10);
|
||||
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
EEPROM.put(MASTER_CAL, calibration);
|
||||
SaveSettingsToEeprom();
|
||||
initOscillators();
|
||||
si5351_set_calibration(calibration);
|
||||
setFrequency(frequency);
|
||||
si5351_set_calibration(globalSettings.oscillatorCal);
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
|
||||
//debounce and delay
|
||||
while(btnDown())
|
||||
@ -148,37 +136,30 @@ void setupFreq(){
|
||||
}
|
||||
|
||||
void setupBFO(){
|
||||
int knob = 0;
|
||||
unsigned long prevCarrier;
|
||||
|
||||
prevCarrier = usbCarrier;
|
||||
|
||||
displayDialog(F("Set BFO"),F("Press TUNE to Save"));
|
||||
|
||||
usbCarrier = 11053000l;
|
||||
si5351bx_setfreq(0, usbCarrier);
|
||||
printCarrierFreq(usbCarrier);
|
||||
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||
printCarrierFreq(globalSettings.usbCarrierFreq);
|
||||
|
||||
while (!btnDown()){
|
||||
knob = enc_read();
|
||||
|
||||
if (knob != 0)
|
||||
usbCarrier -= 50 * knob;
|
||||
else
|
||||
int knob = enc_read();
|
||||
if(knob != 0){
|
||||
globalSettings.usbCarrierFreq -= 50 * knob;
|
||||
}
|
||||
else{
|
||||
continue; //don't update the frequency or the display
|
||||
}
|
||||
|
||||
si5351bx_setfreq(0, usbCarrier);
|
||||
setFrequency(frequency);
|
||||
printCarrierFreq(usbCarrier);
|
||||
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
printCarrierFreq(globalSettings.usbCarrierFreq);
|
||||
|
||||
active_delay(100);
|
||||
}
|
||||
|
||||
EEPROM.put(USB_CAL, usbCarrier);
|
||||
si5351bx_setfreq(0, usbCarrier);
|
||||
setFrequency(frequency);
|
||||
updateDisplay();
|
||||
menuOn = 0;
|
||||
SaveSettingsToEeprom();
|
||||
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
}
|
||||
|
||||
void setupCwDelay(){
|
||||
@ -188,44 +169,41 @@ void setupCwDelay(){
|
||||
displayDialog(F("Set CW T/R Delay"),F("Press tune to Save"));
|
||||
|
||||
active_delay(500);
|
||||
prev_cw_delay = cwDelayTime;
|
||||
prev_cw_delay = globalSettings.cwActiveTimeoutMs;
|
||||
|
||||
itoa(10 * (int)cwDelayTime, b, 10);
|
||||
ltoa(globalSettings.cwActiveTimeoutMs, b, 10);
|
||||
strcat_P(b,(const char*)F(" msec"));
|
||||
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
|
||||
|
||||
while (!btnDown()){
|
||||
knob = enc_read();
|
||||
|
||||
if (knob < 0 && cwDelayTime > 10)
|
||||
cwDelayTime -= 10;
|
||||
else if (knob > 0 && cwDelayTime < 100)
|
||||
cwDelayTime += 10;
|
||||
if (knob < 0 && globalSettings.cwActiveTimeoutMs > 100)
|
||||
globalSettings.cwActiveTimeoutMs -= 100;
|
||||
else if (knob > 0 && globalSettings.cwActiveTimeoutMs < 1000)
|
||||
globalSettings.cwActiveTimeoutMs += 100;
|
||||
else
|
||||
continue; //don't update the frequency or the display
|
||||
|
||||
itoa(10 * (int)cwDelayTime, b, 10);
|
||||
ltoa(globalSettings.cwActiveTimeoutMs, b, 10);
|
||||
strcat_P(b,(const char*)F(" msec"));
|
||||
displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
|
||||
|
||||
}
|
||||
|
||||
EEPROM.put(CW_DELAYTIME, cwDelayTime);
|
||||
|
||||
SaveSettingsToEeprom();
|
||||
active_delay(500);
|
||||
menuOn = 0;
|
||||
setupExit();
|
||||
}
|
||||
|
||||
void setupKeyer(){
|
||||
int tmp_key, knob;
|
||||
|
||||
displayDialog(F("Set CW Keyer"),F("Press tune to Save"));
|
||||
|
||||
if (!Iambic_Key){
|
||||
if(KeyerMode_e::KEYER_STRAIGHT == globalSettings.keyerMode){
|
||||
strcpy_P(c,(const char*)F("< Hand Key >"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
else if (keyerControl & IAMBICB){
|
||||
else if(KeyerMode_e::KEYER_IAMBIC_A == globalSettings.keyerMode){
|
||||
strcpy_P(c,(const char*)F("< Iambic A >"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
@ -234,56 +212,42 @@ void setupKeyer(){
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
if (!Iambic_Key)
|
||||
tmp_key = 0; //hand key
|
||||
else if (keyerControl & IAMBICB)
|
||||
tmp_key = 2; //Iambic B
|
||||
else
|
||||
tmp_key = 1;
|
||||
|
||||
int knob = 0;
|
||||
uint32_t tmp_mode = globalSettings.keyerMode;
|
||||
while (!btnDown())
|
||||
{
|
||||
knob = enc_read();
|
||||
if (knob == 0){
|
||||
if(knob == 0){
|
||||
active_delay(50);
|
||||
continue;
|
||||
}
|
||||
if (knob < 0 && tmp_key > 0)
|
||||
tmp_key--;
|
||||
if (knob > 0)
|
||||
tmp_key++;
|
||||
if (tmp_key > 2)
|
||||
tmp_key = 0;
|
||||
if(knob < 0 && tmp_mode > KeyerMode_e::KEYER_STRAIGHT){
|
||||
tmp_mode--;
|
||||
}
|
||||
if(knob > 0 && tmp_mode < KeyerMode_e::KEYER_IAMBIC_B){
|
||||
tmp_mode++;
|
||||
}
|
||||
|
||||
if (tmp_key == 0){
|
||||
if (KeyerMode_e::KEYER_STRAIGHT == tmp_mode){
|
||||
strcpy_P(c,(const char*)F("< Hand Key >"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
else if (tmp_key == 1){
|
||||
else if(KeyerMode_e::KEYER_IAMBIC_A == tmp_mode){
|
||||
strcpy_P(c,(const char*)F("< Iambic A >"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
else if (tmp_key == 2){
|
||||
else if (KeyerMode_e::KEYER_IAMBIC_B == tmp_mode){
|
||||
strcpy_P(c,(const char*)F("< Iambic B >"));
|
||||
displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
active_delay(500);
|
||||
if (tmp_key == 0)
|
||||
Iambic_Key = false;
|
||||
else if (tmp_key == 1){
|
||||
Iambic_Key = true;
|
||||
keyerControl &= ~IAMBICB;
|
||||
}
|
||||
else if (tmp_key == 2){
|
||||
Iambic_Key = true;
|
||||
keyerControl |= IAMBICB;
|
||||
}
|
||||
|
||||
EEPROM.put(CW_KEY_TYPE, tmp_key);
|
||||
globalSettings.keyerMode = tmp_mode;
|
||||
SaveSettingsToEeprom();
|
||||
|
||||
menuOn = 0;
|
||||
setupExit();
|
||||
}
|
||||
|
||||
const char MI_SET_FREQ [] PROGMEM = "Set Freq...";
|
||||
|
84
ubitx.h
84
ubitx.h
@ -1,3 +1,4 @@
|
||||
#include "settings.h"
|
||||
|
||||
/* The ubitx is powered by an arduino nano. The pin assignment is as folows
|
||||
*
|
||||
@ -56,7 +57,6 @@ it uses an ILI9341 display controller and an XPT2046 touch controller.
|
||||
* the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable.
|
||||
*/
|
||||
extern char c[30], b[30];
|
||||
extern char printBuff[2][20]; //mirrors what is showing on the two lines of the display
|
||||
|
||||
/**
|
||||
* The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig.
|
||||
@ -69,37 +69,6 @@ extern char printBuff[2][20]; //mirrors what is showing on the two lines of the
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* These are the indices where these user changable settinngs are stored in the EEPROM
|
||||
*/
|
||||
#define MASTER_CAL 0
|
||||
#define LSB_CAL 4
|
||||
#define USB_CAL 8
|
||||
#define SIDE_TONE 12
|
||||
//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values
|
||||
#define VFO_A 16
|
||||
#define VFO_B 20
|
||||
#define CW_SIDETONE 24
|
||||
#define CW_SPEED 28
|
||||
// the screen calibration parameters : int slope_x=104, slope_y=137, offset_x=28, offset_y=29;
|
||||
#define SLOPE_X 32
|
||||
#define SLOPE_Y 36
|
||||
#define OFFSET_X 40
|
||||
#define OFFSET_Y 44
|
||||
#define CW_DELAYTIME 48
|
||||
|
||||
//These are defines for the new features back-ported from KD8CEC's software
|
||||
//these start from beyond 256 as Ian, KD8CEC has kept the first 256 bytes free for the base version
|
||||
#define VFO_A_MODE 256 // 2: LSB, 3: USB
|
||||
#define VFO_B_MODE 257
|
||||
|
||||
//values that are stroed for the VFO modes
|
||||
#define VFO_MODE_LSB 2
|
||||
#define VFO_MODE_USB 3
|
||||
|
||||
// handkey, iambic a, iambic b : 0,1,2f
|
||||
#define CW_KEY_TYPE 358
|
||||
|
||||
/**
|
||||
* The uBITX is an upconnversion transceiver. The first IF is at 45 MHz.
|
||||
* The first IF frequency is not exactly at 45 Mhz but about 5 khz lower,
|
||||
@ -121,62 +90,23 @@ extern char printBuff[2][20]; //mirrors what is showing on the two lines of the
|
||||
// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz
|
||||
#define LOWEST_FREQ (100000l)
|
||||
#define HIGHEST_FREQ (30000000l)
|
||||
static const uint32_t THRESHOLD_USB_LSB = 10000000L;
|
||||
|
||||
//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes
|
||||
//these are the parameter passed to startTx
|
||||
#define TX_SSB 0
|
||||
#define TX_CW 1
|
||||
|
||||
extern char ritOn;
|
||||
extern char vfoActive;
|
||||
extern unsigned long vfoA, vfoB, sideTone, usbCarrier;
|
||||
extern char isUsbVfoA, isUsbVfoB;
|
||||
extern unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial
|
||||
extern unsigned long firstIF;
|
||||
|
||||
// if cwMode is flipped on, the rx frequency is tuned down by sidetone hz instead of being zerobeat
|
||||
extern int cwMode;
|
||||
|
||||
|
||||
//these are variables that control the keyer behaviour
|
||||
extern int cwSpeed; //this is actuall the dot period in milliseconds
|
||||
extern int32_t calibration;
|
||||
extern int cwDelayTime;
|
||||
extern bool Iambic_Key;
|
||||
|
||||
#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B
|
||||
extern unsigned char keyerControl;
|
||||
//during CAT commands, we will freeeze the display until CAT is disengaged
|
||||
extern unsigned char doingCAT;
|
||||
|
||||
|
||||
/**
|
||||
* Raduino needs to keep track of current state of the transceiver. These are a few variables that do it
|
||||
*/
|
||||
extern boolean txCAT; //turned on if the transmitting due to a CAT command
|
||||
extern char inTx; //it is set to 1 if in transmit mode (whatever the reason : cw, ptt or cat)
|
||||
extern int splitOn; //working split, uses VFO B as the transmit frequency
|
||||
extern char keyDown; //in cw mode, denotes the carrier is being transmitted
|
||||
extern char isUSB; //upper sideband was selected, this is reset to the default for the
|
||||
//frequency when it crosses the frequency border of 10 MHz
|
||||
extern byte menuOn; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited
|
||||
extern unsigned long cwTimeout; //milliseconds to go before the cw transmit line is released and the radio goes back to rx mode
|
||||
extern unsigned long dbgCount; //not used now
|
||||
extern unsigned char txFilter ; //which of the four transmit filters are in use
|
||||
extern boolean modeCalibrate;//this mode of menus shows extended menus to calibrate the oscillators and choose the proper
|
||||
//beat frequency
|
||||
extern uint8_t menuOn;
|
||||
|
||||
/* these are functions implemented in the main file named as ubitx_xxx.ino */
|
||||
void active_delay(int delay_by);
|
||||
void saveVFOs();
|
||||
void setFrequency(unsigned long f);
|
||||
void startTx(byte txMode);
|
||||
void startTx(TuningMode_e tx_mode);
|
||||
void stopTx();
|
||||
void ritEnable(unsigned long f);
|
||||
void ritDisable();
|
||||
void checkCAT();
|
||||
void cwKeyer(void);
|
||||
void switchVFO(int vfoSelect);
|
||||
void switchVFO(Vfo_e vfoSelect);
|
||||
|
||||
int enc_read(void); // returns the number of ticks in a short interval, +ve in clockwise, -ve in anti-clockwise
|
||||
void enc_setup(void); // Setups up initial values and interrupts.
|
||||
@ -203,10 +133,6 @@ void checkTouch(); //does the commands with a touch on the buttons
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* these are functiosn implemented in ubitx_si5351.cpp */
|
||||
void si5351bx_setfreq(uint8_t clknum, uint32_t fout);
|
||||
void initOscillators();
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <Arduino.h>
|
||||
#include "settings.h"
|
||||
#include "ubitx.h"
|
||||
#include "nano_gui.h"
|
||||
|
||||
@ -159,7 +160,7 @@ void catReadEEPRom(void)
|
||||
//5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE
|
||||
//6 :
|
||||
//7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0)
|
||||
cat[0] = 0x80 + (vfoActive == VFO_B ? 1 : 0);
|
||||
cat[0] = 0x80 + ((VFO_B == globalSettings.activeVfo) ? 1 : 0);
|
||||
cat[1] = 0x00;
|
||||
break;
|
||||
case 0x57 : //
|
||||
@ -187,11 +188,11 @@ void catReadEEPRom(void)
|
||||
//5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel
|
||||
//7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW
|
||||
//CAT_BUFF[0] = 0x08;
|
||||
cat[0] = (sideTone - 300)/50;
|
||||
cat[0] = (globalSettings.cwSideToneFreq - 300)/50;
|
||||
cat[1] = 0x25;
|
||||
break;
|
||||
case 0x61 : //Sidetone (Volume) (#44)
|
||||
cat[0] = sideTone % 50;
|
||||
case 0x61 : //globalSettings.cwSideToneFreq (Volume) (#44)
|
||||
cat[0] = globalSettings.cwSideToneFreq % 50;
|
||||
cat[1] = 0x08;
|
||||
break;
|
||||
case 0x5F : //
|
||||
@ -203,14 +204,14 @@ void catReadEEPRom(void)
|
||||
cat[1] = 0x08;
|
||||
break;
|
||||
case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms
|
||||
cat[0] = cwDelayTime;
|
||||
cat[0] = globalSettings.cwActiveTimeoutMs / 10;
|
||||
cat[1] = 0x32;
|
||||
break;
|
||||
case 0x62 : //
|
||||
//5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps)
|
||||
//7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours
|
||||
//CAT_BUFF[0] = 0x08;
|
||||
cat[0] = 1200 / cwSpeed - 4;
|
||||
cat[0] = 1200 / globalSettings.cwDitDurationMs - 4;
|
||||
cat[1] = 0xB2;
|
||||
break;
|
||||
case 0x63 : //
|
||||
@ -226,7 +227,7 @@ void catReadEEPRom(void)
|
||||
cat[1] = 0xB2;
|
||||
break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed
|
||||
case 0x78 :
|
||||
if (isUSB)
|
||||
if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode())
|
||||
cat[0] = CAT_MODE_USB;
|
||||
else
|
||||
cat[0] = CAT_MODE_LSB;
|
||||
@ -252,7 +253,7 @@ void catReadEEPRom(void)
|
||||
//7A 6 ? ?
|
||||
//7A 7 SPL On/Off 0 = Off, 1 = On
|
||||
|
||||
cat[0] = (splitOn ? 0xFF : 0x7F);
|
||||
cat[0] = (globalSettings.splitOn ? 0xFF : 0x7F);
|
||||
break;
|
||||
case 0xB3 : //
|
||||
cat[0] = 0x00;
|
||||
@ -288,16 +289,16 @@ void processCATCommand2(byte* cmd) {
|
||||
|
||||
case 0x02:
|
||||
//split on
|
||||
splitOn = 1;
|
||||
globalSettings.splitOn = 1;
|
||||
break;
|
||||
case 0x82:
|
||||
//split off
|
||||
splitOn = 0;
|
||||
globalSettings.splitOn = 0;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
writeFreq(frequency,response); // Put the frequency into the buffer
|
||||
if (isUSB)
|
||||
writeFreq(GetActiveVfoFreq(),response); // Put the frequency into the buffer
|
||||
if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode())
|
||||
response[4] = 0x01; //USB
|
||||
else
|
||||
response[4] = 0x00; //LSB
|
||||
@ -307,21 +308,21 @@ void processCATCommand2(byte* cmd) {
|
||||
|
||||
case 0x07: // set mode
|
||||
if (cmd[0] == 0x00 || cmd[0] == 0x03)
|
||||
isUSB = 0;
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||
else
|
||||
isUSB = 1;
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||
response[0] = 0x00;
|
||||
Serial.write(response, 1);
|
||||
setFrequency(frequency);
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
//printLine2("cat: mode changed");
|
||||
//updateDisplay();
|
||||
break;
|
||||
|
||||
case 0x08: // PTT On
|
||||
if (!inTx) {
|
||||
if (!globalSettings.txActive) {
|
||||
response[0] = 0;
|
||||
txCAT = true;
|
||||
startTx(TX_SSB);
|
||||
globalSettings.txCatActive = true;
|
||||
startTx(TuningMode_e::TUNE_SSB);
|
||||
updateDisplay();
|
||||
} else {
|
||||
response[0] = 0xf0;
|
||||
@ -331,9 +332,9 @@ void processCATCommand2(byte* cmd) {
|
||||
break;
|
||||
|
||||
case 0x88 : //PTT OFF
|
||||
if (inTx) {
|
||||
if (globalSettings.txActive) {
|
||||
stopTx();
|
||||
txCAT = false;
|
||||
globalSettings.txCatActive = false;
|
||||
}
|
||||
response[0] = 0;
|
||||
Serial.write(response,1);
|
||||
@ -343,7 +344,7 @@ void processCATCommand2(byte* cmd) {
|
||||
case 0x81:
|
||||
//toggle the VFOs
|
||||
response[0] = 0;
|
||||
if (vfoActive == VFO_A)
|
||||
if (VFO_A == globalSettings.activeVfo)
|
||||
switchVFO(VFO_B);
|
||||
else
|
||||
switchVFO(VFO_A);
|
||||
@ -366,14 +367,14 @@ void processCATCommand2(byte* cmd) {
|
||||
case 0xf7:
|
||||
{
|
||||
boolean isHighSWR = false;
|
||||
boolean isSplitOn = false;
|
||||
boolean issplitOn = false;
|
||||
|
||||
/*
|
||||
Inverted -> *ptt = ((p->tx_status & 0x80) == 0); <-- souce code in ft817.c (hamlib)
|
||||
*/
|
||||
response[0] = ((inTx ? 0 : 1) << 7) +
|
||||
response[0] = ((globalSettings.txActive ? 0 : 1) << 7) +
|
||||
((isHighSWR ? 1 : 0) << 6) + //hi swr off / on
|
||||
((isSplitOn ? 1 : 0) << 5) + //Split on / off
|
||||
((issplitOn ? 1 : 0) << 5) + //Split on / off
|
||||
(0 << 4) + //dummy data
|
||||
0x08; //P0 meter data
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include "settings.h"
|
||||
#include "ubitx.h"
|
||||
|
||||
// ************* SI5315 routines - tks Jerry Gaffke, KE7ER ***********************
|
||||
@ -48,7 +49,6 @@ uint32_t si5351bx_vcoa = (SI5351BX_XTAL*SI5351BX_MSA); // 25mhzXtal calibrate
|
||||
uint8_t si5351bx_rdiv = 0; // 0-7, CLK pin sees fout/(2**rdiv)
|
||||
uint8_t si5351bx_drive[3] = {3, 3, 3}; // 0=2ma 1=4ma 2=6ma 3=8ma for CLK 0,1,2
|
||||
uint8_t si5351bx_clken = 0xFF; // Private, all CLK output drivers off
|
||||
int32_t calibration = 0;
|
||||
|
||||
void i2cWrite(uint8_t reg, uint8_t val) { // write reg via i2c
|
||||
Wire.beginTransmission(SI5351BX_ADDR);
|
||||
@ -115,14 +115,13 @@ void si5351bx_setfreq(uint8_t clknum, uint32_t fout) { // Set a CLK to fout Hz
|
||||
|
||||
void si5351_set_calibration(int32_t cal){
|
||||
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + cal; // apply the calibration correction factor
|
||||
si5351bx_setfreq(0, usbCarrier);
|
||||
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||
}
|
||||
|
||||
void initOscillators(){
|
||||
//initialize the SI5351
|
||||
si5351bx_init();
|
||||
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor
|
||||
si5351bx_setfreq(0, usbCarrier);
|
||||
si5351_set_calibration(globalSettings.oscillatorCal);
|
||||
}
|
||||
|
||||
|
||||
|
269
ubitx_ui.cpp
269
ubitx_ui.cpp
@ -1,6 +1,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <EEPROM.h>
|
||||
#include "morse.h"
|
||||
#include "settings.h"
|
||||
#include "ubitx.h"
|
||||
#include "nano_gui.h"
|
||||
|
||||
@ -147,40 +148,13 @@ boolean getButton(btn_set_e index, Button* button){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This formats the frequency given in f
|
||||
*/
|
||||
void formatFreq(long f, char *buff) {
|
||||
// tks Jack Purdum W8TEE
|
||||
// replaced fsprint commmands by str commands for code size reduction
|
||||
|
||||
memset(buff, 0, 10);
|
||||
memset(b, 0, sizeof(b));
|
||||
|
||||
ultoa(f, b, DEC);
|
||||
|
||||
//one mhz digit if less than 10 M, two digits if more
|
||||
if (f < 10000000l){
|
||||
buff[0] = ' ';
|
||||
strncat(buff, b, 4);
|
||||
strcat(buff, ".");
|
||||
strncat(buff, &b[4], 2);
|
||||
}
|
||||
else {
|
||||
strncat(buff, b, 5);
|
||||
strcat(buff, ".");
|
||||
strncat(buff, &b[5], 2);
|
||||
}
|
||||
}
|
||||
|
||||
inline void drawCommandbar(char* text){
|
||||
displayText(text, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
/** A generic control to read variable values
|
||||
*/
|
||||
int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* prefix, char *postfix)
|
||||
int getValueByKnob(int minimum, int maximum, int step_size, int initial, const __FlashStringHelper* prefix, const __FlashStringHelper* postfix)
|
||||
{
|
||||
int knob = 0;
|
||||
int knob_value;
|
||||
@ -191,10 +165,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char*
|
||||
active_delay(200);
|
||||
knob_value = initial;
|
||||
|
||||
strcpy(b, prefix);
|
||||
strcpy_P(b,(const char*)prefix);
|
||||
itoa(knob_value, c, 10);
|
||||
strcat(b, c);
|
||||
strcat(b, postfix);
|
||||
strcat_P(b, (const char*)postfix);
|
||||
drawCommandbar(b);
|
||||
|
||||
while(!btnDown() && digitalRead(PTT) == HIGH){
|
||||
@ -205,10 +179,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char*
|
||||
if (knob_value < maximum && knob > 0)
|
||||
knob_value += step_size;
|
||||
|
||||
strcpy(b, prefix);
|
||||
strcpy_P(b,(const char*)prefix);
|
||||
itoa(knob_value, c, 10);
|
||||
strcat(b, c);
|
||||
strcat(b, postfix);
|
||||
strcat_P(b,(const char*)postfix);
|
||||
drawCommandbar(b);
|
||||
}
|
||||
checkCAT();
|
||||
@ -218,13 +192,13 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char*
|
||||
return knob_value;
|
||||
}
|
||||
|
||||
void displayVFO(int vfo){
|
||||
void displayVFO(Vfo_e vfo){
|
||||
int x, y;
|
||||
int displayColor, displayBackground, displayBorder;
|
||||
Button button;
|
||||
|
||||
if (splitOn){
|
||||
if (vfoActive == vfo){
|
||||
if (globalSettings.splitOn){
|
||||
if (vfo == globalSettings.activeVfo){
|
||||
c[0] = 'R';
|
||||
}
|
||||
else{
|
||||
@ -245,32 +219,30 @@ void displayVFO(int vfo){
|
||||
c[1] = ':';
|
||||
|
||||
|
||||
if (vfo == VFO_A){
|
||||
if (VFO_A == vfo){
|
||||
getButton(BUTTON_VFOA, &button);
|
||||
formatFreq(globalSettings.vfoA.frequency, c+2, sizeof(c)-2);
|
||||
|
||||
if (vfoActive == VFO_A){
|
||||
formatFreq(frequency, c+2);
|
||||
if (VFO_A == globalSettings.activeVfo){
|
||||
displayColor = COLOR_ACTIVE_VFO_TEXT;
|
||||
displayBackground = COLOR_ACTIVE_VFO_BACKGROUND;
|
||||
displayBorder = COLOR_ACTIVE_BORDER;
|
||||
}else{
|
||||
formatFreq(vfoA, c+2);
|
||||
displayColor = COLOR_INACTIVE_VFO_TEXT;
|
||||
displayBackground = COLOR_INACTIVE_VFO_BACKGROUND;
|
||||
displayBorder = COLOR_INACTIVE_BORDER;
|
||||
}
|
||||
}
|
||||
|
||||
if (vfo == VFO_B){
|
||||
if (VFO_B == vfo){
|
||||
getButton(BUTTON_VFOB, &button);
|
||||
formatFreq(globalSettings.vfoB.frequency, c+2, sizeof(c)-2);
|
||||
|
||||
if (vfoActive == VFO_B){
|
||||
formatFreq(frequency, c+2);
|
||||
if (VFO_B == globalSettings.activeVfo){
|
||||
displayColor = COLOR_ACTIVE_VFO_TEXT;
|
||||
displayBackground = COLOR_ACTIVE_VFO_BACKGROUND;
|
||||
displayBorder = COLOR_ACTIVE_BORDER;
|
||||
} else {
|
||||
formatFreq(vfoB, c+2);
|
||||
displayColor = COLOR_INACTIVE_VFO_TEXT;
|
||||
displayBackground = COLOR_INACTIVE_VFO_BACKGROUND;
|
||||
displayBorder = COLOR_INACTIVE_BORDER;
|
||||
@ -301,7 +273,7 @@ void btnDraw(struct Button *button){
|
||||
}
|
||||
case BUTTON_RIT:
|
||||
{
|
||||
if(1 == ritOn){
|
||||
if(globalSettings.ritOn){
|
||||
btnDrawActive(button);
|
||||
}
|
||||
else{
|
||||
@ -311,7 +283,7 @@ void btnDraw(struct Button *button){
|
||||
}
|
||||
case BUTTON_USB:
|
||||
{
|
||||
if(1 == isUSB){
|
||||
if(VFO_MODE_USB == GetActiveVfoMode()){
|
||||
btnDrawActive(button);
|
||||
}
|
||||
else{
|
||||
@ -321,7 +293,7 @@ void btnDraw(struct Button *button){
|
||||
}
|
||||
case BUTTON_LSB:
|
||||
{
|
||||
if(0 == isUSB){
|
||||
if(VFO_MODE_LSB == GetActiveVfoMode()){
|
||||
btnDrawActive(button);
|
||||
}
|
||||
else{
|
||||
@ -331,7 +303,7 @@ void btnDraw(struct Button *button){
|
||||
}
|
||||
case BUTTON_SPL:
|
||||
{
|
||||
if(1 == splitOn){
|
||||
if(globalSettings.splitOn){
|
||||
btnDrawActive(button);
|
||||
}
|
||||
else{
|
||||
@ -341,7 +313,7 @@ void btnDraw(struct Button *button){
|
||||
}
|
||||
case BUTTON_CW:
|
||||
{
|
||||
if(1 == cwMode){
|
||||
if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){
|
||||
btnDrawActive(button);
|
||||
}
|
||||
else{
|
||||
@ -361,10 +333,10 @@ void btnDraw(struct Button *button){
|
||||
void displayRIT(){
|
||||
c[0] = 0;
|
||||
displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND);
|
||||
if (ritOn){
|
||||
if(globalSettings.ritOn){
|
||||
strcpy_P(c,(const char*)F("TX:"));
|
||||
formatFreq(ritTxFrequency, c+3);
|
||||
if (vfoActive == VFO_A)
|
||||
formatFreq(globalSettings.ritFrequency, c+3, sizeof(c)-3);
|
||||
if (VFO_A == globalSettings.activeVfo)
|
||||
displayText(c, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
else
|
||||
displayText(c, LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
@ -372,14 +344,13 @@ void displayRIT(){
|
||||
}
|
||||
|
||||
void fastTune(){
|
||||
int encoder;
|
||||
|
||||
//if the btn is down, wait until it is up
|
||||
while(btnDown())
|
||||
active_delay(50);
|
||||
active_delay(300);
|
||||
|
||||
displayText("Fast tune", LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
strcpy_P(c,(const char*)F("Fast tune"));
|
||||
displayText(c, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
while(1){
|
||||
checkCAT();
|
||||
|
||||
@ -394,15 +365,17 @@ void fastTune(){
|
||||
return;
|
||||
}
|
||||
|
||||
encoder = enc_read();
|
||||
int encoder = enc_read();
|
||||
if (encoder != 0){
|
||||
|
||||
if (encoder > 0 && frequency < 30000000l)
|
||||
frequency += 50000l;
|
||||
else if (encoder < 0 && frequency > 600000l)
|
||||
frequency -= 50000l;
|
||||
setFrequency(frequency);
|
||||
displayVFO(vfoActive);
|
||||
uint32_t freq = GetActiveVfoFreq();
|
||||
if (encoder > 0 && freq < 30000000l){
|
||||
freq += 50000l;
|
||||
}
|
||||
else if (encoder < 0 && freq > 600000l){
|
||||
freq -= 50000l;
|
||||
}
|
||||
setFrequency(freq);
|
||||
displayVFO(globalSettings.activeVfo);
|
||||
}
|
||||
}// end of the event loop
|
||||
}
|
||||
@ -410,7 +383,6 @@ void fastTune(){
|
||||
void enterFreq(){
|
||||
//force the display to refresh everything
|
||||
//display all the buttons
|
||||
int f;
|
||||
|
||||
for (int i = 0; i < KEYS_TOTAL; i++){
|
||||
Button button;
|
||||
@ -420,7 +392,6 @@ void enterFreq(){
|
||||
|
||||
int cursor_pos = 0;
|
||||
memset(c, 0, sizeof(c));
|
||||
f = frequency / 1000l;
|
||||
|
||||
while(1){
|
||||
|
||||
@ -444,14 +415,16 @@ void enterFreq(){
|
||||
switch(button.id){
|
||||
case KEYS_OK:
|
||||
{
|
||||
long f = atol(c);
|
||||
if(30000 >= f && f > 100){
|
||||
frequency = f * 1000l;
|
||||
setFrequency(frequency);
|
||||
if (vfoActive == VFO_A)
|
||||
vfoA = frequency;
|
||||
else
|
||||
vfoB = frequency;
|
||||
long freq = atol(c);
|
||||
if((LOWEST_FREQ/1000 <= freq) && (freq <= HIGHEST_FREQ/1000)){
|
||||
freq *= 1000L;
|
||||
setFrequency(freq);
|
||||
if (VFO_A == globalSettings.activeVfo){
|
||||
globalSettings.vfoA.frequency = freq;
|
||||
}
|
||||
else{
|
||||
globalSettings.vfoB.frequency = freq;
|
||||
}
|
||||
saveVFOs();
|
||||
}
|
||||
guiUpdate();
|
||||
@ -499,32 +472,35 @@ void enterFreq(){
|
||||
}//if button hit test
|
||||
}// end of the button scanning loop
|
||||
strcpy(b, c);
|
||||
strcat(b, " KHz");
|
||||
strcat_P(b,(const char*)F(" KHz"));
|
||||
displayText(b, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
delay(300);
|
||||
active_delay(300);
|
||||
while(readTouch())
|
||||
checkCAT();
|
||||
} // end of event loop : while(1)
|
||||
}
|
||||
|
||||
void drawCWStatus(){
|
||||
strcpy(b, " cw: ");
|
||||
int wpm = 1200/cwSpeed;
|
||||
strcpy_P(b,(const char*)F(" cw: "));
|
||||
int wpm = 1200/globalSettings.cwDitDurationMs;
|
||||
itoa(wpm,c, 10);
|
||||
strcat(b, c);
|
||||
strcat(b, "wpm, ");
|
||||
itoa(sideTone, c, 10);
|
||||
strcat_P(b,(const char*)F("wpm, "));
|
||||
itoa(globalSettings.cwSideToneFreq, c, 10);
|
||||
strcat(b, c);
|
||||
strcat(b, "hz");
|
||||
strcat_P(b,(const char*)F("hz"));
|
||||
displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
|
||||
|
||||
void drawTx(){
|
||||
if (inTx)
|
||||
displayText("TX", LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND);
|
||||
else
|
||||
if (globalSettings.txActive){
|
||||
strcpy_P(b,(const char*)F("TX"));
|
||||
displayText(b, LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND);
|
||||
}
|
||||
else{
|
||||
displayFillrect(LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_BACKGROUND);
|
||||
}
|
||||
}
|
||||
void drawStatusbar(){
|
||||
drawCWStatus();
|
||||
@ -562,7 +538,7 @@ void guiUpdate(){
|
||||
|
||||
// this builds up the top line of the display with frequency and mode
|
||||
void updateDisplay() {
|
||||
displayVFO(vfoActive);
|
||||
displayVFO(globalSettings.activeVfo);
|
||||
}
|
||||
|
||||
|
||||
@ -708,21 +684,19 @@ int enc_read(void) {
|
||||
|
||||
|
||||
void ritToggle(struct Button *button){
|
||||
if (ritOn == 0){
|
||||
ritEnable(frequency);
|
||||
if(!globalSettings.ritOn){
|
||||
ritEnable(GetActiveVfoFreq());
|
||||
}
|
||||
else
|
||||
else{
|
||||
ritDisable();
|
||||
}
|
||||
btnDraw(button);
|
||||
displayRIT();
|
||||
}
|
||||
|
||||
void splitToggle(Button *button){
|
||||
|
||||
if (splitOn)
|
||||
splitOn = 0;
|
||||
else
|
||||
splitOn = 1;
|
||||
globalSettings.splitOn = !globalSettings.splitOn;
|
||||
|
||||
btnDraw(button);
|
||||
|
||||
@ -740,17 +714,17 @@ void splitToggle(Button *button){
|
||||
|
||||
void vfoReset(){
|
||||
Button button;
|
||||
if (vfoActive = VFO_A)
|
||||
vfoB = vfoA;
|
||||
if (VFO_A == globalSettings.activeVfo)
|
||||
globalSettings.vfoB.frequency = globalSettings.vfoA.frequency;
|
||||
else
|
||||
vfoA = vfoB;
|
||||
globalSettings.vfoA.frequency = globalSettings.vfoB.frequency;
|
||||
|
||||
if (splitOn){
|
||||
if(globalSettings.splitOn){
|
||||
getButton(BUTTON_SPL, &button);
|
||||
splitToggle(&button);
|
||||
}
|
||||
|
||||
if (ritOn){
|
||||
if(globalSettings.ritOn){
|
||||
getButton(BUTTON_RIT, &button);
|
||||
ritToggle(&button);
|
||||
}
|
||||
@ -762,21 +736,22 @@ void vfoReset(){
|
||||
}
|
||||
|
||||
void cwToggle(struct Button *b){
|
||||
if (cwMode == 0){
|
||||
cwMode = 1;
|
||||
if (TuningMode_e::TUNE_SSB == globalSettings.tuningMode){
|
||||
globalSettings.tuningMode = TuningMode_e::TUNE_CW;
|
||||
}
|
||||
else{
|
||||
globalSettings.tuningMode = TuningMode_e::TUNE_SSB;
|
||||
}
|
||||
else
|
||||
cwMode = 0;
|
||||
|
||||
setFrequency(frequency);
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
btnDraw(b);
|
||||
}
|
||||
|
||||
void sidebandToggle(Button* button){
|
||||
if(BUTTON_LSB == button->id)
|
||||
isUSB = 0;
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||
else
|
||||
isUSB = 1;
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||
|
||||
struct Button button2;
|
||||
getButton(BUTTON_USB, &button2);
|
||||
@ -805,51 +780,57 @@ void redrawVFOs(){
|
||||
}
|
||||
|
||||
|
||||
void switchBand(long bandfreq){
|
||||
long offset;
|
||||
void switchBand(uint32_t bandfreq){
|
||||
|
||||
// Serial.println(frequency);
|
||||
// Serial.println(bandfreq);
|
||||
if (3500000l <= frequency && frequency <= 4000000l)
|
||||
offset = frequency - 3500000l;
|
||||
else if (24800000l <= frequency && frequency <= 25000000l)
|
||||
offset = frequency - 24800000l;
|
||||
//Serial.println(frequency);
|
||||
//Serial.println(bandfreq);
|
||||
uint32_t offset;
|
||||
uint32_t freq = GetActiveVfoFreq();
|
||||
if (3500000L <= freq && freq <= 4000000L)
|
||||
offset = freq - 3500000l;
|
||||
else if (24800000L <= freq && freq <= 25000000L)
|
||||
offset = freq - 24800000L;
|
||||
else
|
||||
offset = frequency % 1000000l;
|
||||
offset = freq % 1000000L;
|
||||
|
||||
// Serial.println(offset);
|
||||
//Serial.println(offset);
|
||||
|
||||
setFrequency(bandfreq + offset);
|
||||
|
||||
if(bandfreq >= THRESHOLD_USB_LSB){
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||
}
|
||||
else{
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||
}
|
||||
|
||||
updateDisplay();
|
||||
saveVFOs();
|
||||
}
|
||||
|
||||
int setCwSpeed(){
|
||||
int knob = 0;
|
||||
int wpm;
|
||||
void setCwSpeed()
|
||||
{
|
||||
int wpm = 1200/globalSettings.cwDitDurationMs;
|
||||
|
||||
wpm = 1200/cwSpeed;
|
||||
wpm = getValueByKnob(1, 100, 1, wpm,F("CW: "),F(" WPM"));
|
||||
|
||||
wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM");
|
||||
|
||||
cwSpeed = 1200/wpm;
|
||||
|
||||
EEPROM.put(CW_SPEED, cwSpeed);
|
||||
active_delay(500);
|
||||
drawStatusbar();
|
||||
// printLine2("");
|
||||
// updateDisplay();
|
||||
globalSettings.cwDitDurationMs = 1200/wpm;
|
||||
SaveSettingsToEeprom();
|
||||
active_delay(500);
|
||||
drawStatusbar();
|
||||
//printLine2("");
|
||||
//updateDisplay();
|
||||
}
|
||||
|
||||
void setCwTone(){
|
||||
int knob = 0;
|
||||
int prev_sideTone;
|
||||
|
||||
tone(CW_TONE, sideTone);
|
||||
itoa(sideTone, c, 10);
|
||||
strcpy(b, "CW Tone: ");
|
||||
tone(CW_TONE, globalSettings.cwSideToneFreq);
|
||||
itoa(globalSettings.cwSideToneFreq, c, 10);
|
||||
strcpy_P(b,(const char*)F("CW Tone: "));
|
||||
strcat(b, c);
|
||||
strcat(b, " Hz");
|
||||
strcat_P(b,(const char*)F(" Hz"));
|
||||
drawCommandbar(b);
|
||||
|
||||
//disable all clock 1 and clock 2
|
||||
@ -857,18 +838,18 @@ void setCwTone(){
|
||||
{
|
||||
knob = enc_read();
|
||||
|
||||
if (knob > 0 && sideTone < 2000)
|
||||
sideTone += 10;
|
||||
else if (knob < 0 && sideTone > 100 )
|
||||
sideTone -= 10;
|
||||
if (knob > 0 && globalSettings.cwSideToneFreq < 2000)
|
||||
globalSettings.cwSideToneFreq += 10;
|
||||
else if (knob < 0 && globalSettings.cwSideToneFreq > 100 )
|
||||
globalSettings.cwSideToneFreq -= 10;
|
||||
else
|
||||
continue; //don't update the frequency or the display
|
||||
|
||||
tone(CW_TONE, sideTone);
|
||||
itoa(sideTone, c, 10);
|
||||
strcpy(b, "CW Tone: ");
|
||||
tone(CW_TONE, globalSettings.cwSideToneFreq);
|
||||
itoa(globalSettings.cwSideToneFreq, c, 10);
|
||||
strcpy_P(b,(const char*)F("CW Tone: "));
|
||||
strcat(b, c);
|
||||
strcat(b, " Hz");
|
||||
strcat_P(b,(const char*)F(" Hz"));
|
||||
drawCommandbar(b);
|
||||
//printLine2(b);
|
||||
|
||||
@ -876,14 +857,14 @@ void setCwTone(){
|
||||
active_delay(20);
|
||||
}
|
||||
noTone(CW_TONE);
|
||||
//save the setting
|
||||
EEPROM.put(CW_SIDETONE, sideTone);
|
||||
|
||||
SaveSettingsToEeprom();
|
||||
|
||||
b[0] = 0;
|
||||
drawCommandbar(b);
|
||||
drawStatusbar();
|
||||
// printLine2("");
|
||||
// updateDisplay();
|
||||
//printLine2("");
|
||||
//updateDisplay();
|
||||
}
|
||||
|
||||
void doCommand(Button* button){
|
||||
@ -918,7 +899,7 @@ void doCommand(Button* button){
|
||||
}
|
||||
case BUTTON_VFOA:
|
||||
{
|
||||
if(VFO_A == vfoActive){
|
||||
if(VFO_A == globalSettings.activeVfo){
|
||||
fastTune();
|
||||
}
|
||||
else{
|
||||
@ -928,7 +909,7 @@ void doCommand(Button* button){
|
||||
}
|
||||
case BUTTON_VFOB:
|
||||
{
|
||||
if(VFO_B == vfoActive){
|
||||
if(VFO_B == globalSettings.activeVfo){
|
||||
fastTune();
|
||||
}
|
||||
else{
|
||||
@ -1057,7 +1038,7 @@ void doCommands(){
|
||||
|
||||
//unfocus the buttons
|
||||
drawFocus(select, COLOR_INACTIVE_BORDER);
|
||||
if (vfoActive == VFO_A)
|
||||
if (VFO_A == globalSettings.activeVfo)
|
||||
drawFocus(BUTTON_VFOA, COLOR_ACTIVE_BORDER);
|
||||
else
|
||||
drawFocus(BUTTON_VFOB, COLOR_ACTIVE_BORDER);
|
||||
|
@ -30,21 +30,10 @@
|
||||
* Si5351 object to control the clocks.
|
||||
*/
|
||||
#include <Wire.h>
|
||||
#include <EEPROM.h>
|
||||
#include "settings.h"
|
||||
#include "ubitx.h"
|
||||
#include "nano_gui.h"
|
||||
|
||||
/**
|
||||
The main chip which generates upto three oscillators of various frequencies in the
|
||||
Raduino is the Si5351a. To learn more about Si5351a you can download the datasheet
|
||||
from www.silabs.com although, strictly speaking it is not a requirment to understand this code.
|
||||
|
||||
We no longer use the standard SI5351 library because of its huge overhead due to many unused
|
||||
features consuming a lot of program space. Instead of depending on an external library we now use
|
||||
Jerry Gaffke's, KE7ER, lightweight standalone mimimalist "si5351bx" routines (see further down the
|
||||
code). Here are some defines and declarations used by Jerry's routines:
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory.
|
||||
* We have to be very careful with variables that are declared inside the functions as they are
|
||||
@ -58,102 +47,10 @@
|
||||
*/
|
||||
char c[30], b[30];
|
||||
|
||||
/**
|
||||
* These are the indices where these user changable settinngs are stored in the EEPROM
|
||||
*/
|
||||
#define MASTER_CAL 0
|
||||
#define LSB_CAL 4
|
||||
#define USB_CAL 8
|
||||
#define SIDE_TONE 12
|
||||
//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values
|
||||
#define VFO_A 16
|
||||
#define VFO_B 20
|
||||
#define CW_SIDETONE 24
|
||||
#define CW_SPEED 28
|
||||
// the screen calibration parameters : int slope_x=104, slope_y=137, offset_x=28, offset_y=29;
|
||||
#define SLOPE_X 32
|
||||
#define SLOPE_Y 36
|
||||
#define OFFSET_X 40
|
||||
#define OFFSET_Y 44
|
||||
#define CW_DELAYTIME 48
|
||||
|
||||
//These are defines for the new features back-ported from KD8CEC's software
|
||||
//these start from beyond 256 as Ian, KD8CEC has kept the first 256 bytes free for the base version
|
||||
#define VFO_A_MODE 256 // 2: LSB, 3: USB
|
||||
#define VFO_B_MODE 257
|
||||
|
||||
//values that are stroed for the VFO modes
|
||||
#define VFO_MODE_LSB 2
|
||||
#define VFO_MODE_USB 3
|
||||
|
||||
// handkey, iambic a, iambic b : 0,1,2f
|
||||
#define CW_KEY_TYPE 358
|
||||
|
||||
/**
|
||||
* The uBITX is an upconnversion transceiver. The first IF is at 45 MHz.
|
||||
* The first IF frequency is not exactly at 45 Mhz but about 5 khz lower,
|
||||
* this shift is due to the loading on the 45 Mhz crystal filter by the matching
|
||||
* L-network used on it's either sides.
|
||||
* The first oscillator works between 48 Mhz and 75 MHz. The signal is subtracted
|
||||
* from the first oscillator to arriive at 45 Mhz IF. Thus, it is inverted : LSB becomes USB
|
||||
* and USB becomes LSB.
|
||||
* The second IF of 12 Mhz has a ladder crystal filter. If a second oscillator is used at
|
||||
* 57 Mhz, the signal is subtracted FROM the oscillator, inverting a second time, and arrives
|
||||
* at the 12 Mhz ladder filter thus doouble inversion, keeps the sidebands as they originally were.
|
||||
* If the second oscillator is at 33 Mhz, the oscilaltor is subtracated from the signal,
|
||||
* thus keeping the signal's sidebands inverted. The USB will become LSB.
|
||||
* We use this technique to switch sidebands. This is to avoid placing the lsbCarrier close to
|
||||
* 12 MHz where its fifth harmonic beats with the arduino's 16 Mhz oscillator's fourth harmonic
|
||||
*/
|
||||
|
||||
#define INIT_USB_FREQ (11059200l)
|
||||
// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz
|
||||
#define LOWEST_FREQ (100000l)
|
||||
#define HIGHEST_FREQ (30000000l)
|
||||
|
||||
//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes
|
||||
//these are the parameter passed to startTx
|
||||
#define TX_SSB 0
|
||||
#define TX_CW 1
|
||||
|
||||
char ritOn = 0;
|
||||
char vfoActive = VFO_A;
|
||||
int8_t meter_reading = 0; // a -1 on meter makes it invisible
|
||||
unsigned long vfoA=7150000L, vfoB=14200000L, sideTone=800, usbCarrier;
|
||||
char isUsbVfoA=0, isUsbVfoB=1;
|
||||
unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial
|
||||
unsigned long firstIF = 45005000L;
|
||||
|
||||
// if cwMode is flipped on, the rx frequency is tuned down by sidetone hz instead of being zerobeat
|
||||
int cwMode = 0;
|
||||
|
||||
|
||||
//these are variables that control the keyer behaviour
|
||||
int cwSpeed = 100; //this is actuall the dot period in milliseconds
|
||||
extern int32_t calibration;
|
||||
int cwDelayTime = 60;
|
||||
bool Iambic_Key = true;
|
||||
#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B
|
||||
unsigned char keyerControl = IAMBICB;
|
||||
//during CAT commands, we will freeeze the display until CAT is disengaged
|
||||
unsigned char doingCAT = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Raduino needs to keep track of current state of the transceiver. These are a few variables that do it
|
||||
*/
|
||||
boolean txCAT = false; //turned on if the transmitting due to a CAT command
|
||||
char inTx = 0; //it is set to 1 if in transmit mode (whatever the reason : cw, ptt or cat)
|
||||
int splitOn = 0; //working split, uses VFO B as the transmit frequency
|
||||
char keyDown = 0; //in cw mode, denotes the carrier is being transmitted
|
||||
char isUSB = 0; //upper sideband was selected, this is reset to the default for the
|
||||
//frequency when it crosses the frequency border of 10 MHz
|
||||
byte menuOn = 0; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited
|
||||
unsigned long cwTimeout = 0; //milliseconds to go before the cw transmit line is released and the radio goes back to rx mode
|
||||
unsigned long dbgCount = 0; //not used now
|
||||
unsigned char txFilter = 0; //which of the four transmit filters are in use
|
||||
boolean modeCalibrate = false;//this mode of menus shows extended menus to calibrate the oscillators and choose the proper
|
||||
//beat frequency
|
||||
|
||||
|
||||
/**
|
||||
* Below are the basic functions that control the uBitx. Understanding the functions before
|
||||
@ -173,27 +70,9 @@ void active_delay(int delay_by){
|
||||
}
|
||||
}
|
||||
|
||||
void saveVFOs(){
|
||||
|
||||
if (vfoActive == VFO_A)
|
||||
EEPROM.put(VFO_A, frequency);
|
||||
else
|
||||
EEPROM.put(VFO_A, vfoA);
|
||||
|
||||
if (isUsbVfoA)
|
||||
EEPROM.put(VFO_A_MODE, VFO_MODE_USB);
|
||||
else
|
||||
EEPROM.put(VFO_A_MODE, VFO_MODE_LSB);
|
||||
|
||||
if (vfoActive == VFO_B)
|
||||
EEPROM.put(VFO_B, frequency);
|
||||
else
|
||||
EEPROM.put(VFO_B, vfoB);
|
||||
|
||||
if (isUsbVfoB)
|
||||
EEPROM.put(VFO_B_MODE, VFO_MODE_USB);
|
||||
else
|
||||
EEPROM.put(VFO_B_MODE, VFO_MODE_LSB);
|
||||
void saveVFOs()
|
||||
{
|
||||
SaveSettingsToEeprom();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -275,38 +154,31 @@ void setTXFilters_v5(unsigned long freq){
|
||||
* through mixing of the second local oscillator.
|
||||
*/
|
||||
|
||||
void setFrequency(unsigned long f){
|
||||
uint64_t osc_f, firstOscillator, secondOscillator;
|
||||
void setFrequency(unsigned long freq){
|
||||
static const unsigned long firstIF = 45005000L;
|
||||
|
||||
setTXFilters(f);
|
||||
setTXFilters(freq);
|
||||
|
||||
/*
|
||||
if (isUSB){
|
||||
si5351bx_setfreq(2, firstIF + f);
|
||||
si5351bx_setfreq(1, firstIF + usbCarrier);
|
||||
uint32_t local_osc_freq;
|
||||
if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){
|
||||
local_osc_freq = firstIF + freq + globalSettings.cwSideToneFreq;
|
||||
}
|
||||
else{
|
||||
si5351bx_setfreq(2, firstIF + f);
|
||||
si5351bx_setfreq(1, firstIF - usbCarrier);
|
||||
}
|
||||
*/
|
||||
//alternative to reduce the intermod spur
|
||||
if (isUSB){
|
||||
if (cwMode)
|
||||
si5351bx_setfreq(2, firstIF + f + sideTone);
|
||||
else
|
||||
si5351bx_setfreq(2, firstIF + f);
|
||||
si5351bx_setfreq(1, firstIF + usbCarrier);
|
||||
}
|
||||
else{
|
||||
if (cwMode)
|
||||
si5351bx_setfreq(2, firstIF + f + sideTone);
|
||||
else
|
||||
si5351bx_setfreq(2, firstIF + f);
|
||||
si5351bx_setfreq(1, firstIF - usbCarrier);
|
||||
local_osc_freq = firstIF + freq;
|
||||
}
|
||||
|
||||
frequency = f;
|
||||
uint32_t ssb_osc_freq;
|
||||
if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){
|
||||
ssb_osc_freq = firstIF + globalSettings.usbCarrierFreq;
|
||||
}
|
||||
else{
|
||||
ssb_osc_freq = firstIF - globalSettings.usbCarrierFreq;
|
||||
}
|
||||
|
||||
si5351bx_setfreq(2, local_osc_freq);
|
||||
si5351bx_setfreq(1, ssb_osc_freq);
|
||||
|
||||
SetActiveVfoFreq(freq);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -316,81 +188,72 @@ void setFrequency(unsigned long f){
|
||||
* CW offest is calculated as lower than the operating frequency when in LSB mode, and vice versa in USB mode
|
||||
*/
|
||||
|
||||
void startTx(byte txMode){
|
||||
unsigned long tx_freq = 0;
|
||||
void startTx(TuningMode_e tx_mode){
|
||||
globalSettings.tuningMode = tx_mode;
|
||||
|
||||
digitalWrite(TX_RX, 1);
|
||||
inTx = 1;
|
||||
|
||||
if (ritOn){
|
||||
if (globalSettings.ritOn){
|
||||
//save the current as the rx frequency
|
||||
ritRxFrequency = frequency;
|
||||
setFrequency(ritTxFrequency);
|
||||
uint32_t rit_tx_freq = globalSettings.ritFrequency;
|
||||
globalSettings.ritFrequency = GetActiveVfoFreq();
|
||||
setFrequency(rit_tx_freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (splitOn == 1) {
|
||||
if (vfoActive == VFO_B) {
|
||||
vfoActive = VFO_A;
|
||||
isUSB = isUsbVfoA;
|
||||
frequency = vfoA;
|
||||
else{
|
||||
if(globalSettings.splitOn){
|
||||
if(Vfo_e::VFO_B == globalSettings.activeVfo){
|
||||
globalSettings.activeVfo = Vfo_e::VFO_A;
|
||||
}
|
||||
else if (vfoActive == VFO_A){
|
||||
vfoActive = VFO_B;
|
||||
frequency = vfoB;
|
||||
isUSB = isUsbVfoB;
|
||||
else{
|
||||
globalSettings.activeVfo = Vfo_e::VFO_B;
|
||||
}
|
||||
}
|
||||
setFrequency(frequency);
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
}
|
||||
|
||||
if (txMode == TX_CW){
|
||||
digitalWrite(TX_RX, 0);
|
||||
|
||||
if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){
|
||||
//turn off the second local oscillator and the bfo
|
||||
si5351bx_setfreq(0, 0);
|
||||
si5351bx_setfreq(1, 0);
|
||||
|
||||
//shif the first oscillator to the tx frequency directly
|
||||
//shift the first oscillator to the tx frequency directly
|
||||
//the key up and key down will toggle the carrier unbalancing
|
||||
//the exact cw frequency is the tuned frequency + sidetone
|
||||
if (isUSB)
|
||||
si5351bx_setfreq(2, frequency + sideTone);
|
||||
else
|
||||
si5351bx_setfreq(2, frequency - sideTone);
|
||||
if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){
|
||||
si5351bx_setfreq(2, GetActiveVfoFreq() + globalSettings.cwSideToneFreq);
|
||||
}
|
||||
else{
|
||||
si5351bx_setfreq(2, GetActiveVfoFreq() - globalSettings.cwSideToneFreq);
|
||||
}
|
||||
|
||||
delay(20);
|
||||
digitalWrite(TX_RX, 1);
|
||||
}
|
||||
digitalWrite(TX_RX, 1);//turn on the tx
|
||||
globalSettings.txActive = true;
|
||||
drawTx();
|
||||
//updateDisplay();
|
||||
}
|
||||
|
||||
void stopTx(){
|
||||
inTx = 0;
|
||||
digitalWrite(TX_RX, 0);//turn off the tx
|
||||
globalSettings.txActive = false;
|
||||
|
||||
digitalWrite(TX_RX, 0); //turn off the tx
|
||||
si5351bx_setfreq(0, usbCarrier); //set back the cardrier oscillator anyway, cw tx switches it off
|
||||
//set back the carrier oscillator - cw tx switches it off
|
||||
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||
|
||||
if (ritOn)
|
||||
setFrequency(ritRxFrequency);
|
||||
if(globalSettings.ritOn){
|
||||
uint32_t rit_rx_freq = globalSettings.ritFrequency;
|
||||
globalSettings.ritFrequency = GetActiveVfoFreq();
|
||||
setFrequency(rit_rx_freq);
|
||||
}
|
||||
else{
|
||||
if (splitOn == 1) {
|
||||
//vfo Change
|
||||
if (vfoActive == VFO_B){
|
||||
vfoActive = VFO_A;
|
||||
frequency = vfoA;
|
||||
isUSB = isUsbVfoA;
|
||||
if(globalSettings.splitOn){
|
||||
if(Vfo_e::VFO_B == globalSettings.activeVfo){
|
||||
globalSettings.activeVfo = Vfo_e::VFO_A;
|
||||
}
|
||||
else if (vfoActive == VFO_A){
|
||||
vfoActive = VFO_B;
|
||||
frequency = vfoB;
|
||||
isUSB = isUsbVfoB;
|
||||
else{
|
||||
globalSettings.activeVfo = Vfo_e::VFO_B;
|
||||
}
|
||||
}
|
||||
setFrequency(frequency);
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
}
|
||||
//updateDisplay();
|
||||
drawTx();
|
||||
}
|
||||
|
||||
@ -398,18 +261,18 @@ void stopTx(){
|
||||
* ritEnable is called with a frequency parameter that determines
|
||||
* what the tx frequency will be
|
||||
*/
|
||||
void ritEnable(unsigned long f){
|
||||
ritOn = 1;
|
||||
void ritEnable(unsigned long freq){
|
||||
globalSettings.ritOn = true;
|
||||
//save the non-rit frequency back into the VFO memory
|
||||
//as RIT is a temporary shift, this is not saved to EEPROM
|
||||
ritTxFrequency = f;
|
||||
globalSettings.ritFrequency = freq;
|
||||
}
|
||||
|
||||
// this is called by the RIT menu routine
|
||||
void ritDisable(){
|
||||
if (ritOn){
|
||||
ritOn = 0;
|
||||
setFrequency(ritTxFrequency);
|
||||
if(globalSettings.ritOn){
|
||||
globalSettings.ritOn = false;
|
||||
setFrequency(globalSettings.ritFrequency);
|
||||
updateDisplay();
|
||||
}
|
||||
}
|
||||
@ -426,15 +289,16 @@ void ritDisable(){
|
||||
|
||||
void checkPTT(){
|
||||
//we don't check for ptt when transmitting cw
|
||||
if (cwTimeout > 0)
|
||||
if (globalSettings.cwExpirationTimeMs > 0){
|
||||
return;
|
||||
}
|
||||
|
||||
if (digitalRead(PTT) == 0 && inTx == 0){
|
||||
startTx(TX_SSB);
|
||||
if(digitalRead(PTT) == 0 && !globalSettings.txActive){
|
||||
startTx(TuningMode_e::TUNE_SSB);
|
||||
active_delay(50); //debounce the PTT
|
||||
}
|
||||
|
||||
if (digitalRead(PTT) == 1 && inTx == 1)
|
||||
if (digitalRead(PTT) == 1 && globalSettings.txActive)
|
||||
stopTx();
|
||||
}
|
||||
|
||||
@ -471,41 +335,13 @@ void checkButton(){
|
||||
active_delay(50);//debounce
|
||||
}
|
||||
|
||||
void switchVFO(int vfoSelect){
|
||||
if (vfoSelect == VFO_A){
|
||||
if (vfoActive == VFO_B){
|
||||
vfoB = frequency;
|
||||
isUsbVfoB = isUSB;
|
||||
EEPROM.put(VFO_B, frequency);
|
||||
if (isUsbVfoB)
|
||||
EEPROM.put(VFO_B_MODE, VFO_MODE_USB);
|
||||
else
|
||||
EEPROM.put(VFO_B_MODE, VFO_MODE_LSB);
|
||||
}
|
||||
vfoActive = VFO_A;
|
||||
// printLine2("Selected VFO A ");
|
||||
frequency = vfoA;
|
||||
isUSB = isUsbVfoA;
|
||||
}
|
||||
else {
|
||||
if (vfoActive == VFO_A){
|
||||
vfoA = frequency;
|
||||
isUsbVfoA = isUSB;
|
||||
EEPROM.put(VFO_A, frequency);
|
||||
if (isUsbVfoA)
|
||||
EEPROM.put(VFO_A_MODE, VFO_MODE_USB);
|
||||
else
|
||||
EEPROM.put(VFO_A_MODE, VFO_MODE_LSB);
|
||||
}
|
||||
vfoActive = VFO_B;
|
||||
// printLine2("Selected VFO B ");
|
||||
frequency = vfoB;
|
||||
isUSB = isUsbVfoB;
|
||||
}
|
||||
void switchVFO(Vfo_e new_vfo){
|
||||
ritDisable();//If we are in RIT mode, we need to disable it before setting the active VFO so that the correct VFO gets it's frequency restored
|
||||
|
||||
setFrequency(frequency);
|
||||
redrawVFOs();
|
||||
saveVFOs();
|
||||
globalSettings.activeVfo = new_vfo;
|
||||
setFrequency(GetActiveVfoFreq());
|
||||
redrawVFOs();
|
||||
saveVFOs();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -516,50 +352,48 @@ void switchVFO(int vfoSelect){
|
||||
*/
|
||||
|
||||
void doTuning(){
|
||||
int s;
|
||||
static unsigned long prev_freq;
|
||||
static unsigned long nextFrequencyUpdate = 0;
|
||||
|
||||
unsigned long now = millis();
|
||||
|
||||
if (now >= nextFrequencyUpdate && prev_freq != frequency){
|
||||
if (now >= nextFrequencyUpdate && prev_freq != GetActiveVfoFreq()){
|
||||
updateDisplay();
|
||||
nextFrequencyUpdate = now + 100;
|
||||
prev_freq = frequency;
|
||||
prev_freq = GetActiveVfoFreq();
|
||||
}
|
||||
|
||||
s = enc_read();
|
||||
int s = enc_read();
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
//Serial.println(s);
|
||||
|
||||
doingCAT = 0; // go back to manual mode if you were doing CAT
|
||||
prev_freq = frequency;
|
||||
prev_freq = GetActiveVfoFreq();
|
||||
uint32_t new_freq = prev_freq;
|
||||
|
||||
// TODO With the new more responsive tuning, 5 and 10 are nearly useless
|
||||
// thresholds for acceleration. I rarely see above 2 or 3 even when turning
|
||||
// the knob quickly.
|
||||
if (s < 5 && s > -5) {
|
||||
frequency += 50l * s;
|
||||
//Serial.println(" 5");
|
||||
if (s > 10 || s < -10){
|
||||
new_freq += 200L * s;
|
||||
}
|
||||
else if (s < 10 && s > -10) {
|
||||
frequency += 100l * s;
|
||||
//Serial.println(" 10");
|
||||
else if (s > 5 || s < -5){
|
||||
new_freq += 100L * s;
|
||||
}
|
||||
else { // if (s >= 10 || s <= -10)
|
||||
frequency += 200l * s;
|
||||
//Serial.println(" <");
|
||||
else{
|
||||
new_freq += 50L * s;
|
||||
}
|
||||
|
||||
if (prev_freq < 10000000l && frequency > 10000000l)
|
||||
isUSB = true;
|
||||
//Transition from below to above the traditional threshold for USB
|
||||
if(prev_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||
}
|
||||
|
||||
if (prev_freq > 10000000l && frequency < 10000000l)
|
||||
isUSB = false;
|
||||
//Transition from aboveo to below the traditional threshold for USB
|
||||
if(prev_freq >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||
}
|
||||
|
||||
setFrequency(frequency);
|
||||
setFrequency(new_freq);
|
||||
}
|
||||
|
||||
|
||||
@ -567,18 +401,17 @@ void doTuning(){
|
||||
* RIT only steps back and forth by 100 hz at a time
|
||||
*/
|
||||
void doRIT(){
|
||||
unsigned long newFreq;
|
||||
|
||||
int knob = enc_read();
|
||||
unsigned long old_freq = frequency;
|
||||
uint32_t old_freq = GetActiveVfoFreq();
|
||||
uint32_t new_freq = old_freq;
|
||||
|
||||
if (knob < 0)
|
||||
frequency -= 100l;
|
||||
new_freq -= 100l;
|
||||
else if (knob > 0)
|
||||
frequency += 100;
|
||||
new_freq += 100;
|
||||
|
||||
if (old_freq != frequency){
|
||||
setFrequency(frequency);
|
||||
if (old_freq != new_freq){
|
||||
setFrequency(new_freq);
|
||||
updateDisplay();
|
||||
}
|
||||
}
|
||||
@ -589,87 +422,8 @@ void doRIT(){
|
||||
* variables.
|
||||
*/
|
||||
void initSettings(){
|
||||
byte x;
|
||||
//read the settings from the eeprom and restore them
|
||||
//if the readings are off, then set defaults
|
||||
EEPROM.get(MASTER_CAL, calibration);
|
||||
EEPROM.get(USB_CAL, usbCarrier);
|
||||
EEPROM.get(VFO_A, vfoA);
|
||||
EEPROM.get(VFO_B, vfoB);
|
||||
EEPROM.get(CW_SIDETONE, sideTone);
|
||||
EEPROM.get(CW_SPEED, cwSpeed);
|
||||
EEPROM.get(CW_DELAYTIME, cwDelayTime);
|
||||
|
||||
// the screen calibration parameters : int slope_x=104, slope_y=137, offset_x=28, offset_y=29;
|
||||
|
||||
if (usbCarrier > 11060000l || usbCarrier < 11048000l)
|
||||
usbCarrier = 11052000l;
|
||||
if (vfoA > 35000000l || 3500000l > vfoA)
|
||||
vfoA = 7150000l;
|
||||
if (vfoB > 35000000l || 3500000l > vfoB)
|
||||
vfoB = 14150000l;
|
||||
if (sideTone < 100 || 2000 < sideTone)
|
||||
sideTone = 800;
|
||||
if (cwSpeed < 10 || 1000 < cwSpeed)
|
||||
cwSpeed = 100;
|
||||
if (cwDelayTime < 10 || cwDelayTime > 100)
|
||||
cwDelayTime = 50;
|
||||
|
||||
/*
|
||||
* The VFO modes are read in as either 2 (USB) or 3(LSB), 0, the default
|
||||
* is taken as 'uninitialized
|
||||
*/
|
||||
|
||||
EEPROM.get(VFO_A_MODE, x);
|
||||
|
||||
switch(x){
|
||||
case VFO_MODE_USB:
|
||||
isUsbVfoA = 1;
|
||||
break;
|
||||
case VFO_MODE_LSB:
|
||||
isUsbVfoA = 0;
|
||||
break;
|
||||
default:
|
||||
if (vfoA > 10000000l)
|
||||
isUsbVfoA = 1;
|
||||
else
|
||||
isUsbVfoA = 0;
|
||||
}
|
||||
|
||||
EEPROM.get(VFO_B_MODE, x);
|
||||
switch(x){
|
||||
case VFO_MODE_USB:
|
||||
isUsbVfoB = 1;
|
||||
break;
|
||||
case VFO_MODE_LSB:
|
||||
isUsbVfoB = 0;
|
||||
break;
|
||||
default:
|
||||
if (vfoA > 10000000l)
|
||||
isUsbVfoB = 1;
|
||||
else
|
||||
isUsbVfoB = 0;
|
||||
}
|
||||
|
||||
//set the current mode
|
||||
isUSB = isUsbVfoA;
|
||||
|
||||
/*
|
||||
* The keyer type splits into two variables
|
||||
*/
|
||||
EEPROM.get(CW_KEY_TYPE, x);
|
||||
|
||||
if (x == 0)
|
||||
Iambic_Key = false;
|
||||
else if (x == 1){
|
||||
Iambic_Key = true;
|
||||
keyerControl &= ~IAMBICB;
|
||||
}
|
||||
else if (x == 2){
|
||||
Iambic_Key = true;
|
||||
keyerControl |= IAMBICB;
|
||||
}
|
||||
|
||||
LoadDefaultSettings();
|
||||
LoadSettingsFromEeprom();
|
||||
}
|
||||
|
||||
void initPorts(){
|
||||
@ -711,24 +465,24 @@ void setup()
|
||||
Serial.begin(38400);
|
||||
Serial.flush();
|
||||
|
||||
displayInit();
|
||||
initSettings();
|
||||
displayInit();
|
||||
initPorts();
|
||||
initOscillators();
|
||||
frequency = vfoA;
|
||||
setFrequency(vfoA);
|
||||
setFrequency(globalSettings.vfoA.frequency);
|
||||
|
||||
if (btnDown()){
|
||||
//Run initial calibration routine if button is pressed during power up
|
||||
if(btnDown()){
|
||||
setupTouch();
|
||||
isUSB = 1;
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||
setFrequency(10000000l);
|
||||
setupFreq();
|
||||
isUSB = 0;
|
||||
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||
setFrequency(7100000l);
|
||||
setupBFO();
|
||||
}
|
||||
guiUpdate();
|
||||
|
||||
guiUpdate();
|
||||
}
|
||||
|
||||
|
||||
@ -736,23 +490,23 @@ void setup()
|
||||
* The loop checks for keydown, ptt, function button and tuning.
|
||||
*/
|
||||
|
||||
byte flasher = 0;
|
||||
boolean wastouched = false;
|
||||
|
||||
void loop(){
|
||||
|
||||
if (cwMode)
|
||||
if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){
|
||||
cwKeyer();
|
||||
else if (!txCAT)
|
||||
}
|
||||
else if(!globalSettings.txCatActive){
|
||||
checkPTT();
|
||||
}
|
||||
|
||||
checkButton();
|
||||
//tune only when not tranmsitting
|
||||
if (!inTx){
|
||||
if (ritOn)
|
||||
if(!globalSettings.txActive){
|
||||
if(globalSettings.ritOn){
|
||||
doRIT();
|
||||
else
|
||||
}
|
||||
else{
|
||||
doTuning();
|
||||
}
|
||||
checkTouch();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user