//====================================================================== // cat.ino //====================================================================== #include "cat.h" // make these messages static inside a function IOPMessage inBuf; // input message buffer IOPMessage outBuf; // output message buffer //====================================================================== // 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: USBDEBUG("IOP_MODE_COMMAND received (from Raduino)"); if (m.len < 1) { return; } else { setRigMode(RigMode(m.data[0])); #if defined(DEBUG) switch(rigMode) { 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 - DIGI"); break; case RIG_MODE_TEST: USBDEBUG("new mode - TEST"); break; } #endif } break; case IOP_START_TX_COMMAND: catPTTOn(); break; case IOP_STOP_TX_COMMAND: catPTTOff(); break; case IOP_CW_CONFIG_MSG: 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(&iopConfig, 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; 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 //======================================================================