diff --git a/iopcomm/iopcomm.cpp b/iopcomm/iopcomm.cpp index df528a0..6931a95 100644 --- a/iopcomm/iopcomm.cpp +++ b/iopcomm/iopcomm.cpp @@ -16,6 +16,16 @@ //====================================================================== +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)); @@ -77,6 +87,70 @@ void sendIOPModeRequest() 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); +} + +//====================================================================== +// DIGI STATUS MESSAGE +//====================================================================== + +void sendIOPDigiStatus(DigiConfig const &c) +{ + IOPMessage m; + m.id = IOP_DIGI_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); +} + //====================================================================== /* diff --git a/iopcomm/iopcomm.h b/iopcomm/iopcomm.h index 9922320..b40dd52 100644 --- a/iopcomm/iopcomm.h +++ b/iopcomm/iopcomm.h @@ -70,7 +70,10 @@ enum MessageID { // Requests IOP_MODE_REQUEST, + IOP_SSB_STATUS_MSG, + IOP_DIGI_STATUS_MSG, IOP_CW_STATUS_MSG, + IOP_TEST_STATUS_MSG, // add any new elements here NUM_MESSAGE_IDS @@ -92,10 +95,10 @@ enum MessageID { */ enum RigMode { - MODE_SSB = 0, - MODE_DIGI, - MODE_CW, - MODE_TEST, + RIG_MODE_SSB = 0, + RIG_MODE_DIGI, + RIG_MODE_CW, + RIG_MODE_TEST, // add any new elements here NUM_RIG_MODES }; @@ -103,17 +106,26 @@ enum RigMode { /* Keyer modes. */ -enum KeyMode { - STRAIGHT = 0, - IAMBIC_A, - IAMBIC_B, - //ULTIMATIC, - //BUG, +enum KeyerMode { + KEYER_MODE_STRAIGHT = 0, + KEYER_MODE_IAMBIC_A, + KEYER_MODE_IAMBIC_B, + //KEYER_ULTIMATIC, + //KEYER_BUG, // add any new elements here - NUM_KEY_MODES + NUM_KEYER_MODES }; -const unsigned char MODE_LETTER[3] = {'S', 'A', 'B'}; +enum RxFilter { + RX_FILTER_NORMAL = 0, + RX_FILTER_NARROW, + RX_FILTER_WIDE, + NUM_RX_FILTERS +}; + +const unsigned char RIG_MODE_LETTER[NUM_RIG_MODES] = {'S', 'D', 'C', 'T'}; +const unsigned char KEYER_MODE_LETTER[NUM_KEYER_MODES] = {'S', 'A', 'B'}; +const unsigned char RX_FILTER_LETTER[NUM_RX_FILTERS] = {'-', 'N', 'W'}; const uint8_t NO_FLAGS = 0; const uint8_t REVERSED = 1; @@ -124,30 +136,58 @@ struct IOPMessage { uint8_t data[IOP_MESSAGE_MAX_LEN]; }; +//====================================================================== +// SSB CONFIGURATION +//====================================================================== -void sendIOPMessage(IOPMessage const&); -void recvIOPMessage(IOPMessage&, const uint8_t*, int); +struct SSBConfig { + // parameters + RxFilter filter = RX_FILTER_NORMAL; +}; -void sendIOPModeCommand(RigMode); -void sendIOPStartTxCommand(); -void sendIOPStopTxCommand(); -void sendIOPModeRequest(); +//====================================================================== +// DIGI CONFIGURATION +//====================================================================== + +struct DigiConfig { + // parameters + RxFilter filter = RX_FILTER_NORMAL; +}; //====================================================================== // CW CONFIGURATION //====================================================================== struct CWConfig { - // mode - KeyMode mode = IAMBIC_A; - // flags - bool reversed = false; - // parameters - uint8_t wpm = 15; - float weight = 3.0; - uint16_t sidetone = 700; + // mode + KeyerMode mode = KEYER_MODE_IAMBIC_A; + // flags + bool reversed = false; + // parameters + uint8_t wpm = 15; + float weight = 3.0; + uint16_t sidetone = 700; + RxFilter filter = RX_FILTER_NORMAL; }; +//====================================================================== +// FUNCTION PROTOTYPES +//====================================================================== + +void sendCATMessage(const uint8_t*); +void sendIOPMessage(IOPMessage const&); +void recvIOPMessage(IOPMessage&, const uint8_t*, int); + +void sendIOPModeCommand(RigMode); +void sendIOPStartTxCommand(); +void sendIOPStopTxCommand(); + +void sendIOPModeRequest(); +void sendIOPSSBStatus(SSBConfig const&); +void sendIOPDigiStatus(DigiConfig const&); +void sendIOPCWStatus(CWConfig const&); +void sendIOPTestStatus(); + //====================================================================== // TRANSLATOR //====================================================================== @@ -187,23 +227,6 @@ class Translator }; */ -//====================================================================== -// CW STATUS MESSAGE -//====================================================================== - -//void packT_DisplayText(TMessage &m, CWConfig const &c) -//{ -// m.id = IOP_CW_STATUS_MSG; -// m.len = 3; -// m.data[0] = ' '; // growth -// m.data[1] = MODE_LETTER[c.mode]; -// m.data[2] = ' '; // TODO: RX filter width -//} - -// No unpack required: this is a string to put on the display. - -//====================================================================== - #endif //====================================================================== diff --git a/ubitx_iop/audio.ino b/ubitx_iop/audio.ino index 3805dbd..97e2e89 100644 --- a/ubitx_iop/audio.ino +++ b/ubitx_iop/audio.ino @@ -304,10 +304,10 @@ void audioTransmit() { switch(rigMode) { // Nothing special for CW, TX audio inputs are already muted. - //case MODE_CW: + //case RIG_MODE_CW: //break; - case MODE_SSB: + case RIG_MODE_SSB: // Mute the incoming RX audio. Can't think of a good reason // to let RX audio in while we're transmitting. muteRxRigIn(); @@ -335,14 +335,14 @@ void audioTransmit() } break; - case MODE_DIGI: + case RIG_MODE_DIGI: // Mute the incoming RX audio. Can't think of a good reason // to let RX audio in while we're transmitting. muteRxRigIn(); updateTxUSBIn(); break; - case MODE_TEST: + case RIG_MODE_TEST: muteRxRigIn(); updateTxTwoToneIn(); break; @@ -359,10 +359,10 @@ void audioTransmit() void audioReceive() { switch(rigMode) { - //case MODE_CW: + //case RIG_MODE_CW: //break; - case MODE_SSB: + case RIG_MODE_SSB: if (audioTxInput == TX_MIC_IN) { muteTxMicIn(); audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); @@ -372,12 +372,12 @@ void audioReceive() restoreRxRigIn(); break; - case MODE_DIGI: + case RIG_MODE_DIGI: muteTxUSBIn(); restoreRxRigIn(); break; - case MODE_TEST: + case RIG_MODE_TEST: muteTxTwoToneIn(); restoreRxRigIn(); break; diff --git a/ubitx_iop/cat.ino b/ubitx_iop/cat.ino index 7ee5d99..e4b4223 100644 --- a/ubitx_iop/cat.ino +++ b/ubitx_iop/cat.ino @@ -30,16 +30,12 @@ void initCAT(long baud, int portConfig) // CAT with PC via USB USBSERIAL.begin(baud); USBSERIAL.flush(); -#if defined(DEBUG) - USBSERIAL.println("IOP: opened USB serial port (to PC)"); -#endif + USBDEBUG("opened USB serial port (to PC)"); // Comm (including CAT passthru) with Raduino via UART HWSERIAL.begin(baud, portConfig); HWSERIAL.flush(); -#if defined(DEBUG) - USBSERIAL.println("IOP: opened H/W serial port (to Raduino)"); -#endif + USBDEBUG("opened H/W serial port (to Raduino)"); //sendIOPModeRequest(); // Raduino doesn't support this yet } @@ -54,19 +50,19 @@ void processIOPCommand(IOPMessage const& m) if (m.len < 1) { return; } else { - setRigMode(m.data[0]); + setRigMode(RigMode(m.data[0])); #if defined(DEBUG) switch(rigMode) { - case MODE_CW: + case RIG_MODE_CW: USBDEBUG("new mode - CW"); break; - case MODE_SSB: + case RIG_MODE_SSB: USBDEBUG("new mode - SSB"); break; - case MODE_DIGI: + case RIG_MODE_DIGI: USBDEBUG("new mode - DIGI"); break; - case MODE_TEST: + case RIG_MODE_TEST: USBDEBUG("new mode - TEST"); break; } @@ -126,8 +122,8 @@ enum SerialState { EEPROM_WRITE, } serialState = NORMAL; -uint8_t readPrefix = 0; -uint8_t readLength = 0; +PrefixID readPrefix; +uint8_t readLength; int cmdLength = 0; byte cmdBuffer[16]; @@ -139,13 +135,37 @@ 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++) { + 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 @@ -176,7 +196,7 @@ void serviceCAT() #else // Don't pass CAT commands through if in DEBUG mode. #if not defined(DEBUG) - HWSERIAL.write(incomingByte); + //HWSERIAL.write(incomingByte); #endif } diff --git a/ubitx_iop/config.h b/ubitx_iop/config.h index 530a743..90fefd2 100644 --- a/ubitx_iop/config.h +++ b/ubitx_iop/config.h @@ -13,7 +13,7 @@ // Uncomment to use the "factory" calibration mode. This is intended to // allow calibration of IOP settings, separately from the uBITX/Raduino. // There will be no pass-thru of any CAT. -#define FACTORY_CALIBRATION +//#define FACTORY_CALIBRATION // IOPConfig // Used to store configuration parameters during runtime, as well as to @@ -84,11 +84,17 @@ struct IOPConfig { float txSine2Vol = 1.0; // rig-out parameters (TX) - default settings are based on hitting 70% of 25mVrms w/ mic uint8_t txRigOutLevel = 31; - float txRigOutCal = 0.043; + float txRigOutCal = 0.1; // 0.061; // USB-out parameters (TX)- debug/monitor use only bool txUSBOutEnable = true; float txUSBOutCal = 1.0; + // SSB configuration + SSBConfig ssb; + + // Digi configuration + DigiConfig digi; + // CW configuration CWConfig cw; }; diff --git a/ubitx_iop/ubitx_iop.h b/ubitx_iop/ubitx_iop.h index 6769ad6..d1eba95 100644 --- a/ubitx_iop/ubitx_iop.h +++ b/ubitx_iop/ubitx_iop.h @@ -12,7 +12,7 @@ #include "keyer.h" // comment this out to disable debugging code -//#define DEBUG +#define DEBUG #if defined(DEBUG) #define USBDEBUG(x) USBSERIAL.print("IOP: "); USBSERIAL.println(x); diff --git a/ubitx_iop/ubitx_iop.ino b/ubitx_iop/ubitx_iop.ino index 4f4eb79..5bb778c 100644 --- a/ubitx_iop/ubitx_iop.ino +++ b/ubitx_iop/ubitx_iop.ino @@ -8,7 +8,8 @@ #include #define BOUNCE_WITH_PROMPT_DETECTION -RigMode rigMode = MODE_SSB; +RigMode rigMode = RIG_MODE_SSB; +RxFilter rxFilter = RX_FILTER_NORMAL; IOPConfig iopConfig; #define MIC_PTT_PIN 21 @@ -44,10 +45,10 @@ void catPTTOn() // CAT should not start or stop TX in CW mode... we really should // not even get this command. But maybe the rig control software is // doing it (but then, we should inhibit this in the Raduino). - //case MODE_CW: + //case RIG_MODE_CW: //break; - case MODE_SSB: + case RIG_MODE_SSB: // In SSB mode, CAT-PTT will always (de-)activate the Line-In TX // audio source. txState = TX_CAT; @@ -56,7 +57,7 @@ void catPTTOn() digitalWrite(PTT_KEY_OUT_PIN, LOW); break; - case MODE_DIGI: + case RIG_MODE_DIGI: // In Digital (USB) mode, CAT-PTT will always (de-)activate the // USB-In TX audio source. txState = TX_CAT; @@ -82,10 +83,10 @@ void catPTTOff() // CAT should not start or stop TX in CW mode... we really should // not even get this command. But maybe the rig control software is // doing it (but then, we should inhibit this in the Raduino). - //case MODE_CW: + //case RIG_MODE_CW: //break; - case MODE_SSB: + case RIG_MODE_SSB: // In SSB mode, CAT-PTT will always (de-)activate the Line-In TX // audio source. digitalWrite(PTT_KEY_OUT_PIN, HIGH); @@ -93,7 +94,7 @@ void catPTTOff() txState = TX_OFF; break; - case MODE_DIGI: + case RIG_MODE_DIGI: // In Digital (USB) mode, CAT-PTT will always (de-)activate the // USB-In TX audio source. digitalWrite(PTT_KEY_OUT_PIN, HIGH); @@ -115,39 +116,35 @@ void checkMicPTT() // was released--the Mic-PTT can always be used to terminate a // transmission from another source. if ((txState != TX_OFF) && micPTT.rose()) { - #if defined(DEBUG) - USBSERIAL.println("DEBUG: mic PTT released"); - #endif + USBDEBUG("mic PTT released"); digitalWrite(PTT_KEY_OUT_PIN, HIGH); // In CW mode, we get a sidetone from the uBITX, so we don't mute // the receive audio. - if (rigMode != MODE_CW) audioReceive(); + if (rigMode != RIG_MODE_CW) audioReceive(); txState = TX_OFF; return; } if ((txState == TX_OFF) && micPTT.fell()) { - #if defined(DEBUG) - USBSERIAL.println("DEBUG: mic PTT depressed"); - #endif + USBDEBUG("mic PTT depressed"); switch(rigMode) { - case MODE_CW: + case RIG_MODE_CW: txState = TX_MIC; digitalWrite(PTT_KEY_OUT_PIN, LOW); break; - case MODE_SSB: + case RIG_MODE_SSB: txState = TX_MIC; audioSelectTxInput(TX_MIC_IN); audioTransmit(); digitalWrite(PTT_KEY_OUT_PIN, LOW); break; - case MODE_DIGI: + case RIG_MODE_DIGI: // Mic PTT actuation during Digital does nothing. break; - case MODE_TEST: + case RIG_MODE_TEST: txState = TX_MIC; audioSelectTxInput(TX_TEST_IN); audioTransmit(); @@ -172,30 +169,30 @@ void checkLinePTT() digitalWrite(PTT_KEY_OUT_PIN, HIGH); // In CW mode, we get a sidetone from the uBITX, so we don't mute // the receive audio. - if (rigMode != MODE_CW) audioReceive(); + if (rigMode != RIG_MODE_CW) audioReceive(); txState = TX_OFF; return; } if ((txState == TX_OFF) && linePTT.fell()) { switch(rigMode) { - case MODE_CW: + case RIG_MODE_CW: txState = TX_LINE; digitalWrite(PTT_KEY_OUT_PIN, LOW); break; - case MODE_SSB: + case RIG_MODE_SSB: txState = TX_LINE; audioSelectTxInput(TX_LINE_IN); audioTransmit(); digitalWrite(PTT_KEY_OUT_PIN, LOW); break; - case MODE_DIGI: + case RIG_MODE_DIGI: // Line PTT actuation during Digital does nothing. break; - case MODE_TEST: + case RIG_MODE_TEST: txState = TX_LINE; audioSelectTxInput(TX_TEST_IN); audioTransmit(); @@ -212,8 +209,8 @@ void setRigMode(RigMode m) rigMode = m; switch(rigMode) { - case MODE_SSB: - case MODE_TEST: + case RIG_MODE_SSB: + case RIG_MODE_TEST: // SSB sets the TX audio input to line-in. Note that this will be // automatically overridden by mic-in, if the mic PTT is pressed. audioSelectTxInput(TX_LINE_IN); @@ -221,7 +218,7 @@ void setRigMode(RigMode m) // dspMenu = &ssbMenu; break; - case MODE_DIGI: + case RIG_MODE_DIGI: // Digi sets the TX audio input to USB-in. Keying in this case must // be via CAT control. Digital modes can also be used through the // line-in, but the rig mode should be set to SSB in that case, and @@ -234,7 +231,7 @@ void setRigMode(RigMode m) // dspMenu = &digiMenu; break; - case MODE_CW: + case RIG_MODE_CW: // CW just gets the radio off of Mic-In; but it won't use Line-In. audioSelectTxInput(TX_LINE_IN); audioCWFilter(); @@ -245,6 +242,8 @@ void setRigMode(RigMode m) //====================================================================== +//elapsedMillis frame10hz = 0; + void setup() { // put your setup code here, to run once: initCAT(38400, SERIAL_8N1); @@ -261,19 +260,23 @@ void setup() { audioInit(); #if defined(FACTORY_CALIBRATION) - setRigMode(MODE_TEST); + setRigMode(RIG_MODE_TEST); #else - setRigMode(MODE_SSB); + setRigMode(RIG_MODE_SSB); #endif + + //frame10Hz = 0; } //====================================================================== void loop() { - elapsedMillis elapsed = 0; +// elapsedMillis elapsed = 0; + RigMode oldRigMode = rigMode; + RxFilter oldRxFilter = rxFilter; switch(rigMode) { - case MODE_CW: + case RIG_MODE_CW: if (keyer.do_paddles()) { if (keyer.is_down()) { digitalWrite(PTT_KEY_OUT_PIN, LOW); @@ -293,6 +296,28 @@ void loop() { serviceCAT(); } + // send current status @ 10 Hz + //if (frame10Hz > 100) { + if ((rigMode != oldRigMode) || (rxFilter != oldRxFilter)) { + switch(rigMode) { + case RIG_MODE_SSB: + sendIOPSSBStatus(iopConfig.ssb); + break; + + case RIG_MODE_DIGI: + sendIOPDigiStatus(iopConfig.digi); + break; + + case RIG_MODE_CW: + sendIOPCWStatus(iopConfig.cw); + break; + + case RIG_MODE_TEST: + sendIOPTestStatus(); + } + //frame10Hz = 0; + } + //dspMenu->update(); /*