2020-05-02 01:54:58 -04:00
|
|
|
//======================================================================
|
|
|
|
// cat.ino
|
|
|
|
//======================================================================
|
|
|
|
|
|
|
|
#include "cat.h"
|
2020-05-26 00:08:55 -04:00
|
|
|
#include "TxSwitch.h"
|
2020-05-01 12:04:26 -04:00
|
|
|
|
2020-05-17 00:48:39 -04:00
|
|
|
// make these messages static inside a function
|
|
|
|
IOPMessage inBuf; // input message buffer
|
|
|
|
IOPMessage outBuf; // output message buffer
|
2020-05-04 00:29:31 -04:00
|
|
|
|
2020-05-26 00:08:55 -04:00
|
|
|
extern CATSwitch catPTT;
|
2020-06-14 01:11:18 -04:00
|
|
|
extern basic_rig rig;
|
2020-05-26 00:08:55 -04:00
|
|
|
|
2020-05-26 11:49:15 -04:00
|
|
|
int received_mode = 0;
|
|
|
|
|
2020-05-01 12:04:26 -04:00
|
|
|
//======================================================================
|
|
|
|
// CAT from PC-to-IOP
|
|
|
|
//
|
|
|
|
// The general concept for IOP use of CAT is for the IOP to pass thru
|
|
|
|
// all incoming CAT data (from the PC) to the Raduino.
|
|
|
|
//
|
|
|
|
// This might change in the future, if we want to grab CAT data straight
|
|
|
|
// from the PC. That might apply to things like specific audio filter
|
|
|
|
// settings or something, but since the Raduino modes are an important
|
|
|
|
// part of the mix, I think the commands really need to come from the
|
|
|
|
// Raduino... and besides, what if a PC is not connected?
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// For data coming from the Raduino, the IOP does have to do a minimal
|
|
|
|
// processing to extra any Raduino-to-IOP commands.
|
|
|
|
//======================================================================
|
|
|
|
|
|
|
|
void initCAT(long baud, int portConfig)
|
|
|
|
{
|
|
|
|
// CAT with PC via USB
|
|
|
|
USBSERIAL.begin(baud);
|
|
|
|
USBSERIAL.flush();
|
2020-05-18 09:16:54 -04:00
|
|
|
USBDEBUG("opened USB serial port (to PC)");
|
2020-05-01 12:04:26 -04:00
|
|
|
|
2020-05-17 00:48:39 -04:00
|
|
|
// Comm (including CAT passthru) with Raduino via UART
|
2020-05-01 12:04:26 -04:00
|
|
|
HWSERIAL.begin(baud, portConfig);
|
2020-05-17 00:48:39 -04:00
|
|
|
HWSERIAL.flush();
|
2020-05-18 09:16:54 -04:00
|
|
|
USBDEBUG("opened H/W serial port (to Raduino)");
|
2020-05-17 00:48:39 -04:00
|
|
|
|
|
|
|
//sendIOPModeRequest(); // Raduino doesn't support this yet
|
2020-05-01 12:04:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
//======================================================================
|
|
|
|
|
2020-05-17 00:48:39 -04:00
|
|
|
void processIOPCommand(IOPMessage const& m)
|
2020-05-01 12:04:26 -04:00
|
|
|
{
|
2020-05-17 00:48:39 -04:00
|
|
|
switch(inBuf.id) {
|
|
|
|
case IOP_MODE_COMMAND:
|
2020-05-26 11:49:15 -04:00
|
|
|
received_mode = 2;
|
2020-05-17 00:48:39 -04:00
|
|
|
USBDEBUG("IOP_MODE_COMMAND received (from Raduino)");
|
|
|
|
if (m.len < 1) {
|
|
|
|
return;
|
|
|
|
} else {
|
2020-06-14 01:11:18 -04:00
|
|
|
rig.set_rig_mode(static_cast<rig_mode>(m.data[0]));
|
2020-05-17 00:48:39 -04:00
|
|
|
#if defined(DEBUG)
|
2020-06-14 01:11:18 -04:00
|
|
|
switch(rig.get_rig_mode()) {
|
|
|
|
case rig_mode::cw:
|
2020-06-13 10:59:11 -04:00
|
|
|
USBDEBUG("new mode - CW");
|
2020-05-26 00:08:55 -04:00
|
|
|
break;
|
2020-06-14 01:11:18 -04:00
|
|
|
case rig_mode::ssb:
|
|
|
|
USBDEBUG("new mode - SSB");
|
2020-05-26 00:08:55 -04:00
|
|
|
break;
|
2020-06-14 01:11:18 -04:00
|
|
|
case rig_mode::digi:
|
2020-06-13 10:59:11 -04:00
|
|
|
USBDEBUG("new mode - DIG");
|
2020-05-17 00:48:39 -04:00
|
|
|
break;
|
2020-06-07 16:27:27 -04:00
|
|
|
default:
|
|
|
|
char errormessage[32];
|
2020-06-14 01:11:18 -04:00
|
|
|
sprintf(errormessage, "unknown mode command - %3d", rig.get_rig_mode());
|
2020-06-07 16:27:27 -04:00
|
|
|
USBDEBUG("mode command not recognized");
|
2020-05-17 00:48:39 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
2020-05-08 01:19:07 -04:00
|
|
|
|
2020-05-17 00:48:39 -04:00
|
|
|
case IOP_START_TX_COMMAND:
|
2020-05-26 00:08:55 -04:00
|
|
|
catPTT.press(rig.mode());
|
2020-05-17 00:48:39 -04:00
|
|
|
break;
|
2020-05-08 01:19:07 -04:00
|
|
|
|
2020-05-17 00:48:39 -04:00
|
|
|
case IOP_STOP_TX_COMMAND:
|
2020-05-26 00:08:55 -04:00
|
|
|
catPTT.release(rig.mode());
|
2020-05-17 00:48:39 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IOP_CW_CONFIG_MSG:
|
|
|
|
break;
|
2020-06-07 16:27:27 -04:00
|
|
|
|
|
|
|
case IOP_DEBUG_MSG:
|
|
|
|
USBDEBUG("IOP_DEBUG_MSG");
|
|
|
|
USBDEBUG((const char*)m.data);
|
|
|
|
break;
|
2020-05-04 00:29:31 -04:00
|
|
|
}
|
2020-05-01 12:04:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
//======================================================================
|
|
|
|
|
2020-05-03 01:37:21 -04:00
|
|
|
void processCalCommand(const char* buf)
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
char cmd;
|
|
|
|
char subcmd;
|
|
|
|
char parm;
|
|
|
|
float value;
|
|
|
|
|
|
|
|
count = sscanf(buf, "%1c %1c %1c %f", &cmd, &subcmd, &parm, &value);
|
|
|
|
|
|
|
|
if (count < 3) {
|
|
|
|
USBSERIAL.println("Calibration: invalid command");
|
|
|
|
} else {
|
|
|
|
switch(cmd) {
|
|
|
|
case 'r':
|
|
|
|
case 'R':
|
|
|
|
case 't':
|
|
|
|
case 'T':
|
2020-05-26 00:08:55 -04:00
|
|
|
//audioCalibrate(&rigConfig.audio, cmd, subcmd, parm, value, (count == 4));
|
2020-05-03 01:37:21 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
USBSERIAL.println("Calibration: invalid command");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//======================================================================
|
|
|
|
|
2020-05-17 00:48:39 -04:00
|
|
|
enum SerialState {
|
2020-05-01 12:04:26 -04:00
|
|
|
NORMAL = 0,
|
|
|
|
CAT_MODE,
|
|
|
|
IOP_MODE,
|
|
|
|
EEPROM_READ,
|
|
|
|
EEPROM_WRITE,
|
2020-05-17 00:48:39 -04:00
|
|
|
} serialState = NORMAL;
|
2020-05-01 12:04:26 -04:00
|
|
|
|
2020-05-18 09:16:54 -04:00
|
|
|
PrefixID readPrefix;
|
|
|
|
uint8_t readLength;
|
2020-05-01 12:04:26 -04:00
|
|
|
|
|
|
|
int cmdLength = 0;
|
2020-05-03 01:37:21 -04:00
|
|
|
byte cmdBuffer[16];
|
|
|
|
char cmdString[17]; // added a char for null termination when required
|
2020-05-01 12:04:26 -04:00
|
|
|
|
|
|
|
uint16_t eepromStartIndex;
|
|
|
|
uint16_t eepromReadLength;
|
|
|
|
int magicFlag = 0;
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2020-05-18 09:16:54 -04:00
|
|
|
uint8_t usbCatLength = 0;
|
|
|
|
byte usbCatBuffer[5];
|
|
|
|
elapsedMillis usbCatTimer;
|
|
|
|
|
|
|
|
#define CAT_RECEIVE_TIMEOUT 500
|
|
|
|
|
2020-05-01 12:04:26 -04:00
|
|
|
void serviceCAT()
|
|
|
|
{
|
2020-05-17 00:48:39 -04:00
|
|
|
uint8_t incomingByte;
|
2020-05-01 12:04:26 -04:00
|
|
|
|
2020-05-26 11:49:15 -04:00
|
|
|
// First, if we've never received or requested a mode command from the Raduino, send a request.
|
|
|
|
if (received_mode == 0) {
|
|
|
|
USBDEBUG("requesting mode");
|
|
|
|
sendIOPModeRequest();
|
|
|
|
received_mode = 1;
|
|
|
|
}
|
|
|
|
|
2020-05-18 09:16:54 -04:00
|
|
|
if ((usbCatLength > 0) && (usbCatTimer > CAT_RECEIVE_TIMEOUT)) {
|
|
|
|
// timeout... clear the buffer and start over
|
|
|
|
usbCatLength = 0;
|
|
|
|
usbCatTimer = 0;
|
|
|
|
}
|
|
|
|
|
2020-05-01 12:04:26 -04:00
|
|
|
// read from the USB serial, pass through to UART serial
|
2020-05-18 09:16:54 -04:00
|
|
|
for (int i = 0; i < USBSERIAL.available(); i++) {
|
2020-05-01 12:04:26 -04:00
|
|
|
incomingByte = USBSERIAL.read();
|
2020-05-18 09:16:54 -04:00
|
|
|
usbCatTimer = 0;
|
|
|
|
|
|
|
|
#if not defined(FACTORY_CALIBRATION)
|
|
|
|
usbCatBuffer[usbCatLength++] = incomingByte;
|
|
|
|
if (usbCatLength == 5) {
|
|
|
|
sendCATMessage(usbCatBuffer);
|
|
|
|
usbCatLength = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: This code does NOT handle any interrupts in COMMS from the PC...
|
|
|
|
|
|
|
|
#endif
|
2020-05-03 01:37:21 -04:00
|
|
|
|
|
|
|
#if defined(FACTORY_CALIBRATION)
|
|
|
|
// unless we're in factory calibration mode, in which case we're going
|
|
|
|
// to process calibration commands...
|
|
|
|
switch(incomingByte) {
|
|
|
|
case ';':
|
|
|
|
cmdString[cmdLength] = '\0';
|
|
|
|
if (cmdLength > 0) {
|
|
|
|
processCalCommand(cmdString);
|
|
|
|
cmdLength = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '\n':
|
|
|
|
case '\r':
|
|
|
|
cmdString[0] = '\0';
|
|
|
|
cmdLength = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
cmdString[cmdLength++] = char(incomingByte);
|
|
|
|
if (cmdLength == 16) {
|
|
|
|
cmdString[cmdLength] = '\0';
|
|
|
|
processCalCommand(cmdString);
|
|
|
|
cmdLength = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2020-05-17 00:48:39 -04:00
|
|
|
// Don't pass CAT commands through if in DEBUG mode.
|
|
|
|
#if not defined(DEBUG)
|
2020-05-18 09:16:54 -04:00
|
|
|
//HWSERIAL.write(incomingByte);
|
2020-05-17 00:48:39 -04:00
|
|
|
#endif
|
2020-05-01 12:04:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// read from the UART serial, see what we need to do with it
|
|
|
|
for (int i = 0; i < HWSERIAL.available(); i++) {
|
|
|
|
incomingByte = HWSERIAL.read();
|
2020-05-17 00:48:39 -04:00
|
|
|
#if defined(DEBUG)
|
|
|
|
char ibBuff[20];
|
|
|
|
itoa(serialState, ibBuff, 10);
|
|
|
|
USBSERIAL.print("IOP: serialState = ");
|
|
|
|
USBSERIAL.print(ibBuff);
|
|
|
|
itoa(incomingByte, ibBuff, 10);
|
|
|
|
USBSERIAL.print("; incomingByte = ");
|
|
|
|
USBSERIAL.println(ibBuff);
|
|
|
|
#endif
|
2020-05-01 12:04:26 -04:00
|
|
|
|
2020-05-17 00:48:39 -04:00
|
|
|
switch(serialState) {
|
2020-05-01 12:04:26 -04:00
|
|
|
case NORMAL:
|
|
|
|
if (incomingByte == ACK) {
|
|
|
|
USBSERIAL.write(incomingByte);
|
2020-05-17 00:48:39 -04:00
|
|
|
} else {
|
|
|
|
readPrefix = byteToPrefix(incomingByte);
|
|
|
|
readLength = byteToLength(incomingByte);
|
|
|
|
#if defined(DEBUG)
|
|
|
|
itoa(readPrefix, ibBuff, 10);
|
|
|
|
USBSERIAL.print("IOP: readPrefix = ");
|
|
|
|
USBSERIAL.print(ibBuff);
|
|
|
|
itoa(readLength, ibBuff, 10);
|
|
|
|
USBSERIAL.print("; readLength = ");
|
|
|
|
USBSERIAL.println(ibBuff);
|
|
|
|
#endif
|
2020-05-01 12:04:26 -04:00
|
|
|
if (readLength > 0) {
|
2020-05-17 00:48:39 -04:00
|
|
|
USBDEBUG("readLength > 0");
|
|
|
|
switch(readPrefix) {
|
2020-05-01 12:04:26 -04:00
|
|
|
case CAT_PREFIX:
|
2020-05-17 00:48:39 -04:00
|
|
|
case RAD_EEPROM_WRITE_PREFIX:
|
|
|
|
serialState = CAT_MODE;
|
2020-05-01 12:04:26 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IOP_PREFIX:
|
2020-05-17 00:48:39 -04:00
|
|
|
USBDEBUG("entering IOP_MODE");
|
|
|
|
serialState = IOP_MODE;
|
|
|
|
cmdLength = 0;
|
2020-05-01 12:04:26 -04:00
|
|
|
break;
|
|
|
|
|
2020-05-17 00:48:39 -04:00
|
|
|
case RAD_EEPROM_READ_PREFIX:
|
|
|
|
serialState = EEPROM_READ;
|
2020-05-01 12:04:26 -04:00
|
|
|
readLength = 5;
|
|
|
|
magicFlag = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// should never happen
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CAT_MODE:
|
|
|
|
// In CAT mode, we just pass thru the remaining bytes to the PC.
|
|
|
|
USBSERIAL.write(incomingByte);
|
|
|
|
readLength--;
|
|
|
|
if (readLength == 0) {
|
2020-05-17 00:48:39 -04:00
|
|
|
serialState = NORMAL;
|
2020-05-01 12:04:26 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IOP_MODE:
|
|
|
|
cmdBuffer[cmdLength] = incomingByte;
|
|
|
|
cmdLength++;
|
|
|
|
readLength--;
|
|
|
|
if (readLength == 0) {
|
2020-05-17 00:48:39 -04:00
|
|
|
recvIOPMessage(inBuf, cmdBuffer, cmdLength);
|
|
|
|
processIOPCommand(inBuf);
|
|
|
|
serialState = NORMAL;
|
2020-05-01 12:04:26 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EEPROM_READ:
|
|
|
|
readLength--;
|
|
|
|
switch(readLength) {
|
|
|
|
case 4:
|
|
|
|
eepromStartIndex = incomingByte;
|
|
|
|
if (incomingByte == 0x16) {
|
|
|
|
magicFlag++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
eepromStartIndex += (256 * incomingByte);
|
|
|
|
if (incomingByte == 0xe8) {
|
|
|
|
magicFlag++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
eepromReadLength = incomingByte;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
eepromReadLength += (256 * incomingByte);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
USBSERIAL.write(incomingByte);
|
|
|
|
if (magicFlag == 2) {
|
|
|
|
readLength = 126 + 2;
|
|
|
|
} else {
|
|
|
|
readLength = eepromReadLength + 2;
|
|
|
|
}
|
2020-05-17 00:48:39 -04:00
|
|
|
serialState = CAT_MODE;
|
2020-05-01 12:04:26 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// should never happen
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EEPROM_WRITE:
|
|
|
|
// TODO
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// should never happen...
|
|
|
|
break;
|
|
|
|
}
|
2020-05-03 01:37:21 -04:00
|
|
|
#endif
|
2020-05-01 12:04:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//======================================================================
|
|
|
|
// EOF
|
|
|
|
//======================================================================
|