//====================================================================== // 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(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 //======================================================================