ubitx-v5d-xcvr/ubitx_iop/cat.ino

355 lines
8.7 KiB
C++

//======================================================================
// cat.ino
//======================================================================
#include "cat.h"
#include "TxSwitch.h"
// make these messages static inside a function
IOPMessage inBuf; // input message buffer
IOPMessage outBuf; // output message buffer
extern CATSwitch catPTT;
extern basic_rig rig;
int received_mode = 0;
//======================================================================
// 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();
USBDEBUG("opened USB serial port (to PC)");
// Comm (including CAT passthru) with Raduino via UART
HWSERIAL.begin(baud, portConfig);
HWSERIAL.flush();
USBDEBUG("opened H/W serial port (to Raduino)");
//sendIOPModeRequest(); // Raduino doesn't support this yet
}
//======================================================================
void processIOPCommand(IOPMessage const& m)
{
switch(inBuf.id) {
case IOP_MODE_COMMAND:
received_mode = 2;
USBDEBUG("IOP_MODE_COMMAND received (from Raduino)");
if (m.len < 1) {
return;
} else {
rig.set_rig_mode(static_cast<rig_mode>(m.data[0]));
#if defined(DEBUG)
switch(rig.get_rig_mode()) {
case rig_mode::cw:
USBDEBUG("new mode - CW");
break;
case rig_mode::ssb:
USBDEBUG("new mode - SSB");
break;
case rig_mode::digi:
USBDEBUG("new mode - DIG");
break;
default:
char errormessage[32];
sprintf(errormessage, "unknown mode command - %3d", rig.get_rig_mode());
USBDEBUG("mode command not recognized");
}
#endif
}
break;
case IOP_START_TX_COMMAND:
catPTT.press(rig.mode());
break;
case IOP_STOP_TX_COMMAND:
catPTT.release(rig.mode());
break;
case IOP_CW_CONFIG_MSG:
break;
case IOP_DEBUG_MSG:
USBDEBUG("IOP_DEBUG_MSG");
USBDEBUG((const char*)m.data);
break;
}
}
//======================================================================
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':
//audioCalibrate(&rigConfig.audio, cmd, subcmd, parm, value, (count == 4));
break;
default:
USBSERIAL.println("Calibration: invalid command");
}
}
}
//======================================================================
enum SerialState {
NORMAL = 0,
CAT_MODE,
IOP_MODE,
EEPROM_READ,
EEPROM_WRITE,
} serialState = NORMAL;
PrefixID readPrefix;
uint8_t readLength;
int cmdLength = 0;
byte cmdBuffer[16];
char cmdString[17]; // added a char for null termination when required
uint16_t eepromStartIndex;
uint16_t eepromReadLength;
int magicFlag = 0;
//----------------------------------------------------------------------
uint8_t usbCatLength = 0;
byte usbCatBuffer[5];
elapsedMillis usbCatTimer;
#define CAT_RECEIVE_TIMEOUT 500
void serviceCAT()
{
uint8_t incomingByte;
// 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;
}
if ((usbCatLength > 0) && (usbCatTimer > CAT_RECEIVE_TIMEOUT)) {
// timeout... clear the buffer and start over
usbCatLength = 0;
usbCatTimer = 0;
}
// read from the USB serial, pass through to UART serial
for (int i = 0; i < USBSERIAL.available(); i++) {
incomingByte = USBSERIAL.read();
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
#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
// Don't pass CAT commands through if in DEBUG mode.
#if not defined(DEBUG)
//HWSERIAL.write(incomingByte);
#endif
}
// read from the UART serial, see what we need to do with it
for (int i = 0; i < HWSERIAL.available(); i++) {
incomingByte = HWSERIAL.read();
#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
switch(serialState) {
case NORMAL:
if (incomingByte == ACK) {
USBSERIAL.write(incomingByte);
} 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
if (readLength > 0) {
USBDEBUG("readLength > 0");
switch(readPrefix) {
case CAT_PREFIX:
case RAD_EEPROM_WRITE_PREFIX:
serialState = CAT_MODE;
break;
case IOP_PREFIX:
USBDEBUG("entering IOP_MODE");
serialState = IOP_MODE;
cmdLength = 0;
break;
case RAD_EEPROM_READ_PREFIX:
serialState = EEPROM_READ;
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) {
serialState = NORMAL;
}
break;
case IOP_MODE:
cmdBuffer[cmdLength] = incomingByte;
cmdLength++;
readLength--;
if (readLength == 0) {
recvIOPMessage(inBuf, cmdBuffer, cmdLength);
processIOPCommand(inBuf);
serialState = NORMAL;
}
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;
}
serialState = CAT_MODE;
break;
default:
// should never happen
break;
}
break;
case EEPROM_WRITE:
// TODO
break;
default:
// should never happen...
break;
}
#endif
}
}
//======================================================================
// EOF
//======================================================================