e481ea2a24
This is the snap of the circuit, wiring instructions for the ubitx pcb. the sketch may change slightly for factory alignment but the rest will remain the same.
573 lines
12 KiB
C++
573 lines
12 KiB
C++
/** 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
|
|
*/
|
|
|
|
|
|
|
|
int menuBand(int btn){
|
|
int knob = 0;
|
|
int band;
|
|
unsigned long offset;
|
|
|
|
// band = frequency/1000000l;
|
|
// offset = frequency % 1000000l;
|
|
|
|
if (!btn){
|
|
printLine2("Band Select?");
|
|
return;
|
|
}
|
|
|
|
printLine2("Press to confirm");
|
|
//wait for the button menu select button to be lifted)
|
|
while (btnDown())
|
|
delay(50);
|
|
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();
|
|
}
|
|
delay(20);
|
|
}
|
|
|
|
while(btnDown())
|
|
delay(50);
|
|
delay(50);
|
|
|
|
printLine2("");
|
|
updateDisplay();
|
|
menuOn = 0;
|
|
}
|
|
|
|
void menuVfoToggle(int btn){
|
|
|
|
if (!btn){
|
|
if (vfoActive == VFO_A)
|
|
printLine2("Select VFO B? ");
|
|
else
|
|
printLine2("Select VFO A? ");
|
|
}
|
|
else {
|
|
if (vfoActive == VFO_B){
|
|
vfoB = frequency;
|
|
EEPROM.put(VFO_B, frequency);
|
|
vfoActive = VFO_A;
|
|
printLine2("Selected VFO A ");
|
|
frequency = vfoA;
|
|
}
|
|
else {
|
|
vfoA = frequency;
|
|
EEPROM.put(VFO_A, frequency);
|
|
vfoActive = VFO_B;
|
|
printLine2("Selected VFO B ");
|
|
frequency = vfoB;
|
|
}
|
|
|
|
ritDisable();
|
|
setFrequency(frequency);
|
|
if (frequency >= 10000000l)
|
|
isUSB = true;
|
|
else
|
|
isUSB = false;
|
|
updateDisplay();
|
|
printLine2("");
|
|
delay(1000);
|
|
//exit the menu
|
|
menuOn = 0;
|
|
}
|
|
}
|
|
|
|
void menuRitToggle(int btn){
|
|
if (!btn){
|
|
if (ritOn == 1)
|
|
printLine2("RIT:On, Off? ");
|
|
else
|
|
printLine2("RIT:Off, On? ");
|
|
}
|
|
else {
|
|
if (ritOn == 0){
|
|
printLine2("RIT is ON");
|
|
//enable RIT so the current frequency is used at transmit
|
|
ritEnable(frequency);
|
|
}
|
|
else{
|
|
printLine2("RIT is OFF");
|
|
ritDisable();
|
|
}
|
|
menuOn = 0;
|
|
delay(500);
|
|
printLine2("");
|
|
updateDisplay();
|
|
}
|
|
}
|
|
|
|
void menuSidebandToggle(int btn){
|
|
if (!btn){
|
|
if (isUSB == true)
|
|
printLine2("Select LSB?");
|
|
else
|
|
printLine2("Select USB?");
|
|
}
|
|
else {
|
|
if (isUSB == true){
|
|
isUSB = false;
|
|
printLine2("LSB Selected");
|
|
delay(500);
|
|
printLine2("");
|
|
}
|
|
else {
|
|
isUSB = true;
|
|
printLine2("USB Selected");
|
|
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
|
|
*/
|
|
void menuSetup(int btn){
|
|
if (!btn){
|
|
if (!modeCalibrate)
|
|
printLine2("Setup On?");
|
|
else
|
|
printLine2("Setup Off?");
|
|
}else {
|
|
if (!modeCalibrate){
|
|
modeCalibrate = true;
|
|
printLine2("Setup:On ");
|
|
}
|
|
else {
|
|
modeCalibrate = false;
|
|
printLine2("Setup:Off ");
|
|
}
|
|
delay(2000);
|
|
printLine2("");
|
|
menuOn = 0;
|
|
}
|
|
}
|
|
|
|
void menuExit(int btn){
|
|
|
|
if (!btn){
|
|
printLine2("Exit Menu? ");
|
|
}
|
|
else{
|
|
printLine2("Exiting menu");
|
|
delay(300);
|
|
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 Change?");
|
|
printLine2(b);
|
|
return;
|
|
}
|
|
|
|
printLine1("Press PTT to set");
|
|
strcpy(b, "WPM:");
|
|
itoa(wpm,c, 10);
|
|
strcat(b, c);
|
|
printLine2(b);
|
|
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, "WPM:");
|
|
itoa(wpm,c, 10);
|
|
strcat(b, c);
|
|
printLine2(b);
|
|
}
|
|
//abort if this button is down
|
|
if (btnDown())
|
|
//re-enable the clock1 and clock 2
|
|
break;
|
|
}
|
|
|
|
//save the setting
|
|
if (digitalRead(PTT) == LOW){
|
|
printLine2("CW Speed set!");
|
|
cwSpeed = 1200/wpm;
|
|
EEPROM.put(CW_SPEED, cwSpeed);
|
|
delay(2000);
|
|
}
|
|
printLine2("");
|
|
menuOn = 0;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* 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;
|
|
|
|
int factoryCalibration(int btn){
|
|
int knob = 0;
|
|
int32_t prev_calibration;
|
|
|
|
|
|
//keep clear of any previous button press
|
|
while (btnDown())
|
|
delay(100);
|
|
delay(100);
|
|
|
|
if (!btn){
|
|
printLine2("Set Calibration?");
|
|
return 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())
|
|
delay(50);
|
|
delay(100);
|
|
}
|
|
|
|
int menuSetupCalibration(int btn){
|
|
int knob = 0;
|
|
int32_t prev_calibration;
|
|
|
|
if (!btn){
|
|
printLine2("Set Calibration?");
|
|
return 0;
|
|
}
|
|
|
|
printLine1("Set to Zero-beat,");
|
|
printLine2("press PTT to save");
|
|
delay(1000);
|
|
|
|
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){
|
|
printLine1("Calibration set!");
|
|
printLine2("Set Carrier now");
|
|
EEPROM.put(MASTER_CAL, calibration);
|
|
delay(2000);
|
|
}
|
|
else
|
|
calibration = prev_calibration;
|
|
|
|
printLine2("");
|
|
initOscillators();
|
|
//si5351_set_calibration(calibration);
|
|
setFrequency(frequency);
|
|
updateDisplay();
|
|
menuOn = 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], 1);
|
|
printLine2(c);
|
|
}
|
|
|
|
void menuSetupCarrier(int btn){
|
|
int knob = 0;
|
|
unsigned long prevCarrier;
|
|
|
|
if (!btn){
|
|
printLine2("Set the BFO");
|
|
return;
|
|
}
|
|
|
|
prevCarrier = usbCarrier;
|
|
printLine1("Tune to best Signal");
|
|
printLine2("PTT to confirm. ");
|
|
delay(1000);
|
|
|
|
usbCarrier = 11995000l;
|
|
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 -= 50;
|
|
else if (knob < 0)
|
|
usbCarrier += 50;
|
|
else
|
|
continue; //don't update the frequency or the display
|
|
|
|
si5351bx_setfreq(0, usbCarrier);
|
|
printCarrierFreq(usbCarrier);
|
|
|
|
delay(100);
|
|
}
|
|
|
|
//save the setting
|
|
if (digitalRead(PTT) == LOW){
|
|
printLine2("Carrier set! ");
|
|
EEPROM.put(USB_CAL, usbCarrier);
|
|
delay(1000);
|
|
}
|
|
else
|
|
usbCarrier = prevCarrier;
|
|
|
|
si5351bx_setfreq(0, usbCarrier);
|
|
setFrequency(frequency);
|
|
updateDisplay();
|
|
printLine2("");
|
|
menuOn = 0;
|
|
}
|
|
|
|
void menuSetupCwTone(int btn){
|
|
int knob = 0;
|
|
int prev_sideTone;
|
|
|
|
if (!btn){
|
|
printLine2("Change CW Tone");
|
|
return;
|
|
}
|
|
|
|
prev_sideTone = sideTone;
|
|
printLine1("Tune CW tone");
|
|
printLine2("PTT to confirm. ");
|
|
delay(1000);
|
|
tone(CW_TONE, sideTone);
|
|
|
|
//disable all clock 1 and clock 2
|
|
while (digitalRead(PTT) == LOW || !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);
|
|
|
|
delay(100);
|
|
}
|
|
noTone(CW_TONE);
|
|
//save the setting
|
|
if (digitalRead(PTT) == LOW){
|
|
printLine2("Sidetone set! ");
|
|
EEPROM.put(CW_SIDETONE, usbCarrier);
|
|
delay(2000);
|
|
}
|
|
else
|
|
sideTone = prev_sideTone;
|
|
|
|
printLine2("");
|
|
updateDisplay();
|
|
menuOn = 0;
|
|
}
|
|
|
|
void doMenu(){
|
|
int select=0, i,btnState;
|
|
|
|
//wait for the button to be raised up
|
|
while(btnDown())
|
|
delay(50);
|
|
delay(50); //debounce
|
|
|
|
menuOn = 2;
|
|
|
|
while (menuOn){
|
|
i = enc_read();
|
|
btnState = btnDown();
|
|
|
|
if (i > 0){
|
|
if (modeCalibrate && select + i < 110)
|
|
select += i;
|
|
if (!modeCalibrate && select + i < 70)
|
|
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)
|
|
menuCWSpeed(btnState);
|
|
else if (select < 60)
|
|
menuSetup(btnState);
|
|
else if (select < 70 && !modeCalibrate)
|
|
menuExit(btnState);
|
|
else if (select < 80 && modeCalibrate)
|
|
menuSetupCalibration(btnState); //crystal
|
|
else if (select < 90 && modeCalibrate)
|
|
menuSetupCarrier(btnState); //lsb
|
|
else if (select < 100 && modeCalibrate)
|
|
menuSetupCwTone(btnState);
|
|
else if (select < 110 && modeCalibrate)
|
|
menuExit(btnState);
|
|
}
|
|
|
|
//debounce the button
|
|
while(btnDown())
|
|
delay(50);
|
|
delay(50);
|
|
}
|
|
|