From 7aafed9e9548251f755bcdac1d0aea1b64aee6bb Mon Sep 17 00:00:00 2001 From: phdlee Date: Wed, 4 Apr 2018 20:29:27 +0900 Subject: [PATCH 1/9] rename ubitx_wspr.cpp to ubitx_wspr.ino --- ubitx_20/ubitx.h | 1 + ubitx_20/{ubitx_wspr.cpp => ubitx_wspr.ino} | 0 2 files changed, 1 insertion(+) rename ubitx_20/{ubitx_wspr.cpp => ubitx_wspr.ino} (100%) diff --git a/ubitx_20/ubitx.h b/ubitx_20/ubitx.h index 64fcd3f..93467c3 100644 --- a/ubitx_20/ubitx.h +++ b/ubitx_20/ubitx.h @@ -34,6 +34,7 @@ extern byte delay_background(unsigned delayTime, byte fromType); extern int btnDown(void); extern char c[30]; extern char b[30]; +extern int enc_read(void); extern unsigned long frequency; diff --git a/ubitx_20/ubitx_wspr.cpp b/ubitx_20/ubitx_wspr.ino similarity index 100% rename from ubitx_20/ubitx_wspr.cpp rename to ubitx_20/ubitx_wspr.ino From 11e47fdccce2695d8553aab52437ce734d865143 Mon Sep 17 00:00:00 2001 From: phdlee Date: Wed, 4 Apr 2018 22:20:04 +0900 Subject: [PATCH 2/9] Added Version Info at top of ubitx_20.ino --- ubitx_20/ubitx_20.ino | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index 79a575b..edb2714 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -1,8 +1,12 @@ +//Firmware Version +#define FIRMWARE_VERSION_INFO F("CE v1.061") +#define FIRMWARE_VERSION_NUM 0x02 //1st Complete Project : 1 (Version 1.061), 2st Project : 2 + /** - Since KD8CEC Version 0.29, most of the original code is no longer available. + Cat Suppoort uBITX CEC Version Most features(TX, Frequency Range, Ham Band, TX Control, CW delay, start Delay... more) have been added by KD8CEC. However, the license rules are subject to the original source rules. - DE Ian KD8CEC + Ian KD8CEC Original source comment ------------------------------------------------------------- * This source file is under General Public License version 3. @@ -104,7 +108,6 @@ #include LiquidCrystal lcd(8,9,10,11,12,13); -#define VERSION_NUM 0x01 //for KD8CEC'S firmware and for memory management software /** * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. @@ -606,13 +609,6 @@ void stopTx(void){ inTx = 0; digitalWrite(TX_RX, 0); //turn off the tx - -/* - if (cwMode == 0) - si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off - else - si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off -*/ SetCarrierFreq(); if (ritOn) @@ -669,7 +665,7 @@ void ritDisable(){ * 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 if (cwTimeout > 0) return; @@ -678,7 +674,7 @@ void checkPTT(){ startTx(TX_SSB, 1); delay(50); //debounce the PTT } - + if (digitalRead(PTT) == 1 && inTx == 1) stopTx(); } @@ -872,8 +868,8 @@ void initSettings(){ } //Version Write for Memory Management Software - if (EEPROM.read(VERSION_ADDRESS) != VERSION_NUM) - EEPROM.write(VERSION_ADDRESS, VERSION_NUM); + if (EEPROM.read(VERSION_ADDRESS) != FIRMWARE_VERSION_NUM) + EEPROM.write(VERSION_ADDRESS, FIRMWARE_VERSION_NUM); EEPROM.get(CW_CAL, cwmCarrier); @@ -1138,7 +1134,7 @@ void setup() //Serial.begin(9600); lcd.begin(16, 2); - printLineF(1, F("CE v1.061")); + printLineF(1, FIRMWARE_VERSION_INFO); Init_Cat(38400, SERIAL_8N1); initMeter(); //not used in this build From 02f22d66e53bdac09cb891d4a1dc8f52be113a85 Mon Sep 17 00:00:00 2001 From: phdlee Date: Thu, 5 Apr 2018 09:50:29 +0900 Subject: [PATCH 3/9] Change Menu codes --- ubitx_20/ubitx_20.ino | 2 +- ubitx_20/ubitx_menu.ino | 1406 +++++++++++++++++++++------------------ 2 files changed, 749 insertions(+), 659 deletions(-) diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index edb2714..08b24d2 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -1,5 +1,5 @@ //Firmware Version -#define FIRMWARE_VERSION_INFO F("CE v1.061") +#define FIRMWARE_VERSION_INFO F("CE v1.070") #define FIRMWARE_VERSION_NUM 0x02 //1st Complete Project : 1 (Version 1.061), 2st Project : 2 /** diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index 4b7d9be..02486c4 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -1,15 +1,11 @@ -/** 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 +/* +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" //Current Frequency and mode to active VFO by KD8CEC @@ -171,160 +167,6 @@ void byteToMode(byte modeValue, byte autoSetModebyFreq){ } } -//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; - - delay_background(500, 0); - updateLine2Buffer(1); - setFrequency(frequency); - - //Off or Change Value - while(!btnDown() ){ - if (needApplyChangeValue ==1) - { - updateLine2Buffer(1); - setFrequency(frequency); - /* - if (cwMode == 0) - si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off - else - si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off - */ - SetCarrierFreq(); - - needApplyChangeValue = 0; - } - - knob = enc_read(); - if (knob != 0){ - if (knob < 0) - ifShiftValue -= 50; - else if (knob > 0) - ifShiftValue += 50; - - needApplyChangeValue = 1; - } - Check_Cat(0); //To prevent disconnections - } - - delay_background(500, 0); //for check Long Press function key - - if (btnDown() || ifShiftValue == 0) - { - isIFShift = 0; - ifShiftValue = 0; - //printLineF2(F("IF Shift is OFF")); - //printLineF2(F("OFF")); - //clearLine2(); - setFrequency(frequency); - SetCarrierFreq(); - //delay_background(1500, 0); - } - - //Store IF Shiift - EEPROM.put(IF_SHIFTVALUE, ifShiftValue); - - menuClearExit(0); - } -} - -//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 { - delay_background(500, 0); - - //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; - - while(!btnDown()){ - //Display Mode Name - memset(c, 0, sizeof(c)); - strcpy(c, " LSB USB CWL CWU"); - c[selectModeType * 4] = '>'; - printLine1(c); - - knob = enc_read(); - - if (knob != 0) - { - moveStep += (knob > 0 ? 1 : -1); - if (moveStep < -3) { - if (selectModeType > 0) - selectModeType--; - - moveStep = 0; - } - else if (moveStep > 3) { - if (selectModeType < 3) - selectModeType++; - - moveStep = 0; - } - } - - //Check_Cat(0); //To prevent disconnections - delay_background(50, 0); - } - - 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); - } - - /* - if (cwMode == 0) - si5351bx_setfreq(0, usbCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off - else - si5351bx_setfreq(0, cwmCarrier + (isIFShift ? ifShiftValue : 0)); //set back the carrier oscillator anyway, cw tx switches it off - */ - SetCarrierFreq(); - - setFrequency(frequency); - menuClearExit(500); - } -} - //Memory to VFO, VFO to Memory by KD8CEC void menuCHMemory(int btn, byte isMemoryToVfo){ @@ -446,69 +288,6 @@ void menuCHMemory(int btn, byte isMemoryToVfo){ } } - -//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 { - //printLineF2(F("Press to set Key")); //for reduce usable flash memory - delay_background(500, 0); - selectedKeyType = cwKeyType; - - while(!btnDown()){ - - //Display Key Type - if (selectedKeyType == 0) - printLineF1(F("Straight")); - else if (selectedKeyType == 1) - printLineF1(F("IAMBICA")); - else if (selectedKeyType == 2) - printLineF1(F("IAMBICB")); - - knob = enc_read(); - - if (knob != 0) - { - moveStep += (knob > 0 ? 1 : -1); - if (moveStep < -3) { - if (selectedKeyType > 0) - selectedKeyType--; - moveStep = 0; - } - else if (moveStep > 3) { - if (selectedKeyType < 2) - selectedKeyType++; - moveStep = 0; - } - } - - Check_Cat(0); //To prevent disconnections - } - - 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); - } -} - //Analog pin monitoring with CW Key and function keys connected. //by KD8CEC void menuADCMonitor(int btn){ @@ -612,28 +391,6 @@ void menuVfoToggle(int btn) } } -//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); - } -} //Split communication using VFOA and VFOB by KD8CEC void menuSplitOnOff(int btn){ @@ -684,98 +441,11 @@ void menuTxOnOff(int btn, byte optionType){ } } -/** - * 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; - /* - if (!modeCalibrate){ - modeCalibrate = true; - //printLineF2(F("Setup:On")); - } - else { - modeCalibrate = false; - //printLineF2(F("Setup:Off")); - } - */ - - menuClearExit(1000); - } -} - -void menuExit(int btn){ - if (!btn){ - printLineF2(F("Exit Menu?")); - } - else - menuClearExit(0); -} - -void 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; - } - - printLineF1(F("Press to set WPM")); - strcpy(b, "WPM:"); - itoa(wpm,c, 10); - strcat(b, c); - printLine2(b); - delay_background(300, 0); - - 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); - } - //abort if this button is down - //if (btnDown()) - //re-enable the clock1 and clock 2 - // break; - - Check_Cat(0); //To prevent disconnections - } - - //save the setting - //printLineF2(F("CW Speed set!")); - cwSpeed = 1200 / wpm; - EEPROM.put(CW_SPEED, cwSpeed); - menuClearExit(1000); -} - void displayEmptyData(void){ printLineF2(F("Empty data")); delay_background(2000, 0); } - //Builtin CW Keyer Logic by KD8CEC void menuCWAutoKey(int btn){ if (!btn){ @@ -791,7 +461,6 @@ void menuCWAutoKey(int btn){ return; } - //printLineF1(F("Press PTT to Send")); printLineF1(F("PTT to Send")); delay_background(500, 0); updateDisplay(); @@ -819,6 +488,256 @@ void menuWSPRSend(int btn){ 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 +// 3 : Select Mode (different display type) +//knobSensitivity : 1 ~ +int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnobValue, int incStep, char* displayTitle, int knobSensitivity) +{ + int knob; + int moveDetectStep = 0; + int negativeSensitivity; + char isInitDisplay = 1; + delay_background(300, 0); //Default Delay + + 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 == 3) //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 + { + itoa(targetValue,c, 10); + strcat(b, c); + } + + printLine2(b); + + if (valueType == 1) //Generate Side Tone + { + tone(CW_TONE, targetValue); + } + else if (valueType == 2) + { + ifShiftValue = targetValue; + setFrequency(frequency); + SetCarrierFreq(); + } + } + + Check_Cat(0); //To prevent disconnections + } + + return targetValue; +} + +void 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; + } + + 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); +} + +//Modified by KD8CEC +void menuSetupCwTone(int btn){ + int knob = 0; + 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, "", 2); //1 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize + + /* + //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); + + delay_background(100, 0); + } + */ + + + noTone(CW_TONE); + + //save the setting + //if (digitalRead(PTT) == LOW){ + printLineF2(F("Sidetone set!")); + EEPROM.put(CW_SIDETONE, sideTone); + delay_background(2000, 0); + //} + //else + // sideTone = prev_sideTone; + + menuClearExit(0); + } + //Modified by KD8CEC @@ -832,12 +751,18 @@ void menuSetupCwDelay(int btn){ } printLineF1(F("Press, set Delay")); + + /* strcpy(b, "DELAY:"); itoa(tmpCWDelay,c, 10); strcat(b, c); printLine2(b); - delay_background(300, 0); + */ + //delay_background(300, 0); + tmpCWDelay = getValueByKnob(0, tmpCWDelay, 3, 2500, 10, "DELAY:", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize + +/* while(!btnDown()){ knob = enc_read(); if (knob != 0){ @@ -857,6 +782,7 @@ void menuSetupCwDelay(int btn){ Check_Cat(0); //To prevent disconnections } +*/ //save the setting //printLineF2(F("CW Delay set!")); @@ -877,8 +803,11 @@ void menuSetupTXCWInterval(int btn){ } printLineF1(F("Press, set Delay")); - delay_background(300, 0); + //delay_background(300, 0); + tmpTXCWInterval = getValueByKnob(0, tmpTXCWInterval, 0, 500, 2, "Start Delay:", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize + +/* while(!btnDown()){ if (needDisplayInformation == 1) { @@ -895,12 +824,7 @@ void menuSetupTXCWInterval(int btn){ tmpTXCWInterval -= 2; if (tmpTXCWInterval < 500 && knob > 0) tmpTXCWInterval += 2; - /* - strcpy(b, "Start Delay:"); - itoa(tmpTXCWInterval,c, 10); - strcat(b, c); - printLine2(b); - */ + needDisplayInformation = 1; } //abort if this button is down @@ -909,6 +833,8 @@ void menuSetupTXCWInterval(int btn){ Check_Cat(0); //To prevent disconnections } +*/ + //save the setting //printLineF2(F("CW Start set!")); @@ -918,6 +844,482 @@ void menuSetupTXCWInterval(int btn){ menuClearExit(1000); } +//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; + + //delay_background(500, 0); + //updateLine2Buffer(1); + //setFrequency(frequency); + + ifShiftValue = getValueByKnob(2, ifShiftValue, -20000, 20000, 50, "IFS:", 2); //2 : IF Setup (updateLine2Buffer(1), SetFrequency), targetValue, minKnobValue, maxKnobValue, stepSize + +/* + //Off or Change Value + while(!btnDown() ){ + if (needApplyChangeValue ==1) + { + updateLine2Buffer(1); + setFrequency(frequency); + SetCarrierFreq(); + needApplyChangeValue = 0; + } + + knob = enc_read(); + if (knob != 0){ + if (knob < 0) + ifShiftValue -= 50; + else if (knob > 0) + ifShiftValue += 50; + + needApplyChangeValue = 1; + } + Check_Cat(0); //To prevent disconnections + } +*/ + + 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); + } +} + + +//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; + + //delay_background(500, 0); + + selectModeType = getValueByKnob(3, selectModeType, 0, 3, 1, " LSB USB CWL CWU", 4); //3 : Select Mode, targetValue, minKnobValue, maxKnobValue, stepSize + +/* + while(!btnDown()){ + //Display Mode Name + memset(c, 0, sizeof(c)); + strcpy(c, " LSB USB CWL CWU"); + c[selectModeType * 4] = '>'; + printLine1(c); + + knob = enc_read(); + + if (knob != 0) + { + moveStep += (knob > 0 ? 1 : -1); + if (moveStep < -3) { + if (selectModeType > 0) + selectModeType--; + + moveStep = 0; + } + else if (moveStep > 3) { + if (selectModeType < 3) + selectModeType++; + + moveStep = 0; + } + } + + //Check_Cat(0); //To prevent disconnections + delay_background(50, 0); + } +*/ + + 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); + } +} + +//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 { + //printLineF2(F("Press to set Key")); //for reduce usable flash memory + //delay_background(500, 0); + selectedKeyType = cwKeyType; + + //selectedKeyType = getValueByKnob(4, selectedKeyType, 0, 2, 1, " KEY:", 5); //4 : Select Key Type, targetValue, minKnobValue, maxKnobValue, stepSize + selectedKeyType = getValueByKnob(3, selectedKeyType, 0, 2, 1, " ST IA IB", 5); //4 : Select Key Type, targetValue, minKnobValue, maxKnobValue, stepSize + + /* + while(!btnDown()){ + + //Display Key Type + if (selectedKeyType == 0) + printLineF1(F("Straight")); + else if (selectedKeyType == 1) + printLineF1(F("IAMBICA")); + else if (selectedKeyType == 2) + printLineF1(F("IAMBICB")); + + knob = enc_read(); + + if (knob != 0) + { + moveStep += (knob > 0 ? 1 : -1); + if (moveStep < -3) { + if (selectedKeyType > 0) + selectedKeyType--; + moveStep = 0; + } + else if (moveStep > 3) { + if (selectedKeyType < 2) + selectedKeyType++; + moveStep = 0; + } + } + + Check_Cat(0); //To prevent disconnections + } + */ + + + 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); + } +} + +//===================================================== +//END OF STANDARD Tune Setup 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; + + while (menuOn){ + i = enc_read(); + btnState = btnDown(); + + if (i > 0){ + if (modeCalibrate && select + i < 240) + select += i; + if (!modeCalibrate && select + i < 130) + select += i; + } + + if (i < 0 && select - i >= -10) + select += i; //caught ya, i is already -ve here, so you add it + + //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 : + menuCWSpeed(btnState); + break; + case 6 : + menuSplitOnOff(btnState); //SplitOn / off + break; + case 7 : + menuCHMemory(btnState, 0); //VFO to Memroy + break; + case 8 : + menuCHMemory(btnState, 1); //Memory to VFO + break; + case 9 : + menuCWAutoKey(btnState); + break; + case 10 : + menuWSPRSend(btnState); + break; + case 11 : + menuSetup(btnState); + break; + case 12 : + menuExit(btnState); + break; + case 13 : + menuSetupCalibration(btnState); //crystal + break; + case 14 : + menuSetupCarrier(btnState); //lsb + break; + case 15 : + menuSetupCWCarrier(btnState); //lsb + break; + case 16 : + menuSetupCwTone(btnState); + break; + case 17 : + menuSetupCwDelay(btnState); + break; + case 18 : + menuSetupTXCWInterval(btnState); + break; + case 19 : + menuSetupKeyType(btnState); + break; + case 20 : + menuADCMonitor(btnState); + break; + case 21 : + menuTxOnOff(btnState, 0x01); //TX OFF / ON + break; + default : + menuExit(btnState); break; + } + + Check_Cat(0); //To prevent disconnections + } +} + +//************************************************************************************* +//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); + } +} + +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); + } +} + + + /** * Take a deep breath, math(ematics) ahead @@ -1143,315 +1545,3 @@ void menuSetupCarrier(int btn){ menuClearExit(0); } -//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); -} - -//Modified by KD8CEC -void menuSetupCwTone(int btn){ - int knob = 0; - int prev_sideTone; - - if (!btn){ - printLineF2(F("Change CW Tone")); - return; - } - - prev_sideTone = sideTone; - printLineF1(F("Tune CW tone")); - printLineF2(F("PTT to confirm.")); - delay_background(1000, 0); - 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); - - delay_background(100, 0); - } - noTone(CW_TONE); - //save the setting - if (digitalRead(PTT) == LOW){ - printLineF2(F("Sidetone set!")); - EEPROM.put(CW_SIDETONE, sideTone); - delay_background(2000, 0); - } - else - sideTone = prev_sideTone; - - menuClearExit(0); - } - -//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; - - while (menuOn){ - i = enc_read(); - btnState = btnDown(); - - if (i > 0){ - if (modeCalibrate && select + i < 240) - select += i; - if (!modeCalibrate && select + i < 130) - select += i; - } - - if (i < 0 && select - i >= -10) - select += i; //caught ya, i is already -ve here, so you add it - - //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 : - menuCWSpeed(btnState); - break; - case 6 : - menuSplitOnOff(btnState); //SplitOn / off - break; - case 7 : - menuCHMemory(btnState, 0); //VFO to Memroy - break; - case 8 : - menuCHMemory(btnState, 1); //Memory to VFO - break; - case 9 : - menuCWAutoKey(btnState); - break; - case 10 : - menuWSPRSend(btnState); - break; - case 11 : - menuSetup(btnState); - break; - case 12 : - menuExit(btnState); - break; - case 13 : - menuSetupCalibration(btnState); //crystal - break; - case 14 : - menuSetupCarrier(btnState); //lsb - break; - case 15 : - menuSetupCWCarrier(btnState); //lsb - break; - case 16 : - menuSetupCwTone(btnState); - break; - case 17 : - menuSetupCwDelay(btnState); - break; - case 18 : - menuSetupTXCWInterval(btnState); - break; - case 19 : - menuSetupKeyType(btnState); - break; - case 20 : - menuADCMonitor(btnState); - break; - case 21 : - menuTxOnOff(btnState, 0x01); //TX OFF / ON - break; - default : - menuExit(btnState); break; - } - /* - else if (select < 130 && modeCalibrate) - menuSetupCalibration(btnState); //crystal - else if (select < 140 && modeCalibrate) - menuSetupCarrier(btnState); //lsb - else if (select < 150 && modeCalibrate) - menuSetupCWCarrier(btnState); //lsb - else if (select < 160 && modeCalibrate) - menuSetupCwTone(btnState); - else if (select < 170 && modeCalibrate) - menuSetupCwDelay(btnState); - else if (select < 180 && modeCalibrate) - menuSetupTXCWInterval(btnState); - else if (select < 190 && modeCalibrate) - menuSetupKeyType(btnState); - else if (select < 200 && modeCalibrate) - menuADCMonitor(btnState); - else if (select < 210 && modeCalibrate) - menuTxOnOff(btnState, 0x01); //TX OFF / ON - else if (select < 220 && modeCalibrate) - menuExit(btnState); - */ - - Check_Cat(0); //To prevent disconnections - } - -/* - //debounce the button - while(btnDown()){ - delay_background(50, 0); //To prevent disconnections - } -*/ -} - From e8d67920731cf72692e5f0462396d0495221bb2d Mon Sep 17 00:00:00 2001 From: phdlee Date: Thu, 5 Apr 2018 17:36:16 +0900 Subject: [PATCH 4/9] complete setup menu ui for reduce program memory --- ubitx_20/ubitx_idle.ino | 189 ++++++++++++++++++---------------------- ubitx_20/ubitx_menu.ino | 31 ++++--- 2 files changed, 104 insertions(+), 116 deletions(-) diff --git a/ubitx_20/ubitx_idle.ino b/ubitx_20/ubitx_idle.ino index 87aa25e..4b72950 100644 --- a/ubitx_20/ubitx_idle.ino +++ b/ubitx_20/ubitx_idle.ino @@ -24,50 +24,18 @@ char line2Buffer[16]; int freqScrollPosition = 0; //Example Line2 Optinal Display //immediate execution, not call by scheulder -void updateLine2Buffer(char isDirectCall) +void updateLine2Buffer(char displayType) { unsigned long tmpFreq = 0; - if (isDirectCall == 0) + if (ritOn) { - if (ritOn) - { - strcpy(line2Buffer, "RitTX:"); - - //display frequency - tmpFreq = ritTxFrequency; - for (int i = 15; i >= 6; i--) { - if (tmpFreq > 0) { - if (i == 12 || i == 8) line2Buffer[i] = '.'; - else { - line2Buffer[i] = tmpFreq % 10 + 0x30; - tmpFreq /= 10; - } - } - else - line2Buffer[i] = ' '; - } - - return; - } //end of ritOn display + strcpy(line2Buffer, "RitTX:"); - //====================================================== - //other VFO display - //====================================================== - if (vfoActive == VFO_B) - { - tmpFreq = vfoA; - } - else - { - tmpFreq = vfoB; - } - - // EXAMPLE 1 & 2 - //U14.150.100 //display frequency - for (int i = 9; i >= 0; i--) { + tmpFreq = ritTxFrequency; + for (int i = 15; i >= 6; i--) { if (tmpFreq > 0) { - if (i == 2 || i == 6) line2Buffer[i] = '.'; + if (i == 12 || i == 8) line2Buffer[i] = '.'; else { line2Buffer[i] = tmpFreq % 10 + 0x30; tmpFreq /= 10; @@ -76,85 +44,101 @@ void updateLine2Buffer(char isDirectCall) else line2Buffer[i] = ' '; } - - //EXAMPLE #1 - if ((displayOption1 & 0x04) == 0x00) //none scroll display - line2Buffer[6] = 'k'; + + return; + } //end of ritOn display + + //====================================================== + //other VFO display + //====================================================== + if (vfoActive == VFO_B) + { + tmpFreq = vfoA; + } + else + { + tmpFreq = vfoB; + } + + // EXAMPLE 1 & 2 + //U14.150.100 + //display frequency + for (int i = 9; i >= 0; i--) { + if (tmpFreq > 0) { + if (i == 2 || i == 6) line2Buffer[i] = '.'; + else { + line2Buffer[i] = tmpFreq % 10 + 0x30; + tmpFreq /= 10; + } + } else + line2Buffer[i] = ' '; + } + + //EXAMPLE #1 + if ((displayOption1 & 0x04) == 0x00) //none scroll display + line2Buffer[6] = 'k'; + else + { + //example #2 + if (freqScrollPosition++ > 18) //none scroll display time { - //example #2 - if (freqScrollPosition++ > 18) //none scroll display time + line2Buffer[6] = 'k'; + if (freqScrollPosition > 25) + freqScrollPosition = -1; + } + else //scroll frequency + { + line2Buffer[10] = 'H'; + line2Buffer[11] = 'z'; + + if (freqScrollPosition < 7) { - line2Buffer[6] = 'k'; - if (freqScrollPosition > 25) - freqScrollPosition = -1; + for (int i = 11; i >= 0; i--) + if (i - (7 - freqScrollPosition) >= 0) + line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)]; + else + line2Buffer[i] = ' '; } - else //scroll frequency + else { - line2Buffer[10] = 'H'; - line2Buffer[11] = 'z'; - - if (freqScrollPosition < 7) - { - for (int i = 11; i >= 0; i--) - if (i - (7 - freqScrollPosition) >= 0) - line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)]; - else - line2Buffer[i] = ' '; - } - else - { - for (int i = 0; i < 11; i++) - if (i + (freqScrollPosition - 7) <= 11) - line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)]; - else - line2Buffer[i] = ' '; - } + for (int i = 0; i < 11; i++) + if (i + (freqScrollPosition - 7) <= 11) + line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)]; + else + line2Buffer[i] = ' '; } - } //scroll - - line2Buffer[7] = ' '; - } //check direct call by encoder + } + } //scroll + + line2Buffer[7] = ' '; if (isIFShift) { - if (isDirectCall == 1) - for (int i = 0; i < 16; i++) - line2Buffer[i] = ' '; +// if (isDirectCall == 1) +// for (int i = 0; i < 16; i++) +// line2Buffer[i] = ' '; //IFShift Offset Value line2Buffer[8] = 'I'; line2Buffer[9] = 'F'; - //if (ifShiftValue == 0) - //{ - /* - line2Buffer[10] = 'S'; - line2Buffer[11] = ':'; - line2Buffer[12] = 'O'; - line2Buffer[13] = 'F'; - line2Buffer[14] = 'F'; - */ - //} - //else - //{ - line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0; - line2Buffer[11] = 0; - line2Buffer[12] = ' '; + line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0; + line2Buffer[11] = 0; + line2Buffer[12] = ' '; + + //11, 12, 13, 14, 15 + memset(b, 0, sizeof(b)); + ltoa(ifShiftValue, b, DEC); + strncat(line2Buffer, b, 5); - //11, 12, 13, 14, 15 - memset(b, 0, sizeof(b)); - ltoa(ifShiftValue, b, DEC); - strncat(line2Buffer, b, 5); - //} - - if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value - printLine2(line2Buffer); + //if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value + printLine2(line2Buffer); } // end of display IF - else // step display + else // step & Key Type display { - if (isDirectCall != 0) - return; + //if (isDirectCall != 0) + // return; memset(&line2Buffer[8], ' ', 8); //Step @@ -174,8 +158,6 @@ void updateLine2Buffer(char isDirectCall) else line2Buffer[i +isStepKhz] = ' '; } - //if (isStepKhz == 1) - // line2Buffer[10] = 'k'; if (isStepKhz == 0) { @@ -184,7 +166,7 @@ void updateLine2Buffer(char isDirectCall) } line2Buffer[13] = ' '; - //if ( + //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb if (cwKeyType == 0) { @@ -202,7 +184,6 @@ void updateLine2Buffer(char isDirectCall) line2Buffer[15] = 'B'; } } - } //meterType : 0 = S.Meter, 1 : P.Meter diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index 02486c4..5d82b51 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -557,6 +557,13 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob int negativeSensitivity; char isInitDisplay = 1; delay_background(300, 0); //Default Delay + + if (valueType < 3) + { + strcpy(b, "Press, set "); + strcat(b, displayTitle); + printLine1(b); + } while(!btnDown()) { @@ -607,6 +614,7 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob */ else { + strcat(b, ":"); itoa(targetValue,c, 10); strcat(b, c); } @@ -646,14 +654,14 @@ void menuCWSpeed(int btn){ return; } - printLineF1(F("Press to set WPM")); + //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); + wpm = getValueByKnob(0, wpm, 3, 50, 1, "WPM", 3); /* while(!btnDown()){ @@ -694,13 +702,13 @@ void menuSetupCwTone(int btn){ } prev_sideTone = sideTone; - printLineF1(F("Tune CW tone")); + //printLineF1(F("Tune CW tone")); //printLineF2(F("PTT to confirm.")); - printLineF1(F("Press to set WPM")); + //printLineF1(F("Press to set WPM")); //delay_background(1000, 0); - tone(CW_TONE, sideTone); + //tone(CW_TONE, sideTone); - sideTone = getValueByKnob(1, sideTone, 100, 2000, 10, "", 2); //1 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize + sideTone = getValueByKnob(1, sideTone, 100, 2000, 10, "Tone", 2); //1 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize /* //disable all clock 1 and clock 2 @@ -750,8 +758,7 @@ void menuSetupCwDelay(int btn){ return; } - printLineF1(F("Press, set Delay")); - + //printLineF1(F("Press, set Delay")); /* strcpy(b, "DELAY:"); itoa(tmpCWDelay,c, 10); @@ -760,7 +767,7 @@ void menuSetupCwDelay(int btn){ */ //delay_background(300, 0); - tmpCWDelay = getValueByKnob(0, tmpCWDelay, 3, 2500, 10, "DELAY:", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize + tmpCWDelay = getValueByKnob(0, tmpCWDelay, 3, 2500, 10, "Delay", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize /* while(!btnDown()){ @@ -802,10 +809,10 @@ void menuSetupTXCWInterval(int btn){ return; } - printLineF1(F("Press, set Delay")); + //printLineF1(F("Press, set Delay")); //delay_background(300, 0); - tmpTXCWInterval = getValueByKnob(0, tmpTXCWInterval, 0, 500, 2, "Start Delay:", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize + tmpTXCWInterval = getValueByKnob(0, tmpTXCWInterval, 0, 500, 2, "Delay", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize /* while(!btnDown()){ @@ -863,7 +870,7 @@ void menuIFSSetup(int btn){ //updateLine2Buffer(1); //setFrequency(frequency); - ifShiftValue = getValueByKnob(2, ifShiftValue, -20000, 20000, 50, "IFS:", 2); //2 : IF Setup (updateLine2Buffer(1), SetFrequency), targetValue, minKnobValue, maxKnobValue, stepSize + ifShiftValue = getValueByKnob(2, ifShiftValue, -20000, 20000, 50, "IFS", 2); //2 : IF Setup (updateLine2Buffer(1), SetFrequency), targetValue, minKnobValue, maxKnobValue, stepSize /* //Off or Change Value From 1210f56cd1660ce3f382aca52d8cd35e64c8e60d Mon Sep 17 00:00:00 2001 From: phdlee Date: Thu, 5 Apr 2018 21:30:35 +0900 Subject: [PATCH 5/9] move display routine ui to idle --- ubitx_20/ubitx_idle.ino | 278 +++++++++++++++++++++++++++++++++++ ubitx_20/ubitx_ui.ino | 315 ---------------------------------------- 2 files changed, 278 insertions(+), 315 deletions(-) diff --git a/ubitx_20/ubitx_idle.ino b/ubitx_20/ubitx_idle.ino index 4b72950..bee7c2f 100644 --- a/ubitx_20/ubitx_idle.ino +++ b/ubitx_20/ubitx_idle.ino @@ -17,6 +17,284 @@ along with this program. If not, see . **************************************************************************/ + +//======================================================================== +//Display Routine +//======================================================================== +const PROGMEM uint8_t meters_bitmap[] = { + B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1 + B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2 + B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3 + B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4 + B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5 + B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6 +}; + +PGM_P p_metes_bitmap = reinterpret_cast(meters_bitmap); + +const PROGMEM uint8_t lock_bitmap[8] = { + 0b01110, + 0b10001, + 0b10001, + 0b11111, + 0b11011, + 0b11011, + 0b11111, + 0b00000}; +PGM_P plock_bitmap = reinterpret_cast(lock_bitmap); + + +// initializes the custom characters +// we start from char 1 as char 0 terminates the string! +void initMeter(){ + uint8_t tmpbytes[8]; + byte i; + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(plock_bitmap + i); + lcd.createChar(0, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i); + lcd.createChar(1, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8); + lcd.createChar(2, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16); + lcd.createChar(3, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24); + lcd.createChar(4, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32); + lcd.createChar(5, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40); + lcd.createChar(6, tmpbytes); +} + +//by KD8CEC +//0 ~ 25 : 30 over : + 10 +void drawMeter(int needle) { + //5Char + O over + int i; + + for (i = 0; i < 5; i++) { + if (needle >= 5) + lcdMeter[i] = 5; //full + else if (needle > 0) + lcdMeter[i] = needle; //full + else //0 + lcdMeter[i] = 0x20; + + needle -= 5; + } + + if (needle > 0) + lcdMeter[5] = 6; + else + lcdMeter[5] = 0x20; +} + + + +// The generic routine to display one line on the LCD +void printLine(unsigned char linenmbr, const char *c) { + if ((displayOption1 & 0x01) == 0x01) + linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle + + if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change + lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line + lcd.print(c); + strcpy(printBuff[linenmbr], c); + + for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached + lcd.print(' '); + } + } +} + +void printLineF(char linenmbr, const __FlashStringHelper *c) +{ + int i; + char tmpBuff[17]; + PGM_P p = reinterpret_cast(c); + + for (i = 0; i < 17; i++){ + unsigned char fChar = pgm_read_byte(p++); + tmpBuff[i] = fChar; + if (fChar == 0) + break; + } + + printLine(linenmbr, tmpBuff); +} + +#define LCD_MAX_COLUMN 16 +void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) { + if ((displayOption1 & 0x01) == 0x01) + linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle + + lcd.setCursor(lcdColumn, linenmbr); + + for (byte i = eepromStartIndex; i <= eepromEndIndex; i++) + { + if (++lcdColumn <= LCD_MAX_COLUMN) + lcd.write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i)); + else + break; + } + + for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space + lcd.write(' '); +} + +// short cut to print to the first line +void printLine1(const char *c){ + printLine(1,c); +} +// short cut to print to the first line +void printLine2(const char *c){ + printLine(0,c); +} + +void clearLine2() +{ + printLine2(""); + line2DisplayStatus = 0; +} + +// short cut to print to the first line +void printLine1Clear(){ + printLine(1,""); +} +// short cut to print to the first line +void printLine2Clear(){ + printLine(0, ""); +} + +void printLine2ClearAndUpdate(){ + printLine(0, ""); + line2DisplayStatus = 0; + updateDisplay(); +} + +//012...89ABC...Z +char byteToChar(byte srcByte){ + if (srcByte < 10) + return 0x30 + srcByte; + else + return 'A' + srcByte - 10; +} + +// this builds up the top line of the display with frequency and mode +void updateDisplay() { + // tks Jack Purdum W8TEE + // replaced fsprint commmands by str commands for code size reduction + // replace code for Frequency numbering error (alignment, point...) by KD8CEC + int i; + unsigned long tmpFreq = frequency; // + + memset(c, 0, sizeof(c)); + + if (inTx){ + if (isCWAutoMode == 2) { + for (i = 0; i < 4; i++) + c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' '); + + //display Sending Index + c[4] = byteToChar(sendingCWTextIndex); + c[5] = '='; + } + else { + if (cwTimeout > 0) + strcpy(c, " CW:"); + else + strcpy(c, " TX:"); + } + } + else { + if (ritOn) + strcpy(c, "RIT "); + else { + if (cwMode == 0) + { + if (isUSB) + strcpy(c, "USB "); + else + strcpy(c, "LSB "); + } + else if (cwMode == 1) + { + strcpy(c, "CWL "); + } + else + { + strcpy(c, "CWU "); + } + } + if (vfoActive == VFO_A) // VFO A is active + strcat(c, "A:"); + else + strcat(c, "B:"); + } + + //Fixed by Mitani Massaru (JE4SMQ) + if (isShiftDisplayCWFreq == 1) + { + if (cwMode == 1) //CWL + tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal; + else if (cwMode == 2) //CWU + tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal; + } + + //display frequency + 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] = ' '; + } + + //remarked by KD8CEC + //already RX/TX status display, and over index (16 x 2 LCD) + //if (inTx) + // strcat(c, " TX"); + printLine(1, c); + + byte diplayVFOLine = 1; + if ((displayOption1 & 0x01) == 0x01) + diplayVFOLine = 0; + + if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) || + (vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) { + lcd.setCursor(5,diplayVFOLine); + lcd.write((uint8_t)0); + } + else if (isCWAutoMode == 2){ + lcd.setCursor(5,diplayVFOLine); + lcd.write(0x7E); + } + else + { + lcd.setCursor(5,diplayVFOLine); + lcd.write(":"); + } +} + + + char line2Buffer[16]; //KD8CEC 200Hz ST //L14.150 200Hz ST diff --git a/ubitx_20/ubitx_ui.ino b/ubitx_20/ubitx_ui.ino index c5089ea..27d570f 100644 --- a/ubitx_20/ubitx_ui.ino +++ b/ubitx_20/ubitx_ui.ino @@ -5,8 +5,6 @@ * of the radio. Occasionally, it is used to provide a two-line information that is * quickly cleared up. */ -//#define printLineF1(x) (printLineF(1, x)) -//#define printLineF2(x) (printLineF(0, x)) //returns true if the button is pressed int btnDown(void){ @@ -16,319 +14,6 @@ int btnDown(void){ return 1; } -/** - * Meter (not used in this build for anything) - * the meter is drawn using special characters. Each character is composed of 5 x 8 matrix. - * The s_meter array holds the definition of the these characters. - * each line of the array is is one character such that 5 bits of every byte - * makes up one line of pixels of the that character (only 5 bits are used) - * The current reading of the meter is assembled in the string called meter - */ - - -/* -const PROGMEM uint8_t s_meter_bitmap[] = { - B00000,B00000,B00000,B00000,B00000,B00100,B00100,B11011, - B10000,B10000,B10000,B10000,B10100,B10100,B10100,B11011, - B01000,B01000,B01000,B01000,B01100,B01100,B01100,B11011, - B00100,B00100,B00100,B00100,B00100,B00100,B00100,B11011, - B00010,B00010,B00010,B00010,B00110,B00110,B00110,B11011, - B00001,B00001,B00001,B00001,B00101,B00101,B00101,B11011 -}; -*/ - -const PROGMEM uint8_t meters_bitmap[] = { - B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1 - B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2 - B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3 - B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4 - B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5 - B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6 -}; - -PGM_P p_metes_bitmap = reinterpret_cast(meters_bitmap); - -const PROGMEM uint8_t lock_bitmap[8] = { - 0b01110, - 0b10001, - 0b10001, - 0b11111, - 0b11011, - 0b11011, - 0b11111, - 0b00000}; -PGM_P plock_bitmap = reinterpret_cast(lock_bitmap); - - -// initializes the custom characters -// we start from char 1 as char 0 terminates the string! -void initMeter(){ - uint8_t tmpbytes[8]; - byte i; - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(plock_bitmap + i); - lcd.createChar(0, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i); - lcd.createChar(1, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8); - lcd.createChar(2, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16); - lcd.createChar(3, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24); - lcd.createChar(4, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32); - lcd.createChar(5, tmpbytes); - - for (i = 0; i < 8; i++) - tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40); - lcd.createChar(6, tmpbytes); -} - -//by KD8CEC -//0 ~ 25 : 30 over : + 10 -void drawMeter(int needle) { - //5Char + O over - int i; - - for (i = 0; i < 5; i++) { - if (needle >= 5) - lcdMeter[i] = 5; //full - else if (needle > 0) - lcdMeter[i] = needle; //full - else //0 - lcdMeter[i] = 0x20; - - needle -= 5; - } - - if (needle > 0) - lcdMeter[5] = 6; - else - lcdMeter[5] = 0x20; -} - -/* -void drawMeter(int8_t needle){ - int16_t best, i, s; - - if (needle < 0) - return; - - s = (needle * 4)/10; - for (i = 0; i < 8; i++){ - if (s >= 5) - lcdMeter[i] = 1; - else if (s >= 0) - lcdMeter[i] = 2 + s; - else - lcdMeter[i] = 1; - s = s - 5; - } - if (needle >= 40) - lcdMeter[i-1] = 6; - lcdMeter[i] = 0; -} -*/ -// The generic routine to display one line on the LCD -void printLine(unsigned char linenmbr, const char *c) { - if ((displayOption1 & 0x01) == 0x01) - linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle - - if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change - lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line - lcd.print(c); - strcpy(printBuff[linenmbr], c); - - for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached - lcd.print(' '); - } - } -} - -void printLineF(char linenmbr, const __FlashStringHelper *c) -{ - int i; - char tmpBuff[17]; - PGM_P p = reinterpret_cast(c); - - for (i = 0; i < 17; i++){ - unsigned char fChar = pgm_read_byte(p++); - tmpBuff[i] = fChar; - if (fChar == 0) - break; - } - - printLine(linenmbr, tmpBuff); -} - -#define LCD_MAX_COLUMN 16 -void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) { - if ((displayOption1 & 0x01) == 0x01) - linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle - - lcd.setCursor(lcdColumn, linenmbr); - - for (byte i = eepromStartIndex; i <= eepromEndIndex; i++) - { - if (++lcdColumn <= LCD_MAX_COLUMN) - lcd.write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i)); - else - break; - } - - for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space - lcd.write(' '); -} - -// short cut to print to the first line -void printLine1(const char *c){ - printLine(1,c); -} -// short cut to print to the first line -void printLine2(const char *c){ - printLine(0,c); -} - -void clearLine2() -{ - printLine2(""); - line2DisplayStatus = 0; -} - -// short cut to print to the first line -void printLine1Clear(){ - printLine(1,""); -} -// short cut to print to the first line -void printLine2Clear(){ - printLine(0, ""); -} - -void printLine2ClearAndUpdate(){ - printLine(0, ""); - line2DisplayStatus = 0; - updateDisplay(); -} - -//012...89ABC...Z -char byteToChar(byte srcByte){ - if (srcByte < 10) - return 0x30 + srcByte; - else - return 'A' + srcByte - 10; -} - -// this builds up the top line of the display with frequency and mode -void updateDisplay() { - // tks Jack Purdum W8TEE - // replaced fsprint commmands by str commands for code size reduction - // replace code for Frequency numbering error (alignment, point...) by KD8CEC - int i; - unsigned long tmpFreq = frequency; // - - memset(c, 0, sizeof(c)); - - if (inTx){ - if (isCWAutoMode == 2) { - for (i = 0; i < 4; i++) - c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' '); - - //display Sending Index - c[4] = byteToChar(sendingCWTextIndex); - c[5] = '='; - } - else { - if (cwTimeout > 0) - strcpy(c, " CW:"); - else - strcpy(c, " TX:"); - } - } - else { - if (ritOn) - strcpy(c, "RIT "); - else { - if (cwMode == 0) - { - if (isUSB) - strcpy(c, "USB "); - else - strcpy(c, "LSB "); - } - else if (cwMode == 1) - { - strcpy(c, "CWL "); - } - else - { - strcpy(c, "CWU "); - } - } - if (vfoActive == VFO_A) // VFO A is active - strcat(c, "A:"); - else - strcat(c, "B:"); - } - - //Fixed by Mitani Massaru (JE4SMQ) - if (isShiftDisplayCWFreq == 1) - { - if (cwMode == 1) //CWL - tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal; - else if (cwMode == 2) //CWU - tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal; - } - - //display frequency - 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] = ' '; - } - - //remarked by KD8CEC - //already RX/TX status display, and over index (16 x 2 LCD) - //if (inTx) - // strcat(c, " TX"); - printLine(1, c); - - byte diplayVFOLine = 1; - if ((displayOption1 & 0x01) == 0x01) - diplayVFOLine = 0; - - if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) || - (vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) { - lcd.setCursor(5,diplayVFOLine); - lcd.write((uint8_t)0); - } - else if (isCWAutoMode == 2){ - lcd.setCursor(5,diplayVFOLine); - lcd.write(0x7E); - } - else - { - lcd.setCursor(5,diplayVFOLine); - lcd.write(":"); - } -} - int enc_prev_state = 3; /** From 5f906a4497233c9f963eb5ceb3f4526e2185a4be Mon Sep 17 00:00:00 2001 From: phdlee Date: Thu, 5 Apr 2018 22:16:54 +0900 Subject: [PATCH 6/9] To Support various LCD Type --- ubitx_20/cw_autokey.ino | 15 +- ubitx_20/ubitx_20.ino | 33 +- ubitx_20/ubitx_lcd_1602i.ino | 561 ++++++++++++++++++ .../{ubitx_idle.ino => ubitx_lcd_1602p.ino} | 42 +- ubitx_20/ubitx_lcd_2404i.ino | 22 + ubitx_20/ubitx_lcd_2404p.ino | 22 + 6 files changed, 663 insertions(+), 32 deletions(-) create mode 100644 ubitx_20/ubitx_lcd_1602i.ino rename ubitx_20/{ubitx_idle.ino => ubitx_lcd_1602p.ino} (92%) create mode 100644 ubitx_20/ubitx_lcd_2404i.ino create mode 100644 ubitx_20/ubitx_lcd_2404p.ino diff --git a/ubitx_20/cw_autokey.ino b/ubitx_20/cw_autokey.ino index 4d2d93f..f5fcbde 100644 --- a/ubitx_20/cw_autokey.ino +++ b/ubitx_20/cw_autokey.ino @@ -299,13 +299,14 @@ void controlAutoCW(){ printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ, 0); - byte diplayAutoCWLine = 0; - if ((displayOption1 & 0x01) == 0x01) - diplayAutoCWLine = 1; - - lcd.setCursor(0, diplayAutoCWLine); - lcd.write(byteToChar(selectedCWTextIndex)); - lcd.write(':'); + //byte diplayAutoCWLine = 0; + //if ((displayOption1 & 0x01) == 0x01) + // diplayAutoCWLine = 1; + + Display_AutoKeyTextIndex(selectedCWTextIndex); + //lcd.setCursor(0, diplayAutoCWLine); + //lcd.write(byteToChar(selectedCWTextIndex)); + //lcd.write(':'); isNeedScroll = (cwEndIndex - cwStartIndex) > 14 ? 1 : 0; scrollDispayTime = millis() + scrollSpeed; beforeCWTextIndex = selectedCWTextIndex; diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index 08b24d2..fc2c584 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -2,6 +2,16 @@ #define FIRMWARE_VERSION_INFO F("CE v1.070") #define FIRMWARE_VERSION_NUM 0x02 //1st Complete Project : 1 (Version 1.061), 2st Project : 2 +//Depending on the type of LCD mounted on the uBITX, uncomment one of the options below. +//You must select only one. + +//#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX +#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD +//#define UBITX_DISPLAY_LCD2404P //24 x 04 LCD +//#define UBITX_DISPLAY_LCD2404I //I2C type 24 x 04 LCD + + + /** Cat Suppoort uBITX CEC Version Most features(TX, Frequency Range, Ham Band, TX Control, CW delay, start Delay... more) have been added by KD8CEC. @@ -91,24 +101,6 @@ #define ANALOG_SPARE (A7) #define ANALOG_SMETER (A7) //by KD8CEC -/** - * The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors: - * - * First, is an 8 pin connector that provides +5v, GND and six analog input pins that can also be - * configured to be used as digital input or output pins. These are referred to as A0,A1,A2, - * A3,A6 and A7 pins. The A4 and A5 pins are missing from this connector as they are used to - * talk to the Si5351 over I2C protocol. - * - * Second is a 16 pin LCD connector. This connector is meant specifically for the standard 16x2 - * LCD display in 4 bit mode. The 4 bit mode requires 4 data lines and two control lines to work: - * Lines used are : RESET, ENABLE, D4, D5, D6, D7 - * We include the library and declare the configuration of the LCD panel too - */ - -#include -LiquidCrystal lcd(8,9,10,11,12,13); - - /** * 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 @@ -120,8 +112,6 @@ LiquidCrystal lcd(8,9,10,11,12,13); * the input and output from the USB port. We must keep a count of the bytes used while reading * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. */ -char c[30], b[30]; -char printBuff[2][17]; //mirrors what is showing on the two lines of the display int count = 0; //to generally count ticks, loops, etc /** @@ -1133,11 +1123,10 @@ void setup() */ //Serial.begin(9600); - lcd.begin(16, 2); + LCD_Init(); printLineF(1, FIRMWARE_VERSION_INFO); Init_Cat(38400, SERIAL_8N1); - initMeter(); //not used in this build initSettings(); if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) { diff --git a/ubitx_20/ubitx_lcd_1602i.ino b/ubitx_20/ubitx_lcd_1602i.ino new file mode 100644 index 0000000..7b56eaf --- /dev/null +++ b/ubitx_20/ubitx_lcd_1602i.ino @@ -0,0 +1,561 @@ +/************************************************************************* + KD8CEC, _______ + uBITX Display Routine for LCD1602 I2C + + 1.Code for 16 x 2 LCD for I2C. + 2.Display related functions of uBITX. Some functions moved from uBITX_Ui. + 3.uBITX Idle time Processing + Functions that run at times that do not affect TX, CW, and CAT + It is called in 1/10 time unit. +----------------------------------------------------------------------------- + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +**************************************************************************/ +#ifdef UBITX_DISPLAY_LCD1602I + + + +/** + * The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors: + * + * First, is an 8 pin connector that provides +5v, GND and six analog input pins that can also be + * configured to be used as digital input or output pins. These are referred to as A0,A1,A2, + * A3,A6 and A7 pins. The A4 and A5 pins are missing from this connector as they are used to + * talk to the Si5351 over I2C protocol. + * + * Second is a 16 pin LCD connector. This connector is meant specifically for the standard 16x2 + * LCD display in 4 bit mode. The 4 bit mode requires 4 data lines and two control lines to work: + * Lines used are : RESET, ENABLE, D4, D5, D6, D7 + * We include the library and declare the configuration of the LCD panel too + */ + +#include +LiquidCrystal lcd(8,9,10,11,12,13); + +char c[30], b[30]; +char printBuff[2][17]; //mirrors what is showing on the two lines of the display + +void LCD_Init(void) +{ + lcd.begin(16, 2); + initMeter(); //for Meter Display +} + +void Display_AutoKeyTextIndex(char textIndex) +{ + byte diplayAutoCWLine = 0; + + if ((displayOption1 & 0x01) == 0x01) + diplayAutoCWLine = 1; + lcd.setCursor(0, diplayAutoCWLine); + lcd.write(byteToChar(selectedCWTextIndex)); + lcd.write(':'); +} + + +//======================================================================== +//Display Routine +//======================================================================== +const PROGMEM uint8_t meters_bitmap[] = { + B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1 + B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2 + B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100 , //custom 3 + B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110 , //custom 4 + B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 , //custom 5 + B01000, B11100, B01000, B00000, B10111, B10101, B10101, B10111 //custom 6 +}; + +PGM_P p_metes_bitmap = reinterpret_cast(meters_bitmap); + +const PROGMEM uint8_t lock_bitmap[8] = { + 0b01110, + 0b10001, + 0b10001, + 0b11111, + 0b11011, + 0b11011, + 0b11111, + 0b00000}; +PGM_P plock_bitmap = reinterpret_cast(lock_bitmap); + + +// initializes the custom characters +// we start from char 1 as char 0 terminates the string! +void initMeter(){ + uint8_t tmpbytes[8]; + byte i; + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(plock_bitmap + i); + lcd.createChar(0, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i); + lcd.createChar(1, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8); + lcd.createChar(2, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16); + lcd.createChar(3, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24); + lcd.createChar(4, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32); + lcd.createChar(5, tmpbytes); + + for (i = 0; i < 8; i++) + tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40); + lcd.createChar(6, tmpbytes); +} + +//by KD8CEC +//0 ~ 25 : 30 over : + 10 +void drawMeter(int needle) { + //5Char + O over + int i; + + for (i = 0; i < 5; i++) { + if (needle >= 5) + lcdMeter[i] = 5; //full + else if (needle > 0) + lcdMeter[i] = needle; //full + else //0 + lcdMeter[i] = 0x20; + + needle -= 5; + } + + if (needle > 0) + lcdMeter[5] = 6; + else + lcdMeter[5] = 0x20; +} + + + +// The generic routine to display one line on the LCD +void printLine(unsigned char linenmbr, const char *c) { + if ((displayOption1 & 0x01) == 0x01) + linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle + + if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change + lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line + lcd.print(c); + strcpy(printBuff[linenmbr], c); + + for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached + lcd.print(' '); + } + } +} + +void printLineF(char linenmbr, const __FlashStringHelper *c) +{ + int i; + char tmpBuff[17]; + PGM_P p = reinterpret_cast(c); + + for (i = 0; i < 17; i++){ + unsigned char fChar = pgm_read_byte(p++); + tmpBuff[i] = fChar; + if (fChar == 0) + break; + } + + printLine(linenmbr, tmpBuff); +} + +#define LCD_MAX_COLUMN 16 +void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) { + if ((displayOption1 & 0x01) == 0x01) + linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle + + lcd.setCursor(lcdColumn, linenmbr); + + for (byte i = eepromStartIndex; i <= eepromEndIndex; i++) + { + if (++lcdColumn <= LCD_MAX_COLUMN) + lcd.write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i)); + else + break; + } + + for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space + lcd.write(' '); +} + +// short cut to print to the first line +void printLine1(const char *c){ + printLine(1,c); +} +// short cut to print to the first line +void printLine2(const char *c){ + printLine(0,c); +} + +void clearLine2() +{ + printLine2(""); + line2DisplayStatus = 0; +} + +// short cut to print to the first line +void printLine1Clear(){ + printLine(1,""); +} +// short cut to print to the first line +void printLine2Clear(){ + printLine(0, ""); +} + +void printLine2ClearAndUpdate(){ + printLine(0, ""); + line2DisplayStatus = 0; + updateDisplay(); +} + +//012...89ABC...Z +char byteToChar(byte srcByte){ + if (srcByte < 10) + return 0x30 + srcByte; + else + return 'A' + srcByte - 10; +} + +// this builds up the top line of the display with frequency and mode +void updateDisplay() { + // tks Jack Purdum W8TEE + // replaced fsprint commmands by str commands for code size reduction + // replace code for Frequency numbering error (alignment, point...) by KD8CEC + int i; + unsigned long tmpFreq = frequency; // + + memset(c, 0, sizeof(c)); + + if (inTx){ + if (isCWAutoMode == 2) { + for (i = 0; i < 4; i++) + c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' '); + + //display Sending Index + c[4] = byteToChar(sendingCWTextIndex); + c[5] = '='; + } + else { + if (cwTimeout > 0) + strcpy(c, " CW:"); + else + strcpy(c, " TX:"); + } + } + else { + if (ritOn) + strcpy(c, "RIT "); + else { + if (cwMode == 0) + { + if (isUSB) + strcpy(c, "USB "); + else + strcpy(c, "LSB "); + } + else if (cwMode == 1) + { + strcpy(c, "CWL "); + } + else + { + strcpy(c, "CWU "); + } + } + if (vfoActive == VFO_A) // VFO A is active + strcat(c, "A:"); + else + strcat(c, "B:"); + } + + //Fixed by Mitani Massaru (JE4SMQ) + if (isShiftDisplayCWFreq == 1) + { + if (cwMode == 1) //CWL + tmpFreq = tmpFreq - sideTone + shiftDisplayAdjustVal; + else if (cwMode == 2) //CWU + tmpFreq = tmpFreq + sideTone + shiftDisplayAdjustVal; + } + + //display frequency + 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] = ' '; + } + + //remarked by KD8CEC + //already RX/TX status display, and over index (16 x 2 LCD) + //if (inTx) + // strcat(c, " TX"); + printLine(1, c); + + byte diplayVFOLine = 1; + if ((displayOption1 & 0x01) == 0x01) + diplayVFOLine = 0; + + if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) || + (vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) { + lcd.setCursor(5,diplayVFOLine); + lcd.write((uint8_t)0); + } + else if (isCWAutoMode == 2){ + lcd.setCursor(5,diplayVFOLine); + lcd.write(0x7E); + } + else + { + lcd.setCursor(5,diplayVFOLine); + lcd.write(":"); + } +} + + + +char line2Buffer[16]; +//KD8CEC 200Hz ST +//L14.150 200Hz ST +//U14.150 +150khz +int freqScrollPosition = 0; +//Example Line2 Optinal Display +//immediate execution, not call by scheulder +void updateLine2Buffer(char displayType) +{ + unsigned long tmpFreq = 0; + if (ritOn) + { + strcpy(line2Buffer, "RitTX:"); + + //display frequency + tmpFreq = ritTxFrequency; + for (int i = 15; i >= 6; i--) { + if (tmpFreq > 0) { + if (i == 12 || i == 8) line2Buffer[i] = '.'; + else { + line2Buffer[i] = tmpFreq % 10 + 0x30; + tmpFreq /= 10; + } + } + else + line2Buffer[i] = ' '; + } + + return; + } //end of ritOn display + + //====================================================== + //other VFO display + //====================================================== + if (vfoActive == VFO_B) + { + tmpFreq = vfoA; + } + else + { + tmpFreq = vfoB; + } + + // EXAMPLE 1 & 2 + //U14.150.100 + //display frequency + for (int i = 9; i >= 0; i--) { + if (tmpFreq > 0) { + if (i == 2 || i == 6) line2Buffer[i] = '.'; + else { + line2Buffer[i] = tmpFreq % 10 + 0x30; + tmpFreq /= 10; + } + } + else + line2Buffer[i] = ' '; + } + + //EXAMPLE #1 + if ((displayOption1 & 0x04) == 0x00) //none scroll display + line2Buffer[6] = 'k'; + else + { + //example #2 + if (freqScrollPosition++ > 18) //none scroll display time + { + line2Buffer[6] = 'k'; + if (freqScrollPosition > 25) + freqScrollPosition = -1; + } + else //scroll frequency + { + line2Buffer[10] = 'H'; + line2Buffer[11] = 'z'; + + if (freqScrollPosition < 7) + { + for (int i = 11; i >= 0; i--) + if (i - (7 - freqScrollPosition) >= 0) + line2Buffer[i] = line2Buffer[i - (7 - freqScrollPosition)]; + else + line2Buffer[i] = ' '; + } + else + { + for (int i = 0; i < 11; i++) + if (i + (freqScrollPosition - 7) <= 11) + line2Buffer[i] = line2Buffer[i + (freqScrollPosition - 7)]; + else + line2Buffer[i] = ' '; + } + } + } //scroll + + line2Buffer[7] = ' '; + + if (isIFShift) + { +// if (isDirectCall == 1) +// for (int i = 0; i < 16; i++) +// line2Buffer[i] = ' '; + + //IFShift Offset Value + line2Buffer[8] = 'I'; + line2Buffer[9] = 'F'; + + line2Buffer[10] = ifShiftValue >= 0 ? '+' : 0; + line2Buffer[11] = 0; + line2Buffer[12] = ' '; + + //11, 12, 13, 14, 15 + memset(b, 0, sizeof(b)); + ltoa(ifShiftValue, b, DEC); + strncat(line2Buffer, b, 5); + + //if (isDirectCall == 1) //if call by encoder (not scheduler), immediate print value + printLine2(line2Buffer); + } // end of display IF + else // step & Key Type display + { + //if (isDirectCall != 0) + // return; + + memset(&line2Buffer[8], ' ', 8); + //Step + long tmpStep = arTuneStep[tuneStepIndex -1]; + + byte isStepKhz = 0; + if (tmpStep >= 1000) + { + isStepKhz = 2; + } + + for (int i = 10; i >= 8 - isStepKhz; i--) { + if (tmpStep > 0) { + line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; + tmpStep /= 10; + } + else + line2Buffer[i +isStepKhz] = ' '; + } + + if (isStepKhz == 0) + { + line2Buffer[11] = 'H'; + line2Buffer[12] = 'z'; + } + + line2Buffer[13] = ' '; + + //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb + if (cwKeyType == 0) + { + line2Buffer[14] = 'S'; + line2Buffer[15] = 'T'; + } + else if (cwKeyType == 1) + { + line2Buffer[14] = 'I'; + line2Buffer[15] = 'A'; + } + else + { + line2Buffer[14] = 'I'; + line2Buffer[15] = 'B'; + } + } +} + +//meterType : 0 = S.Meter, 1 : P.Meter +void DisplayMeter(byte meterType, byte meterValue, char drawPosition) +{ + if (meterType == 0 || meterType == 1 || meterType == 2) + { + drawMeter(meterValue); //call original source code + int lineNumber = 0; + if ((displayOption1 & 0x01) == 0x01) + lineNumber = 1; + + lcd.setCursor(drawPosition, lineNumber); + + for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 + lcd.write(lcdMeter[i]); + } +} + +byte testValue = 0; +char checkCount = 0; +void idle_process() +{ + //space for user graphic display + if (menuOn == 0) + { + if ((displayOption1 & 0x10) == 0x10) //always empty topline + return; + + //if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message + if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) { + if (checkCount++ > 1) + { + updateLine2Buffer(0); //call by scheduler + printLine2(line2Buffer); + line2DisplayStatus = 2; + checkCount = 0; + } + + //EX for Meters + /* + DisplayMeter(0, testValue++, 7); + if (testValue > 30) + testValue = 0; + */ + } + } +} + + +#endif diff --git a/ubitx_20/ubitx_idle.ino b/ubitx_20/ubitx_lcd_1602p.ino similarity index 92% rename from ubitx_20/ubitx_idle.ino rename to ubitx_20/ubitx_lcd_1602p.ino index bee7c2f..b37bb45 100644 --- a/ubitx_20/ubitx_idle.ino +++ b/ubitx_20/ubitx_lcd_1602p.ino @@ -1,7 +1,10 @@ /************************************************************************* - KD8CEC's uBITX Idle time Processing - Functions that run at times that do not affect TX, CW, and CAT - It is called in 1/10 time unit. + KD8CEC's uBITX Display Routine for LCD1602 Parrel + 1.This is the display code for the default LCD mounted in uBITX. + 2.Display related functions of uBITX. Some functions moved from uBITX_Ui. + 3.uBITX Idle time Processing + Functions that run at times that do not affect TX, CW, and CAT + It is called in 1/10 time unit. ----------------------------------------------------------------------------- This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,6 +20,37 @@ along with this program. If not, see . **************************************************************************/ +#ifdef UBITX_DISPLAY_LCD1602P + + +//========================================================================= +//Hardware Control routines +//========================================================================= + + +#include +LiquidCrystal lcd(8,9,10,11,12,13); + +char c[30], b[30]; +char printBuff[2][17]; //mirrors what is showing on the two lines of the display + +void LCD_Init(void) +{ + lcd.begin(16, 2); + initMeter(); //for Meter Display +} + +void Display_AutoKeyTextIndex(char textIndex) +{ + byte diplayAutoCWLine = 0; + + if ((displayOption1 & 0x01) == 0x01) + diplayAutoCWLine = 1; + lcd.setCursor(0, diplayAutoCWLine); + lcd.write(byteToChar(selectedCWTextIndex)); + lcd.write(':'); +} + //======================================================================== //Display Routine @@ -511,3 +545,5 @@ void idle_process() } } + +#endif diff --git a/ubitx_20/ubitx_lcd_2404i.ino b/ubitx_20/ubitx_lcd_2404i.ino new file mode 100644 index 0000000..bee57ab --- /dev/null +++ b/ubitx_20/ubitx_lcd_2404i.ino @@ -0,0 +1,22 @@ +/************************************************************************* + KD8CEC's uBITX Display Routine for LCD2404 I2C + uBITX Idle time Processing + Functions that run at times that do not affect TX, CW, and CAT + It is called in 1/10 time unit. +----------------------------------------------------------------------------- + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +**************************************************************************/ + + diff --git a/ubitx_20/ubitx_lcd_2404p.ino b/ubitx_20/ubitx_lcd_2404p.ino new file mode 100644 index 0000000..66c9868 --- /dev/null +++ b/ubitx_20/ubitx_lcd_2404p.ino @@ -0,0 +1,22 @@ +/************************************************************************* + KD8CEC's uBITX Display Routine for LCD2404 Parrel + uBITX Idle time Processing + Functions that run at times that do not affect TX, CW, and CAT + It is called in 1/10 time unit. +----------------------------------------------------------------------------- + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +**************************************************************************/ + + From d4ed0589e592ee13fe0aff64faf005c3773b74ce Mon Sep 17 00:00:00 2001 From: phdlee Date: Thu, 5 Apr 2018 22:57:07 +0900 Subject: [PATCH 7/9] Applied 1602 Tiny LCD Library for reduce program Memory --- ubitx_20/ubitx_lcd_1602i.ino | 81 +++++------ ubitx_20/ubitx_lcd_1602p.ino | 263 +++++++++++++++++++++++++++-------- ubitx_20/ubitx_ui.ino | 7 + 3 files changed, 247 insertions(+), 104 deletions(-) diff --git a/ubitx_20/ubitx_lcd_1602i.ino b/ubitx_20/ubitx_lcd_1602i.ino index 7b56eaf..c8546f0 100644 --- a/ubitx_20/ubitx_lcd_1602i.ino +++ b/ubitx_20/ubitx_lcd_1602i.ino @@ -25,48 +25,23 @@ #ifdef UBITX_DISPLAY_LCD1602I - -/** - * The Raduino board is the size of a standard 16x2 LCD panel. It has three connectors: - * - * First, is an 8 pin connector that provides +5v, GND and six analog input pins that can also be - * configured to be used as digital input or output pins. These are referred to as A0,A1,A2, - * A3,A6 and A7 pins. The A4 and A5 pins are missing from this connector as they are used to - * talk to the Si5351 over I2C protocol. - * - * Second is a 16 pin LCD connector. This connector is meant specifically for the standard 16x2 - * LCD display in 4 bit mode. The 4 bit mode requires 4 data lines and two control lines to work: - * Lines used are : RESET, ENABLE, D4, D5, D6, D7 - * We include the library and declare the configuration of the LCD panel too - */ - +//======================================================================== +//Begin of LCD Hardware define +//======================================================================== #include LiquidCrystal lcd(8,9,10,11,12,13); + +//======================================================================== +//End of LCD Hardware define +//======================================================================== + +//======================================================================== +//Begin of Display Base Routines (Init, printLine..) +//======================================================================== char c[30], b[30]; char printBuff[2][17]; //mirrors what is showing on the two lines of the display -void LCD_Init(void) -{ - lcd.begin(16, 2); - initMeter(); //for Meter Display -} - -void Display_AutoKeyTextIndex(char textIndex) -{ - byte diplayAutoCWLine = 0; - - if ((displayOption1 & 0x01) == 0x01) - diplayAutoCWLine = 1; - lcd.setCursor(0, diplayAutoCWLine); - lcd.write(byteToChar(selectedCWTextIndex)); - lcd.write(':'); -} - - -//======================================================================== -//Display Routine -//======================================================================== const PROGMEM uint8_t meters_bitmap[] = { B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1 B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2 @@ -125,6 +100,12 @@ void initMeter(){ lcd.createChar(6, tmpbytes); } +void LCD_Init(void) +{ + lcd.begin(16, 2); + initMeter(); //for Meter Display +} + //by KD8CEC //0 ~ 25 : 30 over : + 10 void drawMeter(int needle) { @@ -161,7 +142,7 @@ void printLine(unsigned char linenmbr, const char *c) { strcpy(printBuff[linenmbr], c); for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached - lcd.print(' '); + lcd.write(' '); } } } @@ -230,14 +211,13 @@ void printLine2ClearAndUpdate(){ line2DisplayStatus = 0; updateDisplay(); } +//=================================================================================== +//End of Display Base Routines +//=================================================================================== -//012...89ABC...Z -char byteToChar(byte srcByte){ - if (srcByte < 10) - return 0x30 + srcByte; - else - return 'A' + srcByte - 10; -} +//=================================================================================== +//Begin of User Interface Routines +//=================================================================================== // this builds up the top line of the display with frequency and mode void updateDisplay() { @@ -335,7 +315,7 @@ void updateDisplay() { else { lcd.setCursor(5,diplayVFOLine); - lcd.write(":"); + lcd.write(':'); } } @@ -557,5 +537,16 @@ void idle_process() } } +void Display_AutoKeyTextIndex(char textIndex) +{ + byte diplayAutoCWLine = 0; + + if ((displayOption1 & 0x01) == 0x01) + diplayAutoCWLine = 1; + lcd.setCursor(0, diplayAutoCWLine); + lcd.write(byteToChar(selectedCWTextIndex)); + lcd.write(':'); +} + #endif diff --git a/ubitx_20/ubitx_lcd_1602p.ino b/ubitx_20/ubitx_lcd_1602p.ino index b37bb45..607d070 100644 --- a/ubitx_20/ubitx_lcd_1602p.ino +++ b/ubitx_20/ubitx_lcd_1602p.ino @@ -23,38 +23,166 @@ #ifdef UBITX_DISPLAY_LCD1602P -//========================================================================= -//Hardware Control routines -//========================================================================= +//======================================================================== +//Begin of TinyLCD Library by KD8CEC +//======================================================================== +/************************************************************************* + LCD1602_TINY Library for 16 x 2 LCD + Referecnce Source : LiquidCrystal.cpp + KD8CEC + This source code is modified version for small program memory + from Arduino LiquidCrystal Library + I wrote this code myself, so there is no license restriction. + So this code allows anyone to write with confidence. + But keep it as long as the original author of the code. + DE Ian KD8CEC +**************************************************************************/ +#define LCD_Command(x) (LCD_Send(x, LOW)) +#define LCD_Write(x) (LCD_Send(x, HIGH)) + +//Define connected PIN +#define LCD_PIN_RS 8 +#define LCD_PIN_EN 9 +uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; + +// commands +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off control +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 + +void write4bits(uint8_t value) +{ + for (int i = 0; i < 4; i++) + digitalWrite(LCD_PIN_DAT[i], (value >> i) & 0x01); + + digitalWrite(LCD_PIN_EN, LOW); + delayMicroseconds(1); + digitalWrite(LCD_PIN_EN, HIGH); + delayMicroseconds(1); // enable pulse must be >450ns + digitalWrite(LCD_PIN_EN, LOW); + delayMicroseconds(100); // commands need > 37us to settle +} + +void LCD_Send(uint8_t value, uint8_t mode) +{ + digitalWrite(LCD_PIN_RS, mode); + write4bits(value>>4); + write4bits(value); +} + +void LCD1602_Init() +{ + pinMode(LCD_PIN_RS, OUTPUT); + pinMode(LCD_PIN_EN, OUTPUT); + for (int i = 0; i < 4; i++) + pinMode(LCD_PIN_DAT[i], OUTPUT); + + delayMicroseconds(50); + + // Now we pull both RS and R/W low to begin commands + digitalWrite(LCD_PIN_RS, LOW); + digitalWrite(LCD_PIN_EN, LOW); + + // we start in 8bit mode, try to set 4 bit mode + write4bits(0x03); + delayMicroseconds(4500); // wait min 4.1ms + + // second try + write4bits(0x03); + delayMicroseconds(4500); // wait min 4.1ms + + // third go! + write4bits(0x03); + delayMicroseconds(150); + + // finally, set to 4-bit interface + write4bits(0x02); + + // finally, set # lines, font size, etc. + LCD_Command(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | LCD_2LINE); + + // turn the display on with no cursor or blinking default + LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF); + + // clear it off + LCD_Command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero + delayMicroseconds(2000); // this command takes a long time! + + LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); +} + +void LCD_Print(const char *c) +{ + for (int i = 0; i < strlen(c); i++) + { + if (*(c + i) == 0x00) return; + LCD_Write(*(c + i)); + } +} + +void LCD_SetCursor(uint8_t col, uint8_t row) +{ + LCD_Command(LCD_SETDDRAMADDR | (col + row * 0x40)); //0 : 0x00, 1 : 0x40, only for 16 x 2 lcd +} + +void LCD_CreateChar(uint8_t location, uint8_t charmap[]) +{ + location &= 0x7; // we only have 8 locations 0-7 + LCD_Command(LCD_SETCGRAMADDR | (location << 3)); + for (int i=0; i<8; i++) + LCD_Write(charmap[i]); +} +//======================================================================== +//End of TinyLCD Library by KD8CEC +//======================================================================== + +/* #include LiquidCrystal lcd(8,9,10,11,12,13); +*/ + +//======================================================================== +//Begin of Display Base Routines (Init, printLine..) +//======================================================================== char c[30], b[30]; char printBuff[2][17]; //mirrors what is showing on the two lines of the display -void LCD_Init(void) -{ - lcd.begin(16, 2); - initMeter(); //for Meter Display -} - -void Display_AutoKeyTextIndex(char textIndex) -{ - byte diplayAutoCWLine = 0; - - if ((displayOption1 & 0x01) == 0x01) - diplayAutoCWLine = 1; - lcd.setCursor(0, diplayAutoCWLine); - lcd.write(byteToChar(selectedCWTextIndex)); - lcd.write(':'); -} - - -//======================================================================== -//Display Routine -//======================================================================== const PROGMEM uint8_t meters_bitmap[] = { B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000 , //custom 1 B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 , //custom 2 @@ -86,31 +214,37 @@ void initMeter(){ for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(plock_bitmap + i); - lcd.createChar(0, tmpbytes); + LCD_CreateChar(0, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i); - lcd.createChar(1, tmpbytes); + LCD_CreateChar(1, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 8); - lcd.createChar(2, tmpbytes); + LCD_CreateChar(2, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 16); - lcd.createChar(3, tmpbytes); + LCD_CreateChar(3, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 24); - lcd.createChar(4, tmpbytes); + LCD_CreateChar(4, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 32); - lcd.createChar(5, tmpbytes); + LCD_CreateChar(5, tmpbytes); for (i = 0; i < 8; i++) tmpbytes[i] = pgm_read_byte(p_metes_bitmap + i + 40); - lcd.createChar(6, tmpbytes); + LCD_CreateChar(6, tmpbytes); +} + +void LCD_Init(void) +{ + LCD1602_Init(); + initMeter(); //for Meter Display } //by KD8CEC @@ -136,20 +270,17 @@ void drawMeter(int needle) { lcdMeter[5] = 0x20; } - - // The generic routine to display one line on the LCD void printLine(unsigned char linenmbr, const char *c) { if ((displayOption1 & 0x01) == 0x01) linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle - if (strcmp(c, printBuff[linenmbr])) { // only refresh the display when there was a change - lcd.setCursor(0, linenmbr); // place the cursor at the beginning of the selected line - lcd.print(c); + LCD_SetCursor(0, linenmbr); // place the cursor at the beginning of the selected line + LCD_Print(c); strcpy(printBuff[linenmbr], c); for (byte i = strlen(c); i < 16; i++) { // add white spaces until the end of the 16 characters line is reached - lcd.print(' '); + LCD_Write(' '); } } } @@ -175,26 +306,28 @@ void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, b if ((displayOption1 & 0x01) == 0x01) linenmbr = (linenmbr == 0 ? 1 : 0); //Line Toggle - lcd.setCursor(lcdColumn, linenmbr); + LCD_SetCursor(lcdColumn, linenmbr); for (byte i = eepromStartIndex; i <= eepromEndIndex; i++) { if (++lcdColumn <= LCD_MAX_COLUMN) - lcd.write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i)); + LCD_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i)); else break; } for (byte i = lcdColumn; i < 16; i++) //Right Padding by Space - lcd.write(' '); + LCD_Write(' '); } // short cut to print to the first line -void printLine1(const char *c){ +void printLine1(const char *c) +{ printLine(1,c); } // short cut to print to the first line -void printLine2(const char *c){ +void printLine2(const char *c) +{ printLine(0,c); } @@ -219,14 +352,16 @@ void printLine2ClearAndUpdate(){ updateDisplay(); } -//012...89ABC...Z -char byteToChar(byte srcByte){ - if (srcByte < 10) - return 0x30 + srcByte; - else - return 'A' + srcByte - 10; -} +//================================================================================== +//End of Display Base Routines +//================================================================================== + +//================================================================================== +//Begin of User Interface Routines +//================================================================================== + +//Main Display // this builds up the top line of the display with frequency and mode void updateDisplay() { // tks Jack Purdum W8TEE @@ -313,17 +448,17 @@ void updateDisplay() { if ((vfoActive == VFO_A && ((isDialLock & 0x01) == 0x01)) || (vfoActive == VFO_B && ((isDialLock & 0x02) == 0x02))) { - lcd.setCursor(5,diplayVFOLine); - lcd.write((uint8_t)0); + LCD_SetCursor(5,diplayVFOLine); + LCD_Write((uint8_t)0); } else if (isCWAutoMode == 2){ - lcd.setCursor(5,diplayVFOLine); - lcd.write(0x7E); + LCD_SetCursor(5,diplayVFOLine); + LCD_Write(0x7E); } else { - lcd.setCursor(5,diplayVFOLine); - lcd.write(":"); + LCD_SetCursor(5,diplayVFOLine); + LCD_Write(':'); } } @@ -360,9 +495,7 @@ void updateLine2Buffer(char displayType) return; } //end of ritOn display - //====================================================== //other VFO display - //====================================================== if (vfoActive == VFO_B) { tmpFreq = vfoA; @@ -508,10 +641,10 @@ void DisplayMeter(byte meterType, byte meterValue, char drawPosition) if ((displayOption1 & 0x01) == 0x01) lineNumber = 1; - lcd.setCursor(drawPosition, lineNumber); + LCD_SetCursor(drawPosition, lineNumber); for (int i = 0; i < 6; i++) //meter 5 + +db 1 = 6 - lcd.write(lcdMeter[i]); + LCD_Write(lcdMeter[i]); } } @@ -545,5 +678,17 @@ void idle_process() } } +//AutoKey LCD Display Routine +void Display_AutoKeyTextIndex(char textIndex) +{ + byte diplayAutoCWLine = 0; + + if ((displayOption1 & 0x01) == 0x01) + diplayAutoCWLine = 1; + LCD_SetCursor(0, diplayAutoCWLine); + LCD_Write(byteToChar(selectedCWTextIndex)); + LCD_Write(':'); +} + #endif diff --git a/ubitx_20/ubitx_ui.ino b/ubitx_20/ubitx_ui.ino index 27d570f..4907282 100644 --- a/ubitx_20/ubitx_ui.ino +++ b/ubitx_20/ubitx_ui.ino @@ -6,6 +6,13 @@ * quickly cleared up. */ + char byteToChar(byte srcByte){ + if (srcByte < 10) + return 0x30 + srcByte; + else + return 'A' + srcByte - 10; +} + //returns true if the button is pressed int btnDown(void){ if (digitalRead(FBUTTON) == HIGH) From 23f1b7cd5cb7ee31966cd02c25708088f7620e55 Mon Sep 17 00:00:00 2001 From: phdlee Date: Fri, 6 Apr 2018 21:43:36 +0900 Subject: [PATCH 8/9] Added IF Tune, ATT, SDR Functions --- ubitx_20/ubitx_20.ino | 38 ++++++++++- ubitx_20/ubitx_menu.ino | 129 ++++++++++++++++++++++++++++---------- ubitx_20/ubitx_si5351.ino | 2 +- 3 files changed, 134 insertions(+), 35 deletions(-) diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index fc2c584..3b674b7 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -5,11 +5,12 @@ //Depending on the type of LCD mounted on the uBITX, uncomment one of the options below. //You must select only one. -//#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX -#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD +#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX +//#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD //#define UBITX_DISPLAY_LCD2404P //24 x 04 LCD //#define UBITX_DISPLAY_LCD2404I //I2C type 24 x 04 LCD +//#define ENABLE_FACTORYALIGN /** @@ -326,6 +327,11 @@ 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 +byte attLevel = 0; //ATT : RF Gain Control (Receive) <-- IF1 Shift, 0 : Off, ShiftValue is attLevel * 100; attLevel 150 = 15K +char if1TuneValue = 0; //0 : OFF, IF1 + if1TuneValue * 100; // + - 12500; +byte sdrModeOn = 0; //SDR MODE ON / OFF +unsigned long SDR_Center_Freq = 32000000; + unsigned long beforeIdle_ProcessTime = 0; //for check Idle time byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle, char lcdMeter[17]; @@ -495,7 +501,32 @@ void setFrequency(unsigned long f){ setTXFilters(f); unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0)); + long if1AdjustValue = ((inTx == 0) ? (attLevel * 200) : 0) + (if1TuneValue * 50); //if1Tune RX, TX Enabled, ATT : only RX Mode + if (sdrModeOn && (inTx == 0)) //IF SDR + { + si5351bx_setfreq(2, 44999500 + if1AdjustValue + f); + si5351bx_setfreq(1, 44999500 + if1AdjustValue + SDR_Center_Freq + 2390); + } + else + { + if (cwMode == 1 || (cwMode == 0 && (!isUSB))) + { + //CWL(cwMode == 1) or LSB (cwMode == 0 && (!isUSB)) + si5351bx_setfreq(2, SECOND_OSC_LSB + if1AdjustValue + appliedCarrier + f); + //si5351bx_setfreq(1, SECOND_OSC_LSB + if1AdjustValue - (sdrModeOn ? (SDR_Center_Freq- usbCarrier) : 0)); + si5351bx_setfreq(1, SECOND_OSC_LSB + if1AdjustValue); + } + else + { + //CWU (cwMode == 2) or LSB (cwMode == 0 and isUSB) + si5351bx_setfreq(2, SECOND_OSC_USB + if1AdjustValue - appliedCarrier + f); + //si5351bx_setfreq(1, SECOND_OSC_USB + if1AdjustValue + (sdrModeOn ? (SDR_Center_Freq- usbCarrier) : 0)); //Increase LO Frequency => 1198500 -> 32Mhz + si5351bx_setfreq(1, SECOND_OSC_USB + if1AdjustValue); //Increase LO Frequency => 1198500 -> 32Mhz + } + } + + /* if (cwMode == 0) { if (isUSB){ @@ -518,6 +549,7 @@ void setFrequency(unsigned long f){ si5351bx_setfreq(1, SECOND_OSC_USB); } } + */ frequency = f; } @@ -1150,8 +1182,10 @@ void setup() setFrequency(vfoA); updateDisplay(); +#ifdef ENABLE_FACTORYALIGN if (btnDown()) factory_alignment(); +#endif } //Auto save Frequency and Mode with Protected eeprom life by KD8CEC diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index 5d82b51..07160ee 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -441,6 +441,37 @@ void menuTxOnOff(int btn, byte optionType){ } } +//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("[OFF]")); + } + else { + sdrModeOn = 1; + + if (ritOn == 1) + ritOn = 0; + + if (splitOn == 1) + splitOn = 0; + + printLineF2(F("[ON]")); + } + + setFrequency(frequency); + menuClearExit(500); + } +} + void displayEmptyData(void){ printLineF2(F("Empty data")); delay_background(2000, 0); @@ -548,9 +579,10 @@ void menuSetupCWCarrier(int btn){ //valueType 0 : Normal // 1 : CW Change -> Generate Tone // 2 : IF Shift Setup -> SetFrequency, Set SideTone -// 3 : Select Mode (different display type) +// 5 : ATT +// 11 : Select Mode (different display type) //knobSensitivity : 1 ~ -int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnobValue, int incStep, char* displayTitle, int knobSensitivity) +int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnobValue, int incStep, const char* displayTitle, int knobSensitivity) { int knob; int moveDetectStep = 0; @@ -558,7 +590,7 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob char isInitDisplay = 1; delay_background(300, 0); //Default Delay - if (valueType < 3) + if (valueType < 10) { strcpy(b, "Press, set "); strcat(b, displayTitle); @@ -597,7 +629,7 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob strcpy(b, displayTitle); - if (valueType == 3) //Mode Select + if (valueType == 11) //Mode Select { b[targetValue * 4] = '>'; } @@ -625,9 +657,13 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob { tone(CW_TONE, targetValue); } - else if (valueType == 2) + else if (valueType == 2 || valueType == 5 ) // 2:IFS, 5:ATT { - ifShiftValue = targetValue; + if (valueType == 2) + ifShiftValue = targetValue; + else + attLevel = targetValue; + setFrequency(frequency); SetCarrierFreq(); } @@ -912,6 +948,31 @@ void menuIFSSetup(int btn){ } } +//ATT SETUP (IF1(45MHZ) SHIFT), by KD8CEC +void menuATTSetup(int btn){ + int knob = 0; + char needApplyChangeValue = 1; + + if (!btn){ + if (isIFShift == 1) + printLineF2(F("ATT Change?")); + else + printLineF2(F("ATT On?")); + } + else + { + attLevel = getValueByKnob(5, attLevel, 0, 200, 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); + } +} //Functions for CWL and CWU by KD8CEC void menuSelectMode(int btn){ @@ -939,7 +1000,7 @@ void menuSelectMode(int btn){ //delay_background(500, 0); - selectModeType = getValueByKnob(3, selectModeType, 0, 3, 1, " LSB USB CWL CWU", 4); //3 : Select Mode, targetValue, minKnobValue, maxKnobValue, stepSize + selectModeType = getValueByKnob(11, selectModeType, 0, 3, 1, " LSB USB CWL CWU", 4); //3 : Select Mode, targetValue, minKnobValue, maxKnobValue, stepSize /* while(!btnDown()){ @@ -1011,8 +1072,8 @@ void menuSetupKeyType(int btn){ //delay_background(500, 0); selectedKeyType = cwKeyType; - //selectedKeyType = getValueByKnob(4, selectedKeyType, 0, 2, 1, " KEY:", 5); //4 : Select Key Type, targetValue, minKnobValue, maxKnobValue, stepSize - selectedKeyType = getValueByKnob(3, selectedKeyType, 0, 2, 1, " ST IA IB", 5); //4 : Select Key Type, targetValue, minKnobValue, maxKnobValue, stepSize + //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 /* while(!btnDown()){ @@ -1170,14 +1231,13 @@ void doMenu(){ if (i > 0){ if (modeCalibrate && select + i < 240) select += i; - if (!modeCalibrate && select + i < 130) + else if (!modeCalibrate && select + i < 150) select += i; } + else if (i < 0 && select - i >= -10) + select += i; - if (i < 0 && select - i >= -10) - select += i; //caught ya, i is already -ve here, so you add it - - //if -> switch reduce program memory 200byte + //if -> switch : reduce program memory 200byte switch (select / 10) { case 0 : @@ -1196,60 +1256,65 @@ void doMenu(){ menuIFSSetup(btnState); break; case 5 : - menuCWSpeed(btnState); + menuATTSetup(btnState); break; case 6 : - menuSplitOnOff(btnState); //SplitOn / off + menuCWSpeed(btnState); break; case 7 : - menuCHMemory(btnState, 0); //VFO to Memroy + menuSplitOnOff(btnState); //SplitOn / off break; case 8 : - menuCHMemory(btnState, 1); //Memory to VFO + menuCHMemory(btnState, 0); //VFO to Memroy break; case 9 : - menuCWAutoKey(btnState); + menuCHMemory(btnState, 1); //Memory to VFO break; case 10 : - menuWSPRSend(btnState); + menuCWAutoKey(btnState); break; case 11 : - menuSetup(btnState); + menuWSPRSend(btnState); break; case 12 : - menuExit(btnState); + menuSDROnOff(btnState); break; case 13 : - menuSetupCalibration(btnState); //crystal + menuSetup(btnState); break; case 14 : - menuSetupCarrier(btnState); //lsb + menuExit(btnState); break; case 15 : - menuSetupCWCarrier(btnState); //lsb + menuSetupCalibration(btnState); //crystal break; case 16 : - menuSetupCwTone(btnState); + menuSetupCarrier(btnState); //ssb break; case 17 : - menuSetupCwDelay(btnState); + menuSetupCWCarrier(btnState); //cw break; case 18 : + menuSetupCwTone(btnState); + break; + case 19 : + menuSetupCwDelay(btnState); + break; + case 20 : menuSetupTXCWInterval(btnState); break; - case 19 : + case 21 : menuSetupKeyType(btnState); break; - case 20 : + case 22 : menuADCMonitor(btnState); break; - case 21 : + case 23 : menuTxOnOff(btnState, 0x01); //TX OFF / ON break; default : menuExit(btnState); break; - } - + } Check_Cat(0); //To prevent disconnections } } diff --git a/ubitx_20/ubitx_si5351.ino b/ubitx_20/ubitx_si5351.ino index 87819f8..6587db6 100644 --- a/ubitx_20/ubitx_si5351.ino +++ b/ubitx_20/ubitx_si5351.ino @@ -127,7 +127,7 @@ void si5351_set_calibration(int32_t cal){ void SetCarrierFreq() { unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0)); - si5351bx_setfreq(0, appliedCarrier); + si5351bx_setfreq(0, (sdrModeOn ? 0 : appliedCarrier)); /* if (cwMode == 0) From 689cfda09e064752950519dd1a95bc55cd7a260c Mon Sep 17 00:00:00 2001 From: phdlee Date: Sat, 7 Apr 2018 21:32:01 +0900 Subject: [PATCH 9/9] Add Support SDR Receiver and improve ATT --- ubitx_20/cat_libs.ino | 36 ++++++++++++++++++++++++ ubitx_20/ubitx_20.ino | 61 +++++++++++++++++++++++++++++++++++------ ubitx_20/ubitx_menu.ino | 13 +++++++-- 3 files changed, 99 insertions(+), 11 deletions(-) diff --git a/ubitx_20/cat_libs.ino b/ubitx_20/cat_libs.ino index c9dca39..2285d52 100644 --- a/ubitx_20/cat_libs.ino +++ b/ubitx_20/cat_libs.ino @@ -611,6 +611,34 @@ void WriteEEPRom_FT817(byte fromType) Serial.write(ACK); } +const byte anlogPinIndex[6] = {A0, A1, A2, A3, A6, A7}; + +//Read ADC Value by uBITX Manager Software +void ReadADCValue(void) +{ + //ADC MAP for uBITX + int readedADCValue; + //5BYTES + //CAT_BUFF[0] [1] [2] [3] [4] //4 COMMAND + //0 READ ADDRESS + readedADCValue = analogRead(anlogPinIndex[CAT_BUFF[0]]); + CAT_BUFF[0] = readedADCValue >> 8; + CAT_BUFF[1] = readedADCValue; + SendCatData(2); + Serial.write(ACK); +} + +void SetIFSValue(void) +{ + //Set IFShift Value + isIFShift = CAT_BUFF[0]; + ifShiftValue = CAT_BUFF[1] + CAT_BUFF[2] * 256; + setFrequency(frequency); + SetCarrierFreq(); + updateLine2Buffer(1); //option, perhap not need + Serial.write(ACK); +} + //void CatRxStatus(byte fromType) void CatRxStatus(void) //for remove warning { @@ -768,6 +796,14 @@ void Check_Cat(byte fromType) WriteEEPRom_FT817(fromType); break; + case 0xDD: //Read uBITX ADC Data + ReadADCValue(); //Call by uBITX Manager Program + break; + + case 0xDE: //IF-Shift Control by CAT + SetIFSValue(); // + break; + case 0xE7 : //Read RX Status CatRxStatus(); break; diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index 3b674b7..13a871d 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -10,7 +10,9 @@ //#define UBITX_DISPLAY_LCD2404P //24 x 04 LCD //#define UBITX_DISPLAY_LCD2404I //I2C type 24 x 04 LCD -//#define ENABLE_FACTORYALIGN +//Compile Option +#define ENABLE_FACTORYALIGN +#define ENABLE_ADCMONITOR //Starting with Version 1.07, you can read ADC values directly from uBITX Manager. So this function is not necessary. /** @@ -145,7 +147,12 @@ int count = 0; //to generally count ticks, loops, etc #define CW_SIDETONE 24 #define CW_SPEED 28 -//AT328 has 1KBytes EEPROM +//KD8CEC EEPROM MAP +#define ADVANCED_FREQ_OPTION1 240 //Bit0: use IFTune_Value, Bit1 : use Stored enabled SDR Mode, Bit2 : dynamic sdr frequency +#define IF1_CAL 241 +#define ENABLE_SDR 242 +#define SDR_FREQUNCY 243 + #define CW_CAL 252 #define VFO_A_MODE 256 #define VFO_B_MODE 257 @@ -326,11 +333,12 @@ 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 - + +byte advancedFreqOption1; //255 : Bit0: use IFTune_Value, Bit1 : use Stored enabled SDR Mode, Bit2 : dynamic sdr frequency byte attLevel = 0; //ATT : RF Gain Control (Receive) <-- IF1 Shift, 0 : Off, ShiftValue is attLevel * 100; attLevel 150 = 15K char if1TuneValue = 0; //0 : OFF, IF1 + if1TuneValue * 100; // + - 12500; byte sdrModeOn = 0; //SDR MODE ON / OFF -unsigned long SDR_Center_Freq = 32000000; +unsigned long SDR_Center_Freq; //DEFAULT Frequency : 32000000 unsigned long beforeIdle_ProcessTime = 0; //for check Idle time byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle, @@ -501,12 +509,30 @@ void setFrequency(unsigned long f){ setTXFilters(f); unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0)); - long if1AdjustValue = ((inTx == 0) ? (attLevel * 200) : 0) + (if1TuneValue * 50); //if1Tune RX, TX Enabled, ATT : only RX Mode + long if1AdjustValue = ((inTx == 0) ? (attLevel * 100) : 0) + (if1TuneValue * 100); //if1Tune RX, TX Enabled, ATT : only RX Mode if (sdrModeOn && (inTx == 0)) //IF SDR { - si5351bx_setfreq(2, 44999500 + if1AdjustValue + f); - si5351bx_setfreq(1, 44999500 + if1AdjustValue + SDR_Center_Freq + 2390); + //Fixed Frequency SDR (Default Frequency : 32Mhz, available change sdr Frequency by uBITX Manager) + //Dynamic Frequency is for SWL without cat + //Offset Frequency + Mhz, + //Example : Offset Frequency : 30Mhz and current Frequncy is 7.080 => 37.080Mhz + // Offset Frequency : 30Mhz and current Frequncy is 14.074 => 34.074Mhz + + //Dynamic Frequency + //if (advancedFreqOption1 & 0x04 != 0x00) + // if1AdjustValue += (f % 10000000); + + si5351bx_setfreq(2, 44991500 + if1AdjustValue + f); + si5351bx_setfreq(1, 44991500 + + if1AdjustValue + + SDR_Center_Freq + + ((advancedFreqOption1 & 0x04) == 0x00 ? 0 : (f % 10000000)) + + 2390); + /* + si5351bx_setfreq(2, 44999500 + f); + si5351bx_setfreq(1, 44999500 + SDR_Center_Freq + 2390); + */ } else { @@ -880,7 +906,7 @@ void initSettings(){ printLineF(1, F("Init EEProm...")); //initial all eeprom - for (unsigned int i = 32; i < 1024; i++) //protect Master_cal, usb_cal + for (unsigned int i = 64; i < 1024; i++) //protect Master_cal, usb_cal EEPROM.write(i, 0); //Write Firmware ID @@ -1033,6 +1059,25 @@ void initSettings(){ isIFShift = ifShiftValue != 0; } + //Advanced Freq control + EEPROM.get(ADVANCED_FREQ_OPTION1, advancedFreqOption1); + + //use Advanced Frequency Control + if (advancedFreqOption1 & 0x01 != 0x00) + { + EEPROM.get(IF1_CAL, if1TuneValue); + + //Stored Enabled SDR Mode + if (advancedFreqOption1 & 0x02 != 0x00) + { + EEPROM.get(ENABLE_SDR, sdrModeOn); + } + } + + EEPROM.get(SDR_FREQUNCY, SDR_Center_Freq); + if (SDR_Center_Freq == 0) + SDR_Center_Freq = 32000000; + //default Value (for original hardware) if (cwAdcSTFrom >= cwAdcSTTo) { diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index 07160ee..094e594 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -290,6 +290,7 @@ void menuCHMemory(int btn, byte isMemoryToVfo){ //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) @@ -359,6 +360,7 @@ void menuADCMonitor(int btn){ menuClearExit(0); } +#endif //VFO Toggle and save VFO Information, modified by KD8CEC void menuVfoToggle(int btn) @@ -467,6 +469,7 @@ void menuSDROnOff(int btn) printLineF2(F("[ON]")); } + EEPROM.put(ENABLE_SDR, sdrModeOn); setFrequency(frequency); menuClearExit(500); } @@ -954,14 +957,14 @@ void menuATTSetup(int btn){ char needApplyChangeValue = 1; if (!btn){ - if (isIFShift == 1) + if (attLevel != 0) printLineF2(F("ATT Change?")); else printLineF2(F("ATT On?")); } else { - attLevel = getValueByKnob(5, attLevel, 0, 200, 5, "ATT", 2); //2 : (SetFrequency), targetValue, minKnobValue, maxKnobValue, stepSize + 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) @@ -1229,7 +1232,7 @@ void doMenu(){ btnState = btnDown(); if (i > 0){ - if (modeCalibrate && select + i < 240) + if (modeCalibrate && select + i < 250) select += i; else if (!modeCalibrate && select + i < 150) select += i; @@ -1306,10 +1309,14 @@ void doMenu(){ 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 :