232 lines
5.5 KiB
Arduino
232 lines
5.5 KiB
Arduino
|
/**
|
||
|
* The CAT protocol is used by many radios to provide remote control to comptuers through
|
||
|
* the serial port.
|
||
|
*
|
||
|
* This is very much a work in progress. Parts of this code have been liberally
|
||
|
* borrowed from other GPLicensed works like hamlib.
|
||
|
*
|
||
|
* WARNING : This is an unstable version and it has worked with fldigi,
|
||
|
* it gives time out error with WSJTX 1.8.0
|
||
|
*/
|
||
|
|
||
|
// The next 4 functions are needed to implement the CAT protocol, which
|
||
|
// uses 4-bit BCD formatting.
|
||
|
//
|
||
|
byte setHighNibble(byte b,byte v) {
|
||
|
// Clear the high nibble
|
||
|
b &= 0x0f;
|
||
|
// Set the high nibble
|
||
|
return b | ((v & 0x0f) << 4);
|
||
|
}
|
||
|
|
||
|
byte setLowNibble(byte b,byte v) {
|
||
|
// Clear the low nibble
|
||
|
b &= 0xf0;
|
||
|
// Set the low nibble
|
||
|
return b | (v & 0x0f);
|
||
|
}
|
||
|
|
||
|
byte getHighNibble(byte b) {
|
||
|
return (b >> 4) & 0x0f;
|
||
|
}
|
||
|
|
||
|
byte getLowNibble(byte b) {
|
||
|
return b & 0x0f;
|
||
|
}
|
||
|
|
||
|
// Takes a number and produces the requested number of decimal digits, staring
|
||
|
// from the least significant digit.
|
||
|
//
|
||
|
void getDecimalDigits(unsigned long number,byte* result,int digits) {
|
||
|
for (int i = 0; i < digits; i++) {
|
||
|
// "Mask off" (in a decimal sense) the LSD and return it
|
||
|
result[i] = number % 10;
|
||
|
// "Shift right" (in a decimal sense)
|
||
|
number /= 10;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Takes a frequency and writes it into the CAT command buffer in BCD form.
|
||
|
//
|
||
|
void writeFreq(unsigned long freq,byte* cmd) {
|
||
|
// Convert the frequency to a set of decimal digits. We are taking 9 digits
|
||
|
// so that we can get up to 999 MHz. But the protocol doesn't care about the
|
||
|
// LSD (1's place), so we ignore that digit.
|
||
|
byte digits[9];
|
||
|
getDecimalDigits(freq,digits,9);
|
||
|
// Start from the LSB and get each nibble
|
||
|
cmd[3] = setLowNibble(cmd[3],digits[1]);
|
||
|
cmd[3] = setHighNibble(cmd[3],digits[2]);
|
||
|
cmd[2] = setLowNibble(cmd[2],digits[3]);
|
||
|
cmd[2] = setHighNibble(cmd[2],digits[4]);
|
||
|
cmd[1] = setLowNibble(cmd[1],digits[5]);
|
||
|
cmd[1] = setHighNibble(cmd[1],digits[6]);
|
||
|
cmd[0] = setLowNibble(cmd[0],digits[7]);
|
||
|
cmd[0] = setHighNibble(cmd[0],digits[8]);
|
||
|
}
|
||
|
|
||
|
// This function takes a frquency that is encoded using 4 bytes of BCD
|
||
|
// representation and turns it into an long measured in Hz.
|
||
|
//
|
||
|
// [12][34][56][78] = 123.45678? Mhz
|
||
|
//
|
||
|
unsigned long readFreq(byte* cmd) {
|
||
|
// Pull off each of the digits
|
||
|
byte d7 = getHighNibble(cmd[0]);
|
||
|
byte d6 = getLowNibble(cmd[0]);
|
||
|
byte d5 = getHighNibble(cmd[1]);
|
||
|
byte d4 = getLowNibble(cmd[1]);
|
||
|
byte d3 = getHighNibble(cmd[2]);
|
||
|
byte d2 = getLowNibble(cmd[2]);
|
||
|
byte d1 = getHighNibble(cmd[3]);
|
||
|
byte d0 = getLowNibble(cmd[3]);
|
||
|
return
|
||
|
(unsigned long)d7 * 100000000L +
|
||
|
(unsigned long)d6 * 10000000L +
|
||
|
(unsigned long)d5 * 1000000L +
|
||
|
(unsigned long)d4 * 100000L +
|
||
|
(unsigned long)d3 * 10000L +
|
||
|
(unsigned long)d2 * 1000L +
|
||
|
(unsigned long)d1 * 100L +
|
||
|
(unsigned long)d0 * 10L;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Responds to all the cat commands, emulates FT-817
|
||
|
*/
|
||
|
|
||
|
void processCATCommand(byte* cmd) {
|
||
|
byte response[5];
|
||
|
|
||
|
// Debugging code, enable it to fix the cat implementation
|
||
|
|
||
|
count++;
|
||
|
if (cmd[4] == 0x00){
|
||
|
response[0]=0;
|
||
|
Serial.write(response, 1);
|
||
|
}
|
||
|
else if (cmd[4] == 0x01) {
|
||
|
unsigned long f = readFreq(cmd);
|
||
|
setFrequency(f);
|
||
|
updateDisplay();
|
||
|
//sprintf(b, "set:%ld", f);
|
||
|
//printLine2(b);
|
||
|
|
||
|
}
|
||
|
// Get frequency
|
||
|
else if (cmd[4] == 0x03){
|
||
|
writeFreq(frequency,response); // Put the frequency into the buffer
|
||
|
if (isUSB)
|
||
|
response[4] = 0x01; //USB
|
||
|
else
|
||
|
response[4] = 0x00; //LSB
|
||
|
Serial.write(response,5);
|
||
|
printLine2("cat:getfreq");
|
||
|
}
|
||
|
else if (cmd[4] == 0x07){ // set mode
|
||
|
if (cmd[0] == 0x00 || cmd[0] == 0x03)
|
||
|
isUSB = 0;
|
||
|
else
|
||
|
isUSB = 1;
|
||
|
response[0] = 0x00;
|
||
|
Serial.write(response, 1);
|
||
|
setFrequency(frequency);
|
||
|
//printLine2("cat: mode changed");
|
||
|
//updateDisplay();
|
||
|
}
|
||
|
else if (cmd[4] == 0x88){
|
||
|
if (inTx){
|
||
|
stopTx();
|
||
|
txCAT = false;
|
||
|
}
|
||
|
else
|
||
|
response[0] = 0xf0;
|
||
|
printLine2("tx > rx");
|
||
|
Serial.write(response,1);
|
||
|
}
|
||
|
else if (cmd[4] == 0x08) { // PTT On
|
||
|
if (!inTx) {
|
||
|
response[0] = 0;
|
||
|
txCAT = true;
|
||
|
startTx(TX_SSB);
|
||
|
updateDisplay();
|
||
|
} else {
|
||
|
response[0] = 0xf0;
|
||
|
}
|
||
|
Serial.write(response,1);
|
||
|
printLine2("rx > tx");
|
||
|
}
|
||
|
// Read TX keyed state
|
||
|
else if (cmd[4] == 0x10) {
|
||
|
if (!inTx) {
|
||
|
response[0] = 0;
|
||
|
} else {
|
||
|
response[0] = 0xf0;
|
||
|
}
|
||
|
Serial.write(response,1);
|
||
|
printLine2("cat;0x10");
|
||
|
}
|
||
|
// PTT Off
|
||
|
else if (cmd[4] == 0x88) {
|
||
|
byte resBuf[0];
|
||
|
if (inTx) {
|
||
|
response[0] = 0;
|
||
|
} else {
|
||
|
response[0] = 0xf0;
|
||
|
}
|
||
|
Serial.write(response,1);
|
||
|
printLine2("cat;0x88");
|
||
|
//keyed = false;
|
||
|
//digitalWrite(13,LOW);
|
||
|
}
|
||
|
// Read receiver status
|
||
|
else if (cmd[4] == 0xe7) {
|
||
|
response[0] = 0x09;
|
||
|
Serial.write(response,1);
|
||
|
printLine2("cat;0xe7");
|
||
|
}
|
||
|
else if (cmd[4] == 0xf5){
|
||
|
|
||
|
}
|
||
|
// Read receiver status
|
||
|
else if (cmd[4] == 0xf7) {
|
||
|
response[0] = 0x00;
|
||
|
if (inTx) {
|
||
|
response[0] = response[0] | 0xf0;
|
||
|
}
|
||
|
Serial.write(response,1);
|
||
|
printLine2("cat;0xf7");
|
||
|
}
|
||
|
else {
|
||
|
//somehow, get this to print the four bytes
|
||
|
ultoa(*((unsigned long *)cmd), c, 16);
|
||
|
itoa(cmd[4], b, 16);
|
||
|
strcat(b, ":");
|
||
|
strcat(b, c);
|
||
|
printLine2(b);
|
||
|
response[0] = 0x00;
|
||
|
Serial.write(response[0]);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void checkCAT(){
|
||
|
static byte cat[5];
|
||
|
byte i;
|
||
|
|
||
|
if (Serial.available() < 5)
|
||
|
return;
|
||
|
|
||
|
cat[4] = cat[3];
|
||
|
cat[3] = cat[2];
|
||
|
cat[2] = cat[0];
|
||
|
for (i = 0; i < 5; i++)
|
||
|
cat[i] = Serial.read();
|
||
|
|
||
|
processCATCommand(cat);
|
||
|
}
|
||
|
|
||
|
|