Initial CAT Code. The radio emulates a Kenwood TS-480. (https://www.kenwood.com/i/products/info/amateur/ts_480/pdf/ts_480_pc.pdf)
Refer to the YouTube video for an explanation.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
int debug = 0;
const int numChars = 14;
volatile long freq = 0;
boolean newCATcmd = false;
char CATcmd[numChars] = {'0'}; // an array to store the received CAT data
int freq10GHz = 0;
int freq1GHz = 0;
int freq100MHz = 0;
int freq10MHz = 1;
int freq1MHz = 4;
int freq100kHz = 1;
int freq10kHz = 2;
int freq1kHz = 3;
int freq100Hz = 4;
int freq10Hz = 5;
int freq1Hz = 6;
int RIT, XIT, MEM1, MEM2, RX, TX, VFO, SCAN, SIMPLEX, CTCSS, TONE1, TONE2 = 0;
int MODE = 2;
SoftwareSerial mySerial(31, 32); // RX, TX
LiquidCrystal_I2C lcd(0x3F, 16, 2);
void setup()
{
lcd.begin();
lcd.backlight();
CalcFreq();
Serial.begin(9600);
// Debug serial port
mySerial.begin(9600);
}
void loop()
{
rxCATcmd();
analyseCATcmd();
}
void rxCATcmd()
{
int index = 0;
char endMarker = ';';
char data; // CAT commands are ASCII characters
while ((Serial.available() > 0) && (newCATcmd == false))
{
data = Serial.read();
if (data != endMarker)
{
CATcmd[index] = data;
index++;
if (index >= numChars)
index = numChars - 1; // leave space for the \0 array termination
}
else
{
CATcmd[index] = ';'; // Indicate end of command
debug = index; // Needed later to print out the command
CATcmd[index + 1] = '\0'; // terminate the array
index = 0; // reset for next CAT command
newCATcmd = true;
}
}
}
void analyseCATcmd()
{
if (newCATcmd == true)
{
newCATcmd = false; // reset for next CAT time
// Debug printing
mySerial.println();
for (int x = 0; x <= debug; x++)
mySerial.print(CATcmd[x]);
mySerial.print("\t");
if ((CATcmd[0] == 'F') && (CATcmd[1] == 'A') && (CATcmd[2] == ';')) // must be freq get command
Command_GETFreqA();
else if ((CATcmd[0] == 'F') && (CATcmd[1] == 'A') && (CATcmd[13] == ';')) // must be freq set command
Command_SETFreqA();
else if ((CATcmd[0] == 'I') && (CATcmd[1] == 'F') && (CATcmd[2] == ';'))
Command_IF();
else if ((CATcmd[0] == 'I') && (CATcmd[1] == 'D') && (CATcmd[2] == ';'))
Command_ID();
else if ((CATcmd[0] == 'P') && (CATcmd[1] == 'S') && (CATcmd[2] == ';'))
Command_PS();
else if ((CATcmd[0] == 'P') && (CATcmd[1] == 'S') && (CATcmd[2] == '1'))
Command_PS1();
else if ((CATcmd[0] == 'A') && (CATcmd[1] == 'I') && (CATcmd[2] == ';'))
Command_AI();
else if ((CATcmd[0] == 'A') && (CATcmd[1] == 'I') && (CATcmd[2] == '0'))
Command_AI0();
else if ((CATcmd[0] == 'M') && (CATcmd[1] == 'D') && (CATcmd[2] == ';'))
Command_MD();
else if ((CATcmd[0] == 'R') && (CATcmd[1] == 'X') && (CATcmd[2] == ';'))
Command_RX();
else if ((CATcmd[0] == 'T') && (CATcmd[1] == 'X') && (CATcmd[2] == ';'))
Command_TX();
else if ((CATcmd[0] == 'T') && (CATcmd[1] == 'X') && (CATcmd[2] == '1'))
Command_TX1();
else if ((CATcmd[0] == 'R') && (CATcmd[1] == 'S') && (CATcmd[2] == ';'))
Command_RS();
Serial.flush(); // Get ready for next command
//delay(50); // Needed to eliminate WSJT-X connection errors
}
}
void Command_ID()
{
Serial.print("ID020;");
mySerial.print("ID020;");
}
void Command_PS()
{
Serial.print("PS1;");
mySerial.print("PS1;");
}
void Command_PS1()
{
Serial.print("PS1;");
mySerial.print("PS1;");
}
void Command_GETFreqA()
{
Serial.print("FA");
Serial.print(freq10GHz);
Serial.print(freq1GHz);
Serial.print(freq100MHz);
Serial.print(freq10MHz);
Serial.print(freq1MHz);
Serial.print(freq100kHz);
Serial.print(freq10kHz);
Serial.print(freq1kHz);
Serial.print(freq100Hz);
Serial.print(freq10Hz);
Serial.print(freq1Hz);
Serial.print(";");
mySerial.print("FA");
mySerial.print(freq10GHz);
mySerial.print(freq1GHz);
mySerial.print(freq100MHz);
mySerial.print(freq10MHz);
mySerial.print(freq1MHz);
mySerial.print(freq100kHz);
mySerial.print(freq10kHz);
mySerial.print(freq1kHz);
mySerial.print(freq100Hz);
mySerial.print(freq10Hz);
mySerial.print(freq1Hz);
mySerial.print(";");
}
void Command_SETFreqA()
{
freq10GHz = CATcmd[2] - 48; // convert ASCII char to int equivalent. int 0 = ASCII 48;
freq1GHz = CATcmd[3] - 48;
freq100MHz = CATcmd[4] - 48;
freq10MHz = CATcmd[5] - 48;
freq1MHz = CATcmd[6] - 48;
freq100kHz = CATcmd[7] - 48;
freq10kHz = CATcmd[8] - 48;
freq1kHz = CATcmd[9] - 48;
freq100Hz = CATcmd[10] - 48;
freq10Hz = CATcmd[11] - 48;
freq1Hz = CATcmd[12] - 48;
//Command_GETFreqA(); // now RSP with FA
Serial.print("FA");
Serial.print(freq10GHz);
Serial.print(freq1GHz);
Serial.print(freq100MHz);
Serial.print(freq10MHz);
Serial.print(freq1MHz);
Serial.print(freq100kHz);
Serial.print(freq10kHz);
Serial.print(freq1kHz);
Serial.print(freq100Hz);
Serial.print(freq10Hz);
Serial.print(freq1Hz);
Serial.print(";");
mySerial.print("FA");
mySerial.print(freq10GHz);
mySerial.print(freq1GHz);
mySerial.print(freq100MHz);
mySerial.print(freq10MHz);
mySerial.print(freq1MHz);
mySerial.print(freq100kHz);
mySerial.print(freq10kHz);
mySerial.print(freq1kHz);
mySerial.print(freq100Hz);
mySerial.print(freq10Hz);
mySerial.print(freq1Hz);
mySerial.print(";");
CalcFreq();
}
void CalcFreq()
{
freq = (
(10000000000L * freq10GHz) +
(1000000000L * freq1GHz) +
(100000000L * freq100MHz) +
(10000000L * freq10MHz) +
(1000000L * freq1MHz) +
(100000L * freq100kHz) +
(10000L * freq10kHz) +
(1000L * freq1kHz) +
(100L * freq100Hz) +
(10L * freq10Hz) +
freq1Hz);
// Debug print
lcd.setCursor(0, 1);
lcd.print(freq10GHz);
lcd.print(freq1GHz);
lcd.print(freq100MHz);
lcd.print(freq10MHz);
lcd.print(freq1MHz);
lcd.print(freq100kHz);
lcd.print(freq10kHz);
lcd.print(freq1kHz);
lcd.print(freq100Hz);
lcd.print(freq10Hz);
lcd.print(freq1Hz);
lcd.setCursor(0, 0); // Col, Row
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(freq);
}
void Command_IF()
{
Serial.print("IF");
Serial.print(freq10GHz); // P1
Serial.print(freq1GHz);
Serial.print(freq100MHz);
Serial.print(freq10MHz);
Serial.print(freq1MHz);
Serial.print(freq100kHz);
Serial.print(freq10kHz);
Serial.print(freq1kHz);
Serial.print(freq100Hz);
Serial.print(freq10Hz);
Serial.print(freq1Hz);
Serial.print("00000"); // P2 Always five 0s
Serial.print("+0000"); // P3 RIT/XIT freq +/-9990
Serial.print(RIT); // P4
Serial.print(XIT); // P5
Serial.print("0"); // P6 Always 0
Serial.print(MEM1); // P7
Serial.print(MEM2);
Serial.print(RX); // P8
Serial.print(MODE); // P9
Serial.print(VFO); // P10 FR/FT 0=VFO
Serial.print(SCAN); // P11
Serial.print(SIMPLEX); // P12
Serial.print(CTCSS); // P13
Serial.print(TONE1); // P14
Serial.print(TONE2);
Serial.print("0"); // P15 Always 0
Serial.print(";");
mySerial.print("IF");
mySerial.print(freq10GHz); // P1
mySerial.print(freq1GHz);
mySerial.print(freq100MHz);
mySerial.print(freq10MHz);
mySerial.print(freq1MHz);
mySerial.print(freq100kHz);
mySerial.print(freq10kHz);
mySerial.print(freq1kHz);
mySerial.print(freq100Hz);
mySerial.print(freq10Hz);
mySerial.print(freq1Hz);
mySerial.print("00000"); // P2 Always five 0s
mySerial.print("+0000"); // P3 RIT/XIT freq +/-9990
mySerial.print(RIT); // P4
mySerial.print(XIT); // P5
mySerial.print("0"); // P6 Always 0
mySerial.print(MEM1); // P7
mySerial.print(MEM2);
mySerial.print(RX); // P8
mySerial.print(MODE); // P9
mySerial.print(VFO); // P10 FR/FT 0=VFO
mySerial.print(SCAN); // P11
mySerial.print(SIMPLEX); // P12
mySerial.print(CTCSS); // P13
mySerial.print(TONE1); // P14
mySerial.print(TONE2);
mySerial.print("0"); // P15 Always 0
mySerial.print(";");
}
void Command_AI()
{
Serial.print("AI0;");
mySerial.print("AI0;");
}
void Command_MD()
{
Serial.print("MD2;");
mySerial.print("MD2;");
}
void Command_AI0()
{
Serial.print("AI0;");
mySerial.print("AI0;");
}
void Command_RX()
{
RX = 0;
TX = 0;
Serial.print("RX0;");
mySerial.print("RX0;");
}
void Command_TX()
{
RX = 1;
TX = 1;
Serial.print("TX0;");
mySerial.print("TX0;");
}
void Command_TX1()
{
RX = 1;
TX = 1;
Serial.print("TX2;");
mySerial.print("TX2;");
}
void Command_RS()
{
Serial.print("RS0;");
mySerial.print("RS0;");
}
***********************************************************
Additional code to enable audio and serial data across the single USB connection. This is test code only at this stage.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <Audio.h> // Teensy audio library
int debug = 0;
const int numChars = 14;
volatile long freq = 0;
boolean newCATcmd = false;
char CATcmd[numChars] = {'0'}; // an array to store the received CAT data
int freq10GHz = 0;
int freq1GHz = 0;
int freq100MHz = 0;
int freq10MHz = 1;
int freq1MHz = 4;
int freq100kHz = 1;
int freq10kHz = 2;
int freq1kHz = 3;
int freq100Hz = 4;
int freq10Hz = 5;
int freq1Hz = 6;
int RIT, XIT, MEM1, MEM2, RX, TX, VFO, SCAN, SIMPLEX, CTCSS, TONE1, TONE2 = 0;
int MODE = 2;
SoftwareSerial mySerial(31, 32); // RX, TX
AudioControlSGTL5000 audioShield;
// Audio objects
AudioInputUSB audioInputUSB;
AudioSynthWaveformSine TestOsc;
AudioOutputUSB audioOutputUSB;
AudioOutputI2S audioOutputHeadphones;
// Audio connections
AudioConnection patchCord5(TestOsc, 0, audioOutputUSB, 0);
AudioConnection patchCord10(TestOsc, 0, audioOutputUSB, 1);
AudioConnection patchCord15(audioInputUSB, 0, audioOutputHeadphones, 0);
AudioConnection patchCord20(audioInputUSB, 1, audioOutputHeadphones, 1);
void setup()
{
CalcFreq();
Serial.begin(9600);
mySerial.begin(9600);
// Setup the audio shield
AudioNoInterrupts();
AudioMemory(12);
audioShield.enable();
TestOsc.amplitude(0.1);
TestOsc.frequency(700);
audioShield.unmuteHeadphone(); // Output to the audio amplifier
audioShield.volume(0.8);
AudioInterrupts();
}
void loop()
{
rxCATcmd();
analyseCATcmd();
}
void rxCATcmd()
{
int index = 0;
char endMarker = ';';
char data; // CAT commands are ASCII characters
while ((Serial.available() > 0) && (newCATcmd == false))
{
data = Serial.read();
if (data != endMarker)
{
CATcmd[index] = data;
index++;
if (index >= numChars)
index = numChars - 1; // leave space for the \0 array termination
}
else
{
CATcmd[index] = ';'; // Indicate end of command
debug = index; // Needed later to print out the command
CATcmd[index + 1] = '\0'; // terminate the array
index = 0; // reset for next CAT command
newCATcmd = true;
}
}
}
void analyseCATcmd()
{
if (newCATcmd == true)
{
newCATcmd = false; // reset for next CAT time
// Debug printing
mySerial.println();
for (int x = 0; x <= debug; x++)
mySerial.print(CATcmd[x]);
mySerial.print("\t");
if ((CATcmd[0] == 'F') && (CATcmd[1] == 'A') && (CATcmd[2] == ';')) // must be freq get command
Command_GETFreqA();
else if ((CATcmd[0] == 'F') && (CATcmd[1] == 'A') && (CATcmd[13] == ';')) // must be freq set command
Command_SETFreqA();
else if ((CATcmd[0] == 'I') && (CATcmd[1] == 'F') && (CATcmd[2] == ';'))
Command_IF();
else if ((CATcmd[0] == 'I') && (CATcmd[1] == 'D') && (CATcmd[2] == ';'))
Command_ID();
else if ((CATcmd[0] == 'P') && (CATcmd[1] == 'S') && (CATcmd[2] == ';'))
Command_PS();
else if ((CATcmd[0] == 'P') && (CATcmd[1] == 'S') && (CATcmd[2] == '1'))
Command_PS1();
else if ((CATcmd[0] == 'A') && (CATcmd[1] == 'I') && (CATcmd[2] == ';'))
Command_AI();
else if ((CATcmd[0] == 'A') && (CATcmd[1] == 'I') && (CATcmd[2] == '0'))
Command_AI0();
else if ((CATcmd[0] == 'M') && (CATcmd[1] == 'D') && (CATcmd[2] == ';'))
Command_MD();
else if ((CATcmd[0] == 'R') && (CATcmd[1] == 'X') && (CATcmd[2] == ';'))
Command_RX();
else if ((CATcmd[0] == 'T') && (CATcmd[1] == 'X') && (CATcmd[2] == ';'))
Command_TX();
else if ((CATcmd[0] == 'T') && (CATcmd[1] == 'X') && (CATcmd[2] == '1'))
Command_TX1();
else if ((CATcmd[0] == 'R') && (CATcmd[1] == 'S') && (CATcmd[2] == ';'))
Command_RS();
Serial.flush(); // Get ready for next command
//delay(50); // Needed to eliminate WSJT-X connection errors
}
}
void Command_ID()
{
Serial.print("ID020;");
mySerial.print("ID020;");
}
void Command_PS()
{
Serial.print("PS1;");
mySerial.print("PS1;");
}
void Command_PS1()
{
Serial.print("PS1;");
mySerial.print("PS1;");
}
void Command_GETFreqA()
{
Serial.print("FA");
Serial.print(freq10GHz);
Serial.print(freq1GHz);
Serial.print(freq100MHz);
Serial.print(freq10MHz);
Serial.print(freq1MHz);
Serial.print(freq100kHz);
Serial.print(freq10kHz);
Serial.print(freq1kHz);
Serial.print(freq100Hz);
Serial.print(freq10Hz);
Serial.print(freq1Hz);
Serial.print(";");
mySerial.print("FA");
mySerial.print(freq10GHz);
mySerial.print(freq1GHz);
mySerial.print(freq100MHz);
mySerial.print(freq10MHz);
mySerial.print(freq1MHz);
mySerial.print(freq100kHz);
mySerial.print(freq10kHz);
mySerial.print(freq1kHz);
mySerial.print(freq100Hz);
mySerial.print(freq10Hz);
mySerial.print(freq1Hz);
mySerial.print(";");
}
void Command_SETFreqA()
{
freq10GHz = CATcmd[2] - 48; // convert ASCII char to int equivalent. int 0 = ASCII 48;
freq1GHz = CATcmd[3] - 48;
freq100MHz = CATcmd[4] - 48;
freq10MHz = CATcmd[5] - 48;
freq1MHz = CATcmd[6] - 48;
freq100kHz = CATcmd[7] - 48;
freq10kHz = CATcmd[8] - 48;
freq1kHz = CATcmd[9] - 48;
freq100Hz = CATcmd[10] - 48;
freq10Hz = CATcmd[11] - 48;
freq1Hz = CATcmd[12] - 48;
//Command_GETFreqA(); // now RSP with FA
Serial.print("FA");
Serial.print(freq10GHz);
Serial.print(freq1GHz);
Serial.print(freq100MHz);
Serial.print(freq10MHz);
Serial.print(freq1MHz);
Serial.print(freq100kHz);
Serial.print(freq10kHz);
Serial.print(freq1kHz);
Serial.print(freq100Hz);
Serial.print(freq10Hz);
Serial.print(freq1Hz);
Serial.print(";");
mySerial.print("FA");
mySerial.print(freq10GHz);
mySerial.print(freq1GHz);
mySerial.print(freq100MHz);
mySerial.print(freq10MHz);
mySerial.print(freq1MHz);
mySerial.print(freq100kHz);
mySerial.print(freq10kHz);
mySerial.print(freq1kHz);
mySerial.print(freq100Hz);
mySerial.print(freq10Hz);
mySerial.print(freq1Hz);
mySerial.print(";");
CalcFreq();
}
void CalcFreq()
{
freq = (
(10000000000L * freq10GHz) +
(1000000000L * freq1GHz) +
(100000000L * freq100MHz) +
(10000000L * freq10MHz) +
(1000000L * freq1MHz) +
(100000L * freq100kHz) +
(10000L * freq10kHz) +
(1000L * freq1kHz) +
(100L * freq100Hz) +
(10L * freq10Hz) +
freq1Hz);
}
void Command_IF()
{
Serial.print("IF");
Serial.print(freq10GHz); // P1
Serial.print(freq1GHz);
Serial.print(freq100MHz);
Serial.print(freq10MHz);
Serial.print(freq1MHz);
Serial.print(freq100kHz);
Serial.print(freq10kHz);
Serial.print(freq1kHz);
Serial.print(freq100Hz);
Serial.print(freq10Hz);
Serial.print(freq1Hz);
Serial.print("00000"); // P2 Always five 0s
Serial.print("+0000"); // P3 RIT/XIT freq +/-9990
Serial.print(RIT); // P4
Serial.print(XIT); // P5
Serial.print("0"); // P6 Always 0
Serial.print(MEM1); // P7
Serial.print(MEM2);
Serial.print(RX); // P8
Serial.print(MODE); // P9
Serial.print(VFO); // P10 FR/FT 0=VFO
Serial.print(SCAN); // P11
Serial.print(SIMPLEX); // P12
Serial.print(CTCSS); // P13
Serial.print(TONE1); // P14
Serial.print(TONE2);
Serial.print("0"); // P15 Always 0
Serial.print(";");
mySerial.print("IF");
mySerial.print(freq10GHz); // P1
mySerial.print(freq1GHz);
mySerial.print(freq100MHz);
mySerial.print(freq10MHz);
mySerial.print(freq1MHz);
mySerial.print(freq100kHz);
mySerial.print(freq10kHz);
mySerial.print(freq1kHz);
mySerial.print(freq100Hz);
mySerial.print(freq10Hz);
mySerial.print(freq1Hz);
mySerial.print("00000"); // P2 Always five 0s
mySerial.print("+0000"); // P3 RIT/XIT freq +/-9990
mySerial.print(RIT); // P4
mySerial.print(XIT); // P5
mySerial.print("0"); // P6 Always 0
mySerial.print(MEM1); // P7
mySerial.print(MEM2);
mySerial.print(RX); // P8
mySerial.print(MODE); // P9
mySerial.print(VFO); // P10 FR/FT 0=VFO
mySerial.print(SCAN); // P11
mySerial.print(SIMPLEX); // P12
mySerial.print(CTCSS); // P13
mySerial.print(TONE1); // P14
mySerial.print(TONE2);
mySerial.print("0"); // P15 Always 0
mySerial.print(";");
}
void Command_AI()
{
Serial.print("AI0;");
mySerial.print("AI0;");
}
void Command_MD()
{
Serial.print("MD2;");
mySerial.print("MD2;");
}
void Command_AI0()
{
Serial.print("AI0;");
mySerial.print("AI0;");
}
void Command_RX()
{
RX = 0;
TX = 0;
Serial.print("RX0;");
mySerial.print("RX0;");
}
void Command_TX()
{
RX = 1;
TX = 1;
Serial.print("TX0;");
mySerial.print("TX0;");
}
void Command_TX1()
{
RX = 1;
TX = 1;
Serial.print("TX2;");
mySerial.print("TX2;");
}
void Command_RS()
{
Serial.print("RS0;");
mySerial.print("RS0;");
}
*************************************************************************
RF Splitter/Combiner
Hi Charlie,
ReplyDeletelooking at your code and i have just a couple of comments ...
1. Why are you using a software serial port on pins 31 & 32, These two pins are actually for a hardware serial port on the teensy.
2.if you change all your code to read serial4 and NOT myserial the code will still work and run faster as its using a hardware UART.
3. why do you think you need a delay in the code to sort out possible errors
best regards
Simon M6FJW
Hi Simon. Thanks for that. I think that was an error, so I'll revisit that once the receiver hardware is complete. As for the delay, that's currently commented out. I did find at higher baud rates that WSJT-X they errors. I know the Teensy was sending the correct indo. It's currently working fine at 9600. Strange.
Delete73
Charlie ZL2CTM
Hi Charlie,
DeleteFrom what you describe it could be a simple timing issue due to the large number of serial print statements that only send a single character. The faster the baud rate the less time you have to process and send data.
serial print strings rather than singular characters, It's more efficient.
The serial printing process goes similar to this ...
1.initialize the stream ready to send to the serial port.
2. send a stream of data (in your case a single letter).
3. close the stream.
Sending a string is more efficient as it sends a stream of data and spends a lot less time initializing and more time on sending actual data.
best regards
Simon M6FJW
Thanks Simon. I will look into that. I guess there will be some more effort (code) to build the char string, but probably worth it. Thanks again.
DeleteCharlie
Hi Charlie,
DeleteYou might think it's a lot more work, but it's actually less work. There are commands available that do most of the work that you need. I have some example code if you wish to see it let me know.
The code I have only uses 6 or 7 lines and deals with getting the command, data and semi colon out the serial buffer in to the strings.
The thing to remember is that CAT control just sends strings back and forth, It's the individual systems that convert to integers, Boolean values or characters for that system ( no need to think what number base, or bit depth the number system uses).
research the Serial commands all aspects of it are useful. There are commands that will fetch multiple bytes from the serial buffer in to a string or char array. These simplify the code. Add in the string commands that are available and you can quickly build a response to send in a single serial print line.
I hope this helps.
Best regards
Simon M6FJW
I will take a look at this Simon. I thought I was loading the received command into a char array. If i could, i will take a quick look at what you did and I'll go dform there. My address is my call at gmail. Thanks again for the steer. Charlie
DeleteHi Charlie,
Deletei have sent you an email with the sample code. yes you did use a character array, but you only used it a single character at a time in your serial print commands which could lead to serial timing issues.
best regards
Simon M6FJW
Hi charlie...can you tell how to get file teensy.SSD1306.h...or can you share the file...thanks
ReplyDeleteOnce you add in Arduino support for the teensy you should have it. If I recall, it comes up under Teensy within the Arduino IDE.
ReplyDeleteCharlie