Merge branch 'kc4upr'.

This commit is contained in:
Rob French 2020-06-14 23:04:45 -05:00
commit 38b696d9c2
11 changed files with 638 additions and 3633 deletions

View File

@ -32,6 +32,8 @@
**************************************************************************/
#include <iopcomm.h>
#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);
}

View File

@ -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 <http://www.gnu.org/licenses/>.
**************************************************************************/
#include <avr/pgmspace.h>
//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<PGM_P>(cwAZTable);
const PROGMEM uint8_t cw09Table[27] = {0b00011111, 0b00001111, 0b00000111, 0b00000011, 0b00000001, 0b00000000, 0b00010000, 0b00011000, 0b00011100, 0b00011110};
PGM_P pcw09Table = reinterpret_cast<PGM_P>(cw09Table);
//# : AR, ~:BT, [:AS, ]:SK, ^:KN
const PROGMEM uint8_t cwSymbolIndex[] = {'.', ',', '?', '"', '!', '/', '(', ')', '&', ':', ';', '=', '+', '-', '_', '\'', '@', '#', '~', '[', ']', '^' };
PGM_P pCwSymbolIndex = reinterpret_cast<PGM_P>(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<PGM_P>(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);
}
}

View File

@ -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.h>
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 <Arduino.h>
//================================================================
//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);
}

View File

@ -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);

View File

@ -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();

View File

@ -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