/** 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 */ /** A generic control to read variable values */ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* prefix, char *postfix) { int knob = 0; int knob_value; while (btnDown()) active_delay(100); active_delay(200); knob_value = initial; strcpy(b, prefix); itoa(knob_value, c, 10); strcat(b, c); strcat(b, postfix); printLine2(b); active_delay(300); while(!btnDown() && digitalRead(PTT) == HIGH){ knob = enc_read(); if (knob != 0){ if (knob_value > minimum && knob < 0) knob_value -= step_size; if (knob_value < maximum && knob > 0) knob_value += step_size; printLine2(prefix); itoa(knob_value, c, 10); strcpy(b, c); strcat(b, postfix); printLine1(b); } checkCAT(); } return knob_value; } //# Menu: 1 int menuBand(int btn){ int knob = 0; int band; unsigned long offset; // band = frequency/1000000l; // offset = frequency % 1000000l; if (!btn){ printLine2("Band Select \x7E"); return; } printLine2("Band Select:"); //wait for the button menu select button to be lifted) while (btnDown()) active_delay(50); active_delay(50); ritDisable(); while(!btnDown()){ knob = enc_read(); if (knob != 0){ /* if (band > 3 && knob < 0) band--; if (band < 30 && knob > 0) band++; if (band > 10) isUSB = true; else isUSB = false; setFrequency(((unsigned long)band * 1000000l) + offset); */ 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(); } checkCAT(); active_delay(20); } while(btnDown()) active_delay(50); active_delay(50); printLine2(""); updateDisplay(); menuOn = 0; } // Menu #2 void menuRitToggle(int btn){ if (!btn){ if (ritOn == 1) printLine2("RIT On \x7E Off"); else printLine2("RIT Off \x7E On"); } else { if (ritOn == 0){ //enable RIT so the current frequency is used at transmit ritEnable(frequency); printLine2("RIT is On"); } else{ ritDisable(); printLine2("RIT is Off"); } menuOn = 0; active_delay(500); printLine2(""); updateDisplay(); } } //Menu #3 void menuVfoToggle(int btn){ if (!btn){ if (vfoActive == VFO_A) printLine2("VFO A \x7E B"); else printLine2("VFO B \x7E A"); } else { 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 { 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; } ritDisable(); setFrequency(frequency); updateDisplay(); printLine2(""); //exit the menu menuOn = 0; } } // Menu #4 void menuSidebandToggle(int btn){ if (!btn){ if (isUSB == true) printLine2("USB \x7E LSB"); else printLine2("LSB \x7E USB"); } else { if (isUSB == true){ isUSB = false; printLine2("LSB Selected"); active_delay(500); printLine2(""); } else { isUSB = true; printLine2("USB Selected"); active_delay(500); printLine2(""); } //Added by KD8CEC if (vfoActive == VFO_B){ isUsbVfoB = isUSB; } else { isUsbVfoB = isUSB; } updateDisplay(); menuOn = 0; } } //Split communication using VFOA and VFOB by KD8CEC //Menu #5 void menuSplitToggle(int btn){ if (!btn){ if (splitOn == 0) printLine2("Split Off \x7E On"); else printLine2("Split On \x7E Off"); } else { if (splitOn == 1){ splitOn = 0; printLine2("Split ON"); } else { splitOn = 1; if (ritOn == 1) ritOn = 0; printLine2("Split Off"); } active_delay(500); printLine2(""); updateDisplay(); menuOn = 0; } } int menuCWSpeed(int btn){ int knob = 0; int wpm; wpm = 1200/cwSpeed; if (!btn){ strcpy(b, "CW: "); itoa(wpm,c, 10); strcat(b, c); strcat(b, " WPM \x7E"); printLine2(b); return; } /* printLine1("Press FN to Set"); strcpy(b, "5:CW>"); itoa(wpm,c, 10); strcat(b, c); strcat(b, " WPM"); printLine2(b); active_delay(300); while(!btnDown() && digitalRead(PTT) == HIGH){ knob = enc_read(); if (knob != 0){ if (wpm > 3 && knob < 0) wpm--; if (wpm < 50 && knob > 0) wpm++; strcpy(b, "5:CW>"); itoa(wpm,c, 10); strcat(b, c); strcat(b, " WPM"); printLine2(b); } //abort if this button is down if (btnDown()) //re-enable the clock1 and clock 2 break; checkCAT(); } */ wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM>"); printLine2("CW Speed set!"); cwSpeed = 1200/wpm; EEPROM.put(CW_SPEED, cwSpeed); active_delay(500); printLine2(""); updateDisplay(); menuOn = 0; } void menuExit(int btn){ if (!btn){ printLine2("Exit Menu \x7E"); } else{ printLine2("Exiting..."); active_delay(500); printLine2(""); updateDisplay(); menuOn = 0; } } /** * The calibration routines are not normally shown in the menu as they are rarely used * They can be enabled by choosing this menu option */ int menuSetup(int btn){ if (!btn){ if (!modeCalibrate) printLine2("Settings \x7E"); else printLine2("Settings \x7E Off"); }else { if (!modeCalibrate){ modeCalibrate = true; printLine2("Settings On"); } else { modeCalibrate = false; printLine2("Settings Off"); } while(btnDown()) active_delay(100); active_delay(500); printLine2(""); return 10; } return 0; } //this is used by the si5351 routines in the ubitx_5351 file extern int32_t calibration; extern uint32_t si5351bx_vcoa; int calibrateClock(){ int knob = 0; int32_t prev_calibration; //keep clear of any previous button press while (btnDown()) active_delay(100); active_delay(100); digitalWrite(TX_LPF_A, 0); digitalWrite(TX_LPF_B, 0); digitalWrite(TX_LPF_C, 0); prev_calibration = calibration; calibration = 0; isUSB = true; //turn off the second local oscillator and the bfo si5351_set_calibration(calibration); startTx(TX_CW); 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(); printLine2("Calibration set!"); EEPROM.put(MASTER_CAL, calibration); initOscillators(); setFrequency(frequency); updateDisplay(); while(btnDown()) active_delay(50); active_delay(100); } int menuSetupCalibration(int btn){ int knob = 0; int32_t prev_calibration; if (!btn){ printLine2("Setup:Calibrate\x7E"); return 0; } printLine1("Press PTT & tune"); printLine2("to exactly 10 MHz"); active_delay(2000); calibrateClock(); } 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], 1); printLine2(c); } void menuSetupCarrier(int btn){ int knob = 0; unsigned long prevCarrier; if (!btn){ printLine2("Setup:BFO \x7E"); return; } prevCarrier = usbCarrier; printLine1("Tune to best Signal"); printLine2("Press to confirm. "); active_delay(1000); usbCarrier = 11053000l; si5351bx_setfreq(0, usbCarrier); printCarrierFreq(usbCarrier); //disable all clock 1 and clock 2 while (!btnDown()){ knob = enc_read(); if (knob > 0) usbCarrier -= 50; else if (knob < 0) usbCarrier += 50; else continue; //don't update the frequency or the display si5351bx_setfreq(0, usbCarrier); printCarrierFreq(usbCarrier); active_delay(100); } printLine2("Carrier set! "); EEPROM.put(USB_CAL, usbCarrier); active_delay(1000); si5351bx_setfreq(0, usbCarrier); setFrequency(frequency); updateDisplay(); printLine2(""); menuOn = 0; } void menuSetupCwTone(int btn){ int knob = 0; int prev_sideTone; if (!btn){ printLine2("Setup:CW Tone \x7E"); return; } prev_sideTone = sideTone; printLine1("Tune CW tone"); printLine2("PTT to confirm. "); active_delay(1000); tone(CW_TONE, sideTone); //disable all clock 1 and clock 2 while (digitalRead(PTT) == HIGH && !btnDown()) { knob = enc_read(); if (knob > 0 && sideTone < 2000) sideTone += 10; else if (knob < 0 && sideTone > 100 ) sideTone -= 10; else continue; //don't update the frequency or the display tone(CW_TONE, sideTone); itoa(sideTone, b, 10); printLine2(b); checkCAT(); active_delay(20); } noTone(CW_TONE); //save the setting if (digitalRead(PTT) == LOW){ printLine2("Sidetone set! "); EEPROM.put(CW_SIDETONE, sideTone); active_delay(2000); } else sideTone = prev_sideTone; printLine2(""); updateDisplay(); menuOn = 0; } void menuSetupCwDelay(int btn){ int knob = 0; int prev_cw_delay; if (!btn){ printLine2("Setup:CW Delay \x7E"); return; } active_delay(500); prev_cw_delay = cwDelayTime; cwDelayTime = getValueByKnob(10, 1000, 50, cwDelayTime, "CW Delay>", " msec"); printLine1("CW Delay Set!"); printLine2(""); active_delay(500); updateDisplay(); menuOn = 0; } void menuSetupKeyer(int btn){ int tmp_key, knob; if (!btn){ if (!Iambic_Key) printLine2("Setup:CW(Hand)\x7E"); else if (keyerControl & IAMBICB) printLine2("Setup:CW(IambA)\x7E"); else printLine2("Setup:CW(IambB)\x7E"); return; } active_delay(500); if (!Iambic_Key) tmp_key = 0; //hand key else if (keyerControl & IAMBICB) tmp_key = 2; //Iambic B else tmp_key = 1; while (!btnDown()) { knob = enc_read(); if (knob < 0 && tmp_key > 0) tmp_key--; if (knob > 0) tmp_key++; if (tmp_key > 2) tmp_key = 0; if (tmp_key == 0) printLine1("Hand Key?"); else if (tmp_key == 1) printLine1("Iambic A?"); else if (tmp_key == 2) printLine1("Iambic B?"); } active_delay(500); if (tmp_key == 0) Iambic_Key = false; else if (tmp_key == 1){ Iambic_Key = true; keyerControl &= ~IAMBICB; } else if (tmp_key == 2){ Iambic_Key = true; keyerControl |= IAMBICB; } EEPROM.put(CW_KEY_TYPE, tmp_key); printLine1("Keyer Set!"); active_delay(600); printLine1(""); //Added KD8CEC printLine2(""); updateDisplay(); menuOn = 0; } void menuReadADC(int btn){ int adc; if (!btn){ printLine2("6:Setup>Read ADC>"); return; } delay(500); while (!btnDown()){ adc = analogRead(ANALOG_KEYER); itoa(adc, b, 10); printLine1(b); } printLine1(""); updateDisplay(); } void doMenu(){ int select=0, i,btnState; //wait for the button to be raised up while(btnDown()) active_delay(50); active_delay(50); //debounce menuOn = 2; while (menuOn){ i = enc_read(); btnState = btnDown(); if (i > 0){ if (modeCalibrate && select + i < 150) select += i; if (!modeCalibrate && select + i < 80) select += i; } if (i < 0 && select - i >= 0) select += i; //caught ya, i is already -ve here, so you add it if (select < 10) menuBand(btnState); else if (select < 20) menuRitToggle(btnState); else if (select < 30) menuVfoToggle(btnState); else if (select < 40) menuSidebandToggle(btnState); else if (select < 50) menuSplitToggle(btnState); else if (select < 60) menuCWSpeed(btnState); else if (select < 70) select += menuSetup(btnState); else if (select < 80 && !modeCalibrate) menuExit(btnState); else if (select < 90 && modeCalibrate) menuSetupCalibration(btnState); //crystal else if (select < 100 && modeCalibrate) menuSetupCarrier(btnState); //lsb else if (select < 110 && modeCalibrate) menuSetupCwTone(btnState); else if (select < 120 && modeCalibrate) menuSetupCwDelay(btnState); else if (select < 130 && modeCalibrate) menuReadADC(btnState); else if (select < 140 && modeCalibrate) menuSetupKeyer(btnState); else menuExit(btnState); } //debounce the button while(btnDown()) active_delay(50); active_delay(50); checkCAT(); }