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/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.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_20.ino b/ubitx_20/ubitx_20.ino index 79a575b..13a871d 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -1,8 +1,25 @@ +//Firmware Version +#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 + +//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. + + /** - 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. @@ -87,25 +104,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); - -#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. * We have to be very careful with variables that are declared inside the functions as they are @@ -117,8 +115,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 /** @@ -151,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 @@ -332,6 +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; //DEFAULT Frequency : 32000000 unsigned long beforeIdle_ProcessTime = 0; //for check Idle time byte line2DisplayStatus = 0; //0:Clear, 1 : menu, 1: DisplayFrom Idle, @@ -502,7 +509,50 @@ void setFrequency(unsigned long f){ setTXFilters(f); unsigned long appliedCarrier = ((cwMode == 0 ? usbCarrier : cwmCarrier) + (isIFShift && (inTx == 0) ? ifShiftValue : 0)); + long if1AdjustValue = ((inTx == 0) ? (attLevel * 100) : 0) + (if1TuneValue * 100); //if1Tune RX, TX Enabled, ATT : only RX Mode + if (sdrModeOn && (inTx == 0)) //IF SDR + { + //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 + { + 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){ @@ -525,6 +575,7 @@ void setFrequency(unsigned long f){ si5351bx_setfreq(1, SECOND_OSC_USB); } } + */ frequency = f; } @@ -606,13 +657,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 +713,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 +722,7 @@ void checkPTT(){ startTx(TX_SSB, 1); delay(50); //debounce the PTT } - + if (digitalRead(PTT) == 1 && inTx == 1) stopTx(); } @@ -862,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 @@ -872,8 +916,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); @@ -1015,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) { @@ -1137,11 +1200,10 @@ void setup() */ //Serial.begin(9600); - lcd.begin(16, 2); - printLineF(1, F("CE v1.061")); + 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)) { @@ -1165,8 +1227,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_idle.ino b/ubitx_20/ubitx_idle.ino deleted file mode 100644 index 87aa25e..0000000 --- a/ubitx_20/ubitx_idle.ino +++ /dev/null @@ -1,254 +0,0 @@ -/************************************************************************* - 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. ------------------------------------------------------------------------------ - 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 . - -**************************************************************************/ -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 isDirectCall) -{ - unsigned long tmpFreq = 0; - if (isDirectCall == 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] = ' '; - } //check direct call by encoder - - if (isIFShift) - { - 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] = ' '; - - //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 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 == 1) - // line2Buffer[10] = 'k'; - - if (isStepKhz == 0) - { - line2Buffer[11] = 'H'; - line2Buffer[12] = 'z'; - } - - line2Buffer[13] = ' '; - //if ( - //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; - */ - } - } -} - diff --git a/ubitx_20/ubitx_lcd_1602i.ino b/ubitx_20/ubitx_lcd_1602i.ino new file mode 100644 index 0000000..c8546f0 --- /dev/null +++ b/ubitx_20/ubitx_lcd_1602i.ino @@ -0,0 +1,552 @@ +/************************************************************************* + 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 + + +//======================================================================== +//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 + +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); +} + +void LCD_Init(void) +{ + lcd.begin(16, 2); + initMeter(); //for Meter Display +} + +//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.write(' '); + } + } +} + +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(); +} +//=================================================================================== +//End of Display Base Routines +//=================================================================================== + +//=================================================================================== +//Begin of User Interface Routines +//=================================================================================== + +// 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; + */ + } + } +} + +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 new file mode 100644 index 0000000..607d070 --- /dev/null +++ b/ubitx_20/ubitx_lcd_1602p.ino @@ -0,0 +1,694 @@ +/************************************************************************* + 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 + 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_LCD1602P + + +//======================================================================== +//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 + +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); +} + +void LCD_Init(void) +{ + LCD1602_Init(); + initMeter(); //for Meter Display +} + +//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_Write(' '); + } + } +} + +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(); +} + +//================================================================================== +//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 + // 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; + */ + } + } +} + +//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_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 . + +**************************************************************************/ + + diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index 4b7d9be..094e594 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,71 +288,9 @@ 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 +#ifdef ENABLE_ADCMONITOR void menuADCMonitor(int btn){ int adcPinA0 = 0; //A0(BLACK, EncoderA) int adcPinA1 = 0; //A1(BROWN, EncoderB) @@ -580,6 +360,7 @@ void menuADCMonitor(int btn){ menuClearExit(0); } +#endif //VFO Toggle and save VFO Information, modified by KD8CEC void menuVfoToggle(int btn) @@ -612,28 +393,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,90 +443,36 @@ 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){ +//Toggle SDR MODE +void menuSDROnOff(int btn) +{ if (!btn){ - if (!modeCalibrate) - printLineF2(F("Setup On?")); + if (sdrModeOn == 0) + printLineF2(F("SDR Mode 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); + printLineF2(F("SDR Mode Off?")); } -} - -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); + else { + if (sdrModeOn == 1){ + sdrModeOn = 0; + printLineF2(F("[OFF]")); } - //abort if this button is down - //if (btnDown()) - //re-enable the clock1 and clock 2 - // break; + else { + sdrModeOn = 1; + + if (ritOn == 1) + ritOn = 0; - Check_Cat(0); //To prevent disconnections - } - - //save the setting - //printLineF2(F("CW Speed set!")); - cwSpeed = 1200 / wpm; - EEPROM.put(CW_SPEED, cwSpeed); - menuClearExit(1000); + if (splitOn == 1) + splitOn = 0; + + printLineF2(F("[ON]")); + } + + EEPROM.put(ENABLE_SDR, sdrModeOn); + setFrequency(frequency); + menuClearExit(500); + } } void displayEmptyData(void){ @@ -775,7 +480,6 @@ void displayEmptyData(void){ delay_background(2000, 0); } - //Builtin CW Keyer Logic by KD8CEC void menuCWAutoKey(int btn){ if (!btn){ @@ -791,7 +495,6 @@ void menuCWAutoKey(int btn){ return; } - //printLineF1(F("Press PTT to Send")); printLineF1(F("PTT to Send")); delay_background(500, 0); updateDisplay(); @@ -819,6 +522,269 @@ 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 +// 5 : ATT +// 11 : Select Mode (different display type) +//knobSensitivity : 1 ~ +int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnobValue, int incStep, const char* displayTitle, int knobSensitivity) +{ + int knob; + int moveDetectStep = 0; + int negativeSensitivity; + char isInitDisplay = 1; + delay_background(300, 0); //Default Delay + + if (valueType < 10) + { + strcpy(b, "Press, set "); + strcat(b, displayTitle); + printLine1(b); + } + + while(!btnDown()) + { + knob = enc_read(); + if (knob != 0 || isInitDisplay == 1) + { + isInitDisplay = 0; + + /* + //Program Size : 29424 (95%) + if (targetValue > minKnobValue && knob < 0) + targetValue -= incStep; + if (targetValue < maxKnobValue && knob > 0) + targetValue += incStep; + */ + + //Program Size : 29560 (increase 135 byte from avobe codes), but a lot of usable functions + moveDetectStep += (knob > 0 ? 1 : -1); + if (moveDetectStep < (knobSensitivity * -1)) { + if (targetValue > minKnobValue) + targetValue -= incStep; + + moveDetectStep = 0; + } + else if (moveDetectStep > knobSensitivity) { + if (targetValue < maxKnobValue) + targetValue += incStep; + + moveDetectStep = 0; + } + + strcpy(b, displayTitle); + + if (valueType == 11) //Mode Select + { + b[targetValue * 4] = '>'; + } + /* + else if (valueType == 4) //CW Key Type Select + { + if (targetValue == 0) + strcat(b, "Straight"); + else if (targetValue == 1) + strcat(b, "IAMBICA"); + else if (targetValue == 2) + strcat(b, "IAMBICB"); + } + */ + else + { + strcat(b, ":"); + itoa(targetValue,c, 10); + strcat(b, c); + } + + printLine2(b); + + if (valueType == 1) //Generate Side Tone + { + tone(CW_TONE, targetValue); + } + else if (valueType == 2 || valueType == 5 ) // 2:IFS, 5:ATT + { + if (valueType == 2) + ifShiftValue = targetValue; + else + attLevel = targetValue; + + 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, "Tone", 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 @@ -831,13 +797,18 @@ void menuSetupCwDelay(int btn){ return; } - printLineF1(F("Press, set Delay")); + //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 +828,7 @@ void menuSetupCwDelay(int btn){ Check_Cat(0); //To prevent disconnections } +*/ //save the setting //printLineF2(F("CW Delay set!")); @@ -876,9 +848,12 @@ void menuSetupTXCWInterval(int btn){ return; } - printLineF1(F("Press, set Delay")); - delay_background(300, 0); + //printLineF1(F("Press, set Delay")); + //delay_background(300, 0); + tmpTXCWInterval = getValueByKnob(0, tmpTXCWInterval, 0, 500, 2, "Delay", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize + +/* while(!btnDown()){ if (needDisplayInformation == 1) { @@ -895,12 +870,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 +879,8 @@ void menuSetupTXCWInterval(int btn){ Check_Cat(0); //To prevent disconnections } +*/ + //save the setting //printLineF2(F("CW Start set!")); @@ -918,6 +890,515 @@ 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); + } +} + +//ATT SETUP (IF1(45MHZ) SHIFT), by KD8CEC +void menuATTSetup(int btn){ + int knob = 0; + char needApplyChangeValue = 1; + + if (!btn){ + if (attLevel != 0) + printLineF2(F("ATT Change?")); + else + printLineF2(F("ATT On?")); + } + else + { + attLevel = getValueByKnob(5, attLevel, 0, 250, 5, "ATT", 2); //2 : (SetFrequency), targetValue, minKnobValue, maxKnobValue, stepSize + delay_background(500, 0); //for check Long Press function key + + if (btnDown() || attLevel == 0) + { + attLevel = 0; + setFrequency(frequency); + //SetCarrierFreq(); + } + menuClearExit(0); + } +} + +//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(11, 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(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()){ + + //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 < 250) + select += i; + else if (!modeCalibrate && select + i < 150) + select += i; + } + else if (i < 0 && select - i >= -10) + select += i; + + //if -> switch : reduce program memory 200byte + switch (select / 10) + { + case 0 : + menuBand(btnState); + break; + case 1 : + menuVfoToggle(btnState); + break; + case 2 : + menuSelectMode(btnState); + break; + case 3 : + menuRitToggle(btnState); + break; + case 4 : + menuIFSSetup(btnState); + break; + case 5 : + menuATTSetup(btnState); + break; + case 6 : + menuCWSpeed(btnState); + break; + case 7 : + menuSplitOnOff(btnState); //SplitOn / off + break; + case 8 : + menuCHMemory(btnState, 0); //VFO to Memroy + break; + case 9 : + menuCHMemory(btnState, 1); //Memory to VFO + break; + case 10 : + menuCWAutoKey(btnState); + break; + case 11 : + menuWSPRSend(btnState); + break; + case 12 : + menuSDROnOff(btnState); + break; + case 13 : + menuSetup(btnState); + break; + case 14 : + menuExit(btnState); + break; + case 15 : + menuSetupCalibration(btnState); //crystal + break; + case 16 : + menuSetupCarrier(btnState); //ssb + break; + case 17 : + menuSetupCWCarrier(btnState); //cw + break; + case 18 : + menuSetupCwTone(btnState); + break; + case 19 : + menuSetupCwDelay(btnState); + break; + case 20 : + menuSetupTXCWInterval(btnState); + break; + case 21 : + menuSetupKeyType(btnState); + break; +#ifdef ENABLE_ADCMONITOR + case 22 : + menuADCMonitor(btnState); + break; + case 23 : +#else + case 22 : +#endif + menuTxOnOff(btnState, 0x01); //TX OFF / ON + break; + default : + menuExit(btnState); break; + } + 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 +1624,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 - } -*/ -} - 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) diff --git a/ubitx_20/ubitx_ui.ino b/ubitx_20/ubitx_ui.ino index c5089ea..4907282 100644 --- a/ubitx_20/ubitx_ui.ino +++ b/ubitx_20/ubitx_ui.ino @@ -5,8 +5,13 @@ * 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)) + + 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){ @@ -16,319 +21,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; /** 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