Version 0.224

This commit is contained in:
phdlee 2018-01-04 09:07:03 +09:00
parent 8921d70f56
commit 0ccdd115e6
6 changed files with 1083 additions and 64 deletions

698
ubitx_20/cat_libs.ino Normal file
View File

@ -0,0 +1,698 @@
/*************************************************************************
This source code is written for uBITX, but it can also be used on other radios.
The CAT protocol is used by many radios to provide remote control to comptuers through
the serial port.
it is based on FT-817, uBITX's only protocol has been added and will be added in the future.
In addition, simple things such as FT-857 frequency control and PTT control can also be
transmitted to the FT-857 protocol.
This code refers to the following code.
- FT857D CAT Library, by Pavel Milanes, CO7WT, pavelmc@gmail.com
https://github.com/pavelmc/FT857d/
- Ham Radio Control Libraries, https://sourceforge.net/projects/hamlib/
- Not found protocols decription were analyzed using an RS-232 analyzer.
using FT-817 and
- http://www.ka7oei.com/ft817_meow.html <-- It was a great help here.
-----------------------------------------------------------------------------
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/>.
**************************************************************************/
//for broken protocol
#define MAX_PROTOCOL_SKIP_COUNT 200
#define CAT_MODE_LSB 0x00
#define CAT_MODE_USB 0x01
#define CAT_MODE_CW 0x02
#define CAT_MODE_CWR 0x03
#define CAT_MODE_AM 0x04
#define CAT_MODE_FM 0x08
#define CAT_MODE_DIG 0x0A
#define CAT_MODE_PKT 0x0C
#define CAT_MODE_FMN 0x88
#define ACK 0
unsigned int skipTimeCount = 0;
byte CAT_BUFF[5];
byte CAT_SNDBUFF[5];
void SendCatData(byte sendCount)
{
for (byte i = 0; i < sendCount; i++)
Serial.write(CAT_BUFF[i]);
//Serial.flush();
}
//PROTOCOL : 0x01
//Computer ->(frequency)-> TRCV CAT_BUFF
void CatSetFreq(byte fromType)
{
//CAT_BUFF
byte i;
unsigned long tempFreq = 0;
if (fromType == 2 || fromType == 3) {
Serial.write(ACK);
return;
}
//2 digit in 1 byte (4 bit + 4bit) * 4.5 byte
for (i = 0; i < 4; i++)
{
tempFreq *= 10;
tempFreq += CAT_BUFF[i] >> 4;
tempFreq *= 10;
tempFreq += CAT_BUFF[i] & 0x0f;
}
tempFreq *= 10;
tempFreq += CAT_BUFF[4] >> 4;
if (!inTx && (frequency != tempFreq))
{
//Check Frequency Range
if (tempFreq >= LOWEST_FREQ_DIAL && tempFreq <= HIGHEST_FREQ_DIAL)
{
setFrequency(tempFreq);
updateDisplay();
}
else
{
//KD8CEC
//Remark for rduce program size, if you need, you can remove remark,
//however alomost rig control software available 1.0 ~ 50Mhz
//printLine(0, "OUT OF RANGE!!!");
//delay_background(300, 0);
}
}
Serial.write(ACK);
}
//#define BCD_LEN 9
//PROTOCOL : 0x03
//Computer <-(frequency)-> TRCV CAT_BUFF
void CatGetFreqMode(unsigned long freq, byte fromType)
{
int i;
byte tmpValue;
unsigned BCD_LEN = 9;
if (BCD_LEN & 1) {
CAT_BUFF[BCD_LEN / 2] &= 0x0f;
CAT_BUFF[BCD_LEN / 2] |= (freq % 10) << 4;
freq /= 10;
}
for (i = (BCD_LEN / 2) - 1; i >= 0; i--) {
tmpValue = freq % 10;
freq /= 10;
tmpValue |= (freq % 10) << 4;
freq /= 10;
CAT_BUFF[i] = tmpValue;
}
//Mode Check
if (isUSB)
CAT_BUFF[4] = CAT_MODE_USB;
else
CAT_BUFF[4] = CAT_MODE_LSB;
SendCatData(5);
}
void CatSetSplit(boolean isSplit, byte fromType)
{
Serial.write(ACK);
}
void CatSetPTT(boolean isPTTOn, byte fromType)
{
if (fromType == 2 || fromType == 3) {
Serial.write(ACK);
return;
}
// Set PTT Mode
if (isPTTOn)
{
if (!inTx)
{
txCAT = true;
startTx(TX_SSB, 1);
}
}
else
{
if (inTx)
{
stopTx();
txCAT = false;
}
}
Serial.write(ACK);
}
void CatVFOToggle(boolean isSendACK, byte fromType)
{
if (fromType != 2 && fromType != 3) {
menuVfoToggle(1);
}
if (isSendACK)
Serial.write(ACK); //Time
}
void CatSetMode(byte tmpMode, byte fromType)
{
if (fromType == 2 || fromType == 3) {
Serial.write(ACK);
return;
}
if (!inTx)
{
if (tmpMode == CAT_MODE_USB)
{
isUSB = true;
}
else
{
isUSB = false;
}
setFrequency(frequency);
updateDisplay();
}
Serial.write(ACK);
}
void ReadEEPRom(byte fromType)
{
// This is to make hamlib happy, PC requested reading two bytes
// we must answer with two bytes, we forge it as empty ones or...
// if the second byte in the request is 0x78 we have to send the first
// with the 5th bit set if the USB or zero if LSB.
// mem zone to "read"
byte temp0 = CAT_BUFF[0];
byte temp1 = CAT_BUFF[1];
// clear the CAT_BUFF
//npadClear();
CAT_BUFF[0] = 0;
CAT_BUFF[1] = 0;
switch (temp1)
{
case 0x45 : //
if (temp0 == 0x03)
{
CAT_BUFF[0] = 0x00;
CAT_BUFF[1] = 0xD0;
}
break;
case 0x47 : //
if (temp0 == 0x03)
{
CAT_BUFF[0] = 0xDC;
CAT_BUFF[1] = 0xE0;
}
break;
case 0x55 :
//0 : VFO A/B 0 = VFO-A, 1 = VFO-B
//1 : MTQMB Select 0 = (Not MTQMB), 1 = MTQMB ("Memory Tune Quick Memory Bank")
//2 : QMB Select 0 = (Not QMB), 1 = QMB ("Quick Memory Bank")
//3 :
//4 : Home Select 0 = (Not HOME), 1 = HOME memory
//5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE
//6 :
//7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0)
CAT_BUFF[0] = 0x80 + (vfoActive == VFO_B ? 1 : 0);
CAT_BUFF[1] = 0x00;
break;
case 0x57 : //
//0 : 1-0 AGC Mode 00 = Auto, 01 = Fast, 10 = Slow, 11 = Off
//2 DSP On/Off 0 = Off, 1 = On (Display format)
//4 PBT On/Off 0 = Off, 1 = On (Passband Tuning)
//5 NB On/Off 0 = Off, 1 = On (Noise Blanker)
//6 Lock On/Off 0 = Off, 1 = On (Dial Lock)
//7 FST (Fast Tuning) On/Off 0 = Off, 1 = On (Fast tuning)
CAT_BUFF[0] = 0xC0;
CAT_BUFF[1] = 0x40;
break;
case 0x59 : // band select VFO A Band Select 0000 = 160 M, 0001 = 75 M, 0010 = 40 M, 0011 = 30 M, 0100 = 20 M, 0101 = 17 M, 0110 = 15 M, 0111 = 12 M, 1000 = 10 M, 1001 = 6 M, 1010 = FM BCB, 1011 = Air, 1100 = 2 M, 1101 = UHF, 1110 = (Phantom)
//http://www.ka7oei.com/ft817_memmap.html
//CAT_BUFF[0] = 0xC2;
//CAT_BUFF[1] = 0x82;
break;
case 0x5C : //Beep Volume (0-100) (#13)
CAT_BUFF[0] = 0xB2;
CAT_BUFF[1] = 0x42;
break;
case 0x5E :
//3-0 : CW Pitch (300-1000 Hz) (#20) From 0 to E (HEX) with 0 = 300 Hz and each step representing 50 Hz
//5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel
//7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW
//CAT_BUFF[0] = 0x08;
CAT_BUFF[0] = sideTonePitch;
CAT_BUFF[1] = 0x25;
break;
case 0x61 : //Sidetone (Volume) (#44)
CAT_BUFF[0] = sideToneSub;
CAT_BUFF[1] = 0x08;
break;
case 0x5F : //
//4-0 CW Weight (1.:2.5-1:4.5) (#22) From 0 to 14 (HEX) with 0 = 1:2.5, incrementing in 0.1 weight steps
//5 420 ARS (#2) 0 = Off, 1 = On
//6 144 ARS (#1) 0 = Off, 1 = On
//7 Sql/RF-G (#45) 0 = Off, 1 = On
CAT_BUFF[0] = 0x32;
CAT_BUFF[1] = 0x08;
break;
case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms
CAT_BUFF[0] = cwDelayTime;
CAT_BUFF[1] = 0x32;
break;
case 0x62 : //
//5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps)
//7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours
//CAT_BUFF[0] = 0x08;
CAT_BUFF[0] = 1200 / cwSpeed - 4;
CAT_BUFF[1] = 0xB2;
break;
case 0x63 : //
//6-0 VOX Gain (#51) Contains 1-100 (decimal) as displayed
//7 Disable AM/FM Dial (#4) 0 = Enable, 1 = Disable
CAT_BUFF[0] = 0xB2;
CAT_BUFF[1] = 0xA5;
break;
case 0x64 : //
break;
case 0x67 : //6-0 SSB Mic (#46) Contains 0-100 (decimal) as displayed
CAT_BUFF[0] = 0xB2;
CAT_BUFF[1] = 0xB2;
break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed
case 0x78 :
if (isUSB)
CAT_BUFF[0] = CAT_MODE_USB;
else
CAT_BUFF[0] = CAT_MODE_LSB;
if (CAT_BUFF[0] != 0) CAT_BUFF[0] = 1 << 5;
break;
case 0x79 : //
//1-0 TX Power (All bands) 00 = High, 01 = L3, 10 = L2, 11 = L1
//3 PRI On/Off 0 = Off, 1 = On
//DW On/Off 0 = Off, 1 = On
//SCN (Scan) Mode 00 = No scan, 10 = Scan up, 11 = Scan down
//ART On/Off 0 = Off, 1 = On
CAT_BUFF[0] = 0x00;
CAT_BUFF[1] = 0x00;
break;
case 0x7A : //SPLIT
//7A 0 HF Antenna Select 0 = Front, 1 = Rear
//7A 1 6 M Antenna Select 0 = Front, 1 = Rear
//7A 2 FM BCB Antenna Select 0 = Front, 1 = Rear
//7A 3 Air Antenna Select 0 = Front, 1 = Rear
//7A 4 2 M Antenna Select 0 = Front, 1 = Rear
//7A 5 UHF Antenna Select 0 = Front, 1 = Rear
//7A 6 ? ?
//7A 7 SPL On/Off 0 = Off, 1 = On
CAT_BUFF[0] = (isSplitOn ? 0xFF : 0x7F);
break;
case 0xB3 : //
CAT_BUFF[0] = 0x00;
CAT_BUFF[1] = 0x4D;
break;
}
// sent the data
SendCatData(2);
}
void WriteEEPRom(byte fromType)
{
byte temp0 = CAT_BUFF[0];
byte temp1 = CAT_BUFF[1];
CAT_BUFF[0] = 0;
CAT_BUFF[1] = 0;
if (fromType == 2 || fromType == 3) {
SendCatData(2);
Serial.write(ACK);
return;
}
switch (temp1)
{
case 0x55 :
//0 : VFO A/B 0 = VFO-A, 1 = VFO-B
//1 : MTQMB Select 0 = (Not MTQMB), 1 = MTQMB ("Memory Tune Quick Memory Bank")
//2 : QMB Select 0 = (Not QMB), 1 = QMB ("Quick Memory Bank")
//3 :
//4 : Home Select 0 = (Not HOME), 1 = HOME memory
//5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE
//6 :
//7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0)
if (CAT_BUFF[2] & 0x01) //vfoB
{
//nowVFO Check
if (vfoActive != VFO_B)
{
CatVFOToggle(false, fromType);
}
}
else
{
//vfoA
if (vfoActive != VFO_A)
{
CatVFOToggle(false, fromType);
}
}
break;
/*
case 0x57 : //
//0 : 1-0 AGC Mode 00 = Auto, 01 = Fast, 10 = Slow, 11 = Off
//2 DSP On/Off 0 = Off, 1 = On (Display format)
//4 PBT On/Off 0 = Off, 1 = On (Passband Tuning)
//5 NB On/Off 0 = Off, 1 = On (Noise Blanker)
//6 Lock On/Off 0 = Off, 1 = On (Dial Lock)
//7 FST (Fast Tuning) On/Off 0 = Off, 1 = On (Fast tuning)
CAT_BUFF[0] = 0xC0;
CAT_BUFF[1] = 0x40;
break;
case 0x59 : // band select VFO A Band Select 0000 = 160 M, 0001 = 75 M, 0010 = 40 M, 0011 = 30 M, 0100 = 20 M, 0101 = 17 M, 0110 = 15 M, 0111 = 12 M, 1000 = 10 M, 1001 = 6 M, 1010 = FM BCB, 1011 = Air, 1100 = 2 M, 1101 = UHF, 1110 = (Phantom)
//http://www.ka7oei.com/ft817_memmap.html
//CAT_BUFF[0] = 0xC2;
//CAT_BUFF[1] = 0x82;
break;
case 0x5C : //Beep Volume (0-100) (#13)
CAT_BUFF[0] = 0xB2;
CAT_BUFF[1] = 0x42;
break;
*/
case 0x5E :
//3-0 : CW Pitch (300-1000 Hz) (#20) From 0 to E (HEX) with 0 = 300 Hz and each step representing 50 Hz
//5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel
//7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW
sideTonePitch = (CAT_BUFF[2] & 0x0F);
if (sideTonePitch != 0 || sideToneSub != 0)
{
sideTone = (sideTonePitch * 50 + 300) + sideToneSub;
//debugBytePrint(CAT_BUFF[2], sideToneSub, 0);
printLine2("Sidetone set! CAT");
EEPROM.put(CW_SIDETONE, sideTone);
delay(500);
printLine2("");
}
break;
case 0x61 : //Sidetone (Volume) (#44)
sideToneSub = (CAT_BUFF[2] & 0x7F);
if (sideTonePitch != 0 || sideToneSub != 0)
{
sideTone = (sideTonePitch * 50 + 300) + sideToneSub;
//debugBytePrint(CAT_BUFF[2], sideToneSub, 0);
printLine2("Sidetone set! CAT");
EEPROM.put(CW_SIDETONE, sideTone);
delay(500);
printLine2("");
}
break;
/*
case 0x5F : //
//4-0 CW Weight (1.:2.5-1:4.5) (#22) From 0 to 14 (HEX) with 0 = 1:2.5, incrementing in 0.1 weight steps
//5 420 ARS (#2) 0 = Off, 1 = On
//6 144 ARS (#1) 0 = Off, 1 = On
//7 Sql/RF-G (#45) 0 = Off, 1 = On
CAT_BUFF[0] = 0x32;
CAT_BUFF[1] = 0x08;
break;
*/
case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms
//CAT_BUFF[0] = 0x19;
cwDelayTime = CAT_BUFF[2];
printLine2("CW Speed set!");
EEPROM.put(CW_DELAY, cwDelayTime);
delay(500);
printLine2("");
break;
case 0x62 : //
//5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps)
//7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours
cwSpeed = 1200 / ((CAT_BUFF[2] & 0x3F) + 4);
printLine2("CW Speed set!");
EEPROM.put(CW_SPEED, cwSpeed);
delay(500);
printLine2("");
break;
/*
case 0x63 : //
//6-0 VOX Gain (#51) Contains 1-100 (decimal) as displayed
//7 Disable AM/FM Dial (#4) 0 = Enable, 1 = Disable
CAT_BUFF[0] = 0xB2;
CAT_BUFF[1] = 0xA5;
break;
case 0x64 : //
//CAT_BUFF[0] = 0xA5;
//CAT_BUFF[1] = 0x00;
break;
case 0x67 : //6-0 SSB Mic (#46) Contains 0-100 (decimal) as displayed
CAT_BUFF[0] = 0xB2;
CAT_BUFF[1] = 0xB2;
//break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed
//CAT_BUFF[0] = 0x32;
//CAT_BUFF[1] = 0x32;
//break;
case 0x78 :
CAT_BUFF[0] = catGetMode();
// check, it must be a bit argument
if (CAT_BUFF[0] != 0) CAT_BUFF[0] = 1<<5;
break;
case 0x79 : //
//1-0 TX Power (All bands) 00 = High, 01 = L3, 10 = L2, 11 = L1
//3 PRI On/Off 0 = Off, 1 = On
//DW On/Off 0 = Off, 1 = On
//SCN (Scan) Mode 00 = No scan, 10 = Scan up, 11 = Scan down
//ART On/Off 0 = Off, 1 = On
CAT_BUFF[0] = 0x00;
CAT_BUFF[1] = 0x00;
break;
case 0x7A : //SPLIT
//7A 0 HF Antenna Select 0 = Front, 1 = Rear
//7A 1 6 M Antenna Select 0 = Front, 1 = Rear
//7A 2 FM BCB Antenna Select 0 = Front, 1 = Rear
//7A 3 Air Antenna Select 0 = Front, 1 = Rear
//7A 4 2 M Antenna Select 0 = Front, 1 = Rear
//7A 5 UHF Antenna Select 0 = Front, 1 = Rear
//7A 6 ? ?
//7A 7 SPL On/Off 0 = Off, 1 = On
CAT_BUFF[0] = (isSplitOn ? 0xFF : 0x7F);
break;
case 0xB3 : //
CAT_BUFF[0] = 0x00;
CAT_BUFF[1] = 0x4D;
break;
*/
}
// sent the data
SendCatData(2);
Serial.write(ACK);
}
void CatRxStatus(byte fromType)
{
byte sMeterValue = 1;
/*
http://www.ka7oei.com/ft817_meow.html
Command E7 - Read Receiver Status: This command returns one byte. Its contents are valid only when the '817 is in receive mode and it should be ignored when transmitting.
The lower 4 bits (0-3) of this byte indicate the current S-meter reading. 00 refers to an S-Zero reading, 04 = S4, 09 = S9, 0A = "10 over," 0B = "20 over" and so on up to 0F.
Bit 4 contains no useful information.
Bit 5 is 0 in non-FM modes, and it is 0 if the discriminator is centered (within 3.5 kHz for standard FM) when in the FM, FMN, or PKT modes, and 1 if the receiver is off-frequency.
Bit 6 is 0 if the CTCSS or DCS is turned off (or in a mode where it is not available.) It is also 0 if there is a signal being receive and the correct CTCSS tone or DCS code is being decoded.
It is 1 if there is a signal and the CTCSS/DCS decoding is enable, but the wrong CTCSS tone, DCS code, or no CTCSS/DCS is present.
Bit 7 is 0 if there is a signal present, or 1 if the receiver is squelched.
*/
// The lower 4 bits (0-3) of this byte indicate the current S-meter reading. 00 refers to an S-Zero reading, 04 = S4, 09 = S9, 0A = "10 over," 0B = "20 over" and so on up to 0F.
CAT_BUFF[0] = sMeterValue & 0b00001111;
SendCatData(1);
}
void CatTxStatus(byte fromType)
{
boolean isHighSWR = false;
boolean isSplitOn = false;
/*
Inverted -> *ptt = ((p->tx_status & 0x80) == 0); <-- souce code in ft817.c (hamlib)
*/
CAT_BUFF[0] = ((inTx ? 0 : 1) << 7) +
((isHighSWR ? 1 : 0) << 6) + //hi swr off / on
((isSplitOn ? 1 : 0) << 5) + //Split on / off
(0 << 4) + //dummy data
0x08; //P0 meter data
SendCatData(1);
}
unsigned int skiptimeCount = 0;
//Prevent Stack Overflow
byte isProcessCheck_Cat = 0;
//fromType normal : 0, TX : 1, CW_STRAIGHT : 2, CW_PADDLE : 3
//if cw mode, no delay
void Check_Cat(byte fromType)
{
byte i;
//Check Serial Port Buffer
if (Serial.available() == 0)
{
skipTimeCount = 0; //Init skipTimeCount for broken protocol
return;
}
else if (Serial.available() < 5)
{
/*
//if Broken Protocol, Reset Buffer
//when TX mode very fast count because stkip dial check, button check functions
if ((fromType == 0 && ++skiptimeCount > MAX_PROTOCOL_SKIP_COUNT) ||
((fromType == 1 || 2) && ++skiptimeCount > MAX_PROTOCOL_SKIP_COUNT * 70) )
{
//Clear Buffer
for (i = 0; i < Serial.available(); i++)
CAT_BUFF[0] = Serial.read();
skipTimeCount = 0; //Init skipTimeCount for broken protocol
}
*/
return;
}
//Arived CAT DATA
for (i = 0; i < 5; i++)
CAT_BUFF[i] = Serial.read();
if (isProcessCheck_Cat == 1)
return;
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
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 0x02 : //Split On
case 0x82: //Split Off
CatSetSplit(CAT_BUFF[4] == 0x02, fromType);
break;
case 0x03 : //Read Frequency and mode
CatGetFreqMode(frequency, fromType);
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
case 0xBB: //Read FT-817 EEPROM Data (for comfirtable)
ReadEEPRom(fromType);
break;
case 0xDC: //Write uBITX EEPROM Data
case 0xBC: //Write FT-817 EEPROM Data (for comfirtable)
WriteEEPRom(fromType);
break;
case 0xE7 : //Read RX Status
CatRxStatus(fromType);
break;
case 0xF7: //Read TX Status
CatTxStatus(fromType);
break;
default:
/*
char buff[16];
sprintf(buff, "DEFAULT : %x", CAT_BUFF[4]);
printLine2(buff);
*/
Serial.write(ACK);
break;
} //end of switch
isProcessCheck_Cat = 0;
}
void Init_Cat(long baud, int portConfig)
{
Serial.begin(baud, portConfig);
Serial.flush();
}

View File

@ -141,6 +141,12 @@ int count = 0; //to generally count ticks, loops, etc
#define CW_SIDETONE 24
#define CW_SPEED 28
//AT328 has 1KBytes EEPROM
#define VFO_A_MODE 256
#define VFO_B_MODE 257
#define CW_DELAY 258
#define CW_START 259
/**
* The uBITX is an upconnversion transceiver. The first IF is at 45 MHz.
* The first IF frequency is not exactly at 45 Mhz but about 5 khz lower,
@ -186,6 +192,20 @@ unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the cur
int cwSpeed = 100; //this is actuall the dot period in milliseconds
extern int32_t calibration;
//for store the mode in eeprom
byte vfoA_mode=0, vfoB_mode = 0; //0: default, 1:not use, 2:LSB, 3:USB, 4:CW, 5:AM, 6:FM
bool isSplitOn = false;
byte cwDelayTime = 60;
byte delayBeforeCWStartTime = 50;
//sideTonePitch + sideToneSub = sideTone
byte sideTonePitch=0;
byte sideToneSub = 0;
//DialLock
byte isDialLock = 0;
/**
* Raduino needs to keep track of current state of the transceiver. These are a few variables that do it
*/
@ -206,6 +226,24 @@ boolean modeCalibrate = false;//this mode of menus shows extended menus to calib
* you start hacking around
*/
/*
KD8CEC
When using the basic delay of the Arduino, the program freezes.
When the delay is used, the program will generate an error because it is not communicating,
so Create a new delay function that can do background processing.
*/
unsigned long delayBeforeTime = 0;
void delay_background(unsigned delayTime, byte fromType){
delayBeforeTime = millis();
while (millis() <= delayBeforeTime + delayTime) {
//Background Work
Check_Cat(fromType);
}
}
/**
* Select the properly tx harmonic filters
* The four harmonic filters use only three relays
@ -261,7 +299,10 @@ void setTXFilters(unsigned long freq){
void setFrequency(unsigned long f){
uint64_t osc_f;
//1 digits discarded
f = (f / 10) * 10;
setTXFilters(f);
if (isUSB){
@ -282,7 +323,7 @@ void setFrequency(unsigned long f){
* Note: In cw mode, doesnt key the radio, only puts it in tx mode
*/
void startTx(byte txMode){
void startTx(byte txMode, byte isDisplayUpdate){
unsigned long tx_freq = 0;
digitalWrite(TX_RX, 1);
inTx = 1;
@ -306,7 +347,10 @@ void startTx(byte txMode){
else
si5351bx_setfreq(2, frequency - sideTone);
}
updateDisplay();
//reduce latency time when begin of CW mode
if (isDisplayUpdate == 1)
updateDisplay();
}
void stopTx(){
@ -359,7 +403,7 @@ void checkPTT(){
return;
if (digitalRead(PTT) == 0 && inTx == 0){
startTx(TX_SSB);
startTx(TX_SSB, 1);
delay(50); //debounce the PTT
}
@ -378,9 +422,12 @@ void checkButton(){
return;
doMenu();
//wait for the button to go up again
while(btnDown())
while(btnDown()) {
delay(10);
Check_Cat(0);
}
delay(50);//debounce
}
@ -397,6 +444,9 @@ void doTuning(){
unsigned long prev_freq;
int incdecValue = 0;
if (isDialLock == 1)
return;
s = enc_read();
if (s){
prev_freq = frequency;
@ -474,17 +524,53 @@ void initSettings(){
EEPROM.get(VFO_B, vfoB);
EEPROM.get(CW_SIDETONE, sideTone);
EEPROM.get(CW_SPEED, cwSpeed);
//for Save VFO_A_MODE to eeprom
//0: default, 1:not use, 2:LSB, 3:USB, 4:CW, 5:AM, 6:FM
EEPROM.get(VFO_A_MODE, vfoA_mode);
EEPROM.get(VFO_B_MODE, vfoB_mode);
//CW DelayTime
EEPROM.get(CW_DELAY, cwDelayTime);
//CW interval between TX and CW Start
EEPROM.get(CW_START, delayBeforeCWStartTime);
if (cwDelayTime < 1 || cwDelayTime > 250)
cwDelayTime = 60;
if (vfoA_mode < 2)
vfoA_mode = 2;
if (vfoB_mode < 2)
vfoB_mode = 3;
if (usbCarrier > 12010000l || usbCarrier < 11990000l)
usbCarrier = 11997000l;
if (vfoA > 35000000l || 3500000l > vfoA)
if (vfoA > 35000000l || 3500000l > vfoA) {
vfoA = 7150000l;
if (vfoB > 35000000l || 3500000l > vfoB)
vfoA_mode = 2;
}
if (vfoB > 35000000l || 3500000l > vfoB) {
vfoB = 14150000l;
vfoB_mode = 3;
}
if (sideTone < 100 || 2000 < sideTone)
sideTone = 800;
if (cwSpeed < 10 || 1000 < cwSpeed)
cwSpeed = 100;
if (sideTone < 300 || sideTone > 1000) {
sideTonePitch = 0;
sideToneSub = 0;;
}
else{
sideTonePitch = (sideTone - 300) / 50;
sideToneSub = sideTone % 50;
}
}
void initPorts(){
@ -522,21 +608,29 @@ void initPorts(){
void setup()
{
Serial.begin(9600);
//Init EEProm for factory reset test
/*
for (int i = 0; i < 512; i++)
EEPROM.write(i, 0);
*/
//Serial.begin(9600);
lcd.begin(16, 2);
//we print this line so this shows up even if the raduino
//crashes later in the code
printLine2("CEC Ver 0.22");
printLine1("uBITX v0.20");
delay(500);
delay_background(500, 0);
printLine2("");
Init_Cat(38400, SERIAL_8N1);
initMeter(); //not used in this build
initSettings();
initPorts();
initOscillators();
frequency = vfoA;
byteToMode(vfoA_mode);
setFrequency(vfoA);
updateDisplay();
@ -548,7 +642,8 @@ void setup()
/**
* The loop checks for keydown, ptt, function button and tuning.
*/
//for debug
int dbgCnt = 0;
byte flasher = 0;
void loop(){
@ -566,5 +661,11 @@ void loop(){
}
//we check CAT after the encoder as it might put the radio into TX
checkCAT();
//checkCAT();
Check_Cat(inTx? 1 : 0);
/*
lcd.setCursor(0, 0); // place the cursor at the beginning of the selected line
lcd.print(dbgCnt++);
*/
}

View File

@ -148,9 +148,9 @@ void processCATCommand(byte* cmd) {
if (!inTx) {
response[0] = 0;
txCAT = true;
startTx(TX_SSB);
updateDisplay();
} else {
startTx(TX_SSB, 1);
}
else {
response[0] = 0xf0;
}
Serial.write(response,1);

View File

@ -23,7 +23,7 @@
// in milliseconds, this is the parameter that determines how long the tx will hold between cw key downs
#define CW_TIMEOUT (600l)
//#define CW_TIMEOUT (600l) //Change to CW Delaytime for value save to eeprom
#define PADDLE_DOT 1
#define PADDLE_DASH 2
#define PADDLE_BOTH 3
@ -61,7 +61,10 @@ void cwKeydown(){
keyDown = 1; //tracks the CW_KEY
tone(CW_TONE, (int)sideTone);
digitalWrite(CW_KEY, 1);
cwTimeout = millis() + CW_TIMEOUT;
//Modified by KD8CEC, for CW Delay Time save to eeprom
//cwTimeout = millis() + CW_TIMEOUT;
cwTimeout = millis() + cwDelayTime * 10;
}
/**
@ -72,7 +75,10 @@ void cwKeyUp(){
keyDown = 0; //tracks the CW_KEY
noTone(CW_TONE);
digitalWrite(CW_KEY, 0);
cwTimeout = millis() + CW_TIMEOUT;
//Modified by KD8CEC, for CW Delay Time save to eeprom
//cwTimeout = millis() + CW_TIMEOUT;
cwTimeout = millis() + cwDelayTime * 10;
}
/**
@ -103,48 +109,64 @@ void cwKeyer(){
//if a paddle was used (not a straight key) we should extend the space to be a full dash
//by adding two more dots long space (one has already been added at the end of the dot or dash)
/*
if (cwTimeout > 0 && lastPaddle != PADDLE_STRAIGHT)
delay(cwSpeed * 2);
delay_background(cwSpeed * 2, 3);
//delay(cwSpeed * 2);
// got back to the begining of the loop, if no further activity happens on the paddle or the straight key
// we will time out, and return out of this routine
delay(5);
*/
continue;
}
Serial.print("paddle:");Serial.println(paddle);
//Remoark Debug code / Serial Use by CAT Protocol
//Serial.print("paddle:");Serial.println(paddle);
// if we are here, it is only because the key or the paddle is pressed
if (!inTx){
keyDown = 0;
cwTimeout = millis() + CW_TIMEOUT;
startTx(TX_CW);
//Modified by KD8CEC, for CW Delay Time save to eeprom
//cwTimeout = millis() + CW_TIMEOUT;
cwTimeout = millis() + cwDelayTime * 10;
startTx(TX_CW, 0); //disable updateDisplay Command for reduce latency time
updateDisplay();
//DelayTime Option
delay_background(delayBeforeCWStartTime * 2, 2);
}
// star the transmission)
// we store the transmitted character in the lastPaddle
cwKeydown();
if (paddle == PADDLE_DOT){
delay(cwSpeed);
//delay(cwSpeed);
delay_background(cwSpeed, 3);
lastPaddle = PADDLE_DOT;
}
else if (paddle == PADDLE_DASH){
delay(cwSpeed * 3);
//delay(cwSpeed * 3);
delay_background(cwSpeed * 3, 3);
lastPaddle = PADDLE_DASH;
}
else if (paddle == PADDLE_BOTH){ //both paddles down
//depending upon what was sent last, send the other
if (lastPaddle == PADDLE_DOT) {
delay(cwSpeed * 3);
//delay(cwSpeed * 3);
delay_background(cwSpeed * 3, 3);
lastPaddle = PADDLE_DASH;
}else{
delay(cwSpeed);
//delay(cwSpeed);
delay_background(cwSpeed, 3);
lastPaddle = PADDLE_DOT;
}
}
else if (paddle == PADDLE_STRAIGHT){
while (getPaddle() == PADDLE_STRAIGHT)
while (getPaddle() == PADDLE_STRAIGHT) {
delay(1);
Check_Cat(2);
}
lastPaddle = PADDLE_STRAIGHT;
}
cwKeyUp();

View File

@ -28,8 +28,11 @@ int menuBand(int btn){
printLine2("Press to confirm");
//wait for the button menu select button to be lifted)
while (btnDown())
while (btnDown()) {
delay(50);
Check_Cat(0); //To prevent disconnections
}
delay(50);
ritDisable();
@ -58,10 +61,14 @@ int menuBand(int btn){
updateDisplay();
}
delay(20);
Check_Cat(0); //To prevent disconnections
}
while(btnDown())
while(btnDown()) {
delay(50);
Check_Cat(0); //To prevent disconnections
}
delay(50);
printLine2("");
@ -69,8 +76,23 @@ int menuBand(int btn){
menuOn = 0;
}
void menuVfoToggle(int btn){
//0: default, 1:not use, 2:LSB, 3:USB, 4:CW, 5:AM, 6:FM
byte modeToByte(){
if (isUSB)
return 3;
else
return 2;
}
void byteToMode(byte modeValue){
if (modeValue == 3)
isUSB = 1;
else
isUSB = 0;
}
void menuVfoToggle(int btn)
{
if (!btn){
if (vfoActive == VFO_A)
printLine2("Select VFO B? ");
@ -80,28 +102,36 @@ void menuVfoToggle(int btn){
else {
if (vfoActive == VFO_B){
vfoB = frequency;
EEPROM.put(VFO_B, frequency);
EEPROM.put(VFO_B, vfoB);
//For save MODE to eeprom
vfoB_mode = modeToByte();
EEPROM.put(VFO_B_MODE, vfoB_mode);
vfoActive = VFO_A;
printLine2("Selected VFO A ");
frequency = vfoA;
byteToMode(vfoA_mode);
}
else {
vfoA = frequency;
EEPROM.put(VFO_A, frequency);
//For save MODE to eeprom
vfoA_mode = modeToByte();
EEPROM.put(VFO_A_MODE, vfoA_mode);
vfoActive = VFO_B;
printLine2("Selected VFO B ");
frequency = vfoB;
byteToMode(vfoB_mode);
}
ritDisable();
setFrequency(frequency);
if (frequency >= 10000000l)
isUSB = true;
else
isUSB = false;
updateDisplay();
printLine2("");
delay(1000);
delay_background(500, 0);
//exit the menu
menuOn = 0;
}
@ -125,7 +155,7 @@ void menuRitToggle(int btn){
ritDisable();
}
menuOn = 0;
delay(500);
delay_background(500, 0);
printLine2("");
updateDisplay();
}
@ -142,15 +172,13 @@ void menuSidebandToggle(int btn){
if (isUSB == true){
isUSB = false;
printLine2("LSB Selected");
delay(500);
printLine2("");
}
else {
isUSB = true;
printLine2("USB Selected");
delay(500);
printLine2("");
}
delay_background(500, 0);
printLine2("");
updateDisplay();
menuOn = 0;
@ -176,7 +204,7 @@ void menuSetup(int btn){
modeCalibrate = false;
printLine2("Setup:Off ");
}
delay(2000);
delay_background(2000, 0);
printLine2("");
menuOn = 0;
}
@ -189,7 +217,7 @@ void menuExit(int btn){
}
else{
printLine2("Exiting menu");
delay(300);
delay_background(300, 0);
printLine2("");
updateDisplay();
menuOn = 0;
@ -216,7 +244,7 @@ int menuCWSpeed(int btn){
itoa(wpm,c, 10);
strcat(b, c);
printLine2(b);
delay(300);
delay_background(300, 0);
while(!btnDown() && digitalRead(PTT) == HIGH){
@ -236,6 +264,8 @@ int menuCWSpeed(int btn){
if (btnDown())
//re-enable the clock1 and clock 2
break;
Check_Cat(0); //To prevent disconnections
}
//save the setting
@ -243,13 +273,110 @@ int menuCWSpeed(int btn){
printLine2("CW Speed set!");
cwSpeed = 1200/wpm;
EEPROM.put(CW_SPEED, cwSpeed);
delay(2000);
delay_background(2000, 0);
}
printLine2("");
updateDisplay();
menuOn = 0;
}
int menuSetupCwDelay(int btn){
int knob = 0;
int tmpCWDelay = cwDelayTime * 10;
if (!btn){
strcpy(b, "CW TX->RX Delay");
printLine2(b);
return;
}
printLine1("Press PTT to set");
strcpy(b, "DELAY:");
itoa(tmpCWDelay,c, 10);
strcat(b, c);
printLine2(b);
delay_background(300, 0);
while(!btnDown() && digitalRead(PTT) == HIGH){
knob = enc_read();
if (knob != 0){
if (tmpCWDelay > 3 && knob < 0)
tmpCWDelay -= 10;
if (tmpCWDelay < 2500 && knob > 0)
tmpCWDelay += 10;
strcpy(b, "DELAY:");
itoa(tmpCWDelay,c, 10);
strcat(b, c);
printLine2(b);
}
//abort if this button is down
if (btnDown())
break;
Check_Cat(0); //To prevent disconnections
}
//save the setting
if (digitalRead(PTT) == LOW){
printLine2("CW Delay set!");
cwDelayTime = tmpCWDelay / 10;
EEPROM.put(CW_DELAY, cwDelayTime);
delay_background(2000, 0);
}
printLine2("");
updateDisplay();
menuOn = 0;
}
int menuSetupTXCWInterval(int btn){
int knob = 0;
int tmpTXCWInterval = delayBeforeCWStartTime * 2;
if (!btn){
strcpy(b, "CW Start Delay");
printLine2(b);
return;
}
printLine1("Press PTT to set");
strcpy(b, "Start Delay:");
itoa(tmpTXCWInterval,c, 10);
strcat(b, c);
printLine2(b);
delay_background(300, 0);
while(!btnDown() && digitalRead(PTT) == HIGH){
knob = enc_read();
if (knob != 0){
if (tmpTXCWInterval > 0 && knob < 0)
tmpTXCWInterval -= 2;
if (tmpTXCWInterval < 500 && knob > 0)
tmpTXCWInterval += 2;
strcpy(b, "Start Delay:");
itoa(tmpTXCWInterval,c, 10);
strcat(b, c);
printLine2(b);
}
//abort if this button is down
if (btnDown())
break;
Check_Cat(0); //To prevent disconnections
}
//save the setting
if (digitalRead(PTT) == LOW){
printLine2("CW Start set!");
delayBeforeCWStartTime = tmpTXCWInterval / 2;
EEPROM.put(CW_START, delayBeforeCWStartTime);
delay_background(2000, 0);
}
printLine2("");
updateDisplay();
menuOn = 0;
}
/**
@ -288,7 +415,7 @@ int factoryCalibration(int btn){
//turn off the second local oscillator and the bfo
si5351_set_calibration(calibration);
startTx(TX_CW);
startTx(TX_CW, 1);
si5351bx_setfreq(2, 10000000l);
strcpy(b, "#1 10 MHz cal:");
@ -347,7 +474,7 @@ int menuSetupCalibration(int btn){
printLine1("Set to Zero-beat,");
printLine2("press PTT to save");
delay(1000);
delay_background(1000, 0);
prev_calibration = calibration;
calibration = 0;
@ -389,7 +516,7 @@ int menuSetupCalibration(int btn){
printLine1("Calibration set!");
printLine2("Set Carrier now");
EEPROM.put(MASTER_CAL, calibration);
delay(2000);
delay_background(2000, 0);
}
else
calibration = prev_calibration;
@ -430,7 +557,7 @@ void menuSetupCarrier(int btn){
prevCarrier = usbCarrier;
printLine1("Tune to best Signal");
printLine2("PTT to confirm. ");
delay(1000);
delay_background(1000, 0);
usbCarrier = 11995000l;
si5351bx_setfreq(0, usbCarrier);
@ -450,7 +577,8 @@ void menuSetupCarrier(int btn){
si5351bx_setfreq(0, usbCarrier);
printCarrierFreq(usbCarrier);
Check_Cat(0); //To prevent disconnections
delay(100);
}
@ -458,7 +586,7 @@ void menuSetupCarrier(int btn){
if (digitalRead(PTT) == LOW){
printLine2("Carrier set! ");
EEPROM.put(USB_CAL, usbCarrier);
delay(1000);
delay_background(1000, 0);
}
else
usbCarrier = prevCarrier;
@ -475,18 +603,18 @@ void menuSetupCwTone(int btn){
int prev_sideTone;
if (!btn){
printLine2("Change CW Tone");
printLine2("Change CW Tone");
return;
}
prev_sideTone = sideTone;
printLine1("Tune CW tone");
printLine2("PTT to confirm. ");
delay(1000);
delay_background(1000, 0);
tone(CW_TONE, sideTone);
//disable all clock 1 and clock 2
while (digitalRead(PTT) == LOW || !btnDown())
while (digitalRead(PTT) == HIGH && !btnDown())
{
knob = enc_read();
@ -502,13 +630,14 @@ void menuSetupCwTone(int btn){
printLine2(b);
delay(100);
Check_Cat(0); //To prevent disconnections
}
noTone(CW_TONE);
//save the setting
if (digitalRead(PTT) == LOW){
printLine2("Sidetone set! ");
EEPROM.put(CW_SIDETONE, usbCarrier);
delay(2000);
delay_background(2000, 0);
}
else
sideTone = prev_sideTone;
@ -518,13 +647,57 @@ void menuSetupCwTone(int btn){
menuOn = 0;
}
void setDialLock(byte tmpLock, byte fromMode) {
isDialLock = tmpLock;
if (fromMode == 2 || fromMode == 3) return;
if (isDialLock == 1)
printLine2("Dial Lock ON");
else
printLine2("Dial Lock OFF");
updateDisplay();
delay_background(1000, 0);
printLine2("");
}
int btnDownTimeCount;
void doMenu(){
int select=0, i,btnState;
//for DialLock On/Off function
btnDownTimeCount = 0;
//wait for the button to be raised up
while(btnDown())
while(btnDown()){
delay(50);
Check_Cat(0); //To prevent disconnections
//btnDownTimeCount++;
//check long time Down Button -> 3 Second
if (btnDownTimeCount++ > (3000 / 50)) {
setDialLock(isDialLock == 1 ? 0 : 1, 0); //Reverse Dialo lock
return;
}
}
delay(50); //debounce
/*
//check long time Down Button -> 3 Second
if (btnDownTimeCount > (3000 / 50)) {
isDialLock = isDialLock == 1 ? 0 : 1; //Reverse Dialo lock
if (isDialLock == 1)
printLine2("Dial Lock ON");
else
printLine2("Dial Lock OFF");
delay_background(1000);
printLine2("");
return;
}
*/
menuOn = 2;
@ -533,7 +706,7 @@ void doMenu(){
btnState = btnDown();
if (i > 0){
if (modeCalibrate && select + i < 110)
if (modeCalibrate && select + i < 130)
select += i;
if (!modeCalibrate && select + i < 70)
select += i;
@ -562,12 +735,20 @@ void doMenu(){
else if (select < 100 && modeCalibrate)
menuSetupCwTone(btnState);
else if (select < 110 && modeCalibrate)
menuExit(btnState);
menuSetupCwDelay(btnState);
else if (select < 120 && modeCalibrate)
menuSetupTXCWInterval(btnState);
else if (select < 130 && modeCalibrate)
menuExit(btnState);
Check_Cat(0); //To prevent disconnections
}
//debounce the button
while(btnDown())
while(btnDown()){
delay(50);
Check_Cat(0); //To prevent disconnections
}
delay(50);
}

View File

@ -34,11 +34,22 @@ byte s_meter_bitmap[] = {
B00001,B00001,B00001,B00001,B00101,B00101,B00101,B11011
};
byte lock_bitmap[8] = {
0b01110,
0b10001,
0b10001,
0b11111,
0b11011,
0b11011,
0b11111,
0b00000};
// initializes the custom characters
// we start from char 1 as char 0 terminates the string!
void initMeter(){
lcd.createChar(0, lock_bitmap);
lcd.createChar(1, s_meter_bitmap);
lcd.createChar(2, s_meter_bitmap + 8);
lcd.createChar(3, s_meter_bitmap + 16);
@ -145,6 +156,12 @@ void updateDisplay() {
strcat(c, " TX");
printLine(1, c);
if (isDialLock == 1)
{
lcd.setCursor(3,1);
lcd.write((uint8_t)0);
}
/*
//now, the second line
memset(c, 0, sizeof(c));