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
164
keyer.cpp
164
keyer.cpp
@ -1,4 +1,5 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "settings.h"
|
||||||
#include "ubitx.h"
|
#include "ubitx.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,72 +29,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//CW ADC Range
|
//CW ADC Range
|
||||||
int cwAdcSTFrom = 0;
|
static const unsigned int cwAdcSTFrom = 0;
|
||||||
int cwAdcSTTo = 50;
|
static const unsigned int cwAdcSTTo = 50;
|
||||||
int cwAdcBothFrom = 51;
|
static const unsigned int cwAdcBothFrom = cwAdcSTTo + 1;
|
||||||
int cwAdcBothTo = 300;
|
static const unsigned int cwAdcBothTo = 300;
|
||||||
int cwAdcDotFrom = 301;
|
static const unsigned int cwAdcDotFrom = cwAdcBothTo + 1;
|
||||||
int cwAdcDotTo = 600;
|
static const unsigned int cwAdcDotTo = 600;
|
||||||
int cwAdcDashFrom = 601;
|
static const unsigned int cwAdcDashFrom = cwAdcDotTo + 1;
|
||||||
int cwAdcDashTo = 800;
|
static const unsigned int cwAdcDashTo = 800;
|
||||||
//byte cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb
|
|
||||||
|
|
||||||
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
|
* Starts transmitting the carrier with the sidetone
|
||||||
* It assumes that we have called cwTxStart and not called cwTxStop
|
* It assumes that we have called cwTxStart and not called cwTxStop
|
||||||
* each time it is called, the cwTimeOut is pushed further into the future
|
* each time it is called, the cwTimeOut is pushed further into the future
|
||||||
*/
|
*/
|
||||||
void cwKeydown(){
|
void cwKeydown(){
|
||||||
|
tone(CW_TONE, globalSettings.cwSideToneFreq);
|
||||||
|
digitalWrite(CW_KEY, 1);
|
||||||
|
|
||||||
keyDown = 1; //tracks the CW_KEY
|
globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs;
|
||||||
tone(CW_TONE, (int)sideTone);
|
|
||||||
digitalWrite(CW_KEY, 1);
|
|
||||||
|
|
||||||
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
|
||||||
//cwTimeout = millis() + CW_TIMEOUT;
|
|
||||||
cwTimeout = millis() + cwDelayTime * 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,13 +57,10 @@ void cwKeydown(){
|
|||||||
* Pushes the cwTimeout further into the future
|
* Pushes the cwTimeout further into the future
|
||||||
*/
|
*/
|
||||||
void cwKeyUp(){
|
void cwKeyUp(){
|
||||||
keyDown = 0; //tracks the CW_KEY
|
|
||||||
noTone(CW_TONE);
|
noTone(CW_TONE);
|
||||||
digitalWrite(CW_KEY, 0);
|
digitalWrite(CW_KEY, 0);
|
||||||
|
|
||||||
//Modified by KD8CEC, for CW Delay Time save to eeprom
|
globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs;
|
||||||
//cwTimeout = millis() + CW_TIMEOUT;
|
|
||||||
cwTimeout = millis() + cwDelayTime * 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Variables for Ron's new logic
|
//Variables for Ron's new logic
|
||||||
@ -119,16 +72,14 @@ void cwKeyUp(){
|
|||||||
enum KSTYPE {IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT };
|
enum KSTYPE {IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT };
|
||||||
static unsigned long ktimer;
|
static unsigned long ktimer;
|
||||||
unsigned char keyerState = IDLE;
|
unsigned char keyerState = IDLE;
|
||||||
|
uint8_t keyerControl = 0;
|
||||||
|
|
||||||
//Below is a test to reduce the keying error. do not delete lines
|
//Below is a test to reduce the keying error. do not delete lines
|
||||||
//create by KD8CEC for compatible with new CW Logic
|
//create by KD8CEC for compatible with new CW Logic
|
||||||
char update_PaddleLatch(byte isUpdateKeyState) {
|
char update_PaddleLatch(bool isUpdateKeyState) {
|
||||||
unsigned char tmpKeyerControl = 0;
|
unsigned char tmpKeyerControl = 0;
|
||||||
|
|
||||||
int paddle = analogRead(ANALOG_KEYER);
|
int paddle = analogRead(ANALOG_KEYER);
|
||||||
//diagnostic, VU2ESE
|
|
||||||
//itoa(paddle, b, 10);
|
|
||||||
//printLine2(b);
|
|
||||||
|
|
||||||
//use the PTT as the key for tune up, quick QSOs
|
//use the PTT as the key for tune up, quick QSOs
|
||||||
if (digitalRead(PTT) == 0)
|
if (digitalRead(PTT) == 0)
|
||||||
@ -138,18 +89,17 @@ char update_PaddleLatch(byte isUpdateKeyState) {
|
|||||||
else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo)
|
else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo)
|
||||||
tmpKeyerControl |= DIT_L;
|
tmpKeyerControl |= DIT_L;
|
||||||
else if (paddle >= cwAdcBothFrom && paddle <= cwAdcBothTo)
|
else if (paddle >= cwAdcBothFrom && paddle <= cwAdcBothTo)
|
||||||
tmpKeyerControl |= (DAH_L | DIT_L) ;
|
tmpKeyerControl |= (DAH_L | DIT_L) ;
|
||||||
else
|
else{
|
||||||
{
|
if (KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode)
|
||||||
if (Iambic_Key)
|
|
||||||
tmpKeyerControl = 0 ;
|
tmpKeyerControl = 0 ;
|
||||||
else if (paddle >= cwAdcSTFrom && paddle <= cwAdcSTTo)
|
else if (paddle >= cwAdcSTFrom && paddle <= cwAdcSTTo)
|
||||||
tmpKeyerControl = DIT_L ;
|
tmpKeyerControl = DIT_L ;
|
||||||
else
|
else
|
||||||
tmpKeyerControl = 0 ;
|
tmpKeyerControl = 0 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUpdateKeyState == 1)
|
if (isUpdateKeyState)
|
||||||
keyerControl |= tmpKeyerControl;
|
keyerControl |= tmpKeyerControl;
|
||||||
|
|
||||||
return tmpKeyerControl;
|
return tmpKeyerControl;
|
||||||
@ -160,22 +110,24 @@ char update_PaddleLatch(byte isUpdateKeyState) {
|
|||||||
// modified by KD8CEC
|
// modified by KD8CEC
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void cwKeyer(void){
|
void cwKeyer(void){
|
||||||
lastPaddle = 0;
|
|
||||||
bool continue_loop = true;
|
bool continue_loop = true;
|
||||||
unsigned tmpKeyControl = 0;
|
unsigned tmpKeyControl = 0;
|
||||||
|
|
||||||
if( Iambic_Key ) {
|
if(KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode){
|
||||||
while(continue_loop) {
|
while(continue_loop){
|
||||||
switch (keyerState) {
|
switch(keyerState){
|
||||||
case IDLE:
|
case IDLE:
|
||||||
tmpKeyControl = update_PaddleLatch(0);
|
tmpKeyControl = update_PaddleLatch(0);
|
||||||
if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L ||
|
if((tmpKeyControl == DAH_L)//Currently dah
|
||||||
tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) {
|
||(tmpKeyControl == DIT_L)//Currently dit
|
||||||
update_PaddleLatch(1);
|
||(tmpKeyControl == (DAH_L | DIT_L))//Currently both
|
||||||
|
||( keyerControl & (DAH_L | DIT_L))){//Resolving either
|
||||||
|
update_PaddleLatch(true);
|
||||||
keyerState = CHK_DIT;
|
keyerState = CHK_DIT;
|
||||||
}else{
|
}
|
||||||
if (0 < cwTimeout && cwTimeout < millis()){
|
else{
|
||||||
cwTimeout = 0;
|
if (0 < globalSettings.cwExpirationTimeMs && globalSettings.cwExpirationTimeMs < millis()){
|
||||||
|
globalSettings.cwExpirationTimeMs = 0;
|
||||||
stopTx();
|
stopTx();
|
||||||
}
|
}
|
||||||
continue_loop = false;
|
continue_loop = false;
|
||||||
@ -185,7 +137,7 @@ void cwKeyer(void){
|
|||||||
case CHK_DIT:
|
case CHK_DIT:
|
||||||
if (keyerControl & DIT_L) {
|
if (keyerControl & DIT_L) {
|
||||||
keyerControl |= DIT_PROC;
|
keyerControl |= DIT_PROC;
|
||||||
ktimer = cwSpeed;
|
ktimer = globalSettings.cwDitDurationMs;
|
||||||
keyerState = KEYED_PREP;
|
keyerState = KEYED_PREP;
|
||||||
}else{
|
}else{
|
||||||
keyerState = CHK_DAH;
|
keyerState = CHK_DAH;
|
||||||
@ -194,7 +146,7 @@ void cwKeyer(void){
|
|||||||
|
|
||||||
case CHK_DAH:
|
case CHK_DAH:
|
||||||
if (keyerControl & DAH_L) {
|
if (keyerControl & DAH_L) {
|
||||||
ktimer = cwSpeed*3;
|
ktimer = 3*globalSettings.cwDitDurationMs;
|
||||||
keyerState = KEYED_PREP;
|
keyerState = KEYED_PREP;
|
||||||
}else{
|
}else{
|
||||||
keyerState = IDLE;
|
keyerState = IDLE;
|
||||||
@ -203,13 +155,11 @@ void cwKeyer(void){
|
|||||||
|
|
||||||
case KEYED_PREP:
|
case KEYED_PREP:
|
||||||
//modified KD8CEC
|
//modified KD8CEC
|
||||||
if (!inTx){
|
if (!globalSettings.txActive){
|
||||||
//DelayTime Option
|
//DelayTime Option
|
||||||
active_delay(delayBeforeCWStartTime * 2);
|
active_delay(delayBeforeCWStartTime * 2);
|
||||||
|
globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs;
|
||||||
keyDown = 0;
|
startTx(TuningMode_e::TUNE_CW);
|
||||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
|
||||||
startTx(TX_CW);
|
|
||||||
}
|
}
|
||||||
ktimer += millis(); // set ktimer to interval end time
|
ktimer += millis(); // set ktimer to interval end time
|
||||||
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits
|
||||||
@ -220,10 +170,11 @@ void cwKeyer(void){
|
|||||||
|
|
||||||
case KEYED:
|
case KEYED:
|
||||||
if (millis() > ktimer) { // are we at end of key down ?
|
if (millis() > ktimer) { // are we at end of key down ?
|
||||||
cwKeyUp();
|
cwKeyUp();
|
||||||
ktimer = millis() + cwSpeed; // inter-element time
|
ktimer = millis() + (globalSettings.cwDitDurationMs / 10); // inter-element time
|
||||||
keyerState = INTER_ELEMENT; // next state
|
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
|
update_PaddleLatch(1); // early paddle latch in Iambic B mode
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -246,20 +197,19 @@ void cwKeyer(void){
|
|||||||
checkCAT();
|
checkCAT();
|
||||||
} //end of while
|
} //end of while
|
||||||
}
|
}
|
||||||
else{
|
else{//KEYER_STRAIGHT
|
||||||
while(1){
|
while(1){
|
||||||
char state = update_PaddleLatch(0);
|
char state = update_PaddleLatch(0);
|
||||||
// Serial.println((int)state);
|
// Serial.println((int)state);
|
||||||
if (state == DIT_L) {
|
if (state == DIT_L) {
|
||||||
// if we are here, it is only because the key is pressed
|
// if we are here, it is only because the key is pressed
|
||||||
if (!inTx){
|
if (!globalSettings.txActive){
|
||||||
startTx(TX_CW);
|
startTx(TuningMode_e::TUNE_CW);
|
||||||
|
|
||||||
//DelayTime Option
|
//DelayTime Option
|
||||||
active_delay(delayBeforeCWStartTime * 2);
|
active_delay(delayBeforeCWStartTime * 2);
|
||||||
|
|
||||||
keyDown = 0;
|
globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwDitDurationMs;
|
||||||
cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT;
|
|
||||||
}
|
}
|
||||||
cwKeydown();
|
cwKeydown();
|
||||||
|
|
||||||
@ -269,24 +219,16 @@ void cwKeyer(void){
|
|||||||
cwKeyUp();
|
cwKeyUp();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (0 < cwTimeout && cwTimeout < millis()){
|
if (0 < globalSettings.cwExpirationTimeMs && globalSettings.cwExpirationTimeMs < millis()){
|
||||||
cwTimeout = 0;
|
globalSettings.cwExpirationTimeMs = 0;
|
||||||
keyDown = 0;
|
|
||||||
stopTx();
|
stopTx();
|
||||||
}
|
}
|
||||||
//if (!cwTimeout) //removed by KD8CEC
|
return;//Tx stop control by Main Loop
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkCAT();
|
checkCAT();
|
||||||
} //end of while
|
} //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 <Arduino.h>
|
||||||
#include "ubitx.h"
|
#include "ubitx.h"
|
||||||
|
#include "settings.h"
|
||||||
#include "morse.h"
|
#include "morse.h"
|
||||||
|
|
||||||
|
struct Morse {
|
||||||
|
char letter;
|
||||||
|
unsigned char code;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each byte of the morse table stores one letter.
|
* Each byte of the morse table stores one letter.
|
||||||
* The 0 is a dot, a 1 is a dash
|
* The 0 is a dot, a 1 is a dash
|
||||||
* From the Most significant byte onwards, the letter is padded with 1s.
|
* 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
|
* 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[] = {
|
static const PROGMEM struct Morse morse_table[] = {
|
||||||
{'a', 0xf9}, // 11111001
|
{'a', 0xf9}, // 11111001
|
||||||
{'b', 0xe8}, // 11101000
|
{'b', 0xe8}, // 11101000
|
||||||
@ -51,9 +51,9 @@ static const PROGMEM struct Morse morse_table[] = {
|
|||||||
{'8', 0xdc}, // 11011100
|
{'8', 0xdc}, // 11011100
|
||||||
{'9', 0xde}, // 11011110
|
{'9', 0xde}, // 11011110
|
||||||
{'0', 0xdf}, // 11011111
|
{'0', 0xdf}, // 11011111
|
||||||
{'.', 0xd5}, // 110010101
|
{'.', 0x95}, // 10010101
|
||||||
{',', 0xd3}, // 110110011 //AD7U 20191217
|
{',', 0xb3}, // 10110011
|
||||||
{'?', 0xcc}, // 11001100 //AD7U 20191217 - Added
|
{'?', 0x8c}, // 10001100
|
||||||
};
|
};
|
||||||
|
|
||||||
static void morseLetter(char c){
|
static void morseLetter(char c){
|
||||||
@ -61,8 +61,8 @@ static void morseLetter(char c){
|
|||||||
|
|
||||||
//handle space character as three dashes
|
//handle space character as three dashes
|
||||||
if (c == ' '){
|
if (c == ' '){
|
||||||
active_delay(cwSpeed * 9);
|
active_delay(9 * globalSettings.cwDitDurationMs);
|
||||||
Serial.print(' ');
|
//Serial.print(' ');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,22 +79,23 @@ static void morseLetter(char c){
|
|||||||
//now we are at the first zero, skip and carry on
|
//now we are at the first zero, skip and carry on
|
||||||
mask = mask >> 1;
|
mask = mask >> 1;
|
||||||
while(mask){
|
while(mask){
|
||||||
tone(CW_TONE, sideTone,10000);
|
tone(CW_TONE, globalSettings.cwSideToneFreq,10000);
|
||||||
if (mask & code){
|
if (mask & code){
|
||||||
delay(3 * (int)cwSpeed);
|
delay(3 * globalSettings.cwDitDurationMs);
|
||||||
//Serial.print('-');
|
//Serial.print('-');
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
delay((int)cwSpeed);
|
delay(globalSettings.cwDitDurationMs);
|
||||||
//Serial.print('.');
|
//Serial.print('.');
|
||||||
}
|
}
|
||||||
//Serial.print('#');
|
//Serial.print('#');
|
||||||
noTone(CW_TONE);
|
noTone(CW_TONE);
|
||||||
delay((int)cwSpeed); // space between dots and dashes
|
delay(globalSettings.cwDitDurationMs); // space between dots and dashes
|
||||||
mask = mask >> 1;
|
mask = mask >> 1;
|
||||||
}
|
}
|
||||||
//Serial.println('@');
|
//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);
|
delay(1000);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Serial.println(sideTone);
|
//Serial.println(globalSettings.cwSideToneFreq);
|
||||||
while(*text){
|
while(*text){
|
||||||
morseLetter(*text++);
|
morseLetter(*text++);
|
||||||
}
|
}
|
||||||
|
80
nano_gui.cpp
80
nano_gui.cpp
@ -1,5 +1,5 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <EEPROM.h>
|
#include "settings.h"
|
||||||
#include "ubitx.h"
|
#include "ubitx.h"
|
||||||
#include "nano_gui.h"
|
#include "nano_gui.h"
|
||||||
|
|
||||||
@ -8,30 +8,45 @@
|
|||||||
|
|
||||||
struct Point ts_point;
|
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(){
|
void readTouchCalibration(){
|
||||||
EEPROM.get(SLOPE_X, slope_x);
|
LoadSettingsFromEeprom();
|
||||||
EEPROM.get(SLOPE_Y, slope_y);
|
/* for debugging
|
||||||
EEPROM.get(OFFSET_X, offset_x);
|
Serial.print(globalSettings.touchSlopeX); Serial.print(' ');
|
||||||
EEPROM.get(OFFSET_Y, offset_y);
|
Serial.print(globalSettings.touchSlopeY); Serial.print(' ');
|
||||||
|
Serial.print(globalSettings.touchOffsetX); Serial.print(' ');
|
||||||
/*
|
Serial.println(globalSettings.touchOffsetY); Serial.println(' ');
|
||||||
//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(' ');
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeTouchCalibration(){
|
void writeTouchCalibration(){
|
||||||
EEPROM.put(SLOPE_X, slope_x);
|
SaveSettingsToEeprom();
|
||||||
EEPROM.put(SLOPE_Y, slope_y);
|
|
||||||
EEPROM.put(OFFSET_X, offset_x);
|
|
||||||
EEPROM.put(OFFSET_Y, offset_y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Z_THRESHOLD 400
|
#define Z_THRESHOLD 400
|
||||||
@ -118,7 +133,7 @@ static void touch_update(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean readTouch(){
|
bool readTouch(){
|
||||||
touch_update();
|
touch_update();
|
||||||
if (zraw >= Z_THRESHOLD) {
|
if (zraw >= Z_THRESHOLD) {
|
||||||
ts_point.x = xraw;
|
ts_point.x = xraw;
|
||||||
@ -130,8 +145,8 @@ boolean readTouch(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scaleTouch(struct Point *p){
|
void scaleTouch(struct Point *p){
|
||||||
p->x = ((long)(p->x - offset_x) * 10l)/ (long)slope_x;
|
p->x = ((long)(p->x - globalSettings.touchOffsetX) * 10L)/ (long)globalSettings.touchSlopeX;
|
||||||
p->y = ((long)(p->y - offset_y) * 10l)/ (long)slope_y;
|
p->y = ((long)(p->y - globalSettings.touchOffsetY) * 10L)/ (long)globalSettings.touchSlopeY;
|
||||||
|
|
||||||
//Serial.print(p->x); Serial.print(",");Serial.println(p->y);
|
//Serial.print(p->x); Serial.print(",");Serial.println(p->y);
|
||||||
}
|
}
|
||||||
@ -169,7 +184,6 @@ void displayInit(void){
|
|||||||
tft.setRotation(1);
|
tft.setRotation(1);
|
||||||
|
|
||||||
xpt2046_Init();
|
xpt2046_Init();
|
||||||
readTouchCalibration();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayPixel(unsigned int x, unsigned int y, unsigned int c){
|
void displayPixel(unsigned int x, unsigned int y, unsigned int c){
|
||||||
@ -184,7 +198,7 @@ void displayVline(unsigned int x, unsigned int y, unsigned int l, unsigned int c
|
|||||||
tft.drawFastVLine(x,y,l,c);
|
tft.drawFastVLine(x,y,l,c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayClear(unsigned int color){
|
void displayClear(unsigned int color){
|
||||||
tft.fillRect(0,0,320,240,color);
|
tft.fillRect(0,0,320,240,color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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
|
// 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,
|
//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
|
//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
|
//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
|
//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
|
//x1, y1 is at 20 pixels
|
||||||
offset_x = x1 + -((20 * slope_x)/10);
|
globalSettings.touchOffsetX = x1 + -((20 * globalSettings.touchSlopeX)/10);
|
||||||
offset_y = y1 + -((20 * slope_y)/10);
|
globalSettings.touchOffsetY = y1 + -((20 * globalSettings.touchSlopeY)/10);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Serial.print(x1);Serial.print(':');Serial.println(y1);
|
Serial.print(x1);Serial.print(':');Serial.println(y1);
|
||||||
@ -307,10 +321,10 @@ void setupTouch(){
|
|||||||
Serial.print(x4);Serial.print(':');Serial.println(y4);
|
Serial.print(x4);Serial.print(':');Serial.println(y4);
|
||||||
|
|
||||||
//for debugging
|
//for debugging
|
||||||
Serial.print(slope_x); Serial.print(' ');
|
Serial.print(globalSettings.touchSlopeX); Serial.print(' ');
|
||||||
Serial.print(slope_y); Serial.print(' ');
|
Serial.print(globalSettings.touchSlopeY); Serial.print(' ');
|
||||||
Serial.print(offset_x); Serial.print(' ');
|
Serial.print(globalSettings.touchOffsetX); Serial.print(' ');
|
||||||
Serial.println(offset_y); Serial.println(' ');
|
Serial.println(globalSettings.touchOffsetY); Serial.println(' ');
|
||||||
*/
|
*/
|
||||||
writeTouchCalibration();
|
writeTouchCalibration();
|
||||||
displayClear(DISPLAY_BLACK);
|
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 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 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 */
|
/* touch functions */
|
||||||
boolean readTouch();
|
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);
|
172
setup.cpp
172
setup.cpp
@ -1,6 +1,7 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include "morse.h"
|
#include "morse.h"
|
||||||
|
#include "settings.h"
|
||||||
#include "ubitx.h"
|
#include "ubitx.h"
|
||||||
#include "nano_gui.h"
|
#include "nano_gui.h"
|
||||||
|
|
||||||
@ -22,7 +23,6 @@ void setupExit(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//this is used by the si5351 routines in the ubitx_5351 file
|
//this is used by the si5351 routines in the ubitx_5351 file
|
||||||
extern int32_t calibration;
|
|
||||||
extern uint32_t si5351bx_vcoa;
|
extern uint32_t si5351bx_vcoa;
|
||||||
|
|
||||||
static const unsigned int COLOR_TEXT = DISPLAY_WHITE;
|
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);
|
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){
|
void printCarrierFreq(unsigned long freq)
|
||||||
|
{
|
||||||
memset(c, 0, sizeof(c));
|
formatFreq(freq,c,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);
|
|
||||||
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);
|
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(){
|
void setupFreq(){
|
||||||
int knob = 0;
|
|
||||||
int32_t prev_calibration;
|
|
||||||
|
|
||||||
displayDialog(F("Set Frequency"),F("Push TUNE to Save"));
|
displayDialog(F("Set Frequency"),F("Push TUNE to Save"));
|
||||||
|
|
||||||
//round off the the nearest khz
|
//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"));
|
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);
|
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"));
|
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);
|
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"));
|
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);
|
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"));
|
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);
|
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);
|
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
|
//keep clear of any previous button press
|
||||||
while (btnDown())
|
while (btnDown())
|
||||||
active_delay(100);
|
active_delay(100);
|
||||||
active_delay(100);
|
active_delay(100);
|
||||||
|
|
||||||
prev_calibration = calibration;
|
|
||||||
calibration = 0;
|
|
||||||
|
|
||||||
while (!btnDown())
|
while (!btnDown())
|
||||||
{
|
{
|
||||||
knob = enc_read();
|
int knob = enc_read();
|
||||||
if (knob != 0)
|
if(knob != 0){
|
||||||
calibration += knob * 875;
|
globalSettings.oscillatorCal += knob * 875;
|
||||||
/* else if (knob < 0)
|
}
|
||||||
calibration -= 875; */
|
else{
|
||||||
else
|
|
||||||
continue; //don't update the frequency or the display
|
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);
|
si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator anyway, cw tx switches it off
|
||||||
setFrequency(frequency);
|
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);
|
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();
|
initOscillators();
|
||||||
si5351_set_calibration(calibration);
|
si5351_set_calibration(globalSettings.oscillatorCal);
|
||||||
setFrequency(frequency);
|
setFrequency(GetActiveVfoFreq());
|
||||||
|
|
||||||
//debounce and delay
|
//debounce and delay
|
||||||
while(btnDown())
|
while(btnDown())
|
||||||
@ -148,37 +136,30 @@ void setupFreq(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setupBFO(){
|
void setupBFO(){
|
||||||
int knob = 0;
|
|
||||||
unsigned long prevCarrier;
|
|
||||||
|
|
||||||
prevCarrier = usbCarrier;
|
|
||||||
|
|
||||||
displayDialog(F("Set BFO"),F("Press TUNE to Save"));
|
displayDialog(F("Set BFO"),F("Press TUNE to Save"));
|
||||||
|
|
||||||
usbCarrier = 11053000l;
|
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||||
si5351bx_setfreq(0, usbCarrier);
|
printCarrierFreq(globalSettings.usbCarrierFreq);
|
||||||
printCarrierFreq(usbCarrier);
|
|
||||||
|
|
||||||
while (!btnDown()){
|
while (!btnDown()){
|
||||||
knob = enc_read();
|
int knob = enc_read();
|
||||||
|
if(knob != 0){
|
||||||
if (knob != 0)
|
globalSettings.usbCarrierFreq -= 50 * knob;
|
||||||
usbCarrier -= 50 * knob;
|
}
|
||||||
else
|
else{
|
||||||
continue; //don't update the frequency or the display
|
continue; //don't update the frequency or the display
|
||||||
|
}
|
||||||
|
|
||||||
si5351bx_setfreq(0, usbCarrier);
|
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||||
setFrequency(frequency);
|
setFrequency(GetActiveVfoFreq());
|
||||||
printCarrierFreq(usbCarrier);
|
printCarrierFreq(globalSettings.usbCarrierFreq);
|
||||||
|
|
||||||
active_delay(100);
|
active_delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
EEPROM.put(USB_CAL, usbCarrier);
|
SaveSettingsToEeprom();
|
||||||
si5351bx_setfreq(0, usbCarrier);
|
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||||
setFrequency(frequency);
|
setFrequency(GetActiveVfoFreq());
|
||||||
updateDisplay();
|
|
||||||
menuOn = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupCwDelay(){
|
void setupCwDelay(){
|
||||||
@ -188,44 +169,41 @@ void setupCwDelay(){
|
|||||||
displayDialog(F("Set CW T/R Delay"),F("Press tune to Save"));
|
displayDialog(F("Set CW T/R Delay"),F("Press tune to Save"));
|
||||||
|
|
||||||
active_delay(500);
|
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"));
|
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);
|
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()){
|
while (!btnDown()){
|
||||||
knob = enc_read();
|
knob = enc_read();
|
||||||
|
|
||||||
if (knob < 0 && cwDelayTime > 10)
|
if (knob < 0 && globalSettings.cwActiveTimeoutMs > 100)
|
||||||
cwDelayTime -= 10;
|
globalSettings.cwActiveTimeoutMs -= 100;
|
||||||
else if (knob > 0 && cwDelayTime < 100)
|
else if (knob > 0 && globalSettings.cwActiveTimeoutMs < 1000)
|
||||||
cwDelayTime += 10;
|
globalSettings.cwActiveTimeoutMs += 100;
|
||||||
else
|
else
|
||||||
continue; //don't update the frequency or the display
|
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"));
|
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);
|
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);
|
active_delay(500);
|
||||||
menuOn = 0;
|
setupExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupKeyer(){
|
void setupKeyer(){
|
||||||
int tmp_key, knob;
|
|
||||||
|
|
||||||
displayDialog(F("Set CW Keyer"),F("Press tune to Save"));
|
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 >"));
|
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);
|
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 >"));
|
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);
|
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);
|
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)
|
int knob = 0;
|
||||||
tmp_key = 0; //hand key
|
uint32_t tmp_mode = globalSettings.keyerMode;
|
||||||
else if (keyerControl & IAMBICB)
|
|
||||||
tmp_key = 2; //Iambic B
|
|
||||||
else
|
|
||||||
tmp_key = 1;
|
|
||||||
|
|
||||||
while (!btnDown())
|
while (!btnDown())
|
||||||
{
|
{
|
||||||
knob = enc_read();
|
knob = enc_read();
|
||||||
if (knob == 0){
|
if(knob == 0){
|
||||||
active_delay(50);
|
active_delay(50);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (knob < 0 && tmp_key > 0)
|
if(knob < 0 && tmp_mode > KeyerMode_e::KEYER_STRAIGHT){
|
||||||
tmp_key--;
|
tmp_mode--;
|
||||||
if (knob > 0)
|
}
|
||||||
tmp_key++;
|
if(knob > 0 && tmp_mode < KeyerMode_e::KEYER_IAMBIC_B){
|
||||||
if (tmp_key > 2)
|
tmp_mode++;
|
||||||
tmp_key = 0;
|
}
|
||||||
|
|
||||||
if (tmp_key == 0){
|
if (KeyerMode_e::KEYER_STRAIGHT == tmp_mode){
|
||||||
strcpy_P(c,(const char*)F("< Hand Key >"));
|
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);
|
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 >"));
|
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);
|
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 >"));
|
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);
|
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);
|
active_delay(500);
|
||||||
if (tmp_key == 0)
|
|
||||||
Iambic_Key = false;
|
globalSettings.keyerMode = tmp_mode;
|
||||||
else if (tmp_key == 1){
|
SaveSettingsToEeprom();
|
||||||
Iambic_Key = true;
|
|
||||||
keyerControl &= ~IAMBICB;
|
|
||||||
}
|
|
||||||
else if (tmp_key == 2){
|
|
||||||
Iambic_Key = true;
|
|
||||||
keyerControl |= IAMBICB;
|
|
||||||
}
|
|
||||||
|
|
||||||
EEPROM.put(CW_KEY_TYPE, tmp_key);
|
setupExit();
|
||||||
|
|
||||||
menuOn = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char MI_SET_FREQ [] PROGMEM = "Set Freq...";
|
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
|
/* 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.
|
* 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 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.
|
* 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 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,
|
* 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
|
// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz
|
||||||
#define LOWEST_FREQ (100000l)
|
#define LOWEST_FREQ (100000l)
|
||||||
#define HIGHEST_FREQ (30000000l)
|
#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;
|
extern unsigned long firstIF;
|
||||||
|
|
||||||
// if cwMode is flipped on, the rx frequency is tuned down by sidetone hz instead of being zerobeat
|
extern uint8_t menuOn;
|
||||||
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
|
|
||||||
|
|
||||||
/* these are functions implemented in the main file named as ubitx_xxx.ino */
|
/* these are functions implemented in the main file named as ubitx_xxx.ino */
|
||||||
void active_delay(int delay_by);
|
void active_delay(int delay_by);
|
||||||
void saveVFOs();
|
void saveVFOs();
|
||||||
void setFrequency(unsigned long f);
|
void setFrequency(unsigned long f);
|
||||||
void startTx(byte txMode);
|
void startTx(TuningMode_e tx_mode);
|
||||||
void stopTx();
|
void stopTx();
|
||||||
void ritEnable(unsigned long f);
|
void ritEnable(unsigned long f);
|
||||||
void ritDisable();
|
void ritDisable();
|
||||||
void checkCAT();
|
void checkCAT();
|
||||||
void cwKeyer(void);
|
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
|
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.
|
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 */
|
/* these are functiosn implemented in ubitx_si5351.cpp */
|
||||||
void si5351bx_setfreq(uint8_t clknum, uint32_t fout);
|
void si5351bx_setfreq(uint8_t clknum, uint32_t fout);
|
||||||
void initOscillators();
|
void initOscillators();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "settings.h"
|
||||||
#include "ubitx.h"
|
#include "ubitx.h"
|
||||||
#include "nano_gui.h"
|
#include "nano_gui.h"
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ void catReadEEPRom(void)
|
|||||||
//5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE
|
//5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE
|
||||||
//6 :
|
//6 :
|
||||||
//7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0)
|
//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;
|
cat[1] = 0x00;
|
||||||
break;
|
break;
|
||||||
case 0x57 : //
|
case 0x57 : //
|
||||||
@ -187,11 +188,11 @@ void catReadEEPRom(void)
|
|||||||
//5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel
|
//5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel
|
||||||
//7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW
|
//7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW
|
||||||
//CAT_BUFF[0] = 0x08;
|
//CAT_BUFF[0] = 0x08;
|
||||||
cat[0] = (sideTone - 300)/50;
|
cat[0] = (globalSettings.cwSideToneFreq - 300)/50;
|
||||||
cat[1] = 0x25;
|
cat[1] = 0x25;
|
||||||
break;
|
break;
|
||||||
case 0x61 : //Sidetone (Volume) (#44)
|
case 0x61 : //globalSettings.cwSideToneFreq (Volume) (#44)
|
||||||
cat[0] = sideTone % 50;
|
cat[0] = globalSettings.cwSideToneFreq % 50;
|
||||||
cat[1] = 0x08;
|
cat[1] = 0x08;
|
||||||
break;
|
break;
|
||||||
case 0x5F : //
|
case 0x5F : //
|
||||||
@ -203,14 +204,14 @@ void catReadEEPRom(void)
|
|||||||
cat[1] = 0x08;
|
cat[1] = 0x08;
|
||||||
break;
|
break;
|
||||||
case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms
|
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;
|
cat[1] = 0x32;
|
||||||
break;
|
break;
|
||||||
case 0x62 : //
|
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)
|
//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
|
//7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours
|
||||||
//CAT_BUFF[0] = 0x08;
|
//CAT_BUFF[0] = 0x08;
|
||||||
cat[0] = 1200 / cwSpeed - 4;
|
cat[0] = 1200 / globalSettings.cwDitDurationMs - 4;
|
||||||
cat[1] = 0xB2;
|
cat[1] = 0xB2;
|
||||||
break;
|
break;
|
||||||
case 0x63 : //
|
case 0x63 : //
|
||||||
@ -226,7 +227,7 @@ void catReadEEPRom(void)
|
|||||||
cat[1] = 0xB2;
|
cat[1] = 0xB2;
|
||||||
break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed
|
break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed
|
||||||
case 0x78 :
|
case 0x78 :
|
||||||
if (isUSB)
|
if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode())
|
||||||
cat[0] = CAT_MODE_USB;
|
cat[0] = CAT_MODE_USB;
|
||||||
else
|
else
|
||||||
cat[0] = CAT_MODE_LSB;
|
cat[0] = CAT_MODE_LSB;
|
||||||
@ -252,7 +253,7 @@ void catReadEEPRom(void)
|
|||||||
//7A 6 ? ?
|
//7A 6 ? ?
|
||||||
//7A 7 SPL On/Off 0 = Off, 1 = On
|
//7A 7 SPL On/Off 0 = Off, 1 = On
|
||||||
|
|
||||||
cat[0] = (splitOn ? 0xFF : 0x7F);
|
cat[0] = (globalSettings.splitOn ? 0xFF : 0x7F);
|
||||||
break;
|
break;
|
||||||
case 0xB3 : //
|
case 0xB3 : //
|
||||||
cat[0] = 0x00;
|
cat[0] = 0x00;
|
||||||
@ -288,16 +289,16 @@ void processCATCommand2(byte* cmd) {
|
|||||||
|
|
||||||
case 0x02:
|
case 0x02:
|
||||||
//split on
|
//split on
|
||||||
splitOn = 1;
|
globalSettings.splitOn = 1;
|
||||||
break;
|
break;
|
||||||
case 0x82:
|
case 0x82:
|
||||||
//split off
|
//split off
|
||||||
splitOn = 0;
|
globalSettings.splitOn = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03:
|
case 0x03:
|
||||||
writeFreq(frequency,response); // Put the frequency into the buffer
|
writeFreq(GetActiveVfoFreq(),response); // Put the frequency into the buffer
|
||||||
if (isUSB)
|
if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode())
|
||||||
response[4] = 0x01; //USB
|
response[4] = 0x01; //USB
|
||||||
else
|
else
|
||||||
response[4] = 0x00; //LSB
|
response[4] = 0x00; //LSB
|
||||||
@ -307,21 +308,21 @@ void processCATCommand2(byte* cmd) {
|
|||||||
|
|
||||||
case 0x07: // set mode
|
case 0x07: // set mode
|
||||||
if (cmd[0] == 0x00 || cmd[0] == 0x03)
|
if (cmd[0] == 0x00 || cmd[0] == 0x03)
|
||||||
isUSB = 0;
|
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||||
else
|
else
|
||||||
isUSB = 1;
|
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||||
response[0] = 0x00;
|
response[0] = 0x00;
|
||||||
Serial.write(response, 1);
|
Serial.write(response, 1);
|
||||||
setFrequency(frequency);
|
setFrequency(GetActiveVfoFreq());
|
||||||
//printLine2("cat: mode changed");
|
//printLine2("cat: mode changed");
|
||||||
//updateDisplay();
|
//updateDisplay();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x08: // PTT On
|
case 0x08: // PTT On
|
||||||
if (!inTx) {
|
if (!globalSettings.txActive) {
|
||||||
response[0] = 0;
|
response[0] = 0;
|
||||||
txCAT = true;
|
globalSettings.txCatActive = true;
|
||||||
startTx(TX_SSB);
|
startTx(TuningMode_e::TUNE_SSB);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
} else {
|
} else {
|
||||||
response[0] = 0xf0;
|
response[0] = 0xf0;
|
||||||
@ -331,9 +332,9 @@ void processCATCommand2(byte* cmd) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x88 : //PTT OFF
|
case 0x88 : //PTT OFF
|
||||||
if (inTx) {
|
if (globalSettings.txActive) {
|
||||||
stopTx();
|
stopTx();
|
||||||
txCAT = false;
|
globalSettings.txCatActive = false;
|
||||||
}
|
}
|
||||||
response[0] = 0;
|
response[0] = 0;
|
||||||
Serial.write(response,1);
|
Serial.write(response,1);
|
||||||
@ -343,7 +344,7 @@ void processCATCommand2(byte* cmd) {
|
|||||||
case 0x81:
|
case 0x81:
|
||||||
//toggle the VFOs
|
//toggle the VFOs
|
||||||
response[0] = 0;
|
response[0] = 0;
|
||||||
if (vfoActive == VFO_A)
|
if (VFO_A == globalSettings.activeVfo)
|
||||||
switchVFO(VFO_B);
|
switchVFO(VFO_B);
|
||||||
else
|
else
|
||||||
switchVFO(VFO_A);
|
switchVFO(VFO_A);
|
||||||
@ -366,14 +367,14 @@ void processCATCommand2(byte* cmd) {
|
|||||||
case 0xf7:
|
case 0xf7:
|
||||||
{
|
{
|
||||||
boolean isHighSWR = false;
|
boolean isHighSWR = false;
|
||||||
boolean isSplitOn = false;
|
boolean issplitOn = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Inverted -> *ptt = ((p->tx_status & 0x80) == 0); <-- souce code in ft817.c (hamlib)
|
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
|
((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
|
(0 << 4) + //dummy data
|
||||||
0x08; //P0 meter data
|
0x08; //P0 meter data
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
#include "settings.h"
|
||||||
#include "ubitx.h"
|
#include "ubitx.h"
|
||||||
|
|
||||||
// ************* SI5315 routines - tks Jerry Gaffke, KE7ER ***********************
|
// ************* 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_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_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
|
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
|
void i2cWrite(uint8_t reg, uint8_t val) { // write reg via i2c
|
||||||
Wire.beginTransmission(SI5351BX_ADDR);
|
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){
|
void si5351_set_calibration(int32_t cal){
|
||||||
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + cal; // apply the calibration correction factor
|
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + cal; // apply the calibration correction factor
|
||||||
si5351bx_setfreq(0, usbCarrier);
|
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initOscillators(){
|
void initOscillators(){
|
||||||
//initialize the SI5351
|
//initialize the SI5351
|
||||||
si5351bx_init();
|
si5351bx_init();
|
||||||
si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor
|
si5351_set_calibration(globalSettings.oscillatorCal);
|
||||||
si5351bx_setfreq(0, usbCarrier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
273
ubitx_ui.cpp
273
ubitx_ui.cpp
@ -1,6 +1,7 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include "morse.h"
|
#include "morse.h"
|
||||||
|
#include "settings.h"
|
||||||
#include "ubitx.h"
|
#include "ubitx.h"
|
||||||
#include "nano_gui.h"
|
#include "nano_gui.h"
|
||||||
|
|
||||||
@ -147,40 +148,13 @@ boolean getButton(btn_set_e index, Button* button){
|
|||||||
return true;
|
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){
|
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);
|
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
|
/** 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 = 0;
|
||||||
int knob_value;
|
int knob_value;
|
||||||
@ -191,10 +165,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char*
|
|||||||
active_delay(200);
|
active_delay(200);
|
||||||
knob_value = initial;
|
knob_value = initial;
|
||||||
|
|
||||||
strcpy(b, prefix);
|
strcpy_P(b,(const char*)prefix);
|
||||||
itoa(knob_value, c, 10);
|
itoa(knob_value, c, 10);
|
||||||
strcat(b, c);
|
strcat(b, c);
|
||||||
strcat(b, postfix);
|
strcat_P(b, (const char*)postfix);
|
||||||
drawCommandbar(b);
|
drawCommandbar(b);
|
||||||
|
|
||||||
while(!btnDown() && digitalRead(PTT) == HIGH){
|
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)
|
if (knob_value < maximum && knob > 0)
|
||||||
knob_value += step_size;
|
knob_value += step_size;
|
||||||
|
|
||||||
strcpy(b, prefix);
|
strcpy_P(b,(const char*)prefix);
|
||||||
itoa(knob_value, c, 10);
|
itoa(knob_value, c, 10);
|
||||||
strcat(b, c);
|
strcat(b, c);
|
||||||
strcat(b, postfix);
|
strcat_P(b,(const char*)postfix);
|
||||||
drawCommandbar(b);
|
drawCommandbar(b);
|
||||||
}
|
}
|
||||||
checkCAT();
|
checkCAT();
|
||||||
@ -218,13 +192,13 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char*
|
|||||||
return knob_value;
|
return knob_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayVFO(int vfo){
|
void displayVFO(Vfo_e vfo){
|
||||||
int x, y;
|
int x, y;
|
||||||
int displayColor, displayBackground, displayBorder;
|
int displayColor, displayBackground, displayBorder;
|
||||||
Button button;
|
Button button;
|
||||||
|
|
||||||
if (splitOn){
|
if (globalSettings.splitOn){
|
||||||
if (vfoActive == vfo){
|
if (vfo == globalSettings.activeVfo){
|
||||||
c[0] = 'R';
|
c[0] = 'R';
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -245,32 +219,30 @@ void displayVFO(int vfo){
|
|||||||
c[1] = ':';
|
c[1] = ':';
|
||||||
|
|
||||||
|
|
||||||
if (vfo == VFO_A){
|
if (VFO_A == vfo){
|
||||||
getButton(BUTTON_VFOA, &button);
|
getButton(BUTTON_VFOA, &button);
|
||||||
|
formatFreq(globalSettings.vfoA.frequency, c+2, sizeof(c)-2);
|
||||||
|
|
||||||
if (vfoActive == VFO_A){
|
if (VFO_A == globalSettings.activeVfo){
|
||||||
formatFreq(frequency, c+2);
|
|
||||||
displayColor = COLOR_ACTIVE_VFO_TEXT;
|
displayColor = COLOR_ACTIVE_VFO_TEXT;
|
||||||
displayBackground = COLOR_ACTIVE_VFO_BACKGROUND;
|
displayBackground = COLOR_ACTIVE_VFO_BACKGROUND;
|
||||||
displayBorder = COLOR_ACTIVE_BORDER;
|
displayBorder = COLOR_ACTIVE_BORDER;
|
||||||
}else{
|
}else{
|
||||||
formatFreq(vfoA, c+2);
|
|
||||||
displayColor = COLOR_INACTIVE_VFO_TEXT;
|
displayColor = COLOR_INACTIVE_VFO_TEXT;
|
||||||
displayBackground = COLOR_INACTIVE_VFO_BACKGROUND;
|
displayBackground = COLOR_INACTIVE_VFO_BACKGROUND;
|
||||||
displayBorder = COLOR_INACTIVE_BORDER;
|
displayBorder = COLOR_INACTIVE_BORDER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vfo == VFO_B){
|
if (VFO_B == vfo){
|
||||||
getButton(BUTTON_VFOB, &button);
|
getButton(BUTTON_VFOB, &button);
|
||||||
|
formatFreq(globalSettings.vfoB.frequency, c+2, sizeof(c)-2);
|
||||||
|
|
||||||
if (vfoActive == VFO_B){
|
if (VFO_B == globalSettings.activeVfo){
|
||||||
formatFreq(frequency, c+2);
|
|
||||||
displayColor = COLOR_ACTIVE_VFO_TEXT;
|
displayColor = COLOR_ACTIVE_VFO_TEXT;
|
||||||
displayBackground = COLOR_ACTIVE_VFO_BACKGROUND;
|
displayBackground = COLOR_ACTIVE_VFO_BACKGROUND;
|
||||||
displayBorder = COLOR_ACTIVE_BORDER;
|
displayBorder = COLOR_ACTIVE_BORDER;
|
||||||
} else {
|
} else {
|
||||||
formatFreq(vfoB, c+2);
|
|
||||||
displayColor = COLOR_INACTIVE_VFO_TEXT;
|
displayColor = COLOR_INACTIVE_VFO_TEXT;
|
||||||
displayBackground = COLOR_INACTIVE_VFO_BACKGROUND;
|
displayBackground = COLOR_INACTIVE_VFO_BACKGROUND;
|
||||||
displayBorder = COLOR_INACTIVE_BORDER;
|
displayBorder = COLOR_INACTIVE_BORDER;
|
||||||
@ -301,7 +273,7 @@ void btnDraw(struct Button *button){
|
|||||||
}
|
}
|
||||||
case BUTTON_RIT:
|
case BUTTON_RIT:
|
||||||
{
|
{
|
||||||
if(1 == ritOn){
|
if(globalSettings.ritOn){
|
||||||
btnDrawActive(button);
|
btnDrawActive(button);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -311,7 +283,7 @@ void btnDraw(struct Button *button){
|
|||||||
}
|
}
|
||||||
case BUTTON_USB:
|
case BUTTON_USB:
|
||||||
{
|
{
|
||||||
if(1 == isUSB){
|
if(VFO_MODE_USB == GetActiveVfoMode()){
|
||||||
btnDrawActive(button);
|
btnDrawActive(button);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -321,7 +293,7 @@ void btnDraw(struct Button *button){
|
|||||||
}
|
}
|
||||||
case BUTTON_LSB:
|
case BUTTON_LSB:
|
||||||
{
|
{
|
||||||
if(0 == isUSB){
|
if(VFO_MODE_LSB == GetActiveVfoMode()){
|
||||||
btnDrawActive(button);
|
btnDrawActive(button);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -331,7 +303,7 @@ void btnDraw(struct Button *button){
|
|||||||
}
|
}
|
||||||
case BUTTON_SPL:
|
case BUTTON_SPL:
|
||||||
{
|
{
|
||||||
if(1 == splitOn){
|
if(globalSettings.splitOn){
|
||||||
btnDrawActive(button);
|
btnDrawActive(button);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -341,7 +313,7 @@ void btnDraw(struct Button *button){
|
|||||||
}
|
}
|
||||||
case BUTTON_CW:
|
case BUTTON_CW:
|
||||||
{
|
{
|
||||||
if(1 == cwMode){
|
if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){
|
||||||
btnDrawActive(button);
|
btnDrawActive(button);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -361,10 +333,10 @@ void btnDraw(struct Button *button){
|
|||||||
void displayRIT(){
|
void displayRIT(){
|
||||||
c[0] = 0;
|
c[0] = 0;
|
||||||
displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND);
|
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:"));
|
strcpy_P(c,(const char*)F("TX:"));
|
||||||
formatFreq(ritTxFrequency, c+3);
|
formatFreq(globalSettings.ritFrequency, c+3, sizeof(c)-3);
|
||||||
if (vfoActive == VFO_A)
|
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);
|
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
|
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);
|
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(){
|
void fastTune(){
|
||||||
int encoder;
|
|
||||||
|
|
||||||
//if the btn is down, wait until it is up
|
//if the btn is down, wait until it is up
|
||||||
while(btnDown())
|
while(btnDown())
|
||||||
active_delay(50);
|
active_delay(50);
|
||||||
active_delay(300);
|
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){
|
while(1){
|
||||||
checkCAT();
|
checkCAT();
|
||||||
|
|
||||||
@ -394,15 +365,17 @@ void fastTune(){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
encoder = enc_read();
|
int encoder = enc_read();
|
||||||
if (encoder != 0){
|
if (encoder != 0){
|
||||||
|
uint32_t freq = GetActiveVfoFreq();
|
||||||
if (encoder > 0 && frequency < 30000000l)
|
if (encoder > 0 && freq < 30000000l){
|
||||||
frequency += 50000l;
|
freq += 50000l;
|
||||||
else if (encoder < 0 && frequency > 600000l)
|
}
|
||||||
frequency -= 50000l;
|
else if (encoder < 0 && freq > 600000l){
|
||||||
setFrequency(frequency);
|
freq -= 50000l;
|
||||||
displayVFO(vfoActive);
|
}
|
||||||
|
setFrequency(freq);
|
||||||
|
displayVFO(globalSettings.activeVfo);
|
||||||
}
|
}
|
||||||
}// end of the event loop
|
}// end of the event loop
|
||||||
}
|
}
|
||||||
@ -410,7 +383,6 @@ void fastTune(){
|
|||||||
void enterFreq(){
|
void enterFreq(){
|
||||||
//force the display to refresh everything
|
//force the display to refresh everything
|
||||||
//display all the buttons
|
//display all the buttons
|
||||||
int f;
|
|
||||||
|
|
||||||
for (int i = 0; i < KEYS_TOTAL; i++){
|
for (int i = 0; i < KEYS_TOTAL; i++){
|
||||||
Button button;
|
Button button;
|
||||||
@ -420,7 +392,6 @@ void enterFreq(){
|
|||||||
|
|
||||||
int cursor_pos = 0;
|
int cursor_pos = 0;
|
||||||
memset(c, 0, sizeof(c));
|
memset(c, 0, sizeof(c));
|
||||||
f = frequency / 1000l;
|
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
|
|
||||||
@ -444,14 +415,16 @@ void enterFreq(){
|
|||||||
switch(button.id){
|
switch(button.id){
|
||||||
case KEYS_OK:
|
case KEYS_OK:
|
||||||
{
|
{
|
||||||
long f = atol(c);
|
long freq = atol(c);
|
||||||
if(30000 >= f && f > 100){
|
if((LOWEST_FREQ/1000 <= freq) && (freq <= HIGHEST_FREQ/1000)){
|
||||||
frequency = f * 1000l;
|
freq *= 1000L;
|
||||||
setFrequency(frequency);
|
setFrequency(freq);
|
||||||
if (vfoActive == VFO_A)
|
if (VFO_A == globalSettings.activeVfo){
|
||||||
vfoA = frequency;
|
globalSettings.vfoA.frequency = freq;
|
||||||
else
|
}
|
||||||
vfoB = frequency;
|
else{
|
||||||
|
globalSettings.vfoB.frequency = freq;
|
||||||
|
}
|
||||||
saveVFOs();
|
saveVFOs();
|
||||||
}
|
}
|
||||||
guiUpdate();
|
guiUpdate();
|
||||||
@ -499,32 +472,35 @@ void enterFreq(){
|
|||||||
}//if button hit test
|
}//if button hit test
|
||||||
}// end of the button scanning loop
|
}// end of the button scanning loop
|
||||||
strcpy(b, c);
|
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);
|
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())
|
while(readTouch())
|
||||||
checkCAT();
|
checkCAT();
|
||||||
} // end of event loop : while(1)
|
} // end of event loop : while(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawCWStatus(){
|
void drawCWStatus(){
|
||||||
strcpy(b, " cw: ");
|
strcpy_P(b,(const char*)F(" cw: "));
|
||||||
int wpm = 1200/cwSpeed;
|
int wpm = 1200/globalSettings.cwDitDurationMs;
|
||||||
itoa(wpm,c, 10);
|
itoa(wpm,c, 10);
|
||||||
strcat(b, c);
|
strcat(b, c);
|
||||||
strcat(b, "wpm, ");
|
strcat_P(b,(const char*)F("wpm, "));
|
||||||
itoa(sideTone, c, 10);
|
itoa(globalSettings.cwSideToneFreq, c, 10);
|
||||||
strcat(b, c);
|
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);
|
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(){
|
void drawTx(){
|
||||||
if (inTx)
|
if (globalSettings.txActive){
|
||||||
displayText("TX", LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND);
|
strcpy_P(b,(const char*)F("TX"));
|
||||||
else
|
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);
|
displayFillrect(LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_BACKGROUND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void drawStatusbar(){
|
void drawStatusbar(){
|
||||||
drawCWStatus();
|
drawCWStatus();
|
||||||
@ -562,7 +538,7 @@ void guiUpdate(){
|
|||||||
|
|
||||||
// this builds up the top line of the display with frequency and mode
|
// this builds up the top line of the display with frequency and mode
|
||||||
void updateDisplay() {
|
void updateDisplay() {
|
||||||
displayVFO(vfoActive);
|
displayVFO(globalSettings.activeVfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -708,21 +684,19 @@ int enc_read(void) {
|
|||||||
|
|
||||||
|
|
||||||
void ritToggle(struct Button *button){
|
void ritToggle(struct Button *button){
|
||||||
if (ritOn == 0){
|
if(!globalSettings.ritOn){
|
||||||
ritEnable(frequency);
|
ritEnable(GetActiveVfoFreq());
|
||||||
}
|
}
|
||||||
else
|
else{
|
||||||
ritDisable();
|
ritDisable();
|
||||||
|
}
|
||||||
btnDraw(button);
|
btnDraw(button);
|
||||||
displayRIT();
|
displayRIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
void splitToggle(Button *button){
|
void splitToggle(Button *button){
|
||||||
|
|
||||||
if (splitOn)
|
globalSettings.splitOn = !globalSettings.splitOn;
|
||||||
splitOn = 0;
|
|
||||||
else
|
|
||||||
splitOn = 1;
|
|
||||||
|
|
||||||
btnDraw(button);
|
btnDraw(button);
|
||||||
|
|
||||||
@ -740,17 +714,17 @@ void splitToggle(Button *button){
|
|||||||
|
|
||||||
void vfoReset(){
|
void vfoReset(){
|
||||||
Button button;
|
Button button;
|
||||||
if (vfoActive = VFO_A)
|
if (VFO_A == globalSettings.activeVfo)
|
||||||
vfoB = vfoA;
|
globalSettings.vfoB.frequency = globalSettings.vfoA.frequency;
|
||||||
else
|
else
|
||||||
vfoA = vfoB;
|
globalSettings.vfoA.frequency = globalSettings.vfoB.frequency;
|
||||||
|
|
||||||
if (splitOn){
|
if(globalSettings.splitOn){
|
||||||
getButton(BUTTON_SPL, &button);
|
getButton(BUTTON_SPL, &button);
|
||||||
splitToggle(&button);
|
splitToggle(&button);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ritOn){
|
if(globalSettings.ritOn){
|
||||||
getButton(BUTTON_RIT, &button);
|
getButton(BUTTON_RIT, &button);
|
||||||
ritToggle(&button);
|
ritToggle(&button);
|
||||||
}
|
}
|
||||||
@ -762,21 +736,22 @@ void vfoReset(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cwToggle(struct Button *b){
|
void cwToggle(struct Button *b){
|
||||||
if (cwMode == 0){
|
if (TuningMode_e::TUNE_SSB == globalSettings.tuningMode){
|
||||||
cwMode = 1;
|
globalSettings.tuningMode = TuningMode_e::TUNE_CW;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
globalSettings.tuningMode = TuningMode_e::TUNE_SSB;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
cwMode = 0;
|
|
||||||
|
|
||||||
setFrequency(frequency);
|
setFrequency(GetActiveVfoFreq());
|
||||||
btnDraw(b);
|
btnDraw(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sidebandToggle(Button* button){
|
void sidebandToggle(Button* button){
|
||||||
if(BUTTON_LSB == button->id)
|
if(BUTTON_LSB == button->id)
|
||||||
isUSB = 0;
|
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||||
else
|
else
|
||||||
isUSB = 1;
|
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||||
|
|
||||||
struct Button button2;
|
struct Button button2;
|
||||||
getButton(BUTTON_USB, &button2);
|
getButton(BUTTON_USB, &button2);
|
||||||
@ -805,51 +780,57 @@ void redrawVFOs(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void switchBand(long bandfreq){
|
void switchBand(uint32_t bandfreq){
|
||||||
long offset;
|
|
||||||
|
|
||||||
// Serial.println(frequency);
|
//Serial.println(frequency);
|
||||||
// Serial.println(bandfreq);
|
//Serial.println(bandfreq);
|
||||||
if (3500000l <= frequency && frequency <= 4000000l)
|
uint32_t offset;
|
||||||
offset = frequency - 3500000l;
|
uint32_t freq = GetActiveVfoFreq();
|
||||||
else if (24800000l <= frequency && frequency <= 25000000l)
|
if (3500000L <= freq && freq <= 4000000L)
|
||||||
offset = frequency - 24800000l;
|
offset = freq - 3500000l;
|
||||||
|
else if (24800000L <= freq && freq <= 25000000L)
|
||||||
|
offset = freq - 24800000L;
|
||||||
else
|
else
|
||||||
offset = frequency % 1000000l;
|
offset = freq % 1000000L;
|
||||||
|
|
||||||
// Serial.println(offset);
|
//Serial.println(offset);
|
||||||
|
|
||||||
setFrequency(bandfreq + offset);
|
setFrequency(bandfreq + offset);
|
||||||
updateDisplay();
|
|
||||||
|
if(bandfreq >= THRESHOLD_USB_LSB){
|
||||||
|
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDisplay();
|
||||||
saveVFOs();
|
saveVFOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
int setCwSpeed(){
|
void setCwSpeed()
|
||||||
int knob = 0;
|
{
|
||||||
int wpm;
|
int wpm = 1200/globalSettings.cwDitDurationMs;
|
||||||
|
|
||||||
|
wpm = getValueByKnob(1, 100, 1, wpm,F("CW: "),F(" WPM"));
|
||||||
|
|
||||||
wpm = 1200/cwSpeed;
|
globalSettings.cwDitDurationMs = 1200/wpm;
|
||||||
|
SaveSettingsToEeprom();
|
||||||
wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM");
|
active_delay(500);
|
||||||
|
drawStatusbar();
|
||||||
cwSpeed = 1200/wpm;
|
//printLine2("");
|
||||||
|
//updateDisplay();
|
||||||
EEPROM.put(CW_SPEED, cwSpeed);
|
|
||||||
active_delay(500);
|
|
||||||
drawStatusbar();
|
|
||||||
// printLine2("");
|
|
||||||
// updateDisplay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCwTone(){
|
void setCwTone(){
|
||||||
int knob = 0;
|
int knob = 0;
|
||||||
int prev_sideTone;
|
int prev_sideTone;
|
||||||
|
|
||||||
tone(CW_TONE, sideTone);
|
tone(CW_TONE, globalSettings.cwSideToneFreq);
|
||||||
itoa(sideTone, c, 10);
|
itoa(globalSettings.cwSideToneFreq, c, 10);
|
||||||
strcpy(b, "CW Tone: ");
|
strcpy_P(b,(const char*)F("CW Tone: "));
|
||||||
strcat(b, c);
|
strcat(b, c);
|
||||||
strcat(b, " Hz");
|
strcat_P(b,(const char*)F(" Hz"));
|
||||||
drawCommandbar(b);
|
drawCommandbar(b);
|
||||||
|
|
||||||
//disable all clock 1 and clock 2
|
//disable all clock 1 and clock 2
|
||||||
@ -857,18 +838,18 @@ void setCwTone(){
|
|||||||
{
|
{
|
||||||
knob = enc_read();
|
knob = enc_read();
|
||||||
|
|
||||||
if (knob > 0 && sideTone < 2000)
|
if (knob > 0 && globalSettings.cwSideToneFreq < 2000)
|
||||||
sideTone += 10;
|
globalSettings.cwSideToneFreq += 10;
|
||||||
else if (knob < 0 && sideTone > 100 )
|
else if (knob < 0 && globalSettings.cwSideToneFreq > 100 )
|
||||||
sideTone -= 10;
|
globalSettings.cwSideToneFreq -= 10;
|
||||||
else
|
else
|
||||||
continue; //don't update the frequency or the display
|
continue; //don't update the frequency or the display
|
||||||
|
|
||||||
tone(CW_TONE, sideTone);
|
tone(CW_TONE, globalSettings.cwSideToneFreq);
|
||||||
itoa(sideTone, c, 10);
|
itoa(globalSettings.cwSideToneFreq, c, 10);
|
||||||
strcpy(b, "CW Tone: ");
|
strcpy_P(b,(const char*)F("CW Tone: "));
|
||||||
strcat(b, c);
|
strcat(b, c);
|
||||||
strcat(b, " Hz");
|
strcat_P(b,(const char*)F(" Hz"));
|
||||||
drawCommandbar(b);
|
drawCommandbar(b);
|
||||||
//printLine2(b);
|
//printLine2(b);
|
||||||
|
|
||||||
@ -876,14 +857,14 @@ void setCwTone(){
|
|||||||
active_delay(20);
|
active_delay(20);
|
||||||
}
|
}
|
||||||
noTone(CW_TONE);
|
noTone(CW_TONE);
|
||||||
//save the setting
|
|
||||||
EEPROM.put(CW_SIDETONE, sideTone);
|
SaveSettingsToEeprom();
|
||||||
|
|
||||||
b[0] = 0;
|
b[0] = 0;
|
||||||
drawCommandbar(b);
|
drawCommandbar(b);
|
||||||
drawStatusbar();
|
drawStatusbar();
|
||||||
// printLine2("");
|
//printLine2("");
|
||||||
// updateDisplay();
|
//updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void doCommand(Button* button){
|
void doCommand(Button* button){
|
||||||
@ -918,7 +899,7 @@ void doCommand(Button* button){
|
|||||||
}
|
}
|
||||||
case BUTTON_VFOA:
|
case BUTTON_VFOA:
|
||||||
{
|
{
|
||||||
if(VFO_A == vfoActive){
|
if(VFO_A == globalSettings.activeVfo){
|
||||||
fastTune();
|
fastTune();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -928,7 +909,7 @@ void doCommand(Button* button){
|
|||||||
}
|
}
|
||||||
case BUTTON_VFOB:
|
case BUTTON_VFOB:
|
||||||
{
|
{
|
||||||
if(VFO_B == vfoActive){
|
if(VFO_B == globalSettings.activeVfo){
|
||||||
fastTune();
|
fastTune();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -1057,7 +1038,7 @@ void doCommands(){
|
|||||||
|
|
||||||
//unfocus the buttons
|
//unfocus the buttons
|
||||||
drawFocus(select, COLOR_INACTIVE_BORDER);
|
drawFocus(select, COLOR_INACTIVE_BORDER);
|
||||||
if (vfoActive == VFO_A)
|
if (VFO_A == globalSettings.activeVfo)
|
||||||
drawFocus(BUTTON_VFOA, COLOR_ACTIVE_BORDER);
|
drawFocus(BUTTON_VFOA, COLOR_ACTIVE_BORDER);
|
||||||
else
|
else
|
||||||
drawFocus(BUTTON_VFOB, COLOR_ACTIVE_BORDER);
|
drawFocus(BUTTON_VFOB, COLOR_ACTIVE_BORDER);
|
||||||
|
@ -30,21 +30,10 @@
|
|||||||
* Si5351 object to control the clocks.
|
* Si5351 object to control the clocks.
|
||||||
*/
|
*/
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <EEPROM.h>
|
#include "settings.h"
|
||||||
#include "ubitx.h"
|
#include "ubitx.h"
|
||||||
#include "nano_gui.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.
|
* 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
|
* 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];
|
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
|
//during CAT commands, we will freeeze the display until CAT is disengaged
|
||||||
unsigned char doingCAT = 0;
|
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
|
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
|
* Below are the basic functions that control the uBitx. Understanding the functions before
|
||||||
@ -168,32 +65,14 @@ void active_delay(int delay_by){
|
|||||||
unsigned long timeStart = millis();
|
unsigned long timeStart = millis();
|
||||||
while (millis() - timeStart <= (unsigned long)delay_by) {
|
while (millis() - timeStart <= (unsigned long)delay_by) {
|
||||||
delay(10);
|
delay(10);
|
||||||
//Background Work
|
//Background Work
|
||||||
checkCAT();
|
checkCAT();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveVFOs(){
|
void saveVFOs()
|
||||||
|
{
|
||||||
if (vfoActive == VFO_A)
|
SaveSettingsToEeprom();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,12 +106,12 @@ void setTXFilters(unsigned long freq){
|
|||||||
else if (freq > 7000000L){
|
else if (freq > 7000000L){
|
||||||
digitalWrite(TX_LPF_A, 0);
|
digitalWrite(TX_LPF_A, 0);
|
||||||
digitalWrite(TX_LPF_B, 1);
|
digitalWrite(TX_LPF_B, 1);
|
||||||
digitalWrite(TX_LPF_C, 0);
|
digitalWrite(TX_LPF_C, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
digitalWrite(TX_LPF_A, 0);
|
digitalWrite(TX_LPF_A, 0);
|
||||||
digitalWrite(TX_LPF_B, 0);
|
digitalWrite(TX_LPF_B, 0);
|
||||||
digitalWrite(TX_LPF_C, 1);
|
digitalWrite(TX_LPF_C, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,12 +131,12 @@ void setTXFilters_v5(unsigned long freq){
|
|||||||
else if (freq > 7000000L){
|
else if (freq > 7000000L){
|
||||||
digitalWrite(TX_LPF_A, 0);
|
digitalWrite(TX_LPF_A, 0);
|
||||||
digitalWrite(TX_LPF_B, 1);
|
digitalWrite(TX_LPF_B, 1);
|
||||||
digitalWrite(TX_LPF_C, 0);
|
digitalWrite(TX_LPF_C, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
digitalWrite(TX_LPF_A, 0);
|
digitalWrite(TX_LPF_A, 0);
|
||||||
digitalWrite(TX_LPF_B, 0);
|
digitalWrite(TX_LPF_B, 0);
|
||||||
digitalWrite(TX_LPF_C, 1);
|
digitalWrite(TX_LPF_C, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,38 +154,31 @@ void setTXFilters_v5(unsigned long freq){
|
|||||||
* through mixing of the second local oscillator.
|
* through mixing of the second local oscillator.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void setFrequency(unsigned long f){
|
void setFrequency(unsigned long freq){
|
||||||
uint64_t osc_f, firstOscillator, secondOscillator;
|
static const unsigned long firstIF = 45005000L;
|
||||||
|
|
||||||
setTXFilters(f);
|
setTXFilters(freq);
|
||||||
|
|
||||||
/*
|
uint32_t local_osc_freq;
|
||||||
if (isUSB){
|
if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){
|
||||||
si5351bx_setfreq(2, firstIF + f);
|
local_osc_freq = firstIF + freq + globalSettings.cwSideToneFreq;
|
||||||
si5351bx_setfreq(1, firstIF + usbCarrier);
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
si5351bx_setfreq(2, firstIF + f);
|
local_osc_freq = firstIF + freq;
|
||||||
si5351bx_setfreq(1, firstIF - usbCarrier);
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
//alternative to reduce the intermod spur
|
uint32_t ssb_osc_freq;
|
||||||
if (isUSB){
|
if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){
|
||||||
if (cwMode)
|
ssb_osc_freq = firstIF + globalSettings.usbCarrierFreq;
|
||||||
si5351bx_setfreq(2, firstIF + f + sideTone);
|
|
||||||
else
|
|
||||||
si5351bx_setfreq(2, firstIF + f);
|
|
||||||
si5351bx_setfreq(1, firstIF + usbCarrier);
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (cwMode)
|
ssb_osc_freq = firstIF - globalSettings.usbCarrierFreq;
|
||||||
si5351bx_setfreq(2, firstIF + f + sideTone);
|
|
||||||
else
|
|
||||||
si5351bx_setfreq(2, firstIF + f);
|
|
||||||
si5351bx_setfreq(1, firstIF - usbCarrier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frequency = f;
|
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
|
* CW offest is calculated as lower than the operating frequency when in LSB mode, and vice versa in USB mode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void startTx(byte txMode){
|
void startTx(TuningMode_e tx_mode){
|
||||||
unsigned long tx_freq = 0;
|
globalSettings.tuningMode = tx_mode;
|
||||||
|
|
||||||
digitalWrite(TX_RX, 1);
|
if (globalSettings.ritOn){
|
||||||
inTx = 1;
|
|
||||||
|
|
||||||
if (ritOn){
|
|
||||||
//save the current as the rx frequency
|
//save the current as the rx frequency
|
||||||
ritRxFrequency = frequency;
|
uint32_t rit_tx_freq = globalSettings.ritFrequency;
|
||||||
setFrequency(ritTxFrequency);
|
globalSettings.ritFrequency = GetActiveVfoFreq();
|
||||||
|
setFrequency(rit_tx_freq);
|
||||||
}
|
}
|
||||||
else
|
else{
|
||||||
{
|
if(globalSettings.splitOn){
|
||||||
if (splitOn == 1) {
|
if(Vfo_e::VFO_B == globalSettings.activeVfo){
|
||||||
if (vfoActive == VFO_B) {
|
globalSettings.activeVfo = Vfo_e::VFO_A;
|
||||||
vfoActive = VFO_A;
|
|
||||||
isUSB = isUsbVfoA;
|
|
||||||
frequency = vfoA;
|
|
||||||
}
|
}
|
||||||
else if (vfoActive == VFO_A){
|
else{
|
||||||
vfoActive = VFO_B;
|
globalSettings.activeVfo = Vfo_e::VFO_B;
|
||||||
frequency = vfoB;
|
|
||||||
isUSB = isUsbVfoB;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setFrequency(frequency);
|
setFrequency(GetActiveVfoFreq());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txMode == TX_CW){
|
if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){
|
||||||
digitalWrite(TX_RX, 0);
|
|
||||||
|
|
||||||
//turn off the second local oscillator and the bfo
|
//turn off the second local oscillator and the bfo
|
||||||
si5351bx_setfreq(0, 0);
|
si5351bx_setfreq(0, 0);
|
||||||
si5351bx_setfreq(1, 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 key up and key down will toggle the carrier unbalancing
|
||||||
//the exact cw frequency is the tuned frequency + sidetone
|
//the exact cw frequency is the tuned frequency + sidetone
|
||||||
if (isUSB)
|
if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){
|
||||||
si5351bx_setfreq(2, frequency + sideTone);
|
si5351bx_setfreq(2, GetActiveVfoFreq() + globalSettings.cwSideToneFreq);
|
||||||
else
|
}
|
||||||
si5351bx_setfreq(2, frequency - sideTone);
|
else{
|
||||||
|
si5351bx_setfreq(2, GetActiveVfoFreq() - globalSettings.cwSideToneFreq);
|
||||||
|
}
|
||||||
|
|
||||||
delay(20);
|
delay(20);
|
||||||
digitalWrite(TX_RX, 1);
|
|
||||||
}
|
}
|
||||||
|
digitalWrite(TX_RX, 1);//turn on the tx
|
||||||
|
globalSettings.txActive = true;
|
||||||
drawTx();
|
drawTx();
|
||||||
//updateDisplay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopTx(){
|
void stopTx(){
|
||||||
inTx = 0;
|
digitalWrite(TX_RX, 0);//turn off the tx
|
||||||
|
globalSettings.txActive = false;
|
||||||
|
|
||||||
digitalWrite(TX_RX, 0); //turn off the tx
|
//set back the carrier oscillator - cw tx switches it off
|
||||||
si5351bx_setfreq(0, usbCarrier); //set back the cardrier oscillator anyway, cw tx switches it off
|
si5351bx_setfreq(0, globalSettings.usbCarrierFreq);
|
||||||
|
|
||||||
if (ritOn)
|
if(globalSettings.ritOn){
|
||||||
setFrequency(ritRxFrequency);
|
uint32_t rit_rx_freq = globalSettings.ritFrequency;
|
||||||
|
globalSettings.ritFrequency = GetActiveVfoFreq();
|
||||||
|
setFrequency(rit_rx_freq);
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
if (splitOn == 1) {
|
if(globalSettings.splitOn){
|
||||||
//vfo Change
|
if(Vfo_e::VFO_B == globalSettings.activeVfo){
|
||||||
if (vfoActive == VFO_B){
|
globalSettings.activeVfo = Vfo_e::VFO_A;
|
||||||
vfoActive = VFO_A;
|
|
||||||
frequency = vfoA;
|
|
||||||
isUSB = isUsbVfoA;
|
|
||||||
}
|
}
|
||||||
else if (vfoActive == VFO_A){
|
else{
|
||||||
vfoActive = VFO_B;
|
globalSettings.activeVfo = Vfo_e::VFO_B;
|
||||||
frequency = vfoB;
|
|
||||||
isUSB = isUsbVfoB;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setFrequency(frequency);
|
setFrequency(GetActiveVfoFreq());
|
||||||
}
|
}
|
||||||
//updateDisplay();
|
|
||||||
drawTx();
|
drawTx();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,18 +261,18 @@ void stopTx(){
|
|||||||
* ritEnable is called with a frequency parameter that determines
|
* ritEnable is called with a frequency parameter that determines
|
||||||
* what the tx frequency will be
|
* what the tx frequency will be
|
||||||
*/
|
*/
|
||||||
void ritEnable(unsigned long f){
|
void ritEnable(unsigned long freq){
|
||||||
ritOn = 1;
|
globalSettings.ritOn = true;
|
||||||
//save the non-rit frequency back into the VFO memory
|
//save the non-rit frequency back into the VFO memory
|
||||||
//as RIT is a temporary shift, this is not saved to EEPROM
|
//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
|
// this is called by the RIT menu routine
|
||||||
void ritDisable(){
|
void ritDisable(){
|
||||||
if (ritOn){
|
if(globalSettings.ritOn){
|
||||||
ritOn = 0;
|
globalSettings.ritOn = false;
|
||||||
setFrequency(ritTxFrequency);
|
setFrequency(globalSettings.ritFrequency);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -424,17 +287,18 @@ void ritDisable(){
|
|||||||
* flip the T/R line to T and update the display to denote transmission
|
* flip the T/R line to T and update the display to denote transmission
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void checkPTT(){
|
void checkPTT(){
|
||||||
//we don't check for ptt when transmitting cw
|
//we don't check for ptt when transmitting cw
|
||||||
if (cwTimeout > 0)
|
if (globalSettings.cwExpirationTimeMs > 0){
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (digitalRead(PTT) == 0 && inTx == 0){
|
if(digitalRead(PTT) == 0 && !globalSettings.txActive){
|
||||||
startTx(TX_SSB);
|
startTx(TuningMode_e::TUNE_SSB);
|
||||||
active_delay(50); //debounce the PTT
|
active_delay(50); //debounce the PTT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (digitalRead(PTT) == 1 && inTx == 1)
|
if (digitalRead(PTT) == 1 && globalSettings.txActive)
|
||||||
stopTx();
|
stopTx();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,41 +335,13 @@ void checkButton(){
|
|||||||
active_delay(50);//debounce
|
active_delay(50);//debounce
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchVFO(int vfoSelect){
|
void switchVFO(Vfo_e new_vfo){
|
||||||
if (vfoSelect == VFO_A){
|
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
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFrequency(frequency);
|
globalSettings.activeVfo = new_vfo;
|
||||||
redrawVFOs();
|
setFrequency(GetActiveVfoFreq());
|
||||||
saveVFOs();
|
redrawVFOs();
|
||||||
|
saveVFOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -516,50 +352,48 @@ void switchVFO(int vfoSelect){
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void doTuning(){
|
void doTuning(){
|
||||||
int s;
|
|
||||||
static unsigned long prev_freq;
|
static unsigned long prev_freq;
|
||||||
static unsigned long nextFrequencyUpdate = 0;
|
static unsigned long nextFrequencyUpdate = 0;
|
||||||
|
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
|
|
||||||
if (now >= nextFrequencyUpdate && prev_freq != frequency){
|
if (now >= nextFrequencyUpdate && prev_freq != GetActiveVfoFreq()){
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
nextFrequencyUpdate = now + 100;
|
nextFrequencyUpdate = now + 100;
|
||||||
prev_freq = frequency;
|
prev_freq = GetActiveVfoFreq();
|
||||||
}
|
}
|
||||||
|
|
||||||
s = enc_read();
|
int s = enc_read();
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//Serial.println(s);
|
//Serial.println(s);
|
||||||
|
|
||||||
doingCAT = 0; // go back to manual mode if you were doing CAT
|
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
|
if (s > 10 || s < -10){
|
||||||
// thresholds for acceleration. I rarely see above 2 or 3 even when turning
|
new_freq += 200L * s;
|
||||||
// the knob quickly.
|
|
||||||
if (s < 5 && s > -5) {
|
|
||||||
frequency += 50l * s;
|
|
||||||
//Serial.println(" 5");
|
|
||||||
}
|
}
|
||||||
else if (s < 10 && s > -10) {
|
else if (s > 5 || s < -5){
|
||||||
frequency += 100l * s;
|
new_freq += 100L * s;
|
||||||
//Serial.println(" 10");
|
|
||||||
}
|
}
|
||||||
else { // if (s >= 10 || s <= -10)
|
else{
|
||||||
frequency += 200l * s;
|
new_freq += 50L * s;
|
||||||
//Serial.println(" <");
|
}
|
||||||
|
|
||||||
|
//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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev_freq < 10000000l && frequency > 10000000l)
|
|
||||||
isUSB = true;
|
|
||||||
|
|
||||||
if (prev_freq > 10000000l && frequency < 10000000l)
|
|
||||||
isUSB = false;
|
|
||||||
|
|
||||||
setFrequency(frequency);
|
setFrequency(new_freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -567,18 +401,17 @@ void doTuning(){
|
|||||||
* RIT only steps back and forth by 100 hz at a time
|
* RIT only steps back and forth by 100 hz at a time
|
||||||
*/
|
*/
|
||||||
void doRIT(){
|
void doRIT(){
|
||||||
unsigned long newFreq;
|
|
||||||
|
|
||||||
int knob = enc_read();
|
int knob = enc_read();
|
||||||
unsigned long old_freq = frequency;
|
uint32_t old_freq = GetActiveVfoFreq();
|
||||||
|
uint32_t new_freq = old_freq;
|
||||||
|
|
||||||
if (knob < 0)
|
if (knob < 0)
|
||||||
frequency -= 100l;
|
new_freq -= 100l;
|
||||||
else if (knob > 0)
|
else if (knob > 0)
|
||||||
frequency += 100;
|
new_freq += 100;
|
||||||
|
|
||||||
if (old_freq != frequency){
|
if (old_freq != new_freq){
|
||||||
setFrequency(frequency);
|
setFrequency(new_freq);
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -589,87 +422,8 @@ void doRIT(){
|
|||||||
* variables.
|
* variables.
|
||||||
*/
|
*/
|
||||||
void initSettings(){
|
void initSettings(){
|
||||||
byte x;
|
LoadDefaultSettings();
|
||||||
//read the settings from the eeprom and restore them
|
LoadSettingsFromEeprom();
|
||||||
//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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initPorts(){
|
void initPorts(){
|
||||||
@ -711,24 +465,24 @@ void setup()
|
|||||||
Serial.begin(38400);
|
Serial.begin(38400);
|
||||||
Serial.flush();
|
Serial.flush();
|
||||||
|
|
||||||
displayInit();
|
|
||||||
initSettings();
|
initSettings();
|
||||||
initPorts();
|
displayInit();
|
||||||
|
initPorts();
|
||||||
initOscillators();
|
initOscillators();
|
||||||
frequency = vfoA;
|
setFrequency(globalSettings.vfoA.frequency);
|
||||||
setFrequency(vfoA);
|
|
||||||
|
|
||||||
if (btnDown()){
|
//Run initial calibration routine if button is pressed during power up
|
||||||
|
if(btnDown()){
|
||||||
setupTouch();
|
setupTouch();
|
||||||
isUSB = 1;
|
SetActiveVfoMode(VfoMode_e::VFO_MODE_USB);
|
||||||
setFrequency(10000000l);
|
setFrequency(10000000l);
|
||||||
setupFreq();
|
setupFreq();
|
||||||
isUSB = 0;
|
SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB);
|
||||||
setFrequency(7100000l);
|
setFrequency(7100000l);
|
||||||
setupBFO();
|
setupBFO();
|
||||||
}
|
}
|
||||||
guiUpdate();
|
|
||||||
|
|
||||||
|
guiUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -736,23 +490,23 @@ void setup()
|
|||||||
* The loop checks for keydown, ptt, function button and tuning.
|
* The loop checks for keydown, ptt, function button and tuning.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
byte flasher = 0;
|
void loop(){
|
||||||
boolean wastouched = false;
|
if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){
|
||||||
|
cwKeyer();
|
||||||
void loop(){
|
}
|
||||||
|
else if(!globalSettings.txCatActive){
|
||||||
if (cwMode)
|
|
||||||
cwKeyer();
|
|
||||||
else if (!txCAT)
|
|
||||||
checkPTT();
|
checkPTT();
|
||||||
|
}
|
||||||
|
|
||||||
checkButton();
|
checkButton();
|
||||||
//tune only when not tranmsitting
|
//tune only when not tranmsitting
|
||||||
if (!inTx){
|
if(!globalSettings.txActive){
|
||||||
if (ritOn)
|
if(globalSettings.ritOn){
|
||||||
doRIT();
|
doRIT();
|
||||||
else
|
}
|
||||||
|
else{
|
||||||
doTuning();
|
doTuning();
|
||||||
|
}
|
||||||
checkTouch();
|
checkTouch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user