diff --git a/ubitx_20/cat_libs.ino b/ubitx_20/cat_libs.ino index 3e71855..608af79 100644 --- a/ubitx_20/cat_libs.ino +++ b/ubitx_20/cat_libs.ino @@ -252,12 +252,35 @@ void ReadEEPRom() //for remove warnings. Serial.write(0x02); //STX checkSum = 0x02; - for (uint16_t i = 0; i < eepromReadLength; i++) + //I2C Scanner + //Magic Key Start 59414, Length : 48583 + //if (eepromStartIndex == 59414 && eepromReadLength == 48583) + if (CAT_BUFF[0] == 0x16 && CAT_BUFF[1] == 0xe8) { - read1Byte = EEPROM.read(eepromStartIndex + i); - checkSum += read1Byte; - Serial.write(read1Byte); + for (uint8_t i = 1; i < 127; i++) + { + Wire.beginTransmission(i); + read1Byte = Wire.endTransmission(); + if (read1Byte == 0) + { + Serial.write(i); + } + else + { + Serial.write(0); + } + } } + else + { + for (uint16_t i = 0; i < eepromReadLength; i++) + { + read1Byte = EEPROM.read(eepromStartIndex + i); + checkSum += read1Byte; + Serial.write(read1Byte); + } + } + Serial.write(checkSum); Serial.write(ACK); } diff --git a/ubitx_20/cw_autokey.ino b/ubitx_20/cw_autokey.ino index f5fcbde..9bf838e 100644 --- a/ubitx_20/cw_autokey.ino +++ b/ubitx_20/cw_autokey.ino @@ -235,30 +235,6 @@ void sendCWChar(char cwKeyChar) } } -/* -void sendAutoCW(int cwSendLength, char *sendString) -{ - byte i; - - if (!inTx){ - keyDown = 0; - cwTimeout = millis() + cwDelayTime * 10; - startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time - updateDisplay(); - - delay_background(delayBeforeCWStartTime * 2, 2); - } - - for (i = 0; i < cwSendLength; i++) - { - sendCWChar(sendString[i]); - if (i != cwSendLength -1) delay_background(cwSpeed * 3, 3); - } - - delay_background(cwDelayTime * 10, 2); - stopTx(); -} -*/ byte isNeedScroll = 0; unsigned long scrollDispayTime = 0; #define scrollSpeed 500 @@ -296,18 +272,19 @@ void controlAutoCW(){ { displayScrolStep = 0; } - + +#ifdef USE_SW_SERIAL + //Not need Scroll + //Display_AutoKeyTextIndex(selectedCWTextIndex); + SendCommand1Num('w', selectedCWTextIndex); //Index + SendEEPromData('a', cwStartIndex + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ, 0) ; //Data + SendCommand1Num('y', 1); //Send YN + isNeedScroll = 0; +#else printLineFromEEPRom(0, 2, cwStartIndex + displayScrolStep + CW_DATA_OFSTADJ, cwEndIndex + CW_DATA_OFSTADJ, 0); - - //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; + Display_AutoKeyTextIndex(selectedCWTextIndex); +#endif scrollDispayTime = millis() + scrollSpeed; beforeCWTextIndex = selectedCWTextIndex; } diff --git a/ubitx_20/softserial_tiny.cpp b/ubitx_20/softserial_tiny.cpp new file mode 100644 index 0000000..4738e87 --- /dev/null +++ b/ubitx_20/softserial_tiny.cpp @@ -0,0 +1,334 @@ +/* +Softserial for Nextion LCD and Control MCU +KD8CEC, Ian Lee +----------------------------------------------------------------------- +It is a library rewritten in C format based on SoftwareSerial.c. +I tried to use as much as possible without modifying the SoftwareSerial. +But eventually I had to modify the code. + +I rewrote it in C for the following reasons. + - Problems occurred when increasing Program Size and Program Memory + - We had to reduce the program size. + Of course, Software Serial is limited to one. + - reduce the steps for transmitting and receiving + +useage +extern void SWSerial_Begin(long speedBaud); +extern void SWSerial_Write(uint8_t b); +extern int SWSerial_Available(void); +extern int SWSerial_Read(void); +extern void SWSerial_Print(uint8_t *b); + +If you use Softwreserial library instead of this library, you can modify the code as shown below. +I kept the function name of SoftwareSerial so you only need to modify a few lines of code. + +define top of source code +#include +SoftwareSerial sSerial(10, 11); // RX, TX + +replace source code +SWSerial_Begin to sSerial.begin +SWSerial_Write to sSerial.write +SWSerial_Available to sSerial.available +SWSerial_Read to sSerial.read + +KD8CEC, Ian Lee +----------------------------------------------------------------------- +License +All licenses for the source code are subject to the license of the original source SoftwareSerial Library. +However, if you use or modify this code, please keep the all comments in this source code. +KD8CEC +----------------------------------------------------------------------- +License from SoftwareSerial +----------------------------------------------------------------------- +SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - +Multi-instance software serial library for Arduino/Wiring +-- Interrupt-driven receive and other improvements by ladyada + (http://ladyada.net) +-- Tuning, circular buffer, derivation from class Print/Stream, + multi-instance support, porting to 8MHz processors, + various optimizations, PROGMEM delay tables, inverse logic and + direct port writing by Mikal Hart (http://www.arduiniana.org) +-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) +-- 20MHz processor support by Garrett Mace (http://www.macetech.com) +-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +The latest version of this library can always be found at +http://arduiniana.org. + */ +#include + +//================================================================ +//Public Variable +//================================================================ +#define TX_PIN 9 +#define RX_PIN 8 +#define _SS_MAX_RX_BUFF 35 // RX buffer size +#define PRINT_MAX_LENGTH 30 + +//================================================================ +//Internal Variable from SoftwareSerial.c and SoftwareSerial.h +//================================================================ +//variable from softwareserial.c and softwareserial.h +static uint8_t swr_receive_buffer[_SS_MAX_RX_BUFF]; + +volatile uint8_t *_transmitPortRegister; //Write Port Register +uint8_t transmit_RegMask; //use Mask bit 1 +uint8_t transmit_InvMask; //use mask bit 0 + +volatile uint8_t *_receivePortRegister; //Read Port Register +uint8_t _receiveBitMask; + +//delay value for Bit +uint16_t _tx_delay; + +//delay value for Receive +uint16_t _rx_delay_stopbit; +uint16_t _rx_delay_centering; +uint16_t _rx_delay_intrabit; + +//Customize for uBITX Protocol +int8_t receiveIndex = 0; +uint8_t receivedCommandLength = 0; +int8_t ffCount = 0; + +//Values for Receive Buffer +//uint16_t _buffer_overflow; +//static volatile uint8_t _receive_buffer_head; +//static volatile uint8_t _receive_buffer_tail; + +//Values for Interrupt (check Start Bit) +volatile uint8_t *_pcint_maskreg; +uint8_t _pcint_maskvalue; + +//================================================================ +//Internal Function from SoftwareSerial.c +//================================================================ +uint16_t subtract_cap(uint16_t num, uint16_t sub) +{ + if (num > sub) + return num - sub; + else + return 1; +} + +inline void tunedDelay(uint16_t delay) +{ + _delay_loop_2(delay); +} + +void setRxIntMsk(bool enable) +{ + if (enable) + *_pcint_maskreg |= _pcint_maskvalue; + else + *_pcint_maskreg &= ~_pcint_maskvalue; +} + +uint8_t rx_pin_read() +{ + return *_receivePortRegister & _receiveBitMask; +} + +// +// The receive routine called by the interrupt handler +// +void softSerail_Recv() +{ +#if GCC_VERSION < 40302 +// Work-around for avr-gcc 4.3.0 OSX version bug +// Preserve the registers that the compiler misses +// (courtesy of Arduino forum user *etracer*) + asm volatile( + "push r18 \n\t" + "push r19 \n\t" + "push r20 \n\t" + "push r21 \n\t" + "push r22 \n\t" + "push r23 \n\t" + "push r26 \n\t" + "push r27 \n\t" + ::); +#endif + + uint8_t d = 0; + + // If RX line is high, then we don't see any start bit + // so interrupt is probably not for us + if (!rx_pin_read()) //Start Bit + { + // Disable further interrupts during reception, this prevents + // triggering another interrupt directly after we return, which can + // cause problems at higher baudrates. + setRxIntMsk(false); + + // Wait approximately 1/2 of a bit width to "center" the sample + tunedDelay(_rx_delay_centering); + + // Read each of the 8 bits + for (uint8_t i=8; i > 0; --i) + { + tunedDelay(_rx_delay_intrabit); + d >>= 1; + + if (rx_pin_read()) + d |= 0x80; + } + + if (receivedCommandLength == 0) //check Already Command + { + //Set Received Data + swr_receive_buffer[receiveIndex++] = d; + + //Finded Command + if (d == 0x73 && ffCount > 1 && receiveIndex > 6) + { + receivedCommandLength = receiveIndex; + receiveIndex = 0; + ffCount = 0; + } + else if (receiveIndex > _SS_MAX_RX_BUFF) + { + //Buffer Overflow + receiveIndex = 0; + ffCount = 0; + } + else if (d == 0xFF) + { + ffCount++; + } + else + { + ffCount = 0; + } + } + + // skip the stop bit + tunedDelay(_rx_delay_stopbit); + + // Re-enable interrupts when we're sure to be inside the stop bit + setRxIntMsk(true); + } + +#if GCC_VERSION < 40302 +// Work-around for avr-gcc 4.3.0 OSX version bug +// Restore the registers that the compiler misses + asm volatile( + "pop r27 \n\t" + "pop r26 \n\t" + "pop r23 \n\t" + "pop r22 \n\t" + "pop r21 \n\t" + "pop r20 \n\t" + "pop r19 \n\t" + "pop r18 \n\t" + ::); +#endif +} + +ISR(PCINT0_vect) +{ + softSerail_Recv(); +} + +//================================================================ +//Public Function from SoftwareSerial.c and modified and create +//================================================================ +// Read data from buffer +void SWSerial_Read(uint8_t * receive_cmdBuffer) +{ + for (int i = 0; i < receivedCommandLength; i++) + receive_cmdBuffer[i] = swr_receive_buffer[i]; +} + +void SWSerial_Write(uint8_t b) +{ + volatile uint8_t *reg = _transmitPortRegister; + uint8_t oldSREG = SREG; + uint16_t delay = _tx_delay; + + cli(); // turn off interrupts for a clean txmit + + // Write the start bit + *reg &= transmit_InvMask; + + tunedDelay(delay); + + // Write each of the 8 bits + for (uint8_t i = 8; i > 0; --i) + { + if (b & 1) // choose bit + *reg |= transmit_RegMask; // send 1 + else + *reg &= transmit_InvMask; // send 0 + + tunedDelay(delay); + b >>= 1; + } + + // restore pin to natural state + *reg |= transmit_RegMask; + + SREG = oldSREG; // turn interrupts back on + tunedDelay(_tx_delay); +} + +void SWSerial_Print(uint8_t *b) +{ + for (int i = 0; i < PRINT_MAX_LENGTH; i++) + { + if (b[i] == 0x00) + break; + else + SWSerial_Write(b[i]); + } +} + +void SWSerial_Begin(long speedBaud) +{ + //INT TX_PIN + digitalWrite(TX_PIN, HIGH); + pinMode(TX_PIN, OUTPUT); + transmit_RegMask = digitalPinToBitMask(TX_PIN); //use Bit 1 + transmit_InvMask = ~digitalPinToBitMask(TX_PIN); //use Bit 0 + _transmitPortRegister = portOutputRegister(digitalPinToPort(TX_PIN)); + + //INIT RX_PIN + pinMode(RX_PIN, INPUT); + digitalWrite(RX_PIN, HIGH); // pullup for normal logic! + _receiveBitMask = digitalPinToBitMask(RX_PIN); + _receivePortRegister = portInputRegister(digitalPinToPort(RX_PIN)); + + //Set Values + uint16_t bit_delay = (F_CPU / speedBaud) / 4; + _tx_delay = subtract_cap(bit_delay, 15 / 4); + + if (digitalPinToPCICR(RX_PIN)) + { + _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); + _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); + *digitalPinToPCICR(RX_PIN) |= _BV(digitalPinToPCICRbit(RX_PIN)); + _pcint_maskreg = digitalPinToPCMSK(RX_PIN); + _pcint_maskvalue = _BV(digitalPinToPCMSKbit(RX_PIN)); + + tunedDelay(_tx_delay); // if we were low this establishes the end + } + + //Start Listen + setRxIntMsk(true); +} diff --git a/ubitx_20/ubitx.h b/ubitx_20/ubitx.h index 18d7be4..fedb46e 100644 --- a/ubitx_20/ubitx.h +++ b/ubitx_20/ubitx.h @@ -24,14 +24,19 @@ //============================================================================== //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 (Parallel) +//#define UBITX_DISPLAY_LCD1602P //LCD mounted on unmodified uBITX (Parallel) //#define UBITX_DISPLAY_LCD1602I //I2C type 16 x 02 LCD //#define UBITX_DISPLAY_LCD1602I_DUAL //I2C type 16 x02 LCD Dual //#define UBITX_DISPLAY_LCD2004P //24 x 04 LCD (Parallel) -//#define UBITX_DISPLAY_LCD2004I //I2C type 24 x 04 LCD +#define UBITX_DISPLAY_LCD2004I //I2C type 24 x 04 LCD +//#define UBITX_DISPLAY_NEXTION //NEXTION LCD -#define I2C_LCD_MASTER_ADDRESS_DEFAULT 0x3F //0x27 //DEFAULT, if Set I2C Address by uBITX Manager, read from EEProm -#define I2C_LCD_SECOND_ADDRESS_DEFAULT 0x27 //0x27 //only using Dual LCD Mode +//#define UBITX_DISPLAY_NEXTION_SAFE //Only EEProm Write 770~775 +#define I2C_LCD_MASTER_ADDRESS_DEFAULT 0x27 //0x27 //DEFAULT, if Set I2C Address by uBITX Manager, read from EEProm +#define I2C_LCD_SECOND_ADDRESS_DEFAULT 0x3F //0x27 //only using Dual LCD Mode + +//Select betwen Analog S-Meter and DSP (I2C) Meter +#define USE_I2CSMETER #define EXTEND_KEY_GROUP1 //MODE, BAND(-), BAND(+), STEP //#define EXTEND_KEY_GROUP2 //Numeric (0~9), Point(.), Enter //Not supported in Version 1.0x @@ -42,9 +47,116 @@ extern byte I2C_LCD_MASTER_ADDRESS; //0x27 //if Set I2C Address by uBITX Manager, read from EEProm extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode - #define SMeterLatency 3 //1 is 0.25 sec +//============================================================================== +// User Select feather list +//============================================================================== +//Enable all features +#define FN_BAND 1 //592 +#define FN_VFO_TOGGLE 1 //78 +#define FN_MODE 1 //20 +#define FN_RIT 1 //58 +#define FN_SPLIT 1 //62 +#define FN_IFSHIFT 1 //238 +#define FN_ATT 1 //128 +#define FN_CW_SPEED 1 //152 +#define FN_VFOTOMEM 1 //254 +#define FN_MEMTOVFO 1 //188 +#define FN_MEMORYKEYER 1 //156 +#define FN_WSPR 1 //1044 +#define FN_SDRMODE 1 //68 +#define FN_CALIBRATION 1 //666 +#define FN_CARRIER 1 //382 +#define FN_CWCARRIER 1 //346 +#define FN_CWTONE 1 //148 +#define FN_CWDELAY 1 //98 +#define FN_TXCWDELAY 1 //94 +#define FN_KEYTYPE 1 //168 +#define FN_ADCMONITOR 1 //516 +#define FN_TXONOFF 1 //58 + +/* +//Test Configuration (88%) +#define FN_BAND 0 //592 +#define FN_VFO_TOGGLE 0 //78 +#define FN_MODE 0 //20 +#define FN_RIT 0 //58 +#define FN_SPLIT 0 //62 +#define FN_IFSHIFT 0 //238 +#define FN_ATT 0 //128 +#define FN_CW_SPEED 1 //152 +#define FN_VFOTOMEM 0 //254 +#define FN_MEMTOVFO 0 //188 +#define FN_MEMORYKEYER 1 //156 +#define FN_WSPR 0 //1044 +#define FN_SDRMODE 1 //68 +#define FN_CALIBRATION 1 //666 +#define FN_CARRIER 1 //382 +#define FN_CWCARRIER 1 //346 +#define FN_CWTONE 1 //148 +#define FN_CWDELAY 1 //98 +#define FN_TXCWDELAY 1 //94 +#define FN_KEYTYPE 1 //168 +#define FN_ADCMONITOR 1 //516 +#define FN_TXONOFF 1 //58 +*/ + +/* +//Recommended Character LCD Developer 87% +#define FN_BAND 1 //592 +#define FN_VFO_TOGGLE 1 //78 +#define FN_MODE 1 //20 +#define FN_RIT 1 //58 +#define FN_SPLIT 1 //62 +#define FN_IFSHIFT 1 //238 +#define FN_ATT 0 //128 +#define FN_CW_SPEED 0 //152 //using MM +#define FN_VFOTOMEM 1 //254 +#define FN_MEMTOVFO 1 //188 +#define FN_MEMORYKEYER 1 //156 +#define FN_WSPR 1 //1044 +#define FN_SDRMODE 1 //68 +#define FN_CALIBRATION 0 //667 //using MM +#define FN_CARRIER 0 //382 //using MM +#define FN_CWCARRIER 0 //346 //using MM +#define FN_CWTONE 0 //148 //using MM +#define FN_CWDELAY 0 //98 //using MM +#define FN_TXCWDELAY 0 //94 //using MM +#define FN_KEYTYPE 0 //168 //using MM +#define FN_ADCMONITOR 0 //516 //using MM +#define FN_TXONOFF 1 //58 +*/ + +/* +//Recommended for Nextion, TJC LCD 88% +#define FN_BAND 1 //600 +#define FN_VFO_TOGGLE 1 //90 +#define FN_MODE 1 //318 +#define FN_RIT 1 //62 +#define FN_SPLIT 1 //2 +#define FN_IFSHIFT 1 //358 +#define FN_ATT 1 //250 +#define FN_CW_SPEED 0 //286 +#define FN_VFOTOMEM 0 //276 +#define FN_MEMTOVFO 0 //234 +#define FN_MEMORYKEYER 1 //168 +#define FN_WSPR 1 //1130 +#define FN_SDRMODE 1 //70 +#define FN_CALIBRATION 0 //790 +#define FN_CARRIER 0 //500 +#define FN_CWCARRIER 0 //464 +#define FN_CWTONE 0 //158 +#define FN_CWDELAY 0 //108 +#define FN_TXCWDELAY 0 //106 +#define FN_KEYTYPE 0 //294 +#define FN_ADCMONITOR 0 //526 //not available with Nextion or Serial UI +#define FN_TXONOFF 1 //70 +*/ +//============================================================================== +// End of User Select Mode and Compil options +//============================================================================== + #ifdef UBITX_DISPLAY_LCD1602I #define USE_I2C_LCD #elif defined(UBITX_DISPLAY_LCD1602I_DUAL) @@ -53,6 +165,17 @@ extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode #define USE_I2C_LCD #endif +#ifdef UBITX_DISPLAY_NEXTION + #define USE_SW_SERIAL + #undef ENABLE_ADCMONITOR + #undef FACTORY_RECOVERY_BOOTUP +#elif defined(UBITX_CONTROL_MCU) + #define USE_SW_SERIAL + #undef ENABLE_ADCMONITOR + #undef FACTORY_RECOVERY_BOOTUP +#endif + + //============================================================================== // Hardware, Define PIN Usage //============================================================================== @@ -64,7 +187,7 @@ extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode * ground and six pins. Each of these six pins can be individually programmed * either as an analog input, a digital input or a digital output. * The pins are assigned as follows (left to right, display facing you): - * Pin 1 (Violet), A7, SPARE + * Pin 1 (Violet), A7, SPARE => Analog S-Meter * Pin 2 (Blue), A6, KEYER (DATA) * Pin 3 (Green), +5v * Pin 4 (Yellow), Gnd @@ -94,7 +217,7 @@ extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode * The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig. * This assignment is as follows : * Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - * GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7 + * GND +5V CLK2 GND GND CLK1 GND GND CLK0 GND D2 D3 D4 D5 D6 D7 * These too are flexible with what you may do with them, for the Raduino, we use them to : * - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer * - CW_KEY line : turns on the carrier for CW @@ -106,6 +229,24 @@ extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode #define TX_LPF_C (3) //Relay #define CW_KEY (2) +//****************************************************** +//DSP (I2C) Meter +//****************************************************** +//S-Meter Address +#define I2CMETER_ADDR 0x58 +//VALUE TYPE============================================ +//Signal +#define I2CMETER_CALCS 0x59 //Calculated Signal Meter +#define I2CMETER_UNCALCS 0x58 //Uncalculated Signal Meter + +//Power +#define I2CMETER_CALCP 0x57 //Calculated Power Meter +#define I2CMETER_UNCALCP 0x56 //UnCalculated Power Meter + +//SWR +#define I2CMETER_CALCR 0x55 //Calculated SWR Meter +#define I2CMETER_UNCALCR 0x54 //Uncalculated SWR Meter + //============================================================================== // for public, Variable, functions //============================================================================== @@ -146,6 +287,8 @@ extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode #define FKEY_TYPE_MAX 0x1F +extern uint8_t SI5351BX_ADDR; //change typical -> variable at Version 1.097, address read from eeprom, default value is 0x60 + //EEProm Address : 63 extern unsigned long frequency; extern byte WsprMSGCount; extern byte sMeterLevels[9]; @@ -153,6 +296,7 @@ extern int currentSMeter; //ADC Value for S.Meter extern byte scaledSMeter; //Calculated S.Meter Level extern byte KeyValues[16][3]; //Set : Start Value, End Value, Key Type, 16 Set (3 * 16 = 48) +extern byte TriggerBySW; //Action Start from Nextion LCD, Other MCU extern void printLine1(const char *c); extern void printLine2(const char *c); @@ -179,6 +323,9 @@ extern char byteToChar(byte srcByte); extern void DisplayCallsign(byte callSignLength); extern void DisplayVersionInfo(const char* fwVersionInfo); +//I2C Signal Meter, Version 1.097 +extern int GetI2CSmeterValue(int valueType); //ubitx_ui.ino + #endif //end of if header define diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index 025fd9f..c9b235f 100644 --- a/ubitx_20/ubitx_20.ino +++ b/ubitx_20/ubitx_20.ino @@ -1,4 +1,4 @@ -//Firmware Version + //Firmware Version //+ : This symbol identifies the firmware. // It was originally called 'CEC V1.072' but it is too long to waste the LCD window. // I do not want to make this Firmware users's uBITX messy with my callsign. @@ -6,8 +6,8 @@ // So I put + in the sense that it was improved one by one based on Original Firmware. // This firmware has been gradually changed based on the original firmware created by Farhan, Jack, Jerry and others. -#define FIRMWARE_VERSION_INFO F("+v1.080") -#define FIRMWARE_VERSION_NUM 0x03 //1st Complete Project : 1 (Version 1.061), 2st Project : 2 +#define FIRMWARE_VERSION_INFO F("+v1.097") +#define FIRMWARE_VERSION_NUM 0x04 //1st Complete Project : 1 (Version 1.061), 2st Project : 2, 1.08: 3, 1.09 : 4 /** Cat Suppoort uBITX CEC Version @@ -192,7 +192,9 @@ byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode byte KeyValues[16][3]; byte isIFShift = 0; //1 = ifShift, 2 extend -int ifShiftValue = 0; // +int ifShiftValue = 0; // + +byte TriggerBySW = 0; //Action Start from Nextion LCD, Other MCU /** * Below are the basic functions that control the uBitx. Understanding the functions before @@ -465,13 +467,17 @@ void startTx(byte txMode, byte isDisplayUpdate){ } else { - if (splitOn == 1) { - if (vfoActive == VFO_B) { + if (splitOn == 1) + { + FrequencyToVFO(1); //Save current Frequency and Mode to eeprom + if (vfoActive == VFO_B) + { vfoActive = VFO_A; frequency = vfoA; byteToMode(vfoA_mode, 0); } - else if (vfoActive == VFO_A){ + else if (vfoActive == VFO_A) + { vfoActive = VFO_B; frequency = vfoB; byteToMode(vfoB_mode, 0); @@ -602,7 +608,18 @@ void checkButton(){ return; if (keyStatus == FKEY_PRESS) //Menu Key + { + //for touch screen +#ifdef USE_SW_SERIAL + SetSWActivePage(1); doMenu(); + + if (isCWAutoMode == 0) + SetSWActivePage(0); +#else + doMenu(); +#endif + } else if (keyStatus <= FKEY_TYPE_MAX) //EXTEND KEY GROUP #1 { @@ -665,74 +682,7 @@ void checkButton(){ menuRitToggle(1); break; } - /* - if (keyStatus == FKEY_MODE) //Press Mode Key - { - if (cwMode == 1) - { - cwMode = 2; - } - else if (cwMode == 2) - { - cwMode = 0; - isUSB = 0; - } - else if (isUSB == 0) - { - isUSB = 1; - } - else - { - cwMode = 1; - } - } - else if (keyStatus == FKEY_BANDUP || keyStatus == FKEY_BANDDOWN) //Press Mode Key - { - char currentBandIndex = -1; - - //Save Band Information - if (tuneTXType == 2 || tuneTXType == 3 || tuneTXType == 102 || tuneTXType == 103) { //only ham band move - currentBandIndex = getIndexHambanBbyFreq(frequency); - - if (currentBandIndex >= 0) { - saveBandFreqByIndex(frequency, modeToByte(), currentBandIndex); - } - } - - setNextHamBandFreq(frequency, keyStatus == FKEY_BANDDOWN ? -1 : 1); //Prior Band - } - else if (keyStatus == FKEY_STEP) //FKEY_BANDUP - { - if (++tuneStepIndex > 5) - tuneStepIndex = 1; - - EEPROM.put(TUNING_STEP, tuneStepIndex); - printLine2ClearAndUpdate(); - } - - else if (keyStatus == FKEY_VFOCHANGE) - { - menuVfoToggle(1); //Vfo Toggle - } - else if (keyStatus == FKEY_SPLIT) - { - menuSplitOnOff(1); - } - else if (keyStatus == FKEY_TXOFF) - { - menuTxOnOff(1, 0x01); - } - else if (keyStatus == FKEY_SDRMODE) - { - menuSDROnOff(1); - } - else if (keyStatus == FKEY_RIT) - { - menuRitToggle(1); - } - */ - FrequencyToVFO(1); SetCarrierFreq(); setFrequency(frequency); @@ -941,6 +891,15 @@ void initSettings(){ if (EEPROM.read(VERSION_ADDRESS) != FIRMWARE_VERSION_NUM) EEPROM.write(VERSION_ADDRESS, FIRMWARE_VERSION_NUM); + //SI5351 I2C Address + //I2C_ADDR_SI5351 + SI5351BX_ADDR = EEPROM.read(I2C_ADDR_SI5351); + if (SI5351BX_ADDR < 0x10 || SI5351BX_ADDR > 0xF0) + { + SI5351BX_ADDR = 0x60; + } + + //Backup Calibration Setting from Factory Setup //Check Factory Setting Backup Y/N if (EEPROM.read(FACTORY_BACKUP_YN) != 0x13) { @@ -1294,11 +1253,18 @@ void setup() Init_Cat(38400, SERIAL_8N1); initSettings(); + initPorts(); - if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) { +#ifdef USE_SW_SERIAL +// if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) +// { + userCallsignLength = userCallsignLength & 0x7F; +// } +#else +//for Chracter LCD + if (userCallsignLength > 0 && ((userCallsignLength & 0x80) == 0x80)) + { userCallsignLength = userCallsignLength & 0x7F; - //printLineFromEEPRom(0, 0, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) - //delay(500); DisplayCallsign(userCallsignLength); } else { @@ -1306,8 +1272,7 @@ void setup() delay(500); clearLine2(); } - - initPorts(); +#endif #ifdef FACTORY_RECOVERY_BOOTUP if (btnDown()) @@ -1320,6 +1285,11 @@ void setup() frequency = vfoA; saveCheckFreq = frequency; //for auto save frequency setFrequency(vfoA); + +#ifdef USE_SW_SERIAL + SendUbitxData(); +#endif + updateDisplay(); #ifdef ENABLE_FACTORYALIGN @@ -1383,4 +1353,9 @@ void loop(){ //we check CAT after the encoder as it might put the radio into TX Check_Cat(inTx? 1 : 0); + + //for SEND SW Serial + #ifdef USE_SW_SERIAL + SWS_Process(); + #endif } diff --git a/ubitx_20/ubitx_eemap.h b/ubitx_20/ubitx_eemap.h index e799187..cc37111 100644 --- a/ubitx_20/ubitx_eemap.h +++ b/ubitx_20/ubitx_eemap.h @@ -35,10 +35,13 @@ //============================================================================== // The spare space available in the original firmware #1 -// Address : 32 ~ 63 +// Address : 32 ~ 62 //============================================================================== #define RESERVE_FOR_FACTORY1 32 +//SI5351 I2C Address (Version 1.097) +#define I2C_ADDR_SI5351 63 + //============================================================================== // The spare space available in the original firmware #2 // (Enabled if the EEProm address is insufficient) @@ -112,7 +115,8 @@ #define CHANNEL_FREQ 630 //Channel 1 ~ 20, 1 Channel = 4 bytes #define CHANNEL_DESC 710 //Channel 1 ~ 20, 1 Channel = 4 bytes -#define RESERVE3 770 //Reserve3 between Channel and Firmware id check +#define EXTERNAL_DEVICE_OPT1 770 //for External Deivce 4byte +#define EXTERNAL_DEVICE_OPT2 774 //for External Deivce 2byte //Check Firmware type and version #define FIRMWAR_ID_ADDR 776 //776 : 0x59, 777 :0x58, 778 : 0x68 : Id Number, if not found id, erase eeprom(32~1023) for prevent system error. diff --git a/ubitx_20/ubitx_lcd_1602.ino b/ubitx_20/ubitx_lcd_1602.ino index 67ca38c..76f2e5b 100644 --- a/ubitx_20/ubitx_lcd_1602.ino +++ b/ubitx_20/ubitx_lcd_1602.ino @@ -738,6 +738,9 @@ void idle_process() { int newSMeter; +#ifdef USE_I2CSMETER + scaledSMeter = GetI2CSmeterValue(I2CMETER_CALCS); +#else //VK2ETA S-Meter from MAX9814 TC pin / divide 4 by KD8CEC for reduce EEPromSize newSMeter = analogRead(ANALOG_SMETER) / 4; @@ -752,6 +755,7 @@ void idle_process() break; } } +#endif DisplayMeter(0, scaledSMeter, 13); checkCountSMeter = 0; //Reset Latency time diff --git a/ubitx_20/ubitx_lcd_1602Dual.ino b/ubitx_20/ubitx_lcd_1602Dual.ino index 211b3ef..48598cb 100644 --- a/ubitx_20/ubitx_lcd_1602Dual.ino +++ b/ubitx_20/ubitx_lcd_1602Dual.ino @@ -669,6 +669,9 @@ void idle_process() int newSMeter; displaySDRON = 0; +#ifdef USE_I2CSMETER + scaledSMeter = GetI2CSmeterValue(I2CMETER_CALCS); +#else //VK2ETA S-Meter from MAX9814 TC pin / divide 4 by KD8CEC for reduce EEPromSize newSMeter = analogRead(ANALOG_SMETER) / 4; @@ -684,9 +687,9 @@ void idle_process() break; } } +#endif DisplayMeter(0, scaledSMeter, 0); - checkCountSMeter = 0; } //end of S-Meter _Addr = I2C_LCD_MASTER_ADDRESS; diff --git a/ubitx_20/ubitx_lcd_2004.ino b/ubitx_20/ubitx_lcd_2004.ino index 2a5a2da..06d44fa 100644 --- a/ubitx_20/ubitx_lcd_2004.ino +++ b/ubitx_20/ubitx_lcd_2004.ino @@ -690,7 +690,10 @@ void idle_process() if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency)) { int newSMeter; - + +#ifdef USE_I2CSMETER + scaledSMeter = GetI2CSmeterValue(I2CMETER_CALCS); +#else //VK2ETA S-Meter from MAX9814 TC pin newSMeter = analogRead(ANALOG_SMETER) / 4; @@ -706,6 +709,7 @@ void idle_process() break; } } +#endif DisplayMeter(0, scaledSMeter, 0); checkCountSMeter = 0; //Reset Latency time diff --git a/ubitx_20/ubitx_lcd_nextion.ino b/ubitx_20/ubitx_lcd_nextion.ino new file mode 100644 index 0000000..096b86b --- /dev/null +++ b/ubitx_20/ubitx_lcd_nextion.ino @@ -0,0 +1,1107 @@ +/************************************************************************* + KD8CEC's uBITX Display Routine for Nextion LCD + + Uses the default protocol of Nextion LCD. + Do not assign a 2 byte address to Nextion LCD. +----------------------------------------------------------------------------- + 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 . + +**************************************************************************/ +#include "ubitx.h" +#include "ubitx_lcd.h" + +//======================================================================== +//Begin of Nextion LCD Library by KD8CEC +//======================================================================== +#ifdef UBITX_DISPLAY_NEXTION +/************************************************************************* + Nextion Library for uBItX + KD8CEC +**************************************************************************/ +extern void SWSerial_Begin(long speedBaud); +extern void SWSerial_Write(uint8_t b); +extern int SWSerial_Available(void); +extern int SWSerial_Read(void); +extern void SWSerial_Print(uint8_t *b); + +#define TEXT_LINE_LENGTH 20 +char softBuffLines[2][TEXT_LINE_LENGTH + 1]; +char softBuffSended[2][TEXT_LINE_LENGTH + 1]; +char softBuffTemp[TEXT_LINE_LENGTH + 1]; //for STR Command + +char c[30], b[30]; +char softBuff[20]; +char softTemp[20]; + +void LCDNextion_Init() +{ + SWSerial_Begin(9600); + memset(softBuffLines[0], ' ', TEXT_LINE_LENGTH); + softBuffLines[0][TEXT_LINE_LENGTH + 1] = 0x00; + memset(softBuffLines[1], ' ', TEXT_LINE_LENGTH); + softBuffLines[1][TEXT_LINE_LENGTH + 1] = 0x00; +} + +void LCD_Init(void) +{ + LCDNextion_Init(); +} + +//=================================================================== +//Begin of Nextion LCD Protocol +// +// v0~v9, va~vz : Numeric (Transceiver -> Nextion LCD) +// s0~s9 : String (Text) (Transceiver -> Nextion LCD) +// vlSendxxx, vloxxx: Reserve for Nextion (Nextion LCD -> Transceiver) +// +//=================================================================== +#define CMD_NOW_DISP '0' //c0 +char L_nowdisp = -1; //Sended nowdisp + +#define CMD_VFO_TYPE 'v' //cv +char L_vfoActive; //vfoActive + +#define CMD_CURR_FREQ 'c' //vc +unsigned long L_vfoCurr; //vfoA +#define CMD_CURR_MODE 'c' //cc +byte L_vfoCurr_mode; //vfoA_mode + +#define CMD_VFOA_FREQ 'a' //va +unsigned long L_vfoA; //vfoA +#define CMD_VFOA_MODE 'a' //ca +byte L_vfoA_mode; //vfoA_mode + +#define CMD_VFOB_FREQ 'b' //vb +unsigned long L_vfoB; //vfoB +#define CMD_VFOB_MODE 'b' //cb +byte L_vfoB_mode; //vfoB_mode + +#define CMD_IS_RIT 'r' //cr +char L_ritOn; +#define CMD_RIT_FREQ 'r' //vr +unsigned long L_ritTxFrequency; //ritTxFrequency + +#define CMD_IS_TX 't' //ct +char L_inTx; + +#define CMD_IS_DIALLOCK 'l' //cl +byte L_isDialLock; //byte isDialLock + +#define CMD_IS_SPLIT 's' //cs +byte L_Split; //isTxType +#define CMD_IS_TXSTOP 'x' //cx +byte L_TXStop; //isTxType + +#define CMD_TUNEINDEX 'n' //cn +byte L_tuneStepIndex; //byte tuneStepIndex + +#define CMD_SMETER 'p' //cs +byte L_scaledSMeter; //scaledSMeter + +#define CMD_SIDE_TONE 't' //vt +unsigned long L_sideTone; //sideTone +#define CMD_KEY_TYPE 'k' //ck +byte L_cwKeyType = -1; //L_cwKeyType 0: straight, 1 : iambica, 2: iambicb + +#define CMD_CW_SPEED 's' //vs +unsigned int L_cwSpeed; //cwSpeed + +#define CMD_CW_DELAY 'y' //vy +byte L_cwDelayTime=-1; //cwDelayTime + +#define CMD_CW_STARTDELAY 'e' //ve +byte L_delayBeforeCWStartTime=-1; //byte delayBeforeCWStartTime + +#define CMD_ATT_LEVEL 'f' //vf +byte L_attLevel; + +byte L_isIFShift; //1 = ifShift, 2 extend +#define CMD_IS_IFSHIFT 'i' //ci + +int L_ifShiftValue; +#define CMD_IFSHIFT_VALUE 'i' //vi + +byte L_sdrModeOn; +#define CMD_SDR_MODE 'j' //cj + +#define CMD_UBITX_INFO 'm' //cm Complete Send uBITX Information + +//Once Send Data, When boot +//arTuneStep, When boot, once send +//long arTuneStep[5]; +#define CMD_AR_TUNE1 '1' //v1 +#define CMD_AR_TUNE2 '2' //v2 +#define CMD_AR_TUNE3 '3' //v3 +#define CMD_AR_TUNE4 '4' //v4 +#define CMD_AR_TUNE5 '5' //v5 + + +#define CMD_IS_CW_SHIFT_DISPLAY 'h' //ch +byte L_isShiftDisplayCWFreq; //byte isShiftDisplayCWFreq + +#define CMD_CW_SHIFT_ADJUST 'h' //vh +int L_shiftDisplayAdjustVal; //int shiftDisplayAdjustVal + +//0:CW Display Shift Confirm, 1 : IFshift save +#define CMD_COMM_OPTION 'o' //vo +byte L_commonOption0; //byte commonOption0 + +//0:Line Toggle, 1 : Always display Callsign, 2 : scroll display, 3 : s.meter +#define CMD_DISP_OPTION1 'p' //vp +byte L_displayOption1; //byte displayOption1 +#define CMD_DISP_OPTION2 'q' //vq +byte L_displayOption2; //byte displayOption2 (Reserve) + +#define CMD_TEXT_LINE0 '0' //s0 +#define CMD_TEXT_LINE1 '1' //s1 + +#define CMD_CW_TEXT 'a' //sa +#define CMD_CALLSIGN 'c' //sc +#define CMD_VERSION 'v' //sv + +#define TS_CMD_MODE 1 +#define TS_CMD_FREQ 2 +#define TS_CMD_BAND 3 +#define TS_CMD_VFO 4 +#define TS_CMD_SPLIT 5 +#define TS_CMD_RIT 6 +#define TS_CMD_TXSTOP 7 +#define TS_CMD_SDR 8 +#define TS_CMD_LOCK 9 //Dial Lock +#define TS_CMD_ATT 10 //ATT +#define TS_CMD_IFS 11 //IFS Enabled +#define TS_CMD_IFSVALUE 12 //IFS VALUE +#define TS_CMD_STARTADC 13 +#define TS_CMD_STOPADC 14 +#define TS_CMD_SPECTRUMOPT 15 //Option for Spectrum +#define TS_CMD_SPECTRUM 16 //Get Spectrum Value +#define TS_CMD_TUNESTEP 17 //Get Spectrum Value +#define TS_CMD_WPM 18 //Set WPM +#define TS_CMD_KEYTYPE 19 //Set KeyType + +#define TS_CMD_SWTRIG 21 //SW Action Trigger for WSPR and more +#define TS_CMD_READMEM 31 //Read EEProm +#define TS_CMD_WRITEMEM 32 //Write EEProm +#define TS_CMD_LOOPBACK0 74 //Loopback1 (Response to Loopback Channgel) +#define TS_CMD_LOOPBACK1 75 //Loopback2 (Response to Loopback Channgel) +#define TS_CMD_LOOPBACK2 76 //Loopback3 (Response to Loopback Channgel) +#define TS_CMD_LOOPBACK3 77 //Loopback4 (Response to Loopback Channgel) +#define TS_CMD_LOOPBACK4 78 //Loopback5 (Response to Loopback Channgel) +#define TS_CMD_LOOPBACK5 79 //Loopback6 (Response to Loopback Channgel) +#define TS_CMD_FACTORYRESET 85 //Factory Reset +#define TS_CMD_UBITX_REBOOT 95 //Reboot + +char nowdisp = 0; + +#define SWS_HEADER_CHAR_TYPE 'c' //1Byte Protocol Prefix +#define SWS_HEADER_INT_TYPE 'v' //Numeric Protocol Prefex +#define SWS_HEADER_STR_TYPE 's' //for TEXT Line compatiable Character LCD Control + +//Control must have prefix 'v' or 's' +char softSTRHeader[11] = {'p', 'm', '.', 's', '0', '.', 't', 'x', 't', '=', '\"'}; +char softINTHeader[10] = {'p', 'm', '.', 'v', '0', '.', 'v', 'a', 'l', '='}; +const byte ADCIndex[6] = {A0, A1, A2, A3, A6, A7}; + +//send data for Nextion LCD +void SendHeader(char varType, char varIndex) +{ + if (varType == SWS_HEADER_STR_TYPE) + { + softSTRHeader[4] = varIndex; + for (int i = 0; i < 11; i++) + SWSerial_Write(softSTRHeader[i]); + } + else + { + softINTHeader[4] = varIndex; + for (int i = 0; i < 10; i++) + SWSerial_Write(softINTHeader[i]); + } +} + +#define INT_ETX 0 +#define STR_ETX 1 +#define TMP_ETX 2 +//Send 0xFF, 0xFF, 0xFF +//etxType : INT_ETX = 0xFF, 0xFF, 0xFF +// STR_ETX = ", 0xFF, 0xFF, 0xFF +// TEMP_ETX = softTemp, 0xFF, 0xFF, 0xff + +void SendCommandETX(char etxType) +{ + if (etxType == 2) + { + SWSerial_Print(softTemp); + } + else if (etxType == 1) + { + SWSerial_Print("\""); + } + + SWSerial_Write(0xff); + SWSerial_Write(0xff); + SWSerial_Write(0xff); +} + +void SendCommandUL(char varIndex, unsigned long sendValue) +{ + SendHeader(SWS_HEADER_INT_TYPE, varIndex); + + memset(softTemp, 0, 20); + ultoa(sendValue, softTemp, DEC); + SendCommandETX(TMP_ETX); +} + +void SendCommandL(char varIndex, long sendValue) +{ + SendHeader(SWS_HEADER_INT_TYPE, varIndex); + + memset(softTemp, 0, 20); + ltoa(sendValue, softTemp, DEC); + SendCommandETX(TMP_ETX); +} + +void SendCommandStr(char varIndex, char* sendValue) +{ + SendHeader(SWS_HEADER_STR_TYPE, varIndex); + + SWSerial_Print(sendValue); + SendCommandETX(STR_ETX); +} + +//Send String data with duplicate check +void SendTextLineBuff(char lineNumber) +{ + //Check Duplicated data + if (strcmp(softBuffLines[lineNumber], softBuffSended[lineNumber])) + { + SendHeader(SWS_HEADER_STR_TYPE, lineNumber + 0x30); //s0.txt, s1.txt + + SWSerial_Print(softBuffLines[lineNumber]); + SendCommandETX(STR_ETX); + + strcpy(softBuffSended[lineNumber], softBuffLines[lineNumber]); + } +} + +void SendTextLineStr(char lineNumber, char* sendValue) +{ + int i = 0; + for (i = 0; i < 16; i++) + { + if (sendValue[i] == 0x00) + break; + else + softBuffLines[lineNumber][i] = sendValue[i]; + } + + for (;i < 20; i++) + { + softBuffLines[lineNumber][i] = ' '; + } + + softBuffLines[lineNumber][TEXT_LINE_LENGTH + 1] = 0x00; + SendTextLineBuff(lineNumber); +} + +void SendEEPromData(char varIndex, int eepromStartIndex, int eepromEndIndex, char offsetTtype) +{ + SendHeader(SWS_HEADER_STR_TYPE, varIndex); + + for (int i = eepromStartIndex; i <= eepromEndIndex; i++) + { + SWSerial_Write(EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i)); + } + + SendCommandETX(STR_ETX); +} + +uint8_t softBuff1Num[14] = {'p', 'm', '.', 'c', '0', '.', 'v', 'a', 'l', '=', 0, 0xFF, 0xFF, 0xFF}; +void SendCommand1Num(char varType, char sendValue) //0~9 : Mode, nowDisp, ActiveVFO, IsDialLock, IsTxtType, IsSplitType +{ + softBuff1Num[4] = varType; + softBuff1Num[10] = sendValue + 0x30; + + for (int i = 0; i < 14; i++) + SWSerial_Write(softBuff1Num[i]); +} + +void SetSWActivePage(char newPageIndex) +{ + if (L_nowdisp != newPageIndex) + { + L_nowdisp = newPageIndex; + SendCommand1Num(CMD_NOW_DISP, L_nowdisp); + } +} +//=================================================================== +//End of Nextion LCD Protocol +//=================================================================== + +// The generic routine to display one line on the LCD +void printLine(unsigned char linenmbr, const char *c) { + SendTextLineStr(linenmbr, c); +} + +void printLineF(char linenmbr, const __FlashStringHelper *c) +{ + int i; + char tmpBuff[21]; + PGM_P p = reinterpret_cast(c); + + for (i = 0; i < 21; i++){ + unsigned char fChar = pgm_read_byte(p++); + tmpBuff[i] = fChar; + if (fChar == 0) + break; + } + + printLine(linenmbr, tmpBuff); +} + +#define LCD_MAX_COLUMN 20 +void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetTtype) +{ + int colIndex = lcdColumn; + for (byte i = eepromStartIndex; i <= eepromEndIndex; i++) + { + if (++lcdColumn <= LCD_MAX_COLUMN) + softBuffLines[linenmbr][colIndex++] = EEPROM.read((offsetTtype == 0 ? USER_CALLSIGN_DAT : WSPR_MESSAGE1) + i); + else + break; + } + + SendTextLineBuff(linenmbr); +} + +// 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 for Nextion LCD +//unsigned long +byte nowPageIndex = 0; + +//sendType == 1 not check different +void sendUIData(int sendType) +{ + char nowActiveVFO = vfoActive == VFO_A ? 0 : 1; + + //#define CMD_VFO_TYPE 'v' //cv + if (L_vfoActive != nowActiveVFO) + { + L_vfoActive = nowActiveVFO; + SendCommand1Num(CMD_VFO_TYPE, L_vfoActive); + } + + //#define CMD_CURR_FREQ 'c' //vc + if (L_vfoCurr != frequency) + { + L_vfoCurr = frequency; + SendCommandUL(CMD_CURR_FREQ, frequency); + } + + //#define CMD_CURR_MODE 'c' //cc + byte vfoCurr_mode = modeToByte(); + if (L_vfoCurr_mode != vfoCurr_mode) + { + L_vfoCurr_mode = vfoCurr_mode; + SendCommand1Num(CMD_CURR_MODE, L_vfoCurr_mode); + } + + //if auto cw key mode, exit + //if (isCWAutoMode != 0 || menuOn != 0) + if (isCWAutoMode != 0) + return; + + //nowPageIndex = 0; + if (menuOn==0) + { + if (sendType == 0) + { + SetSWActivePage(0); + } + else + { + SetSWActivePage(0); + } + } + else + { + //Text Line Mode + SetSWActivePage(1); + } + + //#define CMD_VFOA_FREQ 'a' //va + //VFOA + if (L_vfoA != vfoA) + { + L_vfoA = vfoA; + SendCommandUL(CMD_VFOA_FREQ, L_vfoA); + } + + //#define CMD_VFOA_MODE 'a' //ca + if (L_vfoA_mode != vfoA_mode) + { + L_vfoA_mode = vfoA_mode; + SendCommand1Num(CMD_VFOA_MODE, L_vfoA_mode); + } + + //#define CMD_VFOB_FREQ 'b' //vb + //VFOB + if (L_vfoB != vfoB) + { + L_vfoB = vfoB; + SendCommandUL(CMD_VFOB_FREQ, L_vfoB); + } + + //#define CMD_VFOB_MODE 'b' //cb + if (L_vfoB_mode != vfoB_mode) + { + L_vfoB_mode = vfoB_mode; + SendCommand1Num(CMD_VFOB_MODE, L_vfoB_mode); + } + + //byte isDialLock = ((isTxType & 0x01) == 0x01) ? 1 : 0; + if (L_isDialLock != isDialLock) + { + L_isDialLock = isDialLock; + SendCommand1Num(CMD_IS_DIALLOCK, L_isDialLock); + } + + //#define CMD_IS_RIT 'r' //cr + if (L_ritOn != ritOn) + { + L_ritOn = ritOn; + SendCommand1Num(CMD_IS_RIT, L_ritOn); + } + + //#define CMD_RIT_FREQ 'r' //vr + //unsigned long L_ritTxFrequency; //ritTxFrequency + if (L_ritTxFrequency != ritTxFrequency) + { + L_ritTxFrequency = ritTxFrequency; + SendCommandUL(CMD_RIT_FREQ, L_ritTxFrequency); + } + + //#define CMD_IS_TX 't' //ct + //char L_inTx; + if (L_inTx != inTx) + { + L_inTx = inTx; + SendCommand1Num(CMD_IS_TX, L_inTx); + } + + //#define CMD_IS_DIALLOCK 'l' //cl + //byte L_isDialLock; //byte isDialLock + if (L_isDialLock != isDialLock) + { + L_isDialLock = isDialLock; + SendCommand1Num(CMD_IS_DIALLOCK, L_isDialLock); + } + + //#define CMD_IS_SPLIT 's' //cs + //byte L_Split; //isTxType + if (L_Split != splitOn) + { + L_Split = splitOn; + SendCommand1Num(CMD_IS_SPLIT, L_Split); + } + + + //#define CMD_IS_TXSTOP 'x' //cx + byte isTXStop = ((isTxType & 0x01) == 0x01); + if (L_TXStop != isTXStop) + { + L_TXStop = isTXStop; + SendCommand1Num(CMD_IS_TXSTOP, L_TXStop); + } + + //#define CMD_TUNEINDEX 'n' //cn + if (L_tuneStepIndex != tuneStepIndex) + { + L_tuneStepIndex = tuneStepIndex; + SendCommand1Num(CMD_TUNEINDEX, L_tuneStepIndex); + } + + //#define CMD_SMETER 'p' //cp + if (L_scaledSMeter != scaledSMeter) + { + L_scaledSMeter = scaledSMeter; + SendCommand1Num(CMD_SMETER, L_scaledSMeter); + } + + //#define CMD_SIDE_TONE 't' //vt + if (L_sideTone != sideTone) + { + L_sideTone = sideTone; + SendCommandL(CMD_SIDE_TONE, L_sideTone); + } + + //#define CMD_KEY_TYPE 'k' //ck + if (L_cwKeyType != cwKeyType) + { + L_cwKeyType = cwKeyType; + SendCommand1Num(CMD_KEY_TYPE, L_cwKeyType); + } + + //#define CMD_CW_SPEED 's' //vs + if (L_cwSpeed != cwSpeed) + { + L_cwSpeed = cwSpeed; + SendCommandL(CMD_CW_SPEED, L_cwSpeed); + } + + //#define CMD_CW_DELAY 'y' //vy + if (L_cwDelayTime != cwDelayTime) + { + L_cwDelayTime = cwDelayTime; + SendCommandL(CMD_CW_DELAY, L_cwDelayTime); + } + + //#define CMD_CW_STARTDELAY 'e' //ve + if (L_delayBeforeCWStartTime != delayBeforeCWStartTime) + { + L_delayBeforeCWStartTime = delayBeforeCWStartTime; + SendCommandL(CMD_CW_STARTDELAY, L_delayBeforeCWStartTime); + } + + //#define CMD_ATT_LEVEL 'f' //vf + if (L_attLevel != attLevel) + { + L_attLevel = attLevel; + SendCommandL(CMD_ATT_LEVEL, L_attLevel); + } + + //#define CMD_IS_IFSHIFT 'i' + if (L_isIFShift != isIFShift) + { + L_isIFShift = isIFShift; + SendCommand1Num(CMD_IS_IFSHIFT, L_isIFShift); + } + + //#define CMD_IFSHIFT_VALUE 'i' + if (L_ifShiftValue != ifShiftValue) + { + L_ifShiftValue = ifShiftValue; + SendCommandL(CMD_IFSHIFT_VALUE, L_ifShiftValue); + } + + //#define CMD_SDR_MODE 'j' //cj + if (L_sdrModeOn != sdrModeOn) + { + L_sdrModeOn = sdrModeOn; + SendCommand1Num(CMD_SDR_MODE, L_sdrModeOn); + } +} + +void updateDisplay() { + sendUIData(0); //UI +} + +//**************************************************************** +// Spectrum for Range scan and Band Scan +//**************************************************************** +#define RESPONSE_SPECTRUM 0 +#define RESPONSE_EEPROM 1 +#define RESPONSE_EEPROM_HEX_F 89 //C Language order +#define RESPONSE_EEPROM_HEX_R 72 //Nextion order (Reverse) +#define RESPONSE_EEPROM_STR 87 //String + +const uint8_t ResponseHeader[11]={'p', 'm', '.', 's', 'h', '.', 't', 'x', 't', '=', '"'}; +const char HexCodes[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', }; + +//void sendSpectrumData(unsigned long startFreq, unsigned long incStep, int scanCount, int delayTime, int sendCount) +//sendResponseData(RESPONSE_EEPROM, 0, eepromIndex, eepromReadLength, eepromDataType, 1); +//protocol Type : 0 - Spectrum, 1 : EEProm +//startFreq : Spectrum - Frequency, EEProm - 0 +//sendOption1 : Spectrum - 1 Step Frequency, EEProm - EEProm Start Address +//scanCount : Spectrum - 1 Set Length, EEProm - Read Length +//sendOption2 : Spectrum - Value offset (because support various S-Meter), EEProm - EEProm Response DataType (0:HEX, 1:String) +//sendCount : Spectrum - All scan set count, EEProm - always 1 +void sendResponseData(int protocolType, unsigned long startFreq, unsigned int sendOption1, int readCount, int sendOption2, int sendCount) //Spectrum and EEProm Data +{ + unsigned long beforFreq = frequency; + unsigned long k; + uint8_t adcBytes[200]; //Maximum 200 Step + + //Voltage drop + //scanResult[0] = analogRead(ANALOG_SMETER); + //adcBytes[0] = analogRead(ANALOG_SMETER); + //delay(10); + int readedValue = 0; + + for (int si = 0; si < sendCount; si++) + { + for (int i = 0; i < 11; i++) + SWSerial_Write(ResponseHeader[i]); + + for (k = 0; k < readCount; k ++) + { + if (protocolType == RESPONSE_SPECTRUM) + { + //Spectrum Data + //Sampling Range + setFrequency(startFreq + (k * sendOption1)); + //Wait time for charging + //delay(10); + +#ifdef USE_I2CSMETER + readedValue = GetI2CSmeterValue(I2CMETER_UNCALCS); +#else + + //ADC + readedValue = analogRead(ANALOG_SMETER); + readedValue -= (sendOption2 * 3); //0 ~ 765 + //Down Scale + readedValue /= 2; + if (readedValue < 0) + { + readedValue = 0; + } + else if (readedValue>255) + { + readedValue=255; + } +#endif + } + else + { + readedValue = EEPROM.read(((sendOption2 == RESPONSE_EEPROM_HEX_R) ? (readCount - k - 1) : k) + sendOption1); + } + + if (protocolType == RESPONSE_EEPROM && sendOption2 == RESPONSE_EEPROM_STR) //None HEX + { + SWSerial_Write(readedValue); + } + else + { + SWSerial_Write(HexCodes[readedValue >> 4]); + SWSerial_Write(HexCodes[readedValue & 0xf]); + } + } + + SendCommandETX(STR_ETX); + } //end of for +} + +//**************************************************************** +//Receive command and processing from External device (LCD or MCU) +//**************************************************************** +int spectrumSendCount = 10; //count of full scan and Send +int spectrumOffset = 0; //offset position +int spectrumScanCount = 100; //Maximum 200 +unsigned int spectrumIncStep = 1000; //Increaase Step +extern uint8_t receivedCommandLength; +extern void SWSerial_Read(uint8_t * receive_cmdBuffer); +uint8_t swr_buffer[20]; + +//SoftwareSerial_Process +void SWS_Process(void) +{ + //Received Command from touch screen + if (receivedCommandLength > 0) + { + SWSerial_Read(swr_buffer); + + int8_t comandLength = receivedCommandLength; + int8_t commandStartIndex = -1; + receivedCommandLength = 0; + + //Data Process + //comandLength //Find start Length + for (int i = 0; i < comandLength - 3; i++) + { + if (swr_buffer[i] == 0x59 && swr_buffer[i+ 1] == 0x58 && swr_buffer[i + 2] == 0x68) + { + commandStartIndex = i; + break; + } + } //end of for + + if (commandStartIndex != -1) + { + //Complete received command from touch screen + uint8_t commandType = swr_buffer[commandStartIndex + 3]; + + if (commandType == TS_CMD_MODE) + { + byteToMode(swr_buffer[commandStartIndex + 4], 1); + } + else if (commandType == TS_CMD_FREQ) + { + unsigned long *tempFreq; + tempFreq = (unsigned long *)(&swr_buffer[commandStartIndex + 4]); + //if (*tempFreq > 3000) //for loss protcol + //{ + frequency = *tempFreq; + //} + } + else if (commandType == TS_CMD_BAND) + { + char currentBandIndex = -1; + if (tuneTXType == 2 || tuneTXType == 3 || tuneTXType == 102 || tuneTXType == 103) + { //only ham band move + currentBandIndex = getIndexHambanBbyFreq(frequency); + + if (currentBandIndex >= 0) + { + saveBandFreqByIndex(frequency, modeToByte(), currentBandIndex); + } + } + setNextHamBandFreq(frequency, swr_buffer[commandStartIndex + 4] == 1 ? -1 : 1); //Prior Band + } + else if (commandType == TS_CMD_VFO) + { + menuVfoToggle(1); //Vfo Toggle + } + else if (commandType == TS_CMD_SPLIT) + { + menuSplitOnOff(10); + } + else if (commandType == TS_CMD_RIT) + { + menuRitToggle(1); + } + else if (commandType == TS_CMD_TXSTOP) + { + menuTxOnOff(1, 0x01); + } + else if (commandType == TS_CMD_SDR) + { + menuSDROnOff(1); + } + else if (commandType == TS_CMD_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 + } + else if (commandType == TS_CMD_ATT) + { + attLevel = swr_buffer[commandStartIndex + 4]; + } + else if (commandType == TS_CMD_IFS) + { + isIFShift = isIFShift ? 0 : 1; //Toggle + } + else if (commandType == TS_CMD_IFSVALUE) + { + ifShiftValue = *(long *)(&swr_buffer[commandStartIndex + 4]); + } + else if (commandType == TS_CMD_STARTADC) + { + int startIndex = swr_buffer[commandStartIndex + 4]; + int endIndex = swr_buffer[commandStartIndex + 5]; + int adcCheckInterval = swr_buffer[commandStartIndex + 6] * 10; + int nowCheckIndex = startIndex; + + while(1 == 1) + { + if (receivedCommandLength > 0) + { + break; + } + + SendCommandL('n', nowCheckIndex); //Index Input + SendCommandL('x', analogRead(ADCIndex[nowCheckIndex++])); + + if (nowCheckIndex > endIndex) + nowCheckIndex = startIndex; + + delay(adcCheckInterval); + } //end of while + } + else if (commandType == TS_CMD_STOPADC) + { + //None Action + return; + } + else if (commandType == TS_CMD_SPECTRUM) + { + //sendSpectrumData(unsigned long startFreq, unsigned int incStep, int scanCount, int delayTime, int sendCount) + //sendSpectrumData(frequency - (1000L * 50), 1000, 100, 0, 10); + //sendSpectrumData(*(long *)(&swr_buffer[commandStartIndex + 4]), spectrumIncStep, spectrumScanCount, spectrumDelayTime, spectrumSendCount); + unsigned long beforeFreq = frequency; + sendResponseData(RESPONSE_SPECTRUM, *(long *)(&swr_buffer[commandStartIndex + 4]), spectrumIncStep, spectrumScanCount, spectrumOffset, spectrumSendCount); + frequency = beforeFreq; + } + else if (commandType == TS_CMD_SPECTRUMOPT) + { + //sendSpectrumData(unsigned long startFreq, unsigned int incStep, int scanCount, int delayTime, int sendCount) + //sendSpectrumData(frequency - (1000L * 50), 1000, 100, 0, 10); + spectrumSendCount = swr_buffer[commandStartIndex + 4]; //count of full scan and Send + spectrumOffset = swr_buffer[commandStartIndex + 5]; //Scan interval time + spectrumScanCount = swr_buffer[commandStartIndex + 6]; //Maximum 120 + spectrumIncStep = swr_buffer[commandStartIndex + 7] * 20; //Increaase Step + } + else if (commandType == TS_CMD_TUNESTEP) //Set Tune Step + { + tuneStepIndex = swr_buffer[commandStartIndex + 4]; //Tune Step Index + } + else if (commandType == TS_CMD_WPM) //Set WPM + { + cwSpeed = swr_buffer[commandStartIndex + 4]; // + } + else if (commandType == TS_CMD_KEYTYPE) //Set Key Type + { + cwKeyType = swr_buffer[commandStartIndex + 4]; + + //for reduce program memory + Iambic_Key = cwKeyType != 0; + //if (cwKeyType == 0) + // Iambic_Key = false; + //else + //Iambic_Key = true; + if (cwKeyType == 1) + keyerControl &= ~IAMBICB; + else + keyerControl |= IAMBICB; + //} + } + else if (commandType == TS_CMD_SWTRIG) + { + TriggerBySW = 1; //Action Trigger by Software + } + else if (commandType == TS_CMD_READMEM ) //Read Mem + { + uint16_t eepromIndex = *(uint16_t *)(&swr_buffer[commandStartIndex + 4]); + byte eepromReadLength = swr_buffer[commandStartIndex + 6]; + byte eepromDataType = swr_buffer[commandStartIndex + 7]; //0 : Hex, 1 : String + + sendResponseData(RESPONSE_EEPROM, 0, eepromIndex, eepromReadLength, eepromDataType, 1); + } + else if (commandType == TS_CMD_WRITEMEM) //Write Mem + { + /* + Address : 2 byte int + Length : Data Length + Checksum : (Addr0+Addr1+Len) %256 + Data : Variable (Max 23) + */ + uint16_t eepromIndex = *(uint16_t *)(&swr_buffer[commandStartIndex + 4]); + byte writeLength = swr_buffer[commandStartIndex + 6]; + byte writeCheckSum = swr_buffer[commandStartIndex + 7]; + + //Check Checksum + if (writeCheckSum == (swr_buffer[commandStartIndex + 4] + swr_buffer[commandStartIndex + 5] + swr_buffer[commandStartIndex + 6])) + //if (writeCheckSum == (swr_buffer[commandStartIndex + 4] + swr_buffer[commandStartIndex + 5] + writeLength)) + { + //if (eepromIndex > 64) //Safe #1 +#ifdef UBITX_DISPLAY_NEXTION_SAFE + //Safe #2 + if (eepromIndex < 770 || eepromIndex > 775 ) + { + eepromIndex = -2; + } + else +#else + if (1 == 1) +#endif + { + for (int i = 0; i < writeLength; i++) + EEPROM.write(eepromIndex + i , swr_buffer[commandStartIndex + 8 + i]); + } + } + else + { + eepromIndex = -2; + } + SendCommandL('n', eepromIndex); //Index Input + } + //else if (TS_CMD_LOOPBACK0 <= commandType && commandType <= TS_CMD_LOOPBACK5) //Loop back Channel 0 ~ 5 Loop back Channel 1~5 : Reserve + else if (TS_CMD_LOOPBACK0 == commandType) //Loop back Channel 0 ~ 5 + { + SendCommandUL('v', *(unsigned long *)&swr_buffer[commandStartIndex + 4]); //Return data + SendCommandUL('g', commandType); //Index Input + //return; + } + else if (commandType == TS_CMD_FACTORYRESET || commandType == TS_CMD_UBITX_REBOOT) + { + if (*(unsigned long *)&swr_buffer[commandStartIndex + 4] == 1497712748) + { + if (commandType == TS_CMD_UBITX_REBOOT) + { + FrequencyToVFO(1); //Save current Frequency and Mode to eeprom + asm volatile (" jmp 0"); + } + else + { + for (unsigned int i = 0; i < 32; i++) //factory setting range + EEPROM.write(i, EEPROM.read(FACTORY_VALUES + i)); //65~96 => 0~31 + } + } + } + + setFrequency(frequency); + SetCarrierFreq(); + updateDisplay(); + } + } +} + +char checkCount = 0; +char checkCountSMeter = 0; + +//execute interval : 0.25sec +void idle_process() +{ + //S-Meter Display + if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency)) + { +#ifdef USE_I2CSMETER + scaledSMeter = GetI2CSmeterValue(I2CMETER_CALCS); +#else + int newSMeter; + + newSMeter = analogRead(ANALOG_SMETER) / 4; + currentSMeter = newSMeter; + + scaledSMeter = 0; + for (byte s = 8; s >= 1; s--) { + if (currentSMeter > sMeterLevels[s]) { + scaledSMeter = s; + break; + } + } + +#endif + checkCountSMeter = 0; //Reset Latency time + } //end of S-Meter + + sendUIData(1); +} + +//When boot time, send data +void SendUbitxData(void) +{ + //Wait for ready other device (LCD, DSP and more) + //delay(500); + delay_background(500, 2); + + SendCommandL(CMD_AR_TUNE1, arTuneStep[0]); + SendCommandL(CMD_AR_TUNE2, arTuneStep[1]); + SendCommandL(CMD_AR_TUNE3, arTuneStep[2]); + SendCommandL(CMD_AR_TUNE4, arTuneStep[3]); + SendCommandL(CMD_AR_TUNE5, arTuneStep[4]); + + SendCommand1Num(CMD_IS_CW_SHIFT_DISPLAY, isShiftDisplayCWFreq); + SendCommandL(CMD_CW_SHIFT_ADJUST, shiftDisplayAdjustVal); + SendCommandL(CMD_COMM_OPTION, commonOption0); + SendCommandL(CMD_DISP_OPTION1, displayOption1); + + unsigned long nextionDisplayOption; + EEPROM.get(EXTERNAL_DEVICE_OPT1, nextionDisplayOption); + SendCommandUL(CMD_DISP_OPTION2, nextionDisplayOption); + + SendCommandStr(CMD_VERSION, (char *)("+v1.097")); //Version + SendEEPromData(CMD_CALLSIGN, 0, userCallsignLength -1, 0); + + /* + //Frequency of Bands + for (int i = 0; i < 11; i++) + SWSerial_Write(SpectrumHeader[i]); + + byte *tmpByte; + tmpByte = (byte *)hamBandRange; + for (byte i = 0; i < (useHamBandCount -1) * 4; i++) + { + SWSerial_Write(HexCodes[*tmpByte >> 4]); + SWSerial_Write(HexCodes[*tmpByte & 0xf]); + tmpByte++; + } + + for (int i = 0; i < 4; i++) + SWSerial_Write(SpectrumFooter[i]); + */ + + //Complte Send Info + SendCommand1Num(CMD_UBITX_INFO, 1); + + //Page Init + L_nowdisp = 0; + SendCommand1Num(CMD_NOW_DISP, L_nowdisp); +} + + +//AutoKey LCD Display Routine +void Display_AutoKeyTextIndex(byte textIndex) +{ + byte diplayAutoCWLine = 0; + + if ((displayOption1 & 0x01) == 0x01) + diplayAutoCWLine = 1; + //LCD_SetCursor(0, diplayAutoCWLine); + + softBuffLines[diplayAutoCWLine][0] = byteToChar(textIndex); + softBuffLines[diplayAutoCWLine][1] = ':'; + + SendTextLineBuff(diplayAutoCWLine); +} + +void LCD_CreateChar(uint8_t location, uint8_t charmap[]) +{ +} + +void updateLine2Buffer(char displayType) +{ +} + +//not use with Nextion LCD +void DisplayCallsign(byte callSignLength) +{ +} + +//Not use with Nextion LCD +void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) +{ +} + +#endif diff --git a/ubitx_20/ubitx_menu.ino b/ubitx_20/ubitx_menu.ino index 42bf7c0..9bcd126 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -389,7 +389,14 @@ void menuVfoToggle(int btn) ritDisable(); setFrequency(frequency); - menuClearExit(0); + +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD + menuClearExit(0); +#endif + } } @@ -406,17 +413,20 @@ void menuSplitOnOff(int btn){ if (splitOn == 1){ splitOn = 0; printLineF2(F("SPT Off")); - //printLineF2(F("[OFF]")); } else { splitOn = 1; if (ritOn == 1) ritOn = 0; printLineF2(F("SPT On")); - //printLineF2(F("[ON]")); } - + +#ifdef USE_SW_SERIAL + menuOn = 0; +#else +//Only Clear And Delay for Character LCD menuClearExit(500); +#endif } } @@ -438,8 +448,13 @@ void menuTxOnOff(int btn, byte optionType){ isTxType &= ~(optionType); printLineF2(F("TX ON")); } - + +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD menuClearExit(500); +#endif } } @@ -472,7 +487,13 @@ void menuSDROnOff(int btn) EEPROM.put(ENABLE_SDR, sdrModeOn); setFrequency(frequency); SetCarrierFreq(); + +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD menuClearExit(500); +#endif } } @@ -498,9 +519,9 @@ void menuCWAutoKey(int btn){ printLineF1(F("PTT to Send")); delay_background(500, 0); - updateDisplay(); beforeCWTextIndex = 255; //255 value is for start check isCWAutoMode = 1; + updateDisplay(); menuOn = 0; } @@ -666,7 +687,11 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob ifShiftValue = targetValue; else attLevel = targetValue; - + +#ifdef USE_SW_SERIAL + menuOn=2; + updateDisplay(); +#endif setFrequency(frequency); SetCarrierFreq(); } @@ -726,7 +751,14 @@ void menuCWSpeed(int btn){ //printLineF2(F("CW Speed set!")); cwSpeed = 1200 / wpm; EEPROM.put(CW_SPEED, cwSpeed); - menuClearExit(1000); + //menuClearExit(1000); +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD + menuClearExit(1000); +#endif + } //Modified by KD8CEC @@ -747,44 +779,22 @@ void menuSetupCwTone(int btn){ 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); + printLineF2(F("Sidetone set!")); + EEPROM.put(CW_SIDETONE, sideTone); + + //delay_background(2000, 0); + //menuClearExit(0); +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD + delay_background(2000, 0); + menuClearExit(0); +#endif } - - //Modified by KD8CEC void menuSetupCwDelay(int btn){ //int knob = 0; @@ -795,44 +805,18 @@ void menuSetupCwDelay(int btn){ return; } - //printLineF1(F("Press, set Delay")); - /* - strcpy(b, "DELAY:"); - itoa(tmpCWDelay,c, 10); - strcat(b, c); - printLine2(b); - */ - //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){ - if (tmpCWDelay > 3 && knob < 0) - tmpCWDelay -= 10; - if (tmpCWDelay < 2500 && knob > 0) - tmpCWDelay += 10; - - strcpy(b, "DELAY:"); - itoa(tmpCWDelay,c, 10); - strcat(b, c); - printLine2(b); - } - //abort if this button is down - if (btnDown()) - break; - - Check_Cat(0); //To prevent disconnections - } -*/ - //save the setting - //printLineF2(F("CW Delay set!")); cwDelayTime = tmpCWDelay / 10; EEPROM.put(CW_DELAY, cwDelayTime); - menuClearExit(1000); + //menuClearExit(1000); +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD + menuClearExit(1000); +#endif } //CW Time delay by KD8CEC @@ -851,41 +835,17 @@ void menuSetupTXCWInterval(int btn){ tmpTXCWInterval = getValueByKnob(0, tmpTXCWInterval, 0, 500, 2, "Delay", 2); //0 : Generate Tone, targetValue, minKnobValue, maxKnobValue, stepSize -/* - while(!btnDown()){ - - if (needDisplayInformation == 1) { - strcpy(b, "Start Delay:"); - itoa(tmpTXCWInterval,c, 10); - strcat(b, c); - printLine2(b); - needDisplayInformation = 0; - } - - knob = enc_read(); - if (knob != 0){ - if (tmpTXCWInterval > 0 && knob < 0) - tmpTXCWInterval -= 2; - if (tmpTXCWInterval < 500 && knob > 0) - tmpTXCWInterval += 2; - - needDisplayInformation = 1; - } - //abort if this button is down - //if (btnDown()) - // break; - - Check_Cat(0); //To prevent disconnections - } -*/ - - - //save the setting - //printLineF2(F("CW Start set!")); delayBeforeCWStartTime = tmpTXCWInterval / 2; EEPROM.put(CW_START, delayBeforeCWStartTime); + //menuClearExit(1000); + +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD + menuClearExit(1000); +#endif - menuClearExit(1000); } //IF Shift function, BFO Change like RIT, by KD8CEC @@ -903,36 +863,7 @@ void menuIFSSetup(int btn){ { 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) @@ -945,7 +876,13 @@ void menuIFSSetup(int btn){ //Store IF Shiift EEPROM.put(IF_SHIFTVALUE, ifShiftValue); - menuClearExit(0); + //menuClearExit(0); +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD + menuClearExit(0); +#endif } } @@ -971,7 +908,15 @@ void menuATTSetup(int btn){ setFrequency(frequency); //SetCarrierFreq(); } + //menuClearExit(0); + +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD menuClearExit(0); +#endif + } } @@ -998,44 +943,10 @@ void menuSelectMode(int btn){ 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) { + if (beforeMode != selectModeType) + { //printLineF1(F("Changed Mode")); if (selectModeType == 0) { cwMode = 0; isUSB = 0; @@ -1054,9 +965,14 @@ void menuSelectMode(int btn){ } SetCarrierFreq(); - setFrequency(frequency); + //menuClearExit(500); +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD menuClearExit(500); +#endif } } @@ -1069,45 +985,11 @@ void menuSetupKeyType(int 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); @@ -1123,7 +1005,14 @@ void menuSetupKeyType(int btn){ keyerControl |= IAMBICB; } + //menuClearExit(1000); +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD menuClearExit(1000); +#endif + } } @@ -1223,7 +1112,191 @@ void doMenu(){ //Below codes are origial code with modified by KD8CEC menuOn = 2; - + TriggerBySW = 0; //Nextion LCD and Other MCU + + //********************************************************************************* + // New type menu for developer by KD8CEC + // Selectable menu + // Version : 1.097 ~ + //********************************************************************************* +#ifndef ENABLE_ADCMONITOR + #define FN_ADCMONITOR 0 +#endif + + #define FN_DEFAULT_MENU 2 //Setup Onff / Exit + #define FN_DEFAULT_SETUP 1 //Exit + + #define FN_BAND_IDX (FN_BAND -1) //0 or -1 + #define FN_VFO_TOGGLE_IDX (FN_BAND_IDX + FN_VFO_TOGGLE) + #define FN_MODE_IDX (FN_VFO_TOGGLE_IDX + FN_MODE) + #define FN_RIT_IDX (FN_MODE_IDX + FN_RIT) + #define FN_IFSHIFT_IDX (FN_RIT_IDX + FN_IFSHIFT) + #define FN_ATT_IDX (FN_IFSHIFT_IDX + FN_ATT) + #define FN_CW_SPEED_IDX (FN_ATT_IDX + FN_CW_SPEED) + #define FN_SPLIT_IDX (FN_CW_SPEED_IDX + FN_SPLIT) + #define FN_VFOTOMEM_IDX (FN_SPLIT_IDX + FN_VFOTOMEM) + #define FN_MEMTOVFO_IDX (FN_VFOTOMEM_IDX + FN_MEMTOVFO) + #define FN_MEMORYKEYER_IDX (FN_MEMTOVFO_IDX + FN_MEMORYKEYER) + #define FN_WSPR_IDX (FN_MEMORYKEYER_IDX + FN_WSPR) + #define FN_SDRMODE_IDX (FN_WSPR_IDX + FN_SDRMODE) + #define FN_SETUP_IDX (FN_SDRMODE_IDX + 1) + #define FN_EXIT_IDX (FN_SETUP_IDX + 1) + #define FN_CALIBRATION_IDX (FN_EXIT_IDX + FN_CALIBRATION) + #define FN_CARRIER_IDX (FN_CALIBRATION_IDX + FN_CARRIER) + #define FN_CWCARRIER_IDX (FN_CARRIER_IDX + FN_CWCARRIER) + #define FN_CWTONE_IDX (FN_CWCARRIER_IDX + FN_CWTONE) + #define FN_CWDELAY_IDX (FN_CWTONE_IDX + FN_CWDELAY) + #define FN_TXCWDELAY_IDX (FN_CWDELAY_IDX + FN_TXCWDELAY) + #define FN_KEYTYPE_IDX (FN_TXCWDELAY_IDX + FN_KEYTYPE) + #define FN_ADCMONITOR_IDX (FN_KEYTYPE_IDX + FN_ADCMONITOR) + #define FN_TXONOFF_IDX (FN_ADCMONITOR_IDX + FN_TXONOFF) + + #define FN_MENU_COUNT (FN_DEFAULT_MENU + FN_BAND + FN_VFO_TOGGLE + FN_MODE + FN_RIT + FN_IFSHIFT + FN_ATT + FN_CW_SPEED + FN_SPLIT + FN_VFOTOMEM + FN_MEMTOVFO + FN_MEMORYKEYER + FN_WSPR + FN_SDRMODE) + #define FN_SETUP_COUNT (FN_DEFAULT_SETUP + FN_CALIBRATION + FN_CARRIER + FN_CWCARRIER + FN_CWTONE + FN_CWDELAY + FN_TXCWDELAY + FN_KEYTYPE + FN_ADCMONITOR + FN_TXONOFF) + #define FN_STEP_COUNT (FN_MENU_COUNT + FN_SETUP_COUNT) + + while (menuOn){ + i = enc_read(); + btnState = btnDown(); + + if (i > 0){ + if (modeCalibrate && select + i < FN_STEP_COUNT * 10) + select += i; + else if (!modeCalibrate && select + i < FN_MENU_COUNT * 10) + select += i; + } + else if (i < 0 && select - i >= -10) + select += i; + + switch (select / 10) + { +#if FN_BAND == 1 + case FN_BAND_IDX : + menuBand(btnState); + break; +#endif +#if FN_VFO_TOGGLE == 1 + case FN_VFO_TOGGLE_IDX : + menuVfoToggle(btnState); + break; +#endif +#if FN_MODE == 1 + case FN_MODE_IDX : + menuSelectMode(btnState); + break; +#endif +#if FN_RIT == 1 + case FN_RIT_IDX : + menuRitToggle(btnState); + break; +#endif +#if FN_IFSHIFT == 1 + case FN_IFSHIFT_IDX : + menuIFSSetup(btnState); + break; +#endif +#if FN_ATT == 1 + case FN_ATT_IDX : + menuATTSetup(btnState); + break; +#endif +#if FN_CW_SPEED == 1 + case FN_CW_SPEED_IDX : + menuCWSpeed(btnState); + break; +#endif +#if FN_SPLIT == 1 + case FN_SPLIT_IDX : + menuSplitOnOff(btnState); //SplitOn / off + break; +#endif +#if FN_VFOTOMEM == 1 + case FN_VFOTOMEM_IDX : + menuCHMemory(btnState, 0); //VFO to Memroy + break; +#endif +#if FN_MEMTOVFO == 1 + case FN_MEMTOVFO_IDX : + menuCHMemory(btnState, 1); //Memory to VFO + break; +#endif +#if FN_MEMORYKEYER == 1 + case FN_MEMORYKEYER_IDX : + menuCWAutoKey(btnState); + break; +#endif +#if FN_WSPR == 1 + case FN_WSPR_IDX : + menuWSPRSend(btnState); + break; +#endif +#if FN_SDRMODE == 1 + case FN_SDRMODE_IDX : + menuSDROnOff(btnState); + break; +#endif + case FN_SETUP_IDX : + menuSetup(btnState); + break; + case FN_EXIT_IDX : + menuExit(btnState); + break; + +#if FN_CALIBRATION == 1 + case FN_CALIBRATION_IDX : + menuSetupCalibration(btnState); //crystal + break; +#endif +#if FN_CARRIER == 1 + case FN_CARRIER_IDX : + menuSetupCarrier(btnState); //ssb + break; +#endif +#if FN_CWCARRIER == 1 + case FN_CWCARRIER_IDX : + menuSetupCWCarrier(btnState); //cw + break; +#endif +#if FN_CWTONE == 1 + case FN_CWTONE_IDX : + menuSetupCwTone(btnState); + break; +#endif +#if FN_CWDELAY == 1 + case FN_CWDELAY_IDX : + menuSetupCwDelay(btnState); + break; +#endif +#if FN_TXCWDELAY == 1 + case FN_TXCWDELAY_IDX : + menuSetupTXCWInterval(btnState); + break; +#endif +#if FN_KEYTYPE == 1 + case FN_KEYTYPE_IDX : + menuSetupKeyType(btnState); + break; +#endif +#if FN_ADCMONITOR == 1 + case FN_ADCMONITOR_IDX : + menuADCMonitor(btnState); + break; +#endif +#if FN_TXONOFF == 1 + case FN_TXONOFF_IDX : + menuTxOnOff(btnState, 0x01); //TX OFF / ON + break; +#endif + default : + menuExit(btnState); break; + } //end of switch + Check_Cat(0); //To prevent disconnections + } //end of while + + //**************************************************************************** + //Before change menu type (Version : ~ 0.95) + //**************************************************************************** + /* while (menuOn){ i = enc_read(); btnState = btnDown(); @@ -1318,9 +1391,10 @@ void doMenu(){ break; default : menuExit(btnState); break; - } + } //end of case Check_Cat(0); //To prevent disconnections - } + } //end of while + */ } //************************************************************************************* @@ -1359,7 +1433,14 @@ void menuSetup(int btn){ else { modeCalibrate = ! modeCalibrate; + //menuClearExit(1000); + +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD menuClearExit(1000); +#endif } } @@ -1390,13 +1471,17 @@ void menuRitToggle(int btn){ ritDisable(); } + //menuClearExit(500); +#ifdef USE_SW_SERIAL + menuOn = 0; +#else + //Only Clear And Delay for Character LCD menuClearExit(500); +#endif + } } - - - /** * Take a deep breath, math(ematics) ahead * The 25 mhz oscillator is multiplied by 35 to run the vco at 875 mhz diff --git a/ubitx_20/ubitx_si5351.ino b/ubitx_20/ubitx_si5351.ino index 2708b36..049cf0b 100644 --- a/ubitx_20/ubitx_si5351.ino +++ b/ubitx_20/ubitx_si5351.ino @@ -47,7 +47,8 @@ #define BB1(x) ((uint8_t)(x>>8)) #define BB2(x) ((uint8_t)(x>>16)) -#define SI5351BX_ADDR 0x60 // I2C address of Si5351 (typical) +//#define SI5351BX_ADDR 0x60 // I2C address of Si5351 (typical) +uint8_t SI5351BX_ADDR; // I2C address of Si5351 (variable from Version 1.097) #define SI5351BX_XTALPF 2 // 1:6pf 2:8pf 3:10pf // If using 27mhz crystal, set XTAL=27000000, MSA=33. Then vco=891mhz diff --git a/ubitx_20/ubitx_ui.ino b/ubitx_20/ubitx_ui.ino index aa3bae9..0aa7c30 100644 --- a/ubitx_20/ubitx_ui.ino +++ b/ubitx_20/ubitx_ui.ino @@ -268,4 +268,32 @@ int enc_read(void) { return(result); } +//=================================================================== +//I2C Signal Meter, Version 1.097 +//=================================================================== + +// 0xA0 ~ 0xCF : CW Decode Mode + 100Hz ~ +// 0xD0 ~ 0xF3 : RTTY Decode Mode + 100Hz ~ +// 0x10 ~ 0x30 : Spectrum Mode +int GetI2CSmeterValue(int valueType) +{ + if (valueType > 0) + { + Wire.beginTransmission(I2CMETER_ADDR); //j : S-Meter + Wire.write(valueType); //Y : Get Value Type + Wire.endTransmission(); + } + + Wire.requestFrom(I2CMETER_ADDR, 1); + + if (Wire.available() > 0) + { + return Wire.read(); + } + else + { + return 0; + } +} + diff --git a/ubitx_20/ubitx_wspr.ino b/ubitx_20/ubitx_wspr.ino index 5765aca..a9281f6 100644 --- a/ubitx_20/ubitx_wspr.ino +++ b/ubitx_20/ubitx_wspr.ino @@ -6,8 +6,6 @@ Thanks to G3ZIL for sharing great code. Due to the limited memory of uBITX, I have implemented at least only a few of the codes in uBITX. Thanks for testing -Beta Tester : - ----------------------------------------------------------------------------- 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 @@ -73,13 +71,14 @@ void SendWSPRManage() if (nowWsprStep == 0) //select Message status { - printLineF2(F("WSPR:")); + //printLineF2(F("WSPR:")); if (selectedWsprMessageIndex != nowSelectedIndex) { selectedWsprMessageIndex = nowSelectedIndex; int wsprMessageBuffIndex = selectedWsprMessageIndex * 46; + printLineF2(F("WSPR:")); //Display WSPR Name tag printLineFromEEPRom(0, 6, wsprMessageBuffIndex, wsprMessageBuffIndex + 4, 1); @@ -146,9 +145,16 @@ void SendWSPRManage() } printLine1(c); - + +#ifdef USE_SW_SERIAL + SWS_Process(); + if ((digitalRead(PTT) == 0) || (TriggerBySW == 1)) + { + TriggerBySW = 0; +#else if (digitalRead(PTT) == 0) { +#endif //SEND WSPR //If you need to consider the Rit and Sprite modes, uncomment them below. //remark = To reduce the size of the program