diff --git a/ubitx_20/cat_libs.ino b/ubitx_20/cat_libs.ino index 608af79..70e2422 100644 --- a/ubitx_20/cat_libs.ino +++ b/ubitx_20/cat_libs.ino @@ -32,6 +32,8 @@ **************************************************************************/ +#include + #include "ubitx.h" //for broken protocol @@ -49,12 +51,45 @@ #define ACK 0 +/* + * KC4UPR - IOP update, 2020-05-03 + * + * Send the current mode to the I/O Processor. + */ +void iopSendMode(char cw_mode, char is_usb, char digi_mode) +{ + rig_mode mode; + + // NOTE: eventually, add sideband (is_usb) to all of these. + if (cw_mode > 0) { + mode = rig_mode::cw; + } else if (digi_mode > 0) { + //mode = (is_usb ? RIG_MODE_DGU : RIG_MODE_DGL); + mode = rig_mode::digi; +// } else if (is_test) { +// mode = (is_usb ? RIG_MODE_TTU : RIG_MODE_TTL); + } else { + mode = rig_mode::ssb; //(is_usb ? usb : lsb); + } + sendIOPModeCommand(mode); +} + unsigned int skipTimeCount = 0; -byte CAT_BUFF[5]; -byte CAT_SNDBUFF[5]; +byte CAT_BUFF[34]; +byte CAT_SNDBUFF[34]; + +byte error_buf[17]; void SendCatData(byte sendCount) { + // KC4UPR--uBITX IOP: Adding an additional byte at the beginning that + // indicates that this is a "CAT mode" transmission. Extra byte includes + // a prefix, as well as the number of bytes being sent. + // + // NOTE: Need to do some error checking at some point to ensure we don't + // try to send more than 15 bytes!!! + Serial.write(prefixAndLengthToByte(CAT_PREFIX, sendCount)); + for (byte i = 0; i < sendCount; i++) Serial.write(CAT_BUFF[i]); //Serial.flush(); @@ -163,7 +198,8 @@ void CatSetSplit(boolean isSplit) //for remove warning messages void CatSetPTT(boolean isPTTOn, byte fromType) { - // + // KC4UPR - so I think this means, that if we're currently processing a CW keyer (auto/manual), + // not to accept a CAT command in the middle of it. if ((!inTx) && (fromType == 2 || fromType == 3)) { Serial.write(ACK); return; @@ -176,19 +212,25 @@ void CatSetPTT(boolean isPTTOn, byte fromType) { txCAT = true; + // KC4UPR - added the next line to tell the IOP we're transmitting + sendIOPStartTxCommand(); + startTx(TX_SSB, 1); //Exit menu, Memory Keyer... ETC - if (isCWAutoMode > 0) { - isCWAutoMode = 0; - printLineF2(F("AutoKey Exit/CAT")); - //delay_background(1000, 0); - } + //if (isCWAutoMode > 0) { + // isCWAutoMode = 0; + // printLineF2(F("AutoKey Exit/CAT")); + // //delay_background(1000, 0); + //} } } else { if (inTx) { + // KC4UPR - added the next line to tell the IOP we're not transmitting + sendIOPStopTxCommand(); + stopTx(); txCAT = false; } @@ -216,21 +258,33 @@ void CatSetMode(byte tmpMode, byte fromType) if (!inTx) { - if (tmpMode == CAT_MODE_CW) - { - cwMode = 1; - } - else if (tmpMode == CAT_MODE_USB) - { - cwMode = 0; - isUSB = true; - } - else - { - cwMode = 0; - isUSB = false; - } + switch(tmpMode) { + case CAT_MODE_CW: + cwMode = 2; // should be CWU + break; + case CAT_MODE_CWR: + cwMode = 1; // should be CWL + break; + + case CAT_MODE_USB: + cwMode = 0; + digiMode = 0; + isUSB = true; + break; + + case CAT_MODE_LSB: + cwMode = 0; + digiMode = 0; + isUSB = false; + break; + + case CAT_MODE_DIG: + cwMode = 0; + digiMode = 1; + isUSB = true; // DGU - but need to eventually use the FT-817 customization + } + iopSendMode(cwMode, isUSB, digiMode); setFrequency(frequency); updateDisplay(); } @@ -250,6 +304,15 @@ void ReadEEPRom() //for remove warnings. byte checkSum = 0; byte read1Byte = 0; + // KC4UPR--uBITX IOP: Adding an additional byte at the beginning that + // indicates that this is a "Memory Manager mode" transmission. + // Then we repeat some of the CAT_BUFF data. + Serial.write(prefixAndLengthToByte(RAD_EEPROM_READ_PREFIX, 5)); + Serial.write(CAT_BUFF[0]); + Serial.write(CAT_BUFF[1]); + Serial.write(CAT_BUFF[2]); + Serial.write(CAT_BUFF[3]); + Serial.write(0x02); //STX checkSum = 0x02; //I2C Scanner @@ -293,6 +356,12 @@ void WriteEEPRom(void) //for remove warning uint16_t eepromStartIndex = CAT_BUFF[0] + CAT_BUFF[1] * 256; byte write1Byte = CAT_BUFF[2]; + // KC4UPR--uBITX IOP: Adding an additional byte at the beginning that + // indicates that this is a "Memory Manager mode" transmission. + // + // Also indicates that we are going to be sending two bytes of data. + Serial.write(prefixAndLengthToByte(RAD_EEPROM_WRITE_PREFIX, 2)); + //Check Checksum if (CAT_BUFF[3] != ((CAT_BUFF[0] + CAT_BUFF[1] + CAT_BUFF[2]) % 256)) { @@ -746,148 +815,218 @@ byte rxBufferCheckCount = 0; //Prevent Stack Overflow byte isProcessCheck_Cat = 0; +//char iopStatusWindow[4] = " "; // may need to move this if it's not visible to ubitx_lcd_1602 +char iopMenuDisplay[17] = " "; + +// KC4UPR - these are used to delay the display of the Smeter, if the +// IOP status has recently been displayed, to give time to see it. +// Put these here because of how Arduino IDE puts .ino files together. +//#define SMETER_DELAY_TIME 5000 +//bool displaySmeter = true; +//int delaySmeter; +int stateTopLine = 0; + //fromType normal : 0, TX : 1, CW_STRAIGHT : 2, CW_PADDLE : 3, CW_AUTOMODE : 4 //if cw mode, no delay void Check_Cat(byte fromType) { byte i; + static PrefixID readPrefix; + static uint8_t readLength; + static IOPMessage msg; + static bool read_in_progress = false; + //Check Serial Port Buffer - if (Serial.available() == 0) + if (Serial.available() == 0 && !read_in_progress) { //Set Buffer Clear status - rxBufferCheckCount = 0; + //rxBufferCheckCount = 0; return; } - else if (Serial.available() < 5) + // KC4UPR - IOP update: changed this to 6 characters, because we're going to have a + // first character which defines if this is CAT or IOP. + else // if (Serial.available() < 6) //5) { - //First Arrived - if (rxBufferCheckCount == 0) - { - rxBufferCheckCount = Serial.available(); - rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; //Set time for timeout - } - else if (rxBufferArriveTime < millis()) //timeout - { - //Clear Buffer - for (i = 0; i < Serial.available(); i++) - rxBufferCheckCount = Serial.read(); + if (!read_in_progress) { + byte first = Serial.read(); + readPrefix = byteToPrefix(first); + readLength = byteToLength(first); - rxBufferCheckCount = 0; - } - else if (rxBufferCheckCount < Serial.available()) //increase buffer count, slow arrived - { rxBufferCheckCount = Serial.available(); - rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; //Set time for timeout + rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; + + read_in_progress = true; + } + + if (Serial.available() < readLength) { // not ready to read everything yet (not enough bytes) + + if (rxBufferCheckCount < Serial.available()) { // increase buffer count, slow arrival + rxBufferCheckCount = Serial.available(); + rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; // update time for timeout + + } else if (rxBufferArriveTime < millis()) { // timeout, so clear buffer + for (i = 0; i < Serial.available(); i++) + rxBufferCheckCount = Serial.read(); + rxBufferCheckCount = 0; + read_in_progress = false; + + } + + return; + } + + for (int i = 0; i < readLength; i++) { + CAT_BUFF[i] = Serial.read(); } - return; } - - //Arived CAT DATA - for (i = 0; i < 5; i++) - CAT_BUFF[i] = Serial.read(); - + + // KC4UPR: I don't understand why this is here or how/when it will ever get called, but I will leave + // it alone for now. if (isProcessCheck_Cat == 1) return; - isProcessCheck_Cat = 1; + isProcessCheck_Cat = 1; - //reference : http://www.ka7oei.com/ft817_meow.html - switch(CAT_BUFF[4]) - { - //The stability has not been verified and there seems to be no need. so i remarked codes, - //if you need, unmark lines - /* - case 0x00 : //Lock On - if (isDialLock == 1) //This command returns 00 if it was unlocked, and F0 if already locked. - CAT_BUFF[0] = 0xF0; - else { - CAT_BUFF[0] = 0x00; - setDialLock(1, fromType); - } - Serial.write(CAT_BUFF[0]); //Time + if (readPrefix == IOP_PREFIX) { + recvIOPMessage(msg, CAT_BUFF, readLength); // not super robust... if IOP ever sends more (or less) than a 5 (6) byte message + // following assumes it's a status message, 4 chars (including trailing null, which I'm ignoring... + switch(msg.id) { + /*case IOP_SSB_STATUS_MSG: + case IOP_DGT_STATUS_MSG: + case IOP_CW_STATUS_MSG: + case IOP_TEST_STATUS_MSG: + iopStatusWindow[0] = msg.data[0]; + iopStatusWindow[1] = msg.data[1]; + iopStatusWindow[2] = msg.data[2]; + displaySmeter = false; + delaySmeter = millis() + SMETER_DELAY_TIME; + break;*/ + + case IOP_MODE_REQUEST: + iopSendMode(cwMode, isUSB, digiMode); + break; + + case IOP_MENU_DISPLAY_MSG: + for (int i = 0; i < 16; i++) { + iopMenuDisplay[i] = msg.data[i]; + } + stateTopLine = 2; + sprintf(error_buf, "# recv'd: %3d", readLength); + sendIOPDebugMessage(error_buf); + sendIOPDebugMessage(iopMenuDisplay); + break; + + case IOP_MENU_INACTIVE_MSG: + stateTopLine = 0; + line2DisplayStatus = 0; // trying to force an update + break; + } + + } else if (readPrefix == CAT_PREFIX) { + + //reference : http://www.ka7oei.com/ft817_meow.html + switch(CAT_BUFF[4]) + { + //The stability has not been verified and there seems to be no need. so i remarked codes, + //if you need, unmark lines + /* + case 0x00 : //Lock On + if (isDialLock == 1) //This command returns 00 if it was unlocked, and F0 if already locked. + CAT_BUFF[0] = 0xF0; + else { + CAT_BUFF[0] = 0x00; + setDialLock(1, fromType); + } + Serial.write(CAT_BUFF[0]); //Time + break; + case 0x80 : //Lock Off + if (isDialLock == 0) //This command returns 00 if the '817 was already locked, and F0 (HEX) if already unlocked. + CAT_BUFF[0] = 0xF0; + else { + CAT_BUFF[0] = 0x00; + setDialLock(0, fromType); + } + Serial.write(CAT_BUFF[0]); //Time + break; + */ + + case 0x01 : //Set Frequency + CatSetFreq(fromType); break; - case 0x80 : //Lock Off - if (isDialLock == 0) //This command returns 00 if the '817 was already locked, and F0 (HEX) if already unlocked. - CAT_BUFF[0] = 0xF0; - else { - CAT_BUFF[0] = 0x00; - setDialLock(0, fromType); - } - Serial.write(CAT_BUFF[0]); //Time + + case 0x02 : //Split On + case 0x82: //Split Off + CatSetSplit(CAT_BUFF[4] == 0x02); break; - */ - - case 0x01 : //Set Frequency - CatSetFreq(fromType); - break; - - case 0x02 : //Split On - case 0x82: //Split Off - CatSetSplit(CAT_BUFF[4] == 0x02); - break; - - case 0x03 : //Read Frequency and mode - CatGetFreqMode(frequency); - break; - - case 0x07 : //Set Operating Mode - CatSetMode(CAT_BUFF[0], fromType); - break; - - case 0x08 : //Set PTT_ON - case 0x88: //Set PTT Off - CatSetPTT(CAT_BUFF[4] == 0x08, fromType); - break; - - case 0x81: //Toggle VFO - CatVFOToggle(true, fromType); - break; - - case 0xDB: //Read uBITX EEPROM Data - ReadEEPRom(); //Call by uBITX Manager Program - break; - case 0xBB: //Read FT-817 EEPROM Data (for comfirtable) - ReadEEPRom_FT817(); - break; - - case 0xDC: //Write uBITX EEPROM Data - WriteEEPRom(); //Call by uBITX Manager Program - break; - case 0xBC: //Write FT-817 EEPROM Data (for comfirtable) - 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; - case 0xF7: //Read TX Status - CatTxStatus(); - break; - default: - /* - char buff[16]; - sprintf(buff, "DEFAULT : %x", CAT_BUFF[4]); - printLine2(buff); - */ - Serial.write(ACK); - break; - } //end of switch + + case 0x03 : //Read Frequency and mode + CatGetFreqMode(frequency); + break; + + case 0x07 : //Set Operating Mode + CatSetMode(CAT_BUFF[0], fromType); + break; + + case 0x08 : //Set PTT_ON + case 0x88: //Set PTT Off + CatSetPTT(CAT_BUFF[4] == 0x08, fromType); + break; + + case 0x81: //Toggle VFO + CatVFOToggle(true, fromType); + break; + + case 0xDB: //Read uBITX EEPROM Data + ReadEEPRom(); //Call by uBITX Manager Program + break; + case 0xBB: //Read FT-817 EEPROM Data (for comfirtable) + ReadEEPRom_FT817(); + break; + + case 0xDC: //Write uBITX EEPROM Data + WriteEEPRom(); //Call by uBITX Manager Program + break; + case 0xBC: //Write FT-817 EEPROM Data (for comfirtable) + 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; + case 0xF7: //Read TX Status + CatTxStatus(); + break; + default: + /* + char buff[16]; + sprintf(buff, "DEFAULT : %x", CAT_BUFF[4]); + printLine2(buff); + */ + Serial.write(ACK); + break; + } //end of switch + } isProcessCheck_Cat = 0; + read_in_progress = false; } void Init_Cat(long baud, int portConfig) { Serial.begin(baud, portConfig); Serial.flush(); -} + // At start, immediately send mode to IOP. Currently, IOP has no way to + // request the mode. + // Moving this to main setup loop. Here, it may actually occur before the Raduino knows its mode! + //iopSendMode(cwMode, isUSB, digiMode, isTest); +} diff --git a/ubitx_20/cw_autokey.ino b/ubitx_20/cw_autokey.ino deleted file mode 100644 index 9bf838e..0000000 --- a/ubitx_20/cw_autokey.ino +++ /dev/null @@ -1,400 +0,0 @@ -/************************************************************************* - KD8CEC's Memory Keyer for HAM - - This source code is written for All amateur radio operator, - I have not had amateur radio communication for a long time. CW has been - around for a long time, and I do not know what kind of keyer and keying - software is fashionable. So I implemented the functions I need mainly. - - To minimize the use of memory space, we used bitwise operations. - For the alphabet, I put Morsecode in 1 byte. The front 4Bit is the length - and the 4Bit is the Morse code. Because the number is fixed in length, - there is no separate length information. The 5Bit on the right side is - the Morse code. - - 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 ------------------------------------------------------------------------------ - 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 - -//27 + 10 + 18 + 1(SPACE) = //56 -const PROGMEM uint8_t cwAZTable[27] = {0b00100100 , 0b01001000 , 0b01001010 , 0b00111000 , 0b00010000, 0b01000010, 0b00111100, 0b01000000 , //A ~ H -0b00100000, 0b01000111 ,0b00111010, 0b01000100, 0b00101100, 0b00101000 , 0b00111110, 0b01000110, 0b01001101, 0b00110100, //I ~ R -0b00110000, 0b00011000, 0b00110010, 0b01000001, 0b00110110, 0b01001001, 0b01001011, 0b01001100}; //S ~ Z -PGM_P pCwAZTable = reinterpret_cast(cwAZTable); - -const PROGMEM uint8_t cw09Table[27] = {0b00011111, 0b00001111, 0b00000111, 0b00000011, 0b00000001, 0b00000000, 0b00010000, 0b00011000, 0b00011100, 0b00011110}; -PGM_P pcw09Table = reinterpret_cast(cw09Table); - -//# : AR, ~:BT, [:AS, ]:SK, ^:KN -const PROGMEM uint8_t cwSymbolIndex[] = {'.', ',', '?', '"', '!', '/', '(', ')', '&', ':', ';', '=', '+', '-', '_', '\'', '@', '#', '~', '[', ']', '^' }; -PGM_P pCwSymbolIndex = reinterpret_cast(cwSymbolIndex); - -const PROGMEM uint8_t cwSymbolTable[] = {0b11010101, 0b11110011, 0b11001100, 0b11011110, 0b11101011, 0b10100100, 0b10101100, 0b11101101, 0b10010000, 0b11111000, 0b11101010, 0b10100010, 0b10010100, 0b11100001, 0b11001101, 0b11010010, 0b11011010, 0b10010100, 0b10100010, 0b10010000, 0b11000101, 0b10101100}; -PGM_P pCwSymbolTable = reinterpret_cast(cwSymbolTable); -////const PROGMEM uint8_t cwSymbolLength[] = {6, 6, 6, 6, 6, 5, 5, 6, 5, 6, 6, 5, 5, 6, 6, 6, 6, 5, 5, 5, 6, 5}; - -// ":(Start"), ':(End "), >: My callsign, <:QSO Callsign (Second Callsign), #:AR, ~:BT, [:AS, ]:SK - -byte knobPosition = 0; -//byte cwTextData[30]; //Maximum 30 Remarked by KD8CE -> Direct Read EEPROM -byte autoCWSendCharEndIndex = 0; -byte autoCWSendCharIndex = 0; -unsigned long autoCWbeforeTime = 0; //for interval time between chars -byte pttBeforeStatus = 1; //PTT : default high -byte isKeyStatusAfterCWStart = 0; //0 : Init, 1 : Keyup after auto CW Start, 2 : Keydown after -byte selectedCWTextIndex = 0; -unsigned long autoCWKeydownCheckTime = 0; //for interval time between chars -byte changeReserveStatus = 0; -byte isAutoCWHold = 0; //auto CW Pause => Manual Keying => auto - -void autoSendPTTCheck() -{ - if (isCWAutoMode == 2) { //Sending Mode - //check PTT Button - //short Press => reservation or cancel - //long Press => Hold - if (digitalRead(PTT) == LOW) - { - //if (isKeyStatusAfterCWStart == 0) //Yet Press PTT from start TX - //{ - //} - - if (isKeyStatusAfterCWStart == 1) //while auto cw send, ptt up and ptt down again - { - //Start Time - autoCWKeydownCheckTime = millis() + 200; //Long push time - isKeyStatusAfterCWStart = 2; //Change status => ptt down agian - } - else if (isKeyStatusAfterCWStart == 2 && autoCWKeydownCheckTime < millis()) - { - //Hold Mode - isAutoCWHold = 1; - isKeyStatusAfterCWStart = 3; - } - else if (isKeyStatusAfterCWStart == 3) - { - autoCWKeydownCheckTime = millis() + 200; - } - } - else - { - //PTT UP - if (isKeyStatusAfterCWStart == 2) //0 (down before cw start) -> 1 (up while cw sending) -> 2 (down while cw sending) - { - if (autoCWKeydownCheckTime > millis()) //Short : Reservation or cancel Next Text - { - if (autoCWSendReservCount == 0 || - (autoCWSendReservCount < AUTO_CW_RESERVE_MAX && - autoCWSendReserv[autoCWSendReservCount - 1] != selectedCWTextIndex)) - { - //Reserve - autoCWSendReserv[autoCWSendReservCount++] = selectedCWTextIndex; - changeReserveStatus = 1; - } - else if (autoCWSendReservCount > 0 && autoCWSendReserv[autoCWSendReservCount - 1] == selectedCWTextIndex) - { - autoCWSendReservCount--; - changeReserveStatus = 1; - } - } // end of Short Key up - } - else if (isKeyStatusAfterCWStart == 3) //play from Hold (pause Auto CW Send) - { - isAutoCWHold = 0; - } - - isKeyStatusAfterCWStart = 1; //Change status => ptt up (while cw send mode) - } //end of PTT UP - } -} - -//Send 1 char -void sendCWChar(char cwKeyChar) -{ - byte sendBuff[7]; - byte i, j, charLength; - byte tmpChar; - - //For Macrofunction - //replace > and < to My callsign, qso callsign, use recursive function call - if (cwKeyChar == '>' || cwKeyChar == '<') - { - uint16_t callsignStartIndex = 0; - uint16_t callsignEndIndex = 0; - - if (cwKeyChar == '>') //replace my callsign - { - if (userCallsignLength > 0) - { - callsignStartIndex = 0; - callsignEndIndex = userCallsignLength; - } - } - else if (cwKeyChar == '<') //replace qso callsign - { - //ReadLength - callsignEndIndex = EEPROM.read(CW_STATION_LEN); - if (callsignEndIndex > 0) - { - callsignStartIndex = CW_STATION_LEN - callsignEndIndex - USER_CALLSIGN_DAT; - callsignEndIndex = callsignStartIndex + callsignEndIndex; - } - } - - if (callsignStartIndex == 0 && callsignEndIndex == 0) - return; - - for (uint16_t i = callsignStartIndex; i <= callsignEndIndex; i++) - { - sendCWChar(EEPROM.read(USER_CALLSIGN_DAT + i)); - autoSendPTTCheck(); //for reserve and cancel next CW Text - if (changeReserveStatus == 1) - { - changeReserveStatus = 0; - updateDisplay(); - } - - if (i < callsignEndIndex) delay_background(cwSpeed * 3, 4); // - } - - return; - } - else if (cwKeyChar >= 'A' && cwKeyChar <= 'Z') //Encode Char by KD8CEC - { - tmpChar = pgm_read_byte(pCwAZTable + (cwKeyChar - 'A')); - charLength = (tmpChar >> 4) & 0x0F; - for (i = 0; i < charLength; i++) - sendBuff[i] = (tmpChar << i) & 0x08; - } - else if (cwKeyChar >= '0' && cwKeyChar <= '9') - { - charLength = 5; - for (i = 0; i < charLength; i++) - sendBuff[i] = (pgm_read_byte(pcw09Table + (cwKeyChar - '0')) << i) & 0x10; - } - else if (cwKeyChar == ' ') - { - charLength = 0; - delay_background(cwSpeed * 4, 4); //7 -> basic interval is 3 - } - else if (cwKeyChar == '$') //7 digit - { - charLength = 7; - for (i = 0; i < 7; i++) - sendBuff[i] = (0b00010010 << i) & 0x80; //...1..1 - } - else - { - //symbol - for (i = 0; i < 22; i++) - { - if (pgm_read_byte(pCwSymbolIndex + i) == cwKeyChar) - { - tmpChar = pgm_read_byte(pCwSymbolTable + i); - charLength = ((tmpChar >> 6) & 0x03) + 3; - - for (j = 0; j < charLength; j++) - sendBuff[j] = (tmpChar << (j + 2)) & 0x80; - - break; - } - else - { - charLength = 0; - } - } - } - - for (i = 0; i < charLength; i++) - { - cwKeydown(); - if (sendBuff[i] == 0) - delay_background(cwSpeed, 4); - else - delay_background(cwSpeed * 3, 4); - cwKeyUp(); - if (i != charLength -1) - delay_background(cwSpeed, 4); - } -} - -byte isNeedScroll = 0; -unsigned long scrollDispayTime = 0; -#define scrollSpeed 500 -byte displayScrolStep = 0; - -void controlAutoCW(){ - int knob = 0; - byte i; - - byte cwStartIndex, cwEndIndex; - - if (cwAutoDialType == 0) - knob = enc_read(); - - if (knob != 0 || beforeCWTextIndex == 255 || isNeedScroll == 1){ //start display - if (knobPosition > 0 && knob < 0) - knobPosition--; - if (knobPosition < cwAutoTextCount * 10 -1 && knob > 0) - knobPosition++; - - selectedCWTextIndex = knobPosition / 10; - - if ((beforeCWTextIndex != selectedCWTextIndex) || - (isNeedScroll == 1 && beforeCWTextIndex == selectedCWTextIndex && scrollDispayTime < millis())) { - //Read CW Text Data Position From EEProm - EEPROM.get(CW_AUTO_DATA + (selectedCWTextIndex * 2), cwStartIndex); - EEPROM.get(CW_AUTO_DATA + (selectedCWTextIndex * 2 + 1), cwEndIndex); - - if (beforeCWTextIndex == selectedCWTextIndex) - { - if (++displayScrolStep > cwEndIndex - cwStartIndex) - displayScrolStep = 0; - } - else - { - 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); - isNeedScroll = (cwEndIndex - cwStartIndex) > 14 ? 1 : 0; - Display_AutoKeyTextIndex(selectedCWTextIndex); -#endif - scrollDispayTime = millis() + scrollSpeed; - beforeCWTextIndex = selectedCWTextIndex; - } - } //end of check knob - - if (isCWAutoMode == 1) { //ready status - if (digitalRead(PTT) == LOW) //PTT Down : Start Auto CW or DialMode Change - { - if (pttBeforeStatus == 1) //High to Low Change - { - autoCWbeforeTime = millis() + 500; //Long push time - pttBeforeStatus = 0; - } - else if (autoCWbeforeTime < millis()) //while press PTT, OK Long push then Send Auto CW Text - { - sendingCWTextIndex = selectedCWTextIndex; - - //Information about Auto Send CW Text - autoCWSendCharEndIndex = cwEndIndex; //length of CW Text //ianlee - autoCWSendCharIndex = cwStartIndex; //position of Sending Char //ianlee - - isCWAutoMode = 2; //auto sending start - autoCWbeforeTime = 0; //interval between chars, 0 = always send - isKeyStatusAfterCWStart = 0; //Init PTT Key status - autoCWSendReservCount = 0; //Init Reserve Count - isAutoCWHold = 0; - if (!inTx){ //if not TX Status, change RX -> TX - keyDown = 0; - startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time - updateDisplay(); - - delay_background(delayBeforeCWStartTime * 2, 2); //for External AMP or personal situation - } - } - } - else if (pttBeforeStatus == 0 && autoCWbeforeTime > 0) //while reade status LOW -> HIGH (before Auto send Before) - { - pttBeforeStatus = 1; //HIGH - if (autoCWbeforeTime > millis()) //short Press -> ? DialModeChange - { - cwAutoDialType = (cwAutoDialType == 1 ? 0 : 1); //Invert DialMode between select CW Text and Frequency Tune - if (cwAutoDialType == 0) - printLineF1(F("Dial:Select Text")); - else - printLineF1(F("Dial:Freq Tune")); - - delay_background(1000, 0); - updateDisplay(); - } - } - } //end of isCWAutoMode == 1 condition - - if (isCWAutoMode == 2) { //Sending Mode - autoSendPTTCheck(); - - //check interval time, if you want adjust interval between chars, modify below - if (isAutoCWHold == 0 && (millis() - autoCWbeforeTime > cwSpeed * 3)) - { - if (!inTx){ //if not TX Status, change RX -> TX - keyDown = 0; - startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time - } - - sendCWChar(EEPROM.read(CW_AUTO_DATA + autoCWSendCharIndex++)); - - if (autoCWSendCharIndex > autoCWSendCharEndIndex) { //finish auto cw send - //check reserve status - if (autoCWSendReservCount > 0) - { - //prepare - sendingCWTextIndex = autoCWSendReserv[0]; - - for (i = 0; i < AUTO_CW_RESERVE_MAX -1; i++) - autoCWSendReserv[i] = autoCWSendReserv[i + 1]; - - EEPROM.get(CW_AUTO_DATA + (sendingCWTextIndex * 2), cwStartIndex); - EEPROM.get(CW_AUTO_DATA + (sendingCWTextIndex * 2 + 1), cwEndIndex); - - //Information about Auto Send CW Text - autoCWSendCharEndIndex = cwEndIndex; //length of CW Text //ianlee - autoCWSendCharIndex = cwStartIndex; //position of Sending Char //ianlee - autoCWSendReservCount--; //Decrease - - sendCWChar(' '); //APPLY SPACE between CW Texts - changeReserveStatus = 1; - } - else - { - isCWAutoMode = 1; //ready status - delay_background(cwDelayTime * 10, 2); - stopTx(); - } - } - - autoCWbeforeTime = millis(); - - if (changeReserveStatus == 1) - { - changeReserveStatus = 0; - updateDisplay(); - } - } - } - - //abort if this button is down - if (btnDown()) - { - isCWAutoMode = 0; //dsiable Auto CW Mode - printLine2ClearAndUpdate(); - delay_background(1000, 0); - } -} - diff --git a/ubitx_20/softserial_tiny.cpp b/ubitx_20/softserial_tiny.cpp deleted file mode 100644 index 6023c67..0000000 --- a/ubitx_20/softserial_tiny.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/* -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 7c17b11..8a97063 100644 --- a/ubitx_20/ubitx.h +++ b/ubitx_20/ubitx.h @@ -48,8 +48,8 @@ //#define USE_CUSTOM_LPF_FILTER //LPF FILTER MOD //#define ENABLE_FACTORYALIGN -#define FACTORY_RECOVERY_BOOTUP //Whether to enter Factory Recovery mode by pressing FKey and turning on power -#define ENABLE_ADCMONITOR //Starting with Version 1.07, you can read ADC values directly from uBITX Manager. So this function is not necessary. +//#define FACTORY_RECOVERY_BOOTUP //Whether to enter Factory Recovery mode by pressing FKey and turning on power +//#define ENABLE_ADCMONITOR //Starting with Version 1.07, you can read ADC values directly from uBITX Manager. So this function is not necessary. 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 @@ -69,7 +69,7 @@ extern byte I2C_LCD_SECOND_ADDRESS; //only using Dual LCD Mode #define FN_CW_SPEED 1 //152 #define FN_VFOTOMEM 1 //254 #define FN_MEMTOVFO 1 //188 -#define FN_MEMORYKEYER 1 //156 +#define FN_MEMORYKEYER 0 //156 #define FN_WSPR 1 //1044 #define FN_SDRMODE 1 //68 #define FN_CALIBRATION 1 //666 @@ -310,8 +310,8 @@ extern void printLineF(char linenmbr, const __FlashStringHelper *c); extern void printLineFromEEPRom(char linenmbr, char lcdColumn, byte eepromStartIndex, byte eepromEndIndex, char offsetType); extern byte delay_background(unsigned delayTime, byte fromType); extern int btnDown(void); -extern char c[30]; -extern char b[30]; +extern char c[40]; +extern char b[40]; extern int enc_read(void); extern void si5351bx_init(void); extern void si5351bx_setfreq(uint8_t clknum, uint32_t fout); diff --git a/ubitx_20/ubitx_20.ino b/ubitx_20/ubitx_20.ino index 2066939..dc39af8 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. @@ -172,15 +172,15 @@ byte isShiftDisplayCWFreq = 1; //Display Frequency int shiftDisplayAdjustVal = 0; // //Variables for auto cw mode -byte isCWAutoMode = 0; //0 : none, 1 : CW_AutoMode_Menu_Selection, 2 : CW_AutoMode Sending -byte cwAutoTextCount = 0; //cwAutoText Count -byte beforeCWTextIndex = 255; //when auto cw start, always beforeCWTextIndex = 255, (for first time check) -byte cwAutoDialType = 0; //0 : CW Text Change, 1 : Frequency Tune +//byte isCWAutoMode = 0; //0 : none, 1 : CW_AutoMode_Menu_Selection, 2 : CW_AutoMode Sending +//byte cwAutoTextCount = 0; //cwAutoText Count +//byte beforeCWTextIndex = 255; //when auto cw start, always beforeCWTextIndex = 255, (for first time check) +//byte cwAutoDialType = 0; //0 : CW Text Change, 1 : Frequency Tune -#define AUTO_CW_RESERVE_MAX 3 -byte autoCWSendReserv[AUTO_CW_RESERVE_MAX]; //Reserve CW Auto Send -byte autoCWSendReservCount = 0; //Reserve CW Text Cound -byte sendingCWTextIndex = 0; //cw auto seding Text Index +//#define AUTO_CW_RESERVE_MAX 3 +//byte autoCWSendReserv[AUTO_CW_RESERVE_MAX]; //Reserve CW Auto Send +//byte autoCWSendReservCount = 0; //Reserve CW Text Cound +//byte sendingCWTextIndex = 0; //cw auto seding Text Index byte userCallsignLength = 0; //7 : display callsign at system startup, 6~0 : callsign length (range : 1~18) @@ -191,10 +191,16 @@ boolean txCAT = false; //turned on if the transmitting due to a CAT comma char inTx = 0; //it is set to 1 if in transmit mode (whatever the reason : cw, ptt or cat) char splitOn = 0; //working split, uses VFO B as the transmit frequency char keyDown = 0; //in cw mode, denotes the carrier is being transmitted -char isUSB = 0; //upper sideband was selected, this is reset to the default for the +char isUSB = 0; //upper sideband was selected, this is reset to the default for the +//char isTest = 0; // two-tone test mode char cwMode = 0; //compatible original source, and extend mode //if cwMode == 0, mode check : isUSB, cwMode > 0, mode Check : cwMode //iscwMode = 0 : ssbmode, 1 :cwl, 2 : cwu, 3 : cwn (none tx) +char digiMode = 0; // 0: normal uBITX behavior (transmit LSB/USB when PTT is depressed) + // 1: user-defined digital mode via USB audio input; DTU (default) USB if isUSB; DTL LSB if !isUSB + // Effect of non-zero digiMode on ubitx software: should disable the physical PTT inputs (front/back), + // but might need to consider physical PTT as a way to stop CAT-based transmission. Also affects the mode + // info sent to the IOP. //frequency when it crosses the frequency border of 10 MHz byte menuOn = 0; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited @@ -316,6 +322,17 @@ unsigned long delayBeforeTime = 0; byte delay_background(unsigned delayTime, byte fromType){ //fromType : 4 autoCWKey -> Check Paddle delayBeforeTime = millis(); + /* + * KC4UPR - IOP review, 2020-05-03 + * + * I don't see anything in here that is either important to, or will adversely affect, IOP + * operation. I'm not planning on using the uBITX autokeyer (since all keying will be in the + * IOP), so neither getPaddle() nor autoSendPTTCheck() will be issues. I do need to look into + * overall CAT operation, in general. + * + * UPDATE: Fixed getPaddle() to be compatible. + */ + while (millis() - delayBeforeTime <= delayTime) { if (fromType == 4) @@ -325,7 +342,7 @@ byte delay_background(unsigned delayTime, byte fromType){ //fromType : 4 autoCWK return 1; //Check PTT while auto Sending - autoSendPTTCheck(); + //autoSendPTTCheck(); Check_Cat(3); } @@ -678,6 +695,10 @@ void ritDisable(){ */ void checkPTT(){ + /* + * KC4UPR - note that some of this is superfluous now that checkPTT() is only executed + * in SSB mode, and cwKeyer is only executed in CW mode... + */ //we don't check for ptt when transmitting cw if (cwTimeout > 0) return; @@ -711,8 +732,8 @@ void checkButton(){ SetSWActivePage(1); doMenu(); - if (isCWAutoMode == 0) - SetSWActivePage(0); + //if (isCWAutoMode == 0) + SetSWActivePage(0); #else doMenu(); #endif @@ -1432,6 +1453,8 @@ void setup() factory_alignment(); #endif + iopSendMode(cwMode, isUSB, digiMode); + } //Auto save Frequency and Mode with Protected eeprom life by KD8CEC @@ -1459,27 +1482,47 @@ void checkAutoSaveFreqMode() } void loop(){ - if (isCWAutoMode == 0){ //when CW AutoKey Mode, disable this process - if (!txCAT) + /* + * KC4UPR - IOP update, 2020-05-03 + * + * Getting rid of the autokeyer code... not planning on using, since any autokeying + * would actually be done by the IOP. We'll check the PTT, but only in SSB mode + * (same line as CW, so it would be caught by cwKeyer() in CW mode). + * + * Only check the CW keyer if we are in one of the CW modes. Why? Because we + * are using the same input for PTT and CW. + */ +// if (isCWAutoMode == 0){ //when CW AutoKey Mode, disable this process +// if (!txCAT) +// checkPTT(); +// checkButton(); +// } +// else +// controlAutoCW(); + // KC4UPR: Note, implementation below leaves no manual way to abort TX due to CAT. May + // want to add in a way to interrupt CAT transmission with a PTT/CW event. + if (!txCAT) { + if (cwMode == 0) checkPTT(); - checkButton(); + else + cwKeyer(); + checkButton(); } - else - controlAutoCW(); - - cwKeyer(); + +//cwKeyer(); //tune only when not tranmsitting if (!inTx){ - if (isCWAutoMode == 0 || cwAutoDialType == 1) - { + //if (isCWAutoMode == 0 || cwAutoDialType == 1) + //{ if (ritOn) doRIT(); else doTuningWithThresHold(); - } + //} - if (isCWAutoMode == 0 && beforeIdle_ProcessTime < millis() - 250) { + // KC4UPR: Updated to 100 msec (instead of 250 msec) for improved display responsiveness) + if (beforeIdle_ProcessTime < millis() - 100) { idle_process(); checkAutoSaveFreqMode(); //move here form out scope for reduce cpu use rate beforeIdle_ProcessTime = millis(); diff --git a/ubitx_20/ubitx_keyer.ino b/ubitx_20/ubitx_keyer.ino index 1ac1c2f..691b1d0 100644 --- a/ubitx_20/ubitx_keyer.ino +++ b/ubitx_20/ubitx_keyer.ino @@ -39,6 +39,22 @@ char lastPaddle = 0; //reads the analog keyer pin and reports the paddle byte getPaddle(){ + /* + * KC4UPR - IOP update, 2020-05-03 + * + * Modifying this for the uBITX IOP. Big picture: + * + * (1) It uses the PTT input line. + * + * (2) It's always "straight key" mode (the IOP provides the keyer). + */ + + if (digitalRead(PTT) == 1) // key/PTT is up + return 0; + else + return PADDLE_STRAIGHT; + +/* int paddle = analogRead(ANALOG_KEYER); if (paddle > 800) // above 4v is up @@ -52,6 +68,7 @@ byte getPaddle(){ return PADDLE_BOTH; //both are between 1 and 2v else return PADDLE_STRAIGHT; //less than 1v is the straight key +*/ } /** @@ -96,9 +113,20 @@ unsigned char keyerState = IDLE; //Below is a test to reduce the keying error. do not delete lines //create by KD8CEC for compatible with new CW Logic char update_PaddleLatch(byte isUpdateKeyState) { + /* + * KC4UPR - IOP update, 2020-05-03 + * + * Modifying this for the uBITX IOP. Big picture: + * + * No iambic keyer. It's always "straight key" based on the IOP. + * + * It uses the PTT line. + */ + return (digitalRead(PTT) ? 0 : DIT_L); +/* unsigned char tmpKeyerControl = 0; int paddle = analogRead(ANALOG_KEYER); - + if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo) tmpKeyerControl |= DAH_L; else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo) @@ -119,6 +147,7 @@ char update_PaddleLatch(byte isUpdateKeyState) { keyerControl |= tmpKeyerControl; return tmpKeyerControl; +*/ } /***************************************************************************** @@ -126,106 +155,113 @@ char update_PaddleLatch(byte isUpdateKeyState) { // modified by KD8CEC ******************************************************************************/ void cwKeyer(void){ - lastPaddle = 0; - bool continue_loop = true; - unsigned tmpKeyControl = 0; - - if( Iambic_Key ) { - while(continue_loop) { - switch (keyerState) { - case IDLE: - tmpKeyControl = update_PaddleLatch(0); - if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L || - tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) { - update_PaddleLatch(1); - keyerState = CHK_DIT; - }else{ - if (0 < cwTimeout && cwTimeout < millis()){ - cwTimeout = 0; - stopTx(); - } - continue_loop = false; - } - break; - - case CHK_DIT: - if (keyerControl & DIT_L) { - keyerControl |= DIT_PROC; - ktimer = cwSpeed; - keyerState = KEYED_PREP; - }else{ - keyerState = CHK_DAH; - } - break; - - case CHK_DAH: - if (keyerControl & DAH_L) { - ktimer = cwSpeed*3; - keyerState = KEYED_PREP; - }else{ - keyerState = IDLE; - } - break; - - case KEYED_PREP: - //modified KD8CEC - /* - ktimer += millis(); // set ktimer to interval end time - keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits - keyerState = KEYED; // next state - if (!inTx){ - //DelayTime Option - delay_background(delayBeforeCWStartTime * 2, 2); - - keyDown = 0; - cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT; - startTx(TX_CW, 1); - } - */ - if (!inTx){ - //DelayTime Option - delay_background(delayBeforeCWStartTime * 2, 2); - - keyDown = 0; - cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT; - startTx(TX_CW, 1); - } - ktimer += millis(); // set ktimer to interval end time - keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits - keyerState = KEYED; // next state - - cwKeydown(); - break; - - case KEYED: - if (millis() > ktimer) { // are we at end of key down ? - cwKeyUp(); - ktimer = millis() + cwSpeed; // inter-element time - keyerState = INTER_ELEMENT; // next state - }else if (keyerControl & IAMBICB) { - update_PaddleLatch(1); // early paddle latch in Iambic B mode - } - break; - - case INTER_ELEMENT: - // Insert time between dits/dahs - update_PaddleLatch(1); // latch paddle state - if (millis() > ktimer) { // are we at end of inter-space ? - if (keyerControl & DIT_PROC) { // was it a dit or dah ? - keyerControl &= ~(DIT_L + DIT_PROC); // clear two bits - keyerState = CHK_DAH; // dit done, check for dah - }else{ - keyerControl &= ~(DAH_L); // clear dah latch - keyerState = IDLE; // go idle - } - } - break; - } - - Check_Cat(2); - } //end of while - } - else{ + /* + * KC4UPR - IOP update, 2020-05-03 + * + * Modifying this for the uBITX IOP. Big picture: + * + * No iambic keyer. It's always "straight key" based on the IOP. + */ +// lastPaddle = 0; +// bool continue_loop = true; +// unsigned tmpKeyControl = 0; +// +// if( Iambic_Key ) { +// while(continue_loop) { +// switch (keyerState) { +// case IDLE: +// tmpKeyControl = update_PaddleLatch(0); +// if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L || +// tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) { +// update_PaddleLatch(1); +// keyerState = CHK_DIT; +// }else{ +// if (0 < cwTimeout && cwTimeout < millis()){ +// cwTimeout = 0; +// stopTx(); +// } +// continue_loop = false; +// } +// break; +// +// case CHK_DIT: +// if (keyerControl & DIT_L) { +// keyerControl |= DIT_PROC; +// ktimer = cwSpeed; +// keyerState = KEYED_PREP; +// }else{ +// keyerState = CHK_DAH; +// } +// break; +// +// case CHK_DAH: +// if (keyerControl & DAH_L) { +// ktimer = cwSpeed*3; +// keyerState = KEYED_PREP; +// }else{ +// keyerState = IDLE; +// } +// break; +// +// case KEYED_PREP: +// //modified KD8CEC +// /* +// ktimer += millis(); // set ktimer to interval end time +// keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits +// keyerState = KEYED; // next state +// if (!inTx){ +// //DelayTime Option +// delay_background(delayBeforeCWStartTime * 2, 2); +// +// keyDown = 0; +// cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT; +// startTx(TX_CW, 1); +// } +// */ +// if (!inTx){ +// //DelayTime Option +// delay_background(delayBeforeCWStartTime * 2, 2); +// +// keyDown = 0; +// cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT; +// startTx(TX_CW, 1); +// } +// ktimer += millis(); // set ktimer to interval end time +// keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits +// keyerState = KEYED; // next state +// +// cwKeydown(); +// break; +// +// case KEYED: +// if (millis() > ktimer) { // are we at end of key down ? +// cwKeyUp(); +// ktimer = millis() + cwSpeed; // inter-element time +// keyerState = INTER_ELEMENT; // next state +// }else if (keyerControl & IAMBICB) { +// update_PaddleLatch(1); // early paddle latch in Iambic B mode +// } +// break; +// +// case INTER_ELEMENT: +// // Insert time between dits/dahs +// update_PaddleLatch(1); // latch paddle state +// if (millis() > ktimer) { // are we at end of inter-space ? +// if (keyerControl & DIT_PROC) { // was it a dit or dah ? +// keyerControl &= ~(DIT_L + DIT_PROC); // clear two bits +// keyerState = CHK_DAH; // dit done, check for dah +// }else{ +// keyerControl &= ~(DAH_L); // clear dah latch +// keyerState = IDLE; // go idle +// } +// } +// break; +// } +// +// Check_Cat(2); +// } //end of while +// } +// else{ while(1){ if (update_PaddleLatch(0) == DIT_L) { // if we are here, it is only because the key is pressed @@ -262,7 +298,7 @@ void cwKeyer(void){ Check_Cat(2); } //end of while - } //end of elese +// } //end of elese } @@ -365,5 +401,3 @@ void cwKeyer(){ } } */ - - diff --git a/ubitx_20/ubitx_lcd_1602.ino b/ubitx_20/ubitx_lcd_1602.ino index 76f2e5b..41c169b 100644 --- a/ubitx_20/ubitx_lcd_1602.ino +++ b/ubitx_20/ubitx_lcd_1602.ino @@ -282,7 +282,7 @@ void LCD_CreateChar(uint8_t location, uint8_t charmap[]) //SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA #define OPTION_SKINNYBARS -char c[30], b[30]; +char c[40], b[40]; char printBuff[2][17]; //mirrors what is showing on the two lines of the display @@ -417,20 +417,20 @@ void updateDisplay() { memset(c, 0, sizeof(c)); if (inTx){ - if (isCWAutoMode == 2) { - for (i = 0; i < 4; i++) - c[3-i] = (i < autoCWSendReservCount ? byteToChar(autoCWSendReserv[i]) : ' '); + //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 { + // c[4] = byteToChar(sendingCWTextIndex); + // c[5] = '='; + //} + //else { if (cwTimeout > 0) strcpy(c, " CW:"); else strcpy(c, " TX:"); - } + //} } else { if (ritOn) @@ -438,18 +438,30 @@ void updateDisplay() { else { if (cwMode == 0) { - if (isUSB) - strcpy(c, "USB "); - else - strcpy(c, "LSB "); + if (digiMode == 1) { +// if (isUSB) + strcpy(c, "DIG "); +// else +// strcpy(c, "DGL "); +// } else if (isTest == 1) { +// if (isUSB) +// strcpy(c, "TTU "); +// else +// strcpy(c, "TTL "); + } else { + if (isUSB) + strcpy(c, "USB "); + else + strcpy(c, "LSB "); + } } else if (cwMode == 1) { - strcpy(c, "CWL "); + strcpy(c, "CWR "); } else { - strcpy(c, "CWU "); + strcpy(c, "CW "); } } if (vfoActive == VFO_A) // VFO A is active @@ -495,10 +507,10 @@ void updateDisplay() { LCD_SetCursor(5,diplayVFOLine); LCD_Write((uint8_t)0); } - else if (isCWAutoMode == 2){ - LCD_SetCursor(5,diplayVFOLine); - LCD_Write(0x7E); - } + //else if (isCWAutoMode == 2){ + // LCD_SetCursor(5,diplayVFOLine); + // LCD_Write(0x7E); + //} else { LCD_SetCursor(5,diplayVFOLine); @@ -506,8 +518,6 @@ void updateDisplay() { } } - - char line2Buffer[17]; //KD8CEC 200Hz ST //L14.150 200Hz ST @@ -520,6 +530,15 @@ int freqScrollPosition = 0; void updateLine2Buffer(char displayType) { unsigned long tmpFreq = 0; + + if (stateTopLine == 2) { + strncpy(line2Buffer, iopMenuDisplay, 16); + stateTopLine = 1; + } + if (stateTopLine == 1) { + return; + } + if (ritOn) { strcpy(line2Buffer, "RitTX:"); @@ -667,7 +686,11 @@ void updateLine2Buffer(char displayType) } line2Buffer[13] = ' '; - + + // KC4UPR: Replacing these all with IOP status + //line2Buffer[13] = iopStatusWindow[0]; + //line2Buffer[14] = iopStatusWindow[1]; + //line2Buffer[15] = iopStatusWindow[2]; //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb if (sdrModeOn == 1) { @@ -723,7 +746,7 @@ void idle_process() return; //if line2DisplayStatus == 0 <-- this condition is clear Line, you can display any message - if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2)) { + if (line2DisplayStatus == 0 || (((displayOption1 & 0x04) == 0x04) && line2DisplayStatus == 2) || stateTopLine > 0) { if (checkCount++ > 1) { updateLine2Buffer(0); //call by scheduler @@ -733,6 +756,16 @@ void idle_process() } } + if (stateTopLine > 0) { + return; + } + + /*if (!displaySmeter) { + if (delaySmeter < millis()) { + displaySmeter = true; + } + }*/ + //S-Meter Display if (((displayOption1 & 0x08) == 0x08 && (sdrModeOn == 0)) && (++checkCountSMeter > SMeterLatency)) { diff --git a/ubitx_20/ubitx_lcd_1602Dual.ino b/ubitx_20/ubitx_lcd_1602Dual.ino deleted file mode 100644 index 48598cb..0000000 --- a/ubitx_20/ubitx_lcd_1602Dual.ino +++ /dev/null @@ -1,727 +0,0 @@ -/************************************************************************* - KD8CEC's uBITX Display Routine for LCD1602 Dual LCD - 1.This is the display code for the 16x02 Dual LCD - 2.Some functions moved from uBITX_Ui. ------------------------------------------------------------------------------ - 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 I2CTinyLCD Library for Dual LCD by KD8CEC -//======================================================================== -#ifdef UBITX_DISPLAY_LCD1602I_DUAL - -#include -/************************************************************************* - I2C Tiny LCD Library - Referecnce Source : LiquidCrystal_I2C.cpp // Based on the work by DFRobot - KD8CEC - - This source code is modified version for small program memory - from Arduino LiquidCrystal_I2C 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. - Ian KD8CEC -**************************************************************************/ -#define UBITX_DISPLAY_LCD1602_BASE - -#define En B00000100 // Enable bit -#define Rw B00000010 // Read/Write bit -#define Rs B00000001 // Register select bit - -#define LCD_Command(x) (LCD_Send(x, 0)) -#define LCD_Write(x) (LCD_Send(x, Rs)) - -uint8_t _Addr; -uint8_t _displayfunction; -uint8_t _displaycontrol; -uint8_t _displaymode; -uint8_t _numlines; -uint8_t _cols; -uint8_t _rows; -uint8_t _backlightval; - -#define printIIC(args) Wire.write(args) - -void expanderWrite(uint8_t _data) -{ - Wire.beginTransmission(_Addr); - printIIC((int)(_data) | _backlightval); - Wire.endTransmission(); -} - -void pulseEnable(uint8_t _data){ - expanderWrite(_data | En); // En high - delayMicroseconds(1); // enable pulse must be >450ns - - expanderWrite(_data & ~En); // En low - delayMicroseconds(50); // commands need > 37us to settle -} - -void write4bits(uint8_t value) -{ - expanderWrite(value); - pulseEnable(value); -} - -void LCD_Send(uint8_t value, uint8_t mode) -{ - uint8_t highnib=value&0xf0; - uint8_t lownib=(value<<4)&0xf0; - write4bits((highnib)|mode); - write4bits((lownib)|mode); -} - - -// Turn the (optional) backlight off/on -void noBacklight(void) { - _backlightval=LCD_NOBACKLIGHT; - expanderWrite(0); -} - -void backlight(void) { - _backlightval=LCD_BACKLIGHT; - expanderWrite(0); -} - -void LCD1602_Dual_Init() -{ - //I2C Init - _cols = 16; - _rows = 2; - _backlightval = LCD_NOBACKLIGHT; - Wire.begin(); - - delay(50); - - // Now we pull both RS and R/W low to begin commands - _Addr = I2C_LCD_MASTER_ADDRESS; - expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) - _Addr = I2C_LCD_SECOND_ADDRESS; - expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) - delay(1000); - //put the LCD into 4 bit mode - // this is according to the hitachi HD44780 datasheet - // figure 24, pg 46 - - _Addr = I2C_LCD_MASTER_ADDRESS; - // we start in 8bit mode, try to set 4 bit mode - write4bits(0x03 << 4); - delayMicroseconds(4500); // wait min 4.1ms - - // second try - write4bits(0x03 << 4); - delayMicroseconds(4500); // wait min 4.1ms - - // third go! - write4bits(0x03 << 4); - delayMicroseconds(150); - - // finally, set to 4-bit interface - write4bits(0x02 << 4); - - // 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! - delayMicroseconds(1000); // this command takes a long time! - - LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); - - backlight(); - - - _Addr = I2C_LCD_SECOND_ADDRESS; - // we start in 8bit mode, try to set 4 bit mode - write4bits(0x03 << 4); - delayMicroseconds(4500); // wait min 4.1ms - - // second try - write4bits(0x03 << 4); - delayMicroseconds(4500); // wait min 4.1ms - - // third go! - write4bits(0x03 << 4); - delayMicroseconds(150); - - // finally, set to 4-bit interface - write4bits(0x02 << 4); - - // 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! - delayMicroseconds(1000); // this command takes a long time! - - LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); - - backlight(); - - //Change to Default LCD (Master) - _Addr = I2C_LCD_MASTER_ADDRESS; -} - - -//======================================================================== -// 16 X 02 LCD Routines -//Begin of Display Base Routines (Init, printLine..) -//======================================================================== - -void LCD_Print(const char *c) -{ - for (uint8_t i = 0; i < strlen(c); i++) - { - if (*(c + i) == 0x00) return; - LCD_Write(*(c + i)); - } -} - -const int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; -void LCD_SetCursor(uint8_t col, uint8_t row) -{ - LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row])); //0 : 0x00, 1 : 0x40, only for 20 x 4 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]); -} - -//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA -//#define OPTION_SKINNYBARS - -char c[30], b[30]; -char printBuff[4][20]; //mirrors what is showing on the two lines of the display - -void LCD_Init(void) -{ - LCD1602_Dual_Init(); - - _Addr = I2C_LCD_SECOND_ADDRESS; - initMeter(); //for Meter Display //when dual LCD, S.Meter on second LCD - _Addr = I2C_LCD_MASTER_ADDRESS; -} - - -// 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 < 20; i++) { // add white spaces until the end of the 20 characters line is reached - LCD_Write(' '); - } - } -} - -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) { - 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 < 20; 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 - // i also Very TNX Purdum for good source code - 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) - 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[20]; -//KD8CEC 200Hz ST -//L14.150 200Hz ST -//U14.150 +150khz -int freqScrollPosition = 0; - -//Example Line2 Optinal Display -//immediate execution, not call by scheulder -//warning : unused parameter 'displayType' <-- ignore, this is reserve -void updateLine2Buffer(char displayType) -{ - unsigned long tmpFreq = 0; - if (ritOn) - { - strcpy(line2Buffer, "RitTX:"); - - //display frequency - tmpFreq = ritTxFrequency; - - //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; - } - - 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] = ' '; - } - - memset(&line2Buffer[10], ' ', 10); - - if (isIFShift) - { - line2Buffer[6] = 'M'; - line2Buffer[7] = ' '; - //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); - - for (int i = 12; i < 17; i++) - { - if (line2Buffer[i] == 0) - line2Buffer[i] = ' '; - } - } // end of display IF - else // step & Key Type display - { - //Step - long tmpStep = arTuneStep[tuneStepIndex -1]; - - byte isStepKhz = 0; - if (tmpStep >= 1000) - { - isStepKhz = 2; - } - - for (int i = 13; i >= 11 - isStepKhz; i--) { - if (tmpStep > 0) { - line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; - tmpStep /= 10; - } - else - line2Buffer[i +isStepKhz] = ' '; - } - - if (isStepKhz == 0) - { - line2Buffer[14] = 'H'; - line2Buffer[15] = 'z'; - } - } - - //line2Buffer[17] = ' '; - /* ianlee - //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb - if (cwKeyType == 0) - { - line2Buffer[18] = 'S'; - line2Buffer[19] = 'T'; - } - else if (cwKeyType == 1) - { - line2Buffer[18] = 'I'; - line2Buffer[19] = 'A'; - } - else - { - line2Buffer[18] = 'I'; - line2Buffer[19] = '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); - - LCD_SetCursor(drawPosition, 0); - LCD_Write('S'); - - LCD_Write(':'); - for (int i = 0; i < 7; i++) - LCD_Write(lcdMeter[i]); - } -} - - -char checkCount = 0; -char checkCountSMeter = 0; - -char beforeKeyType = -1; -char displaySDRON = 0; - -//execute interval : 0.25sec -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; - - //check change CW Key Type - if (beforeKeyType != cwKeyType) - { - _Addr = I2C_LCD_SECOND_ADDRESS; - LCD_SetCursor(10, 0); - LCD_Write('K'); - LCD_Write('E'); - LCD_Write('Y'); - LCD_Write(':'); - - //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb - if (cwKeyType == 0) - { - LCD_Write('S'); - LCD_Write('T'); - } - else if (cwKeyType == 1) - { - LCD_Write('I'); - LCD_Write('A'); - } - else - { - LCD_Write('I'); - LCD_Write('B'); - } - - beforeKeyType = cwKeyType; - _Addr = I2C_LCD_MASTER_ADDRESS; - } //Display Second Screen - - } - } - - //EX for Meters - - //S-Meter Display - _Addr = I2C_LCD_SECOND_ADDRESS; - if (sdrModeOn == 1) - { - if (displaySDRON == 0) //once display - { - displaySDRON = 1; - LCD_SetCursor(0, 0); - LCD_Write('S'); - LCD_Write('D'); - LCD_Write('R'); - LCD_Write(' '); - LCD_Write('M'); - LCD_Write('O'); - LCD_Write('D'); - LCD_Write('E'); - } - } - else if (((displayOption1 & 0x08) == 0x08) && (++checkCountSMeter > 3)) - { - 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; - - //Faster attack, Slower release - //currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10); - //currentSMeter = (currentSMeter * 3 + newSMeter * 7) / 10; //remarked becaused of have already Latency time - currentSMeter = newSMeter; - - scaledSMeter = 0; - for (byte s = 8; s >= 1; s--) { - if (currentSMeter > sMeterLevels[s]) { - scaledSMeter = s; - break; - } - } -#endif - - DisplayMeter(0, scaledSMeter, 0); - checkCountSMeter = 0; - } //end of S-Meter - _Addr = I2C_LCD_MASTER_ADDRESS; - - - } -} - -//AutoKey LCD Display Routine -void Display_AutoKeyTextIndex(byte textIndex) -{ - byte diplayAutoCWLine = 0; - - if ((displayOption1 & 0x01) == 0x01) - diplayAutoCWLine = 1; - LCD_SetCursor(0, diplayAutoCWLine); - LCD_Write(byteToChar(textIndex)); - LCD_Write(':'); -} - -void DisplayCallsign(byte callSignLength) -{ - _Addr = I2C_LCD_SECOND_ADDRESS; - printLineFromEEPRom(1, 16 - userCallsignLength, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) - _Addr = I2C_LCD_MASTER_ADDRESS; -} - -void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) -{ - _Addr = I2C_LCD_SECOND_ADDRESS; - printLineF(1, fwVersionInfo); - _Addr = I2C_LCD_MASTER_ADDRESS; -} - -#endif diff --git a/ubitx_20/ubitx_lcd_2004.ino b/ubitx_20/ubitx_lcd_2004.ino deleted file mode 100644 index 06d44fa..0000000 --- a/ubitx_20/ubitx_lcd_2004.ino +++ /dev/null @@ -1,743 +0,0 @@ -/************************************************************************* - KD8CEC's uBITX Display Routine for LCD2004 Parrel & I2C - 1.This is the display code for the 20x04 LCD - 2.Some functions moved from uBITX_Ui. ------------------------------------------------------------------------------ - 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 TinyLCD Library by KD8CEC -//======================================================================== - -#ifdef UBITX_DISPLAY_LCD2004P -/************************************************************************* - LCD2004TINY Library for 20 x 4 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 UBITX_DISPLAY_LCD2004_BASE - -//Define connected PIN -#define LCD_PIN_RS 8 -#define LCD_PIN_EN 9 -uint8_t LCD_PIN_DAT[4] = {10, 11, 12, 13}; - -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 LCD2004_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); -} -#endif -//======================================================================== -//End of TinyLCD Library by KD8CEC -//======================================================================== - - - -//======================================================================== -//Begin of I2CTinyLCD Library by KD8CEC -//======================================================================== -#ifdef UBITX_DISPLAY_LCD2004I - -#include -/************************************************************************* - I2C Tiny LCD Library - Referecnce Source : LiquidCrystal_I2C.cpp // Based on the work by DFRobot - KD8CEC - - This source code is modified version for small program memory - from Arduino LiquidCrystal_I2C 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. - Ian KD8CEC -**************************************************************************/ -#define UBITX_DISPLAY_LCD2004_BASE - -#define En B00000100 // Enable bit -#define Rw B00000010 // Read/Write bit -#define Rs B00000001 // Register select bit - -#define LCD_Command(x) (LCD_Send(x, 0)) -#define LCD_Write(x) (LCD_Send(x, Rs)) - -uint8_t _Addr; -uint8_t _displayfunction; -uint8_t _displaycontrol; -uint8_t _displaymode; -uint8_t _numlines; -uint8_t _cols; -uint8_t _rows; -uint8_t _backlightval; - -#define printIIC(args) Wire.write(args) - -void expanderWrite(uint8_t _data) -{ - Wire.beginTransmission(_Addr); - printIIC((int)(_data) | _backlightval); - Wire.endTransmission(); -} - -void pulseEnable(uint8_t _data){ - expanderWrite(_data | En); // En high - delayMicroseconds(1); // enable pulse must be >450ns - - expanderWrite(_data & ~En); // En low - delayMicroseconds(50); // commands need > 37us to settle -} - -void write4bits(uint8_t value) -{ - expanderWrite(value); - pulseEnable(value); -} - -void LCD_Send(uint8_t value, uint8_t mode) -{ - uint8_t highnib=value&0xf0; - uint8_t lownib=(value<<4)&0xf0; - write4bits((highnib)|mode); - write4bits((lownib)|mode); -} - - -// Turn the (optional) backlight off/on -void noBacklight(void) { - _backlightval=LCD_NOBACKLIGHT; - expanderWrite(0); -} - -void backlight(void) { - _backlightval=LCD_BACKLIGHT; - expanderWrite(0); -} - -void LCD2004_Init() -{ - //I2C Init - _Addr = I2C_LCD_MASTER_ADDRESS; - _cols = 20; - _rows = 4; - _backlightval = LCD_NOBACKLIGHT; - Wire.begin(); - - delay(50); - - // Now we pull both RS and R/W low to begin commands - expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) - delay(1000); - //put the LCD into 4 bit mode - // this is according to the hitachi HD44780 datasheet - // figure 24, pg 46 - - // we start in 8bit mode, try to set 4 bit mode - write4bits(0x03 << 4); - delayMicroseconds(4500); // wait min 4.1ms - - // second try - write4bits(0x03 << 4); - delayMicroseconds(4500); // wait min 4.1ms - - // third go! - write4bits(0x03 << 4); - delayMicroseconds(150); - - // finally, set to 4-bit interface - write4bits(0x02 << 4); - - // 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! - delayMicroseconds(1000); // this command takes a long time! - - LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT); - - backlight(); -} -#endif -//======================================================================== -//End of I2CTinyLCD Library by KD8CEC -//======================================================================== - - -//======================================================================== -// 20 X 04 LCD Routines -//Begin of Display Base Routines (Init, printLine..) -//======================================================================== -#ifdef UBITX_DISPLAY_LCD2004_BASE - -void LCD_Print(const char *c) -{ - for (uint8_t i = 0; i < strlen(c); i++) - { - if (*(c + i) == 0x00) return; - LCD_Write(*(c + i)); - } -} - -const int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; -void LCD_SetCursor(uint8_t col, uint8_t row) -{ - LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row])); //0 : 0x00, 1 : 0x40, only for 20 x 4 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]); -} - -//SWR GRAPH, DrawMeter and drawingMeter Logic function by VK2ETA -//#define OPTION_SKINNYBARS - -char c[30], b[30]; -char printBuff[4][21]; //mirrors what is showing on the two lines of the display - -void LCD_Init(void) -{ - LCD2004_Init(); - initMeter(); //for Meter Display -} - - -// 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 < 20; i++) { // add white spaces until the end of the 20 characters line is reached - LCD_Write(' '); - } - } -} - -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) { - 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 < 20; 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 - // i also Very TNX Purdum for good source code - 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] = ' '; - } - - if (sdrModeOn) - strcat(c, " SDR"); - else - strcat(c, " SPK"); - - //remarked by KD8CEC - //already RX/TX status display, and over index (20 x 4 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[20]; -//KD8CEC 200Hz ST -//L14.150 200Hz ST -//U14.150 +150khz -int freqScrollPosition = 0; - -//Example Line2 Optinal Display -//immediate execution, not call by scheulder -//warning : unused parameter 'displayType' <-- ignore, this is reserve -void updateLine2Buffer(char displayType) -{ - unsigned long tmpFreq = 0; - if (ritOn) - { - strcpy(line2Buffer, "RitTX:"); - - //display frequency - tmpFreq = ritTxFrequency; - - //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; - } - - 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] = ' '; - } - - memset(&line2Buffer[10], ' ', 10); - - if (isIFShift) - { - line2Buffer[6] = 'M'; - line2Buffer[7] = ' '; - //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); - - for (int i = 12; i < 17; i++) - { - if (line2Buffer[i] == 0) - line2Buffer[i] = ' '; - } - } // end of display IF - else // step & Key Type display - { - //Step - long tmpStep = arTuneStep[tuneStepIndex -1]; - - byte isStepKhz = 0; - if (tmpStep >= 1000) - { - isStepKhz = 2; - } - - for (int i = 14; i >= 12 - isStepKhz; i--) { - if (tmpStep > 0) { - line2Buffer[i + isStepKhz] = tmpStep % 10 + 0x30; - tmpStep /= 10; - } - else - line2Buffer[i +isStepKhz] = ' '; - } - - if (isStepKhz == 0) - { - line2Buffer[15] = 'H'; - line2Buffer[16] = 'z'; - } - } - - line2Buffer[17] = ' '; - - //Check CW Key cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb - if (cwKeyType == 0) - { - line2Buffer[18] = 'S'; - line2Buffer[19] = 'T'; - } - else if (cwKeyType == 1) - { - line2Buffer[18] = 'I'; - line2Buffer[19] = 'A'; - } - else - { - line2Buffer[18] = 'I'; - line2Buffer[19] = '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); - - LCD_SetCursor(drawPosition, 2); - LCD_Write('S'); - LCD_Write(':'); - for (int i = 0; i < 7; i++) //meter 5 + +db 1 = 6 - LCD_Write(lcdMeter[i]); - } -} - -char checkCount = 0; -char checkCountSMeter = 0; - -//execute interval : 0.25sec -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++, 0); - if (testValue > 30) - testValue = 0; - */ - - //Sample - //DisplayMeter(0, analogRead(ANALOG_SMETER) / 30, 0); - //DisplayMeter(0, analogRead(ANALOG_SMETER) / 10, 0); - //delay_background(10, 0); - //DisplayMeter(0, analogRead(ANALOG_SMETER), 0); - //if (testValue > 30) - // testValue = 0; - - //S-Meter Display - 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; - - //Faster attack, Slower release - //currentSMeter = (newSMeter > currentSMeter ? ((currentSMeter * 3 + newSMeter * 7) + 5) / 10 : ((currentSMeter * 7 + newSMeter * 3) + 5) / 10); - //currentSMeter = ((currentSMeter * 7 + newSMeter * 3) + 5) / 10; - currentSMeter = newSMeter; - - scaledSMeter = 0; - for (byte s = 8; s >= 1; s--) { - if (currentSMeter > sMeterLevels[s]) { - scaledSMeter = s; - break; - } - } -#endif - - DisplayMeter(0, scaledSMeter, 0); - checkCountSMeter = 0; //Reset Latency time - } //end of S-Meter - - } -} - -//AutoKey LCD Display Routine -void Display_AutoKeyTextIndex(byte textIndex) -{ - byte diplayAutoCWLine = 0; - - if ((displayOption1 & 0x01) == 0x01) - diplayAutoCWLine = 1; - LCD_SetCursor(0, diplayAutoCWLine); - LCD_Write(byteToChar(textIndex)); - LCD_Write(':'); -} - -void DisplayCallsign(byte callSignLength) -{ - printLineFromEEPRom(3, 20 - userCallsignLength, 0, userCallsignLength -1, 0); //eeprom to lcd use offset (USER_CALLSIGN_DAT) -} - -void DisplayVersionInfo(const __FlashStringHelper * fwVersionInfo) -{ - printLineF(3, fwVersionInfo); -} - -#endif diff --git a/ubitx_20/ubitx_lcd_nextion.ino b/ubitx_20/ubitx_lcd_nextion.ino deleted file mode 100644 index 62667af..0000000 --- a/ubitx_20/ubitx_lcd_nextion.ino +++ /dev/null @@ -1,1107 +0,0 @@ -/************************************************************************* - 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.200")); //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 502bd94..53b0f98 100644 --- a/ubitx_20/ubitx_menu.ino +++ b/ubitx_20/ubitx_menu.ino @@ -127,9 +127,13 @@ void menuBand(int btn){ //Convert Mode, Number by KD8CEC //0: default, 1:not use, 2:LSB, 3:USB, 4:CWL, 5:CWU, 6:FM -byte modeToByte(){ +// Updated: KC4UPR - 6: DIG +byte modeToByte() { if (cwMode == 0) { + if (digiMode > 0) { + return 6; + } if (isUSB) return 3; else @@ -149,20 +153,53 @@ byte modeToByte(){ //autoSetModebyFreq : 0 //autoSetModebyFreq : 1, if (modValue is not set, set mode by frequency) void byteToMode(byte modeValue, byte autoSetModebyFreq){ - if (modeValue == 4) - cwMode = 1; - else if (modeValue == 5) - cwMode = 2; - else - { + //isTest = false; // test never settable from EEPROM + isUSB = false; + cwMode = 0; + digiMode = 0; + + if (autoSetModebyFreq == 1 && (modeValue == 0)) { + isUSB = (frequency > 10000000l) ? true : false; + } else { + switch(modeValue) { + // LSB by default, so we can skip this case + //case 2: // LSB + //break; + + case 3: // USB + isUSB = true; + break; + + case 4: // CWL + cwMode = 1; + break; + + case 5: // CWU + cwMode = 2; + break; + + case 6: // DIG + digiMode = 1; + isUSB = true; + break; + } + } +/* if (modeValue == 4) { + cwMode = 1; digiMode = 0; + } else if (modeValue == 5) { + cwMode = 2; digiMode = 0; + } else { cwMode = 0; - if (modeValue == 3) - isUSB = 1; + if (modeValue == 3) { + isUSB = 1; digiMode = 0; + } else if (modeValue == 6) { + isUSB = + } else if (autoSetModebyFreq == 1 && (modeValue == 0)) isUSB = (frequency > 10000000l) ? true : false; else isUSB = 0; - } + }*/ } @@ -502,6 +539,7 @@ void displayEmptyData(void){ delay_background(2000, 0); } +/* //Builtin CW Keyer Logic by KD8CEC void menuCWAutoKey(int btn){ if (!btn){ @@ -524,6 +562,7 @@ void menuCWAutoKey(int btn){ updateDisplay(); menuOn = 0; } +*/ //Standalone WSPR Beacone void menuWSPRSend(int btn){ @@ -651,12 +690,19 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob moveDetectStep = 0; } - strcpy(b, displayTitle); - if (valueType == 11) //Mode Select { - b[targetValue * 4] = '>'; - } + int tmpCol = targetValue * 4; + if (tmpCol >= 16) { + tmpCol -= 16; + strcpy(b, &displayTitle[16]); + } else { + strcpy(b, displayTitle); + } + b[tmpCol] = '>'; + } else { + strcpy(b, displayTitle); + /* else if (valueType == 4) //CW Key Type Select { @@ -668,8 +714,6 @@ int getValueByKnob(int valueType, int targetValue, int minKnobValue, int maxKnob strcat(b, "IAMBICB"); } */ - else - { strcat(b, ":"); itoa(targetValue,c, 10); strcat(b, c); @@ -932,34 +976,57 @@ void menuSelectMode(int btn){ } else { - //LSB, USB, CWL, CWU - if (cwMode == 0 && isUSB == 0) + //LSB, USB, CWL, CWU, DGL, DGU, TTL, TTU + if (cwMode == 0) { + if (isUSB == 0) { + selectModeType = 0; // LSB + } else { + selectModeType = 1; // USB + } + // modify if digital mode is set + if (digiMode > 0) { + + selectModeType = 4; + } + } else if (cwMode == 2) { + selectModeType = 2; // CW + } else { + selectModeType = 3; // CWR + } + /*if (cwMode == 0 && isUSB == 0) selectModeType = 0; else if (cwMode == 0 && isUSB == 1) selectModeType = 1; else if (cwMode == 1) selectModeType = 2; else - selectModeType = 3; + selectModeType = 3;*/ beforeMode = selectModeType; - selectModeType = getValueByKnob(11, selectModeType, 0, 3, 1, " LSB USB CWL CWU", 4); //3 : Select Mode, targetValue, minKnobValue, maxKnobValue, stepSize + selectModeType = getValueByKnob(11, selectModeType, 0, 4, 1, " LSB USB CW CWR DIG", 4); //3 : Select Mode, targetValue, minKnobValue, maxKnobValue, stepSize 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; + cwMode = 0; isUSB = 0; digiMode = 0; //isTest = 0; + } else if (selectModeType == 1) { + cwMode = 0; isUSB = 1; digiMode = 0; //isTest = 0; + } else if (selectModeType == 2) { + cwMode = 2; digiMode = 0; //isTest = 0; + } else if (selectModeType == 3) { + cwMode = 1; digiMode = 0; //isTest = 0; + } else if (selectModeType == 4) { + cwMode = 0; isUSB = 1; digiMode = 1; //isTest = 0; +// } else if (selectModeType == 5) { +// cwMode = 0; isUSB = 1; digiMode = 1; isTest = 0; +// } else if (selectModeType == 6) { +// cwMode = 0; isUSB = 0; digiMode = 0; isTest = 1; +// } else if (selectModeType == 7) { +// cwMode = 0; isUSB = 1; digiMode = 0; isTest = 1; } + // KC4UPR: sending mode to IOP + iopSendMode(cwMode, isUSB, digiMode); FrequencyToVFO(1); }