ubitx-v5x/Raduino/ubitx_menu.ino

1717 lines
41 KiB
C++

/*
This source code started with Farhan's original source. The license rules are followed as well.
Calibration related functions kept the original source except for the minor ones.
The part is collected in the last minute of this source.
Ian KD8CEC
*/
#include "ubitx.h"
#include "ubitx_eemap.h"
//Current Frequency and mode to active VFO by KD8CEC
void FrequencyToVFO(byte isSaveFreq)
{
//Save Frequency & Mode Information
if (vfoActive == VFO_A)
{
vfoA = frequency;
vfoA_mode = modeToByte();
if (isSaveFreq)
storeFrequencyAndMode(1);
}
else
{
vfoB = frequency;
vfoB_mode = modeToByte();
if (isSaveFreq)
storeFrequencyAndMode(2);
}
}
//Commonly called functions when exiting menus by KD8CEC
void menuClearExit(int delayTime)
{
if (delayTime > 0)
delay_background(delayTime, 0);
printLine2ClearAndUpdate();
menuOn = 0;
}
//Ham band or general band movement by KD8CEC
void menuBand(int btn){
int knob = 0;
int stepChangeCount = 0;
byte btnPressCount = 0;
if (!btn){
printLineF2(F("Band Select?"));
return;
}
//printLineF2(F("Press to confirm"));
//wait for the button menu select button to be lifted)
while (btnDown()) {
delay_background(50, 0);
if (btnPressCount++ > 20) {
btnPressCount = 0;
if (tuneTXType > 0) { //Just toggle 0 <-> 2, if tuneTXType is 100, 100 -> 0 -> 2
tuneTXType = 0;
printLineF2(F("General"));
}
else {
tuneTXType = 2;
printLineF2(F("Ham band"));
}
delay_background(1000, 0);
printLine2ClearAndUpdate();
}
}
printLineF2(F("Press to confirm"));
char currentBandIndex = -1;
//Save Band Information
if (tuneTXType == 2 || tuneTXType == 3 || tuneTXType == 102 || tuneTXType == 103) { //only ham band move
//Get Now Band Index
currentBandIndex = getIndexHambanBbyFreq(frequency);
if (currentBandIndex >= 0) {
//Save Frequency to Band Frequncy Record
saveBandFreqByIndex(frequency, modeToByte(), currentBandIndex);
}
}
//delay(50);
ritDisable();
while(!btnDown()){
knob = enc_read();
if (knob != 0){
if (tuneTXType == 2 || tuneTXType == 3 || tuneTXType == 102 || tuneTXType == 103) { //only ham band move
if (knob < 0) {
if (stepChangeCount-- < -3) {
setNextHamBandFreq(frequency, -1); //Prior Band
stepChangeCount = 0;
}
}
else if (knob > 0) {
if (stepChangeCount++ > 3) {
setNextHamBandFreq(frequency, 1); //Next Band
stepChangeCount = 0;
}
}
} //end of only ham band move
else { //original source
if (knob < 0 && frequency > 3000000l)
setFrequency(frequency - 200000l);
if (knob > 0 && frequency < 30000000l)
setFrequency(frequency + 200000l);
if (frequency > 10000000l)
isUSB = true;
else
isUSB = false;
}
updateDisplay();
}
delay_background(20, 0);
}
FrequencyToVFO(1);
menuClearExit(500);
}
//Convert Mode, Number by KD8CEC
//0: default, 1:not use, 2:LSB, 3:USB, 4:CWL, 5:CWU, 6:FM
byte modeToByte(){
if (cwMode == 0)
{
if (isUSB)
return 3;
else
return 2;
}
else if (cwMode == 1)
{
return 4;
}
else
{
return 5;
}
}
//Convert Number to Mode by KD8CEC
//autoSetModebyFreq : 0
//autoSetModebyFreq : 1, if (modValue is not set, set mode by frequency)
void byteToMode(byte modeValue, byte autoSetModebyFreq){
if (modeValue == 4)
cwMode = 1;
else if (modeValue == 5)
cwMode = 2;
else
{
cwMode = 0;
if (modeValue == 3)
isUSB = 1;
else if (autoSetModebyFreq == 1 && (modeValue == 0))
isUSB = (frequency > 10000000l) ? true : false;
else
isUSB = 0;
}
}
//Memory to VFO, VFO to Memory by KD8CEC
void menuCHMemory(int btn, byte isMemoryToVfo){
int knob = 0;
int selectChannel = 0;
byte isDisplayInfo = 1;
int moveStep = 0;
unsigned long resultFreq, tmpFreq = 0;
byte loadMode = 0;
if (!btn){
if (isMemoryToVfo == 1)
printLineF2(F("Channel To VFO?"));
else
printLineF2(F("VFO To Channel?"));
}
else {
delay_background(500, 0);
while(!btnDown()){
if (isDisplayInfo == 1) {
//Display Channel info *********************************
memset(c, 0, sizeof(c));
if (selectChannel >= 20 || selectChannel <=-1)
{
//strcpy(c, "Exit setup?");
strcpy(c, "Exit?");
}
else
{
//Read Frequency from eeprom
EEPROM.get(CHANNEL_FREQ + 4 * selectChannel, resultFreq);
loadMode = (byte)(resultFreq >> 29);
resultFreq = resultFreq & 0x1FFFFFFF;
//display channel description
if (selectChannel < 10 && EEPROM.read(CHANNEL_DESC + 6 * selectChannel) == 0x03) { //0x03 is display Chnnel Name
//display Channel Name
for (int i = 0; i < 5; i++)
c[i] = EEPROM.read(CHANNEL_DESC + 6 * selectChannel + i + 1);
c[5] = ':';
}
else {
//Display frequency
//1 LINE : Channel Information : CH00
strcpy(c, "CH");
if (selectChannel < 9)
c[2] = '0';
ltoa(selectChannel + 1, b, 10);
strcat(c, b); //append channel Number;
strcat(c, " :"); //append channel Number;
}
//display frequency
tmpFreq = resultFreq;
for (int i = 15; i >= 6; i--) {
if (tmpFreq > 0) {
if (i == 12 || i == 8) c[i] = '.';
else {
c[i] = tmpFreq % 10 + 0x30;
tmpFreq /= 10;
}
}
else
c[i] = ' ';
}
}
printLine2(c);
isDisplayInfo = 0;
}
knob = enc_read();
if (knob != 0)
{
moveStep += (knob > 0 ? 1 : -1);
if (moveStep < -3) {
if (selectChannel > -1)
selectChannel--;
isDisplayInfo = 1;
moveStep = 0;
}
else if (moveStep > 3) {
if (selectChannel < 20)
selectChannel++;
isDisplayInfo = 1;
moveStep = 0;
}
}
Check_Cat(0); //To prevent disconnections
} //end of while (knob)
if (selectChannel < 20 && selectChannel >= 0)
{
if (isMemoryToVfo == 1)
{
if (resultFreq > 3000 && resultFreq < 60000000)
{
byteToMode(loadMode, 1);
setFrequency(resultFreq);
}
}
else
{
//Save current Frequency to Channel (selectChannel)
EEPROM.put(CHANNEL_FREQ + 4 * selectChannel, (frequency & 0x1FFFFFFF) | (((unsigned long)modeToByte()) << 29) );
printLine2("Saved Frequency");
}
}
menuClearExit(500);
}
}
//Analog pin monitoring with CW Key and function keys connected.
//by KD8CEC
#ifdef ENABLE_ADCMONITOR
void menuADCMonitor(int btn){
int adcPinA0 = 0; //A0(BLACK, EncoderA)
int adcPinA1 = 0; //A1(BROWN, EncoderB)
int adcPinA2 = 0; //A2(RED, Function Key)
int adcPinA3 = 0; //A3(ORANGE, CW Key)
int adcPinA6 = 0; //A6(BLUE, Ptt)
int adcPinA7 = 0; //A7(VIOLET, Spare)
unsigned long pressKeyTime = 0;
if (!btn){
printLineF2(F("ADC Line Monitor"));
return;
}
printLineF2(F("Exit:Long PTT"));
delay_background(2000, 0);
printLineF1(F("A0 A1 A2"));
printLineF2(F("A3 A6 A7"));
delay_background(3000, 0);
while (true) {
adcPinA0 = analogRead(A0); //A0(BLACK, EncoderA)
adcPinA1 = analogRead(A1); //A1(BROWN, EncoderB)
adcPinA2 = analogRead(A2); //A2(RED, Function Key)
adcPinA3 = analogRead(A3); //A3(PTT)
adcPinA6 = analogRead(A6); //A6(KEYER)
adcPinA7 = analogRead(A7); //A7(VIOLET, Spare)
if (adcPinA3 < 50) {
if (pressKeyTime == 0)
pressKeyTime = millis();
else if (pressKeyTime < (millis() - 3000))
break;
}
else
pressKeyTime = 0;
ltoa(adcPinA0, c, 10);
//strcat(b, c);
strcpy(b, c);
strcat(b, ", ");
ltoa(adcPinA1, c, 10);
strcat(b, c);
strcat(b, ", ");
ltoa(adcPinA2, c, 10);
strcat(b, c);
printLine1(b);
//strcpy(b, " ");
ltoa(adcPinA3, c, 10);
strcpy(b, c);
strcat(b, ", ");
ltoa(adcPinA6, c, 10);
strcat(b, c);
strcat(b, ", ");
ltoa(adcPinA7, c, 10);
strcat(b, c);
printLine2(b);
delay_background(200, 0);
} //end of while
menuClearExit(0);
}
#endif
//VFO Toggle and save VFO Information, modified by KD8CEC
void menuVfoToggle(int btn)
{
if (!btn){
if (vfoActive == VFO_A)
printLineF2(F("Select VFO B?"));
else
printLineF2(F("Select VFO A?"));
}
else {
FrequencyToVFO(1);
if (vfoActive == VFO_B){
vfoActive = VFO_A;
frequency = vfoA;
saveCheckFreq = frequency;
byteToMode(vfoA_mode, 0);
}
else {
vfoActive = VFO_B;
frequency = vfoB;
saveCheckFreq = frequency;
byteToMode(vfoB_mode, 0);
}
ritDisable();
setFrequency(frequency);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(0);
#endif
}
}
//Split communication using VFOA and VFOB by KD8CEC
void menuSplitOnOff(int btn){
if (!btn){
if (splitOn == 0)
printLineF2(F("Split On?"));
else
printLineF2(F("Split Off?"));
}
else {
if (splitOn == 1){
splitOn = 0;
printLineF2(F("SPT Off"));
}
else {
splitOn = 1;
if (ritOn == 1)
ritOn = 0;
printLineF2(F("SPT On"));
}
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(500);
#endif
}
}
//Function to disbled transmission
//by KD8CEC
void menuTxOnOff(int btn, byte optionType){
if (!btn){
if ((isTxType & optionType) == 0)
printLineF2(F("TX OFF?"));
else
printLineF2(F("TX ON?"));
}
else {
if ((isTxType & optionType) == 0){
isTxType |= optionType;
printLineF2(F("TX OFF"));
}
else {
isTxType &= ~(optionType);
printLineF2(F("TX ON"));
}
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(500);
#endif
}
}
//Toggle SDR MODE
void menuSDROnOff(int btn)
{
if (!btn){
if (sdrModeOn == 0)
printLineF2(F("SDR Mode On?"));
else
printLineF2(F("SDR Mode Off?"));
}
else {
if (sdrModeOn == 1){
sdrModeOn = 0;
printLineF2(F("SPK MODE"));
}
else {
sdrModeOn = 1;
if (ritOn == 1)
ritOn = 0;
if (splitOn == 1)
splitOn = 0;
printLineF2(F("SDR MODE"));
}
EEPROM.put(ENABLE_SDR, sdrModeOn);
setFrequency(frequency);
SetCarrierFreq();
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(500);
#endif
}
}
void displayEmptyData(void){
printLineF2(F("Empty data"));
delay_background(2000, 0);
}
//Builtin CW Keyer Logic by KD8CEC
void menuCWAutoKey(int btn){
if (!btn){
printLineF2(F("Memory Keyer"));
return;
}
//Check CW_AUTO_MAGIC_KEY and CW Text Count
EEPROM.get(CW_AUTO_COUNT, cwAutoTextCount);
if (EEPROM.read(CW_AUTO_MAGIC_KEY) != 0x73 || cwAutoTextCount < 1)
{
displayEmptyData();
return;
}
printLineF1(F("PTT to Send"));
delay_background(500, 0);
beforeCWTextIndex = 255; //255 value is for start check
isCWAutoMode = 1;
updateDisplay();
menuOn = 0;
}
//Standalone WSPR Beacone
void menuWSPRSend(int btn){
if (!btn){
printLineF2(F("WSPR Beacon"));
return;
}
WsprMSGCount = EEPROM.read(WSPR_COUNT);
if (WsprMSGCount < 1)
{
displayEmptyData();
return;
}
SendWSPRManage();
menuClearExit(1000);
}
//Append by KD8CEC
void menuSetupCWCarrier(int btn){
int knob = 0;
unsigned long prevCarrier;
if (!btn){
printLineF2(F("Set CW RX BFO"));
return;
}
prevCarrier = cwmCarrier;
printLineF1(F("PTT to confirm. "));
delay_background(1000, 0);
si5351bx_setfreq(0, cwmCarrier);
printCarrierFreq(cwmCarrier);
//disable all clock 1 and clock 2
while (digitalRead(PTT) == HIGH && !btnDown())
{
knob = enc_read();
if (knob > 0)
cwmCarrier -= 5;
else if (knob < 0)
cwmCarrier += 5;
else
continue; //don't update the frequency or the display
si5351bx_setfreq(0, cwmCarrier);
printCarrierFreq(cwmCarrier);
delay_background(100, 0);
}
//save the setting
if (digitalRead(PTT) == LOW){
printLineF2(F("Carrier set!"));
EEPROM.put(CW_CAL, cwmCarrier);
delay_background(1000, 0);
}
else
cwmCarrier = prevCarrier;
if (cwMode == 0)
si5351bx_setfreq(0, usbCarrier); //set back the carrier oscillator anyway, cw tx switches it off
else
si5351bx_setfreq(0, cwmCarrier); //set back the carrier oscillator anyway, cw tx switches it off
setFrequency(frequency);
menuClearExit(0);
}
//=======================================================
//BEGIN OF STANDARD TUNE SETUP for reduce Program Memory
// by KD8CEC
//=======================================================
//valueType 0 : Normal
// 1 : CW Change -> Generate Tone
// 2 : IF Shift Setup -> SetFrequency, Set SideTone
// 5 : ATT
// 11 : Select Mode (different display type)
//knobSensitivity : 1 ~
int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnobValue, int incStep, const char* displayTitle, int knobSensitivity)
{
int knob;
int moveDetectStep = 0;
char isInitDisplay = 1;
delay_background(300, 0); //Default Delay
if (valueType < 10)
{
strcpy(b, "Press, set ");
strcat(b, displayTitle);
printLine1(b);
}
while(!btnDown())
{
knob = enc_read();
if (knob != 0 || isInitDisplay == 1)
{
isInitDisplay = 0;
/*
//Program Size : 29424 (95%)
if (targetValue > minKnobValue && knob < 0)
targetValue -= incStep;
if (targetValue < maxKnobValue && knob > 0)
targetValue += incStep;
*/
//Program Size : 29560 (increase 135 byte from avobe codes), but a lot of usable functions
moveDetectStep += (knob > 0 ? 1 : -1);
if (moveDetectStep < (knobSensitivity * -1)) {
if (targetValue > minKnobValue)
targetValue -= incStep;
moveDetectStep = 0;
}
else if (moveDetectStep > knobSensitivity) {
if (targetValue < maxKnobValue)
targetValue += incStep;
moveDetectStep = 0;
}
strcpy(b, displayTitle);
if (valueType == 11) //Mode Select
{
b[targetValue * 4] = '>';
}
/*
else if (valueType == 4) //CW Key Type Select
{
if (targetValue == 0)
strcat(b, "Straight");
else if (targetValue == 1)
strcat(b, "IAMBICA");
else if (targetValue == 2)
strcat(b, "IAMBICB");
}
*/
else
{
strcat(b, ":");
itoa(targetValue,c, 10);
strcat(b, c);
}
printLine2(b);
if (valueType == 1) //Generate Side Tone
{
tone(CW_TONE, targetValue);
}
else if (valueType == 2 || valueType == 5 ) // 2:IFS, 5:ATT
{
if (valueType == 2)
ifShiftValue = targetValue;
else
attLevel = targetValue;
#ifdef USE_SW_SERIAL
menuOn=2;
updateDisplay();
#endif
setFrequency(frequency);
SetCarrierFreq();
}
}
Check_Cat(0); //To prevent disconnections
}
return targetValue;
}
void menuCWSpeed(int btn){
int wpm;
wpm = 1200/cwSpeed;
if (!btn){
strcpy(b, "CW:");
itoa(wpm,c, 10);
strcat(b, c);
strcat(b, "WPM Change?");
printLine2(b);
return;
}
//printLineF1(F("Press to set WPM"));
//strcpy(b, "WPM:");
//itoa(wpm,c, 10);
//strcat(b, c);
//printLine2(b);
//delay_background(300, 0);
wpm = getValueByKnob(0, wpm, 3, 50, 1, "WPM", 3);
/*
while(!btnDown()){
knob = enc_read();
if (knob != 0){
if (wpm > 3 && knob < 0)
wpm--;
if (wpm < 50 && knob > 0)
wpm++;
strcpy(b, "WPM:");
itoa(wpm,c, 10);
strcat(b, c);
printLine2(b);
}
Check_Cat(0); //To prevent disconnections
}
*/
//save the setting
//printLineF2(F("CW Speed set!"));
cwSpeed = 1200 / wpm;
EEPROM.put(CW_SPEED, cwSpeed);
//menuClearExit(1000);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(1000);
#endif
}
//Modified by KD8CEC
void menuSetupCwTone(int btn){
//int prev_sideTone;
if (!btn){
printLineF2(F("Change CW Tone"));
return;
}
//prev_sideTone = sideTone;
//printLineF1(F("Tune CW tone"));
//printLineF2(F("PTT to confirm."));
//printLineF1(F("Press to set WPM"));
//delay_background(1000, 0);
//tone(CW_TONE, sideTone);
sideTone = getValueByKnob(1, sideTone, 100, 2000, 10, "Tone", 2); //1 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize
noTone(CW_TONE);
printLineF2(F("Sidetone set!"));
EEPROM.put(CW_SIDETONE, sideTone);
//delay_background(2000, 0);
//menuClearExit(0);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
delay_background(2000, 0);
menuClearExit(0);
#endif
}
//Modified by KD8CEC
void menuSetupCwDelay(int btn){
//int knob = 0;
int tmpCWDelay = cwDelayTime * 10;
if (!btn){
printLineF2(F("CW TX->RX Delay"));
return;
}
tmpCWDelay = getValueByKnob(0, tmpCWDelay, 3, 2500, 10, "Delay", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize
//save the setting
cwDelayTime = tmpCWDelay / 10;
EEPROM.put(CW_DELAY, cwDelayTime);
//menuClearExit(1000);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(1000);
#endif
}
//CW Time delay by KD8CEC
void menuSetupTXCWInterval(int btn){
//char needDisplayInformation = 1;
//int knob = 0;
int tmpTXCWInterval = delayBeforeCWStartTime * 2;
if (!btn){
printLineF2(F("CW Start Delay"));
return;
}
//printLineF1(F("Press, set Delay"));
//delay_background(300, 0);
tmpTXCWInterval = getValueByKnob(0, tmpTXCWInterval, 0, 500, 2, "Delay", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize
delayBeforeCWStartTime = tmpTXCWInterval / 2;
EEPROM.put(CW_START, delayBeforeCWStartTime);
//menuClearExit(1000);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(1000);
#endif
}
//IF Shift function, BFO Change like RIT, by KD8CEC
void menuIFSSetup(int btn){
//int knob = 0;
//char needApplyChangeValue = 1;
if (!btn){
if (isIFShift == 1)
printLineF2(F("IF Shift Change?"));
else
printLineF2(F("IF Shift On?"));
}
else
{
isIFShift = 1;
ifShiftValue = getValueByKnob(2, ifShiftValue, -20000, 20000, 50, "IFS", 2); //2 : IF Setup (updateLine2Buffer(1), SetFrequency), targetValue, minKnobValue, maxKnobValue, stepSize
delay_background(500, 0); //for check Long Press function key
if (btnDown() || ifShiftValue == 0)
{
isIFShift = 0;
ifShiftValue = 0;
setFrequency(frequency);
SetCarrierFreq();
}
//Store IF Shiift
EEPROM.put(IF_SHIFTVALUE, ifShiftValue);
//menuClearExit(0);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(0);
#endif
}
}
//ATT SETUP (IF1(45MHZ) SHIFT), by KD8CEC
void menuATTSetup(int btn){
//int knob = 0;
//char needApplyChangeValue = 1;
if (!btn){
if (attLevel != 0)
printLineF2(F("ATT Change?"));
else
printLineF2(F("ATT On?"));
}
else
{
attLevel = getValueByKnob(5, attLevel, 0, 250, 5, "ATT", 2); //2 : (SetFrequency), targetValue, minKnobValue, maxKnobValue, stepSize
delay_background(500, 0); //for check Long Press function key
if (btnDown() || attLevel == 0)
{
attLevel = 0;
setFrequency(frequency);
//SetCarrierFreq();
}
//menuClearExit(0);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(0);
#endif
}
}
//Functions for CWL and CWU by KD8CEC
void menuSelectMode(int btn){
//int knob = 0;
int selectModeType = 0;
int beforeMode = 0;
//int moveStep = 0;
if (!btn){
printLineF2(F("Select Mode?"));
}
else
{
//LSB, USB, CWL, CWU
if (cwMode == 0 && isUSB == 0)
selectModeType = 0;
else if (cwMode == 0 && isUSB == 1)
selectModeType = 1;
else if (cwMode == 1)
selectModeType = 2;
else
selectModeType = 3;
beforeMode = selectModeType;
selectModeType = getValueByKnob(11, selectModeType, 0, 3, 1, " LSB USB CWL CWU", 4); //3 : Select Mode, targetValue, minKnobValue, maxKnobValue, stepSize
if (beforeMode != selectModeType)
{
//printLineF1(F("Changed Mode"));
if (selectModeType == 0) {
cwMode = 0; isUSB = 0;
}
else if (selectModeType == 1) {
cwMode = 0; isUSB = 1;
}
else if (selectModeType == 2) {
cwMode = 1;
}
else if (selectModeType == 3) {
cwMode = 2;
}
FrequencyToVFO(1);
}
SetCarrierFreq();
setFrequency(frequency);
//menuClearExit(500);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(500);
#endif
}
}
//Select CW Key Type by KD8CEC
void menuSetupKeyType(int btn){
//int knob = 0;
int selectedKeyType = 0;
//int moveStep = 0;
if (!btn){
printLineF2(F("Change Key Type?"));
}
else {
selectedKeyType = cwKeyType;
//selectedKeyType = getValueByKnob(12, selectedKeyType, 0, 2, 1, " KEY:", 5); //4 : Select Key Type, targetValue, minKnobValue, maxKnobValue, stepSize
selectedKeyType = getValueByKnob(11, selectedKeyType, 0, 2, 1, " ST IA IB", 5); //4 : Select Key Type, targetValue, minKnobValue, maxKnobValue, stepSize
printLineF2(F("CW Key Type set!"));
cwKeyType = selectedKeyType;
EEPROM.put(CW_KEY_TYPE, cwKeyType);
if (cwKeyType == 0)
Iambic_Key = false;
else
{
Iambic_Key = true;
if (cwKeyType == 1)
keyerControl &= ~IAMBICB;
else
keyerControl |= IAMBICB;
}
//menuClearExit(1000);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(1000);
#endif
}
}
//=====================================================
//END OF STANDARD Set by Knob for reduce Program Memory
//=====================================================
//Lock Dial move by KD8CEC
void setDialLock(byte tmpLock, byte fromMode) {
if (tmpLock == 1)
isDialLock |= (vfoActive == VFO_A ? 0x01 : 0x02);
else
isDialLock &= ~(vfoActive == VFO_A ? 0x01 : 0x02);
if (fromMode == 2 || fromMode == 3) return;
//delay_background(1000, 0);
printLine2ClearAndUpdate();
}
byte btnDownTimeCount;
#define PRESS_ADJUST_TUNE 20 //1000msec 20 * 50 = 1000milisec
#define PRESS_LOCK_CONTROL 40 //2000msec 40 * 50 = 2000milisec
//Modified by KD8CEC
void doMenu(){
int select=0, i,btnState;
char isNeedDisplay = 0;
//for DialLock On/Off function
btnDownTimeCount = 0;
//wait for the button to be raised up
//Appened Lines by KD8CEC for Adjust Tune step and Set Dial lock
while(btnDown()){
delay_background(50, 0);
if (btnDownTimeCount++ == (PRESS_ADJUST_TUNE)) { //Set Tune Step
printLineF2(F("Set Tune Step?"));
}
else if (btnDownTimeCount > (PRESS_LOCK_CONTROL)) { //check long time Down Button -> 2.5 Second => Lock
if (vfoActive == VFO_A)
setDialLock((isDialLock & 0x01) == 0x01 ? 0 : 1, 0); //Reverse Dial lock
else
setDialLock((isDialLock & 0x02) == 0x02 ? 0 : 1, 0); //Reverse Dial lock
return;
}
}
delay(50); //debounce
//ADJUST TUNE STEP
if (btnDownTimeCount > PRESS_ADJUST_TUNE)
{
printLineF1(F("Press to set"));
isNeedDisplay = 1; //check to need display for display current value
while (!btnDown())
{
delay_background(50, 0);
if (isNeedDisplay) {
strcpy(b, "Tune Step:");
itoa(arTuneStep[tuneStepIndex -1], c, 10);
strcat(b, c);
printLine2(b);
isNeedDisplay = 0;
}
i = enc_read();
if (i != 0) {
select += (i > 0 ? 1 : -1);
if (select * select >= 25) { //Threshold 5 * 5 = 25
if (select < 0) {
if (tuneStepIndex > 1)
tuneStepIndex--;
}
else {
if (tuneStepIndex < 5)
tuneStepIndex++;
}
select = 0;
isNeedDisplay = 1;
}
}
} //end of while
EEPROM.put(TUNING_STEP, tuneStepIndex);
delay_background(500, 0);
printLine2ClearAndUpdate();
return;
} //set tune step
//Below codes are origial code with modified by KD8CEC
menuOn = 2;
TriggerBySW = 0; //Nextion LCD and Other MCU
//*********************************************************************************
// New type menu for developer by KD8CEC
// Selectable menu
// Version : 1.097 ~
//*********************************************************************************
#ifndef ENABLE_ADCMONITOR
#define FN_ADCMONITOR 0
#endif
#define FN_DEFAULT_MENU 2 //Setup Onff / Exit
#define FN_DEFAULT_SETUP 1 //Exit
#define FN_BAND_IDX (FN_BAND -1) //0 or -1
#define FN_VFO_TOGGLE_IDX (FN_BAND_IDX + FN_VFO_TOGGLE)
#define FN_MODE_IDX (FN_VFO_TOGGLE_IDX + FN_MODE)
#define FN_RIT_IDX (FN_MODE_IDX + FN_RIT)
#define FN_IFSHIFT_IDX (FN_RIT_IDX + FN_IFSHIFT)
#define FN_ATT_IDX (FN_IFSHIFT_IDX + FN_ATT)
#define FN_CW_SPEED_IDX (FN_ATT_IDX + FN_CW_SPEED)
#define FN_SPLIT_IDX (FN_CW_SPEED_IDX + FN_SPLIT)
#define FN_VFOTOMEM_IDX (FN_SPLIT_IDX + FN_VFOTOMEM)
#define FN_MEMTOVFO_IDX (FN_VFOTOMEM_IDX + FN_MEMTOVFO)
#define FN_MEMORYKEYER_IDX (FN_MEMTOVFO_IDX + FN_MEMORYKEYER)
#define FN_WSPR_IDX (FN_MEMORYKEYER_IDX + FN_WSPR)
#define FN_SDRMODE_IDX (FN_WSPR_IDX + FN_SDRMODE)
#define FN_SETUP_IDX (FN_SDRMODE_IDX + 1)
#define FN_EXIT_IDX (FN_SETUP_IDX + 1)
#define FN_CALIBRATION_IDX (FN_EXIT_IDX + FN_CALIBRATION)
#define FN_CARRIER_IDX (FN_CALIBRATION_IDX + FN_CARRIER)
#define FN_CWCARRIER_IDX (FN_CARRIER_IDX + FN_CWCARRIER)
#define FN_CWTONE_IDX (FN_CWCARRIER_IDX + FN_CWTONE)
#define FN_CWDELAY_IDX (FN_CWTONE_IDX + FN_CWDELAY)
#define FN_TXCWDELAY_IDX (FN_CWDELAY_IDX + FN_TXCWDELAY)
#define FN_KEYTYPE_IDX (FN_TXCWDELAY_IDX + FN_KEYTYPE)
#define FN_ADCMONITOR_IDX (FN_KEYTYPE_IDX + FN_ADCMONITOR)
#define FN_TXONOFF_IDX (FN_ADCMONITOR_IDX + FN_TXONOFF)
#define FN_MENU_COUNT (FN_DEFAULT_MENU + FN_BAND + FN_VFO_TOGGLE + FN_MODE + FN_RIT + FN_IFSHIFT + FN_ATT + FN_CW_SPEED + FN_SPLIT + FN_VFOTOMEM + FN_MEMTOVFO + FN_MEMORYKEYER + FN_WSPR + FN_SDRMODE)
#define FN_SETUP_COUNT (FN_DEFAULT_SETUP + FN_CALIBRATION + FN_CARRIER + FN_CWCARRIER + FN_CWTONE + FN_CWDELAY + FN_TXCWDELAY + FN_KEYTYPE + FN_ADCMONITOR + FN_TXONOFF)
#define FN_STEP_COUNT (FN_MENU_COUNT + FN_SETUP_COUNT)
while (menuOn){
i = enc_read();
btnState = btnDown();
if (i > 0){
if (modeCalibrate && select + i < FN_STEP_COUNT * 10)
select += i;
else if (!modeCalibrate && select + i < FN_MENU_COUNT * 10)
select += i;
}
else if (i < 0 && select - i >= -10)
select += i;
switch (select / 10)
{
#if FN_BAND == 1
case FN_BAND_IDX :
menuBand(btnState);
break;
#endif
#if FN_VFO_TOGGLE == 1
case FN_VFO_TOGGLE_IDX :
menuVfoToggle(btnState);
break;
#endif
#if FN_MODE == 1
case FN_MODE_IDX :
menuSelectMode(btnState);
break;
#endif
#if FN_RIT == 1
case FN_RIT_IDX :
menuRitToggle(btnState);
break;
#endif
#if FN_IFSHIFT == 1
case FN_IFSHIFT_IDX :
menuIFSSetup(btnState);
break;
#endif
#if FN_ATT == 1
case FN_ATT_IDX :
menuATTSetup(btnState);
break;
#endif
#if FN_CW_SPEED == 1
case FN_CW_SPEED_IDX :
menuCWSpeed(btnState);
break;
#endif
#if FN_SPLIT == 1
case FN_SPLIT_IDX :
menuSplitOnOff(btnState); //SplitOn / off
break;
#endif
#if FN_VFOTOMEM == 1
case FN_VFOTOMEM_IDX :
menuCHMemory(btnState, 0); //VFO to Memroy
break;
#endif
#if FN_MEMTOVFO == 1
case FN_MEMTOVFO_IDX :
menuCHMemory(btnState, 1); //Memory to VFO
break;
#endif
#if FN_MEMORYKEYER == 1
case FN_MEMORYKEYER_IDX :
menuCWAutoKey(btnState);
break;
#endif
#if FN_WSPR == 1
case FN_WSPR_IDX :
menuWSPRSend(btnState);
break;
#endif
#if FN_SDRMODE == 1
case FN_SDRMODE_IDX :
menuSDROnOff(btnState);
break;
#endif
case FN_SETUP_IDX :
menuSetup(btnState);
break;
case FN_EXIT_IDX :
menuExit(btnState);
break;
#if FN_CALIBRATION == 1
case FN_CALIBRATION_IDX :
menuSetupCalibration(btnState); //crystal
break;
#endif
#if FN_CARRIER == 1
case FN_CARRIER_IDX :
menuSetupCarrier(btnState); //ssb
break;
#endif
#if FN_CWCARRIER == 1
case FN_CWCARRIER_IDX :
menuSetupCWCarrier(btnState); //cw
break;
#endif
#if FN_CWTONE == 1
case FN_CWTONE_IDX :
menuSetupCwTone(btnState);
break;
#endif
#if FN_CWDELAY == 1
case FN_CWDELAY_IDX :
menuSetupCwDelay(btnState);
break;
#endif
#if FN_TXCWDELAY == 1
case FN_TXCWDELAY_IDX :
menuSetupTXCWInterval(btnState);
break;
#endif
#if FN_KEYTYPE == 1
case FN_KEYTYPE_IDX :
menuSetupKeyType(btnState);
break;
#endif
#if FN_ADCMONITOR == 1
case FN_ADCMONITOR_IDX :
menuADCMonitor(btnState);
break;
#endif
#if FN_TXONOFF == 1
case FN_TXONOFF_IDX :
menuTxOnOff(btnState, 0x01); //TX OFF / ON
break;
#endif
default :
menuExit(btnState); break;
} //end of switch
Check_Cat(0); //To prevent disconnections
} //end of while
//****************************************************************************
//Before change menu type (Version : ~ 0.95)
//****************************************************************************
/*
while (menuOn){
i = enc_read();
btnState = btnDown();
if (i > 0){
if (modeCalibrate && select + i < 250)
select += i;
else if (!modeCalibrate && select + i < 150)
select += i;
}
else if (i < 0 && select - i >= -10)
select += i;
//if -> switch : reduce program memory 200byte
switch (select / 10)
{
case 0 :
menuBand(btnState);
break;
case 1 :
menuVfoToggle(btnState);
break;
case 2 :
menuSelectMode(btnState);
break;
case 3 :
menuRitToggle(btnState);
break;
case 4 :
menuIFSSetup(btnState);
break;
case 5 :
menuATTSetup(btnState);
break;
case 6 :
menuCWSpeed(btnState);
break;
case 7 :
menuSplitOnOff(btnState); //SplitOn / off
break;
case 8 :
menuCHMemory(btnState, 0); //VFO to Memroy
break;
case 9 :
menuCHMemory(btnState, 1); //Memory to VFO
break;
case 10 :
menuCWAutoKey(btnState);
break;
case 11 :
menuWSPRSend(btnState);
break;
case 12 :
menuSDROnOff(btnState);
break;
case 13 :
menuSetup(btnState);
break;
case 14 :
menuExit(btnState);
break;
case 15 :
menuSetupCalibration(btnState); //crystal
break;
case 16 :
menuSetupCarrier(btnState); //ssb
break;
case 17 :
menuSetupCWCarrier(btnState); //cw
break;
case 18 :
menuSetupCwTone(btnState);
break;
case 19 :
menuSetupCwDelay(btnState);
break;
case 20 :
menuSetupTXCWInterval(btnState);
break;
case 21 :
menuSetupKeyType(btnState);
break;
#ifdef ENABLE_ADCMONITOR
case 22 :
menuADCMonitor(btnState);
break;
case 23 :
#else
case 22 :
#endif
menuTxOnOff(btnState, 0x01); //TX OFF / ON
break;
default :
menuExit(btnState); break;
} //end of case
Check_Cat(0); //To prevent disconnections
} //end of while
*/
}
//*************************************************************************************
//Original Source Part
//The code below is the original source part that I kept unchanged for compatibility.
//By KD8CEC
//*************************************************************************************
/**
Original source comment
* Menus
* The Radio menus are accessed by tapping on the function button.
* - The main loop() constantly looks for a button press and calls doMenu() when it detects
* a function button press.
* - As the encoder is rotated, at every 10th pulse, the next or the previous menu
* item is displayed. Each menu item is controlled by it's own function.
* - Eache menu function may be called to display itself
* - Each of these menu routines is called with a button parameter.
* - The btn flag denotes if the menu itme was clicked on or not.
* - If the menu item is clicked on, then it is selected,
* - If the menu item is NOT clicked on, then the menu's prompt is to be displayed
*/
/**
* The calibration routines are not normally shown in the menu as they are rarely used
* They can be enabled by choosing this menu option
*/
void menuSetup(int btn){
if (!btn)
{
if (!modeCalibrate)
printLineF2(F("Setup On?"));
else
printLineF2(F("Setup Off?"));
}
else
{
modeCalibrate = ! modeCalibrate;
//menuClearExit(1000);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(1000);
#endif
}
}
void menuExit(int btn){
if (!btn){
printLineF2(F("Exit Menu?"));
}
else
menuClearExit(0);
}
//modified for reduce used flash memory by KD8CEC
void menuRitToggle(int btn){
if (!btn){
if (ritOn == 1)
printLineF2(F("RIT Off?"));
else
printLineF2(F("RIT On?"));
}
else {
if (ritOn == 0){
//printLineF2(F("RIT is ON"));
//enable RIT so the current frequency is used at transmit
ritEnable(frequency);
}
else{
//printLineF2(F("RIT is OFF"));
ritDisable();
}
//menuClearExit(500);
#ifdef USE_SW_SERIAL
menuOn = 0;
#else
//Only Clear And Delay for Character LCD
menuClearExit(500);
#endif
}
}
/**
* Take a deep breath, math(ematics) ahead
* The 25 mhz oscillator is multiplied by 35 to run the vco at 875 mhz
* This is divided by a number to generate different frequencies.
* If we divide it by 875, we will get 1 mhz signal
* So, if the vco is shifted up by 875 hz, the generated frequency of 1 mhz is shifted by 1 hz (875/875)
* At 12 Mhz, the carrier will needed to be shifted down by 12 hz for every 875 hz of shift up of the vco
*
*/
//this is used by the si5351 routines in the ubitx_5351 file
extern int32_t calibration;
extern uint32_t si5351bx_vcoa;
void factoryCalibration(int btn){
int knob = 0;
//keep clear of any previous button press
while (btnDown())
delay(100);
delay(100);
if (!btn){
printLineF2(F("Set Calibration?"));
return;
}
calibration = 0;
cwMode = 0;
isUSB = true;
//turn off the second local oscillator and the bfo
si5351_set_calibration(calibration);
startTx(TX_CW, 1);
si5351bx_setfreq(2, 10000000l);
strcpy(b, "#1 10 MHz cal:");
ltoa(calibration/8750, c, 10);
strcat(b, c);
printLine2(b);
while (!btnDown())
{
if (digitalRead(PTT) == LOW && !keyDown)
cwKeydown();
if (digitalRead(PTT) == HIGH && keyDown)
cwKeyUp();
knob = enc_read();
if (knob > 0)
calibration += 875;
else if (knob < 0)
calibration -= 875;
else
continue; //don't update the frequency or the display
si5351_set_calibration(calibration);
si5351bx_setfreq(2, 10000000l);
strcpy(b, "#1 10 MHz cal:");
ltoa(calibration/8750, c, 10);
strcat(b, c);
printLine2(b);
}
cwTimeout = 0;
keyDown = 0;
stopTx();
printLineF2(F("Calibration set!"));
EEPROM.put(MASTER_CAL, calibration);
initOscillators();
setFrequency(frequency);
updateDisplay();
while(btnDown())
delay(50);
menuClearExit(100);
}
void menuSetupCalibration(int btn){
int knob = 0;
int32_t prev_calibration;
if (!btn){
printLineF2(F("Set Calibration?"));
return;
}
printLineF1(F("Set to Zero-beat,"));
printLineF2(F("press PTT to save"));
delay_background(1000, 0);
prev_calibration = calibration;
calibration = 0;
si5351_set_calibration(calibration);
setFrequency(frequency);
strcpy(b, "cal:");
ltoa(calibration/8750, c, 10);
strcat(b, c);
printLine2(b);
while (digitalRead(PTT) == HIGH && !btnDown())
{
knob = enc_read();
if (knob > 0){
calibration += 8750;
usbCarrier += 120;
}
else if (knob < 0){
calibration -= 8750;
usbCarrier -= 120;
}
else
continue; //don't update the frequency or the display
si5351_set_calibration(calibration);
si5351bx_setfreq(0, usbCarrier);
setFrequency(frequency);
strcpy(b, "cal:");
ltoa(calibration/8750, c, 10);
strcat(b, c);
printLine2(b);
}
//save the setting
if (digitalRead(PTT) == LOW){
printLineF1(F("Calibration set!"));
printLineF2(F("Set Carrier now"));
EEPROM.put(MASTER_CAL, calibration);
delay_background(2000, 0);
}
else
calibration = prev_calibration;
initOscillators();
//si5351_set_calibration(calibration);
setFrequency(frequency);
//printLine2ClearAndUpdate();
//menuOn = 0;
menuClearExit(0);
}
void printCarrierFreq(unsigned long freq){
memset(c, 0, sizeof(c));
memset(b, 0, sizeof(b));
ultoa(freq, b, DEC);
strncat(c, b, 2);
strcat(c, ".");
strncat(c, &b[2], 3);
strcat(c, ".");
strncat(c, &b[5], 3);
printLine2(c);
}
//modified by KD8CEC (just 1 line remarked //usbCarrier = ...
void menuSetupCarrier(int btn){
int knob = 0;
unsigned long prevCarrier;
if (!btn){
printLineF2(F("Set the BFO"));
return;
}
prevCarrier = usbCarrier;
printLineF1(F("Tune to best Signal"));
printLineF1(F("PTT to confirm. "));
delay_background(1000, 0);
//usbCarrier = 11995000l; //Remarked by KD8CEC, Suggest from many user, if entry routine factoryrest
/*
//for uBITX V5.0, but not used by KD8CEC, if you want default value of carrier on Calibration, delete remark symbols
#if UBITX_BOARD_VERSION == 5
usbCarrier = 11053000l;
#else
usbCarrier = 11995000l;
#endif
*/
si5351bx_setfreq(0, usbCarrier);
printCarrierFreq(usbCarrier);
//disable all clock 1 and clock 2
while (digitalRead(PTT) == HIGH && !btnDown())
{
knob = enc_read();
if (knob > 0)
usbCarrier -= 5;
else if (knob < 0)
usbCarrier += 5;
else
continue; //don't update the frequency or the display
si5351bx_setfreq(0, usbCarrier);
printCarrierFreq(usbCarrier);
Check_Cat(0); //To prevent disconnections
delay(100);
}
//save the setting
if (digitalRead(PTT) == LOW){
printLineF2(F("Carrier set!"));
EEPROM.put(USB_CAL, usbCarrier);
delay_background(1000, 0);
}
else
usbCarrier = prevCarrier;
//si5351bx_setfreq(0, usbCarrier);
if (cwMode == 0)
si5351bx_setfreq(0, usbCarrier); //set back the carrier oscillator anyway, cw tx switches it off
else
si5351bx_setfreq(0, cwmCarrier); //set back the carrier oscillator anyway, cw tx switches it off
setFrequency(frequency);
//printLine2ClearAndUpdate();
//menuOn = 0;
menuClearExit(0);
}