//====================================================================== // iopcomm.cpp //====================================================================== #include #include "iopcomm.h" #if defined(TEENSYDUINO) // Compiling for the Teensy, so assuming this is IOP code. #define MYSERIAL Serial1 #else // Not compiling for the Teensy, so assuming this is Raduino code. #define MYSERIAL Serial #endif //====================================================================== void sendCATMessage(const uint8_t* buf) { MYSERIAL.write(prefixAndLengthToByte(CAT_PREFIX, 5)); for (int i = 0; i < 5; i++) { MYSERIAL.write(buf[i]); } } //====================================================================== void sendIOPMessage(IOPMessage const& msg) { MYSERIAL.write(prefixAndLengthToByte(IOP_PREFIX, msg.len + 1)); MYSERIAL.write(msg.id); for (int i = 0; i < msg.len; i++) { MYSERIAL.write(msg.data[i]); } } //====================================================================== void recvIOPMessage(IOPMessage& msg, const uint8_t* buf, int len) { msg.id = buf[0]; msg.len = len - 1; for (int i = 1; i < len; i++) { msg.data[i-1] = buf[i]; } } //====================================================================== void sendIOPModeCommand(rig_mode mode) { IOPMessage m; m.id = IOP_MODE_COMMAND; m.len = 1; m.data[0] = static_cast(mode); sendIOPMessage(m); } //====================================================================== void sendIOPStartTxCommand() { IOPMessage m; m.id = IOP_START_TX_COMMAND; m.len = 0; sendIOPMessage(m); } //====================================================================== void sendIOPStopTxCommand() { IOPMessage m; m.id = IOP_STOP_TX_COMMAND; m.len = 0; sendIOPMessage(m); } //====================================================================== void sendIOPModeRequest() { IOPMessage m; m.id = IOP_MODE_REQUEST; m.len = 4; // NOTE: LEN = 4 for padding only... temporary sendIOPMessage(m); } //====================================================================== void sendIOPDebugMessage(const char* text) { IOPMessage m; m.id = IOP_DEBUG_MSG; m.len = strlen(text); if (m.len > IOP_MESSAGE_MAX_LEN) { m.len = IOP_MESSAGE_MAX_LEN; } strncpy(m.data, text, m.len); sendIOPMessage(m); }; ////====================================================================== //// SSB STATUS MESSAGE ////====================================================================== //void sendIOPSSBStatus(SSBConfig const &c) //{ //IOPMessage m; //m.id = IOP_SSB_STATUS_MSG; //m.len = 4; //m.data[0] = 'S'; // current mode; redundant w/ Raduino mode, but maybe useful for debugging //m.data[1] = '-'; // placeholder for transmit filter/compressor //m.data[2] = RX_FILTER_LETTER[c.filter]; //m.data[3] = '\0'; //sendIOPMessage(m); //} ////====================================================================== //// DGT STATUS MESSAGE ////====================================================================== //void sendIOPDGTStatus(DGTConfig const &c) //{ //IOPMessage m; //m.id = IOP_DGT_STATUS_MSG; //m.len = 4; //m.data[0] = 'D'; // current mode; redundant w/ Raduino mode, but maybe useful for debugging //m.data[1] = '-'; // placeholder for future digital submodes? //m.data[2] = RX_FILTER_LETTER[c.filter]; //m.data[3] = '\0'; //sendIOPMessage(m); //} ////====================================================================== //// CW STATUS MESSAGE ////====================================================================== //void sendIOPCWStatus(CWConfig const &c) //{ //IOPMessage m; //m.id = IOP_CW_STATUS_MSG; //m.len = 4; //m.data[0] = 'C'; // current mode; redundant w/ Raduino mode, but maybe useful for debugging //m.data[1] = KEYER_MODE_LETTER[c.mode]; //m.data[2] = RX_FILTER_LETTER[c.filter]; //m.data[3] = '\0'; //sendIOPMessage(m); //} ////====================================================================== //// TEST STATUS MESSAGE ////====================================================================== //void sendIOPTestStatus() //{ //IOPMessage m; //m.id = IOP_TEST_STATUS_MSG; //m.len = 4; //m.data[0] = ' '; //m.data[1] = 'T'; //m.data[2] = 'T'; //m.data[3] = '\0'; //sendIOPMessage(m); //} //====================================================================== // MENU DISPLAY MESSAGE //====================================================================== void sendIOPMenuDisplay(const char* text) { IOPMessage m; int l = strlen(text); m.id = IOP_MENU_DISPLAY_MSG; m.len = 16; for (int i = 0; i < 16; i++) { if (i < l) { m.data[i] = text[i]; } else { m.data[i] = ' '; } } m.data[16] = '\0'; sendIOPMessage(m); } //====================================================================== // MENU INACTIVE MESSAGE //====================================================================== void sendIOPMenuInactive() { IOPMessage m; m.id = IOP_MENU_INACTIVE_MSG; m.len = 4; // NOTE: LEN = 4 for padding only... temporary sendIOPMessage(m); } //====================================================================== /* enum SerialState { NORMAL = 0, CAT_MODE, IOP_MODE, EEPROM_READ, EEPROM_WRITE, }; Translator::Translator(RigMode& m, CWConfig& c, Stream& s = SERIAL): mode(m), cwConfig(c), serial(s) { for (int i = 0; i < NUM_PREFIX_IDS; i++) { prefixCb[i] = NULL; } for (int i = 0; i < NUM_MESSAGE_IDS; i++) { messageCb[i] = NULL; } } void Translator::sendACK() { serial.write(prefixAndLengthToByte(ACK, 0)); } void Translator::sendCATMessage(byte b, bool continued=false) { if (!continued) { // we're starting a CAT transmission sequence } else { // we're continuing a CAT transmission sequence } } void Translator::sendIOPMessage(IOPMessage const& m) { serial.write(prefixAndLengthToByte(IOP_PREFIX, m.len+1)); serial.write(m.id); for (int i = 0; i < m.len; i++) { serial.write(m.data[i]); } } static void Translator::receive() { static SerialState state; static PrefixID readPrefix = 0; static uint8_t readLength = 0; static IOPMessage iopMsg; static uint8_t cmdLength = 0; static byte cmdBuffer[16]; static char cmdString[17]; // added a char for null termination when required static uint16_t eepromStartIndex; static uint16_t eepromReadLength; static int eepromMagicFlag = 0; int incomingByte; for (int i = 0; i < serial.available(); i++) { incomingByte = serial.read(); switch(state) { case NORMAL: if (incomingByte == ACK) { prefixCb[ACK](NULL); } else { readPrefix = byteToPrefix(incomingbyte); readLength = byteToLength(incomingbyte); if (readLength > 0) { switch(readPrefix) { case CAT_PREFIX: case RAD_EEPROM_WRITE_PREFIX: state = CAT_MODE; break; case IOP_PREFIX: state = IOP_MODE; iopMsg.len = readLength - 1; cmdLength = 0; break; case RAD_EEPROM_READ_PREFIX: state = EEPROM_READ; readLength = 5; eepromMagicFlag = 0; break; default: // should never happen break; } } } break; case CAT_MODE: // In CAT mode, we just pass thru the remaining bytes to the PC. if USBSERIAL.write(incomingByte); readLength--; if (readLength == 0) { state = NORMAL; } break; case IOP_MODE: cmdBuffer[cmdLength] = incomingByte; cmdLength++; readLength--; if (readLength == 0) { processIOPCommand(cmdBuffer, cmdLength); state = 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; } state = CAT_MODE; break; default: // should never happen break; } break; case EEPROM_WRITE: // TODO break; default: // should never happen... break; } } } void Translator::registerPrefixCb(PrefixID id, void (*func)(void*)) { if (id >= 0 && id < NUM_PREFIX_IDS) { prefixCb[id] = func; } void Translator::registerMessageCb(MessageID id, void (*func)(void*)) { if (id >= 0 && id < NUM_MESSAGE_IDS) { messageCb[id] = func; } } void Translator::pack_ModeCommand(IOPMessage& m, RigMode r) { m.id = IOP_MODE_COMMAND; m.len = 1; m.data[0] = r; } void Translator::unpack_ModeCommand(IOPMessage const& m) { *mode = RigMode(m.data[0]); } void Translator::pack_CWConfig(IOPMessage &m, CWConfig const& c) { m.id = IOP_CW_CONFIG_MSG; m.len = 6; // mode m.data[0] = byte(c.mode); // flags m.data[1] = NO_FLAGS; m.data[1] |= (c.reversed ? REVERSED : 0); // parameters m.data[2] = byte(c.wpm); m.data[3] = byte(c.weight * 10.0); m.data[4] = byte(c.sidetone >> 8); m.data[5] = byte(c.sidetone | 0x0F); } void Translator::unpack_CWConfig(IOPMessage const &m) { //if (m.id != IOP_CW_CONFIG_MSG || m.len != 6) { // // do some error thing... //} //mode cwConfig->mode = KeyMode(m.data[0]); // flags cwConfig->reversed = bool(m.data[1] & REVERSED); // parameters cwConfig->wpm = uint8_t(m.data[2]); cwConfig->weight = float(m.data[3]) / 10.0; cwConfig->sidetone = (m.data[4] << 8) | m.data[5]; } void Translator::pack_ModeRequest(IOPMessage& m) { m.id = IOP_MODE_REQUEST; m.len = 0; } void Translator::unpack_ModeRequest(IOPMessage const& m) { } void Translator::unpack(IOPMessage const& m) { switch (m.id) { case IOP_MODE_COMMAND: unpack_ModeCommand(m); messageCb[m.id](mode); break; case IOP_START_TX_COMMAND: break; case IOP_STOP_TX_COMMAND: break; case IOP_CW_CONFIG_MSG: unpack_CWConfig(m); messageCb[m.id](cwConfig); break; case IOP_MODE_REQUEST: unpack_ModeRequest(m); messageCb[m.id](NULL); break; case IOP_CW_STATUS_MSG: break; } } */ //====================================================================== // EOF //======================================================================