diff --git a/References/B5A-0180-20.pdf b/References/B5A-0180-20.pdf new file mode 100644 index 0000000..8a399a9 Binary files /dev/null and b/References/B5A-0180-20.pdf differ diff --git a/References/ts_590_g_pc_command_e.pdf b/References/ts_590_g_pc_command_e.pdf new file mode 100644 index 0000000..e63716b Binary files /dev/null and b/References/ts_590_g_pc_command_e.pdf differ diff --git a/TeensyDSP/DSP.cpp b/TeensyDSP/DSP.cpp index 8418dbc..3344123 100644 --- a/TeensyDSP/DSP.cpp +++ b/TeensyDSP/DSP.cpp @@ -165,11 +165,10 @@ void UBitxDSP::setupRxAudio() { audioCtrl.lineOutLevel(29, 31); // RX, TX // Line Output (RX) - lineOutAmp.gain(1.0); + setLineOutLevel(1.0); // USB Output (RX) - usbOutAmp.gain(1.0); - usbBypassAmp.gain(1.0); + setUSBOutLevel(1.0); } void UBitxDSP::setupTxAudio() { @@ -231,6 +230,27 @@ void UBitxDSP::unmuteRxIn(RxAudioCh ch) { } } +void UBitxDSP::setLineOutLevel(float level) { + state.rxOut[LINE_OUT].level = level; + lineOutAmp.gain(state.rxOut[LINE_OUT].mute ? 0.0 : state.rxOut[LINE_OUT].level); +} + +void UBitxDSP::setUSBOutLevel(float level) { + state.rxOut[USB_OUT].level = level; + usbOutAmp.gain(state.rxOut[USB_OUT].mute ? 0.0 : state.rxOut[USB_OUT].level); + usbBypassAmp.gain(state.rxOut[USB_OUT].mute ? 0.0 : state.rxOut[USB_OUT].level); +} + +void UBitxDSP::setLineOut255(unsigned level) { setLineOutLevel<255>(level); } +void UBitxDSP::setLineOut9(unsigned level) { setLineOutLevel<9>(level); } +void UBitxDSP::setUSBOut255(unsigned level) { setUSBOutLevel<255>(level); } +void UBitxDSP::setUSBOut9(unsigned level) { setUSBOutLevel<9>(level); } + +unsigned UBitxDSP::getLineOut255() const { return getLineOutLevel<255>(); } +unsigned UBitxDSP::getLineOut9() const { return getLineOutLevel<9>(); } +unsigned UBitxDSP::getUSBOut255() const { return getUSBOutLevel<255>(); } +unsigned UBitxDSP::getUSBOut9() const { return getUSBOutLevel<9>(); } + /********************************************************************** * Transmit audio chain **********************************************************************/ @@ -286,6 +306,26 @@ void UBitxDSP::unmuteTxOut() { } } +void UBitxDSP::setLineInLevel(float level) { + state.txIn[TX_LINE].level = level; + txAudio.gain(TX_LINE, state.txIn[TX_LINE].mute ? 0.0 : state.txIn[TX_LINE].level); +} + +void UBitxDSP::setUSBInLevel(float level) { + state.txIn[TX_USB].level = level; + txAudio.gain(TX_USB, state.txIn[TX_USB].mute ? 0.0 : state.txIn[TX_USB].level); +} + +void UBitxDSP::setLineIn255(unsigned level) { setLineInLevel<255>(level); } +void UBitxDSP::setLineIn9(unsigned level) { setLineInLevel<9>(level); } +void UBitxDSP::setUSBIn255(unsigned level) { setUSBInLevel<255>(level); } +void UBitxDSP::setUSBIn9(unsigned level) { setUSBInLevel<9>(level); } + +unsigned UBitxDSP::getLineIn255() const { return getLineInLevel<255>(); } +unsigned UBitxDSP::getLineIn9() const { return getLineInLevel<9>(); } +unsigned UBitxDSP::getUSBIn255() const { return getUSBInLevel<255>(); } +unsigned UBitxDSP::getUSBIn9() const { return getUSBInLevel<9>(); } + void UBitxDSP::setTxAudioIn(TxAudioIn src, bool isTemp) { if (!isTemp) { txSrc = src; @@ -426,6 +466,34 @@ void UBitxDSP::setRxFilterCenter(int center) { setRxFilter(lo, hi); } +/********************************************************************** + * Transmit Voice-Operated-Switch (VOX) + **********************************************************************/ + +void UBitxDSP::setLineVOXThresh9(unsigned level) { + state.vox[TX_LINE].threshold = static_cast(level) / 9.0; +} + +unsigned UBitxDSP::getLineVOXThresh9() const { + return static_cast(state.vox[TX_LINE].threshold * 9.0); +} + +void UBitxDSP::setUSBVOXThresh9(unsigned level) { + state.vox[TX_USB].threshold = static_cast(level) / 9.0; +} + +unsigned UBitxDSP::getUSBVOXThresh9() const { + return static_cast(state.vox[TX_USB].threshold * 9.0); +} + +void UBitxDSP::setDataVoxDelay(unsigned msec) { + state.voxDelay = msec; +} + +unsigned UBitxDSP::getDataVoxDelay() const { + return state.voxDelay; +} + /********************************************************************** * Singleton - the DSP instance **********************************************************************/ diff --git a/TeensyDSP/DSP.h b/TeensyDSP/DSP.h index b3fe031..65010bf 100644 --- a/TeensyDSP/DSP.h +++ b/TeensyDSP/DSP.h @@ -48,6 +48,13 @@ enum RxAudioIn { NUM_RX_AUDIO_IN // Total number of inputs }; +//! Defines the different RX audio outputs. +enum RxAudioOut { + LINE_OUT = 0, // Line audio out (and speaker) + USB_OUT, // USB audio out + NUM_RX_AUDIO_OUT +}; + //! Defines the four separate TX audio input channels available. enum TxAudioCh { TX_LINE = 0, // Line and/or mic audio input channel @@ -94,7 +101,10 @@ struct DSPState { }; //! Receiver audio output; defaults to muted. - AudioChannel rxOut = {true, 1.0}; + AudioChannel rxOut[NUM_RX_AUDIO_OUT] = { + {false, 1.0}, // line + {false, 1.0} // USB + }; //! Transmitter audio inputs; all default to muted. AudioChannel txIn[NUM_TX_AUDIO_CH] = { @@ -177,10 +187,48 @@ class UBitxDSP { // Basic control of RX audio inputs and outputs. public: - void setRxInLevel(RxAudioCh ch, float level); // Set the audio input level for a given channel. - void muteRxIn(); // Mute all RX audio input channels. - void muteRxIn(RxAudioCh ch); // Mute a specific RX audio input channel. - void unmuteRxIn(RxAudioCh ch); // Un-mute a specific RX audio input channel. + void setRxInLevel(RxAudioCh ch, float level); // Set the audio input level for a given channel. + void muteRxIn(); // Mute all RX audio input channels. + void muteRxIn(RxAudioCh ch); // Mute a specific RX audio input channel. + void unmuteRxIn(RxAudioCh ch); // Un-mute a specific RX audio input channel. + + void setLineOutLevel(float level); // Set the line output level (0.0 - 1.0). + void setUSBOutLevel(float level); // Set the USB output level (0.0 - 1.0). + + // Discrete control intended for use with TS-590 CAT. + void setLineOut255(unsigned level); // Set the line output level (0 - 255). + void setLineOut9(unsigned level); // Set the line output level (0 - 9). + void setUSBOut255(unsigned level); // Set the USB output level (0 - 255). + void setUSBOut9(unsigned level); // Set the USB output level (0 - 9). + + unsigned getLineOut255() const; // Get the line output level (0 - 255). + unsigned getLineOut9() const; // Get the line output level (0 - 9). + unsigned getUSBOut255() const; // Get the USB output level (0 - 255). + unsigned getUSBOut9() const; // Get the USB output level (0 - 9). + + //! Set the line output level based on an integer value. + template + void setLineOutLevel(unsigned level) { + setLineOutLevel(static_cast(level) / static_cast(MAX)); + } + + //! Set the USB output level based on an integer value. + template + void setUSBOutLevel(unsigned level) { + setUSBOutLevel(static_cast(level) / static_cast(MAX)); + } + + //! Get the line output level as an integer value. + template + unsigned getLineOutLevel() const { + return static_cast(state.rxOut[LINE_OUT].level * static_cast(MAX)); + } + + //! Get the USB output level as an integer value. + template + unsigned getUSBOutLevel() const { + return static_cast(state.rxOut[USB_OUT].level * static_cast(MAX)); + } /******************************************************************** * Transmit audio chain @@ -192,10 +240,49 @@ class UBitxDSP { void muteTxIn(); // Mute all TX audio input channels. void muteTxIn(TxAudioCh ch); // Mute a specific TX audio input channel. void unmuteTxIn(TxAudioCh ch); // Un-mute a specific TX audio input channel. + void setTxOutLevel(float level); // Set the TX audio output level. void muteTxOut(); // Mute the TX audio output. void unmuteTxOut(); // Un-mute the TX audio output. - + + void setLineInLevel(float level); // Set the line input level (0.0 - 1.0). + void setUSBInLevel(float level); // Set the USB input level (0.0 - 1.0). + + // Discrete control intended for use with TS-590 CAT. + void setLineIn255(unsigned level); // Set the line input level (0 - 255). + void setLineIn9(unsigned level); // Set the line input level (0 - 9). + void setUSBIn255(unsigned level); // Set the USB input level (0 - 255). + void setUSBIn9(unsigned level); // Set the USB input level (0 - 9). + + unsigned getLineIn255() const; // Get the line input level (0 - 255). + unsigned getLineIn9() const; // Get the line input level (0 - 9). + unsigned getUSBIn255() const; // Get the USB input level (0 - 255). + unsigned getUSBIn9() const; // Get the USB input level (0 - 9). + + //! Set the line input level based on an integer value. + template + void setLineInLevel(unsigned level) { + setLineInLevel(static_cast(level) / static_cast(MAX)); + } + + //! Set the USB input level based on an integer value. + template + void setUSBInLevel(unsigned level) { + setUSBInLevel(static_cast(level) / static_cast(MAX)); + } + + //! Get the line input level as an integer value. + template + unsigned getLineInLevel() const { + return static_cast(state.txIn[LINE_OUT].level * static_cast(MAX)); + } + + //! Get the USB input level as an integer value. + template + unsigned getUSBInLevel() const { + return static_cast(state.txIn[USB_OUT].level * static_cast(MAX)); + } + // Transmit audio selection (may be overriden at actual transmit time). public: void setTxAudioIn(TxAudioIn src, bool isTemp = false); // Select a specific TX audio input path, and identify it as permanent or temporary. @@ -246,6 +333,15 @@ class UBitxDSP { inline bool voxActive() { return isVoxActive; } inline bool voxInactive() { return !isVoxActive; } + void setLineVOXThresh9(unsigned level); + unsigned getLineVOXThresh9() const; + + void setUSBVOXThresh9(unsigned level); + unsigned getUSBVOXThresh9() const; + + void setDataVoxDelay(unsigned msec); + unsigned getDataVoxDelay() const; + /******************************************************************** * Private state ********************************************************************/ diff --git a/TeensyDSP/TS590.cpp b/TeensyDSP/TS590.cpp index 8149e71..55d2305 100644 --- a/TeensyDSP/TS590.cpp +++ b/TeensyDSP/TS590.cpp @@ -34,12 +34,9 @@ void ts590SendCommand(const char* format, ...) { * than two are supplied, then the command will be * initialized with a null prefix. */ -TS590Command::TS590Command(const char* pre) { - if (strlen(pre) >= 2) { - myPrefix[0] = pre[0]; - myPrefix[1] = pre[1]; - } -} +TS590Command::TS590Command(const char* pre) +: myPrefix(pre), prefixLength(strlen(pre)) +{} TS590Command::~TS590Command() {} @@ -49,7 +46,7 @@ TS590Command::~TS590Command() {} * @return True if a Read command; false otherwise. */ bool TS590Command::isReadCommand(const char* cmd) const { - if (strlen(cmd) == 2) { + if (strlen(cmd) == prefixLength) { return true; } else { return false; @@ -145,6 +142,30 @@ TS590Error TS590Command::theError = NoError; /**********************************************************************/ +void TS590Command_UL::handleCommand(const char* cmd) { + unsigned val = static_cast(strtoul(&prefix()[length()], NULL, 10)); + if (val < myMin) { + val = myMin; + } else if (val > myMax) { + val = myMax; + } + val = (val * mySlope) + myIntercept; + setter(val); +} + +void TS590Command_UL::sendResponse(const char* cmd) { + unsigned val = getter(); + val = (val - myIntercept) / mySlope; + if (val < myMin) { + val = myMin; + } else if (val > myMax) { + val = myMax; + } + ts590SendCommand("%s%0*u", prefix(), myWidth, getter()); +} + +/**********************************************************************/ + void TS590_FR::handleCommand(const char* cmd) { if (strlen(cmd) == 3) { switch (cmd[2]) { @@ -329,6 +350,58 @@ void TS590_VX::sendResponse(const char* cmd) { /**********************************************************************/ +void nullSetFunc(unsigned x) { return; } +unsigned getIDFunc() { +#ifndef USE_TS590SG_CAT + return 021; +#else + return 023; +#endif +} + +SetUL setAG = SetUL::create(DSP); +GetUL getAG = GetUL::create(DSP); +//SetUL setSidetone = SetUL::create(...); +//GetUL getSidetone = GetUL::create(...); +SetUL setUSBin = SetUL::create(DSP); +GetUL getUSBin = GetUL::create(DSP); +SetUL setUSBout = SetUL::create(DSP); +GetUL getUSBout = GetUL::create(DSP); +SetUL setACC2in = SetUL::create(DSP); +GetUL getACC2in = GetUL::create(DSP); +SetUL setACC2out = SetUL::create(DSP); +GetUL getACC2out = GetUL::create(DSP); +SetUL setVoxDelay = SetUL::create(DSP); +GetUL getVoxDelay = GetUL::create(DSP); +SetUL setUSBvox = SetUL::create(DSP); +GetUL getUSBvox = GetUL::create(DSP); +SetUL setACC2vox = SetUL::create(DSP); +GetUL getACC2vox = GetUL::create(DSP); +SetUL setID = SetUL::create(); +GetUL getID = GetUL::create(); + +TS590Command_UL TS590_AG("AG0", 3, 0, 255, setAG, getAG); +#ifndef USE_TS590SG_CAT +//TS590Command_UL TS590_EX034("EX0340000", 2, 0, 14, 50, 300, setSideTone, getSideTone); +TS590Command_UL TS590_EX064("EX0640000", 1, 0, 9, setUSBin, getUSBin); +TS590Command_UL TS590_EX065("EX0650000", 1, 0, 9, setUSBout, getUSBout); +TS590Command_UL TS590_EX066("EX0660000", 1, 0, 9, setACC2in, getACC2in); +TS590Command_UL TS590_EX067("EX0670000", 1, 0, 9, setACC2out, getACC2out); +TS590Command_UL TS590_EX070("EX0700000", 2, 0, 20, 5, 0, setVoxDelay, getVoxDelay); +TS590Command_UL TS590_EX071("EX0710000", 1, 0, 9, setUSBvox, getUSBvox); +TS590Command_UL TS590_EX072("EX0720000", 1, 0, 9, setACC2vox, getACC2vox); +#else +//TS590Command_UL TS590_EX040("EX0400000", 2, 0, 14, 50, 300, setSideTone, getSideTone); +TS590Command_UL TS590_EX071("EX0710000", 1, 0, 9, setUSBin, getUSBin); +TS590Command_UL TS590_EX072("EX0720000", 1, 0, 9, setUSBout, getUSBout); +TS590Command_UL TS590_EX073("EX0730000", 1, 0, 9, setACC2in, getACC2in); +TS590Command_UL TS590_EX074("EX0740000", 1, 0, 9, setACC2out, getACC2out); +TS590Command_UL TS590_EX077("EX0770000", 2, 0, 20, 5, 0, setVoxDelay, getVoxDelay); +TS590Command_UL TS590_EX078("EX0780000", 1, 0, 9, setUSBvox, getUSBvox); +TS590Command_UL TS590_EX079("EX0790000", 1, 0, 9, setACC2vox, getACC2vox); +#endif +TS590Command_UL TS590_ID("ID", 3, 21, 23, setID, getID); + TS590_FA cmdFA; TS590_FB cmdFB; TS590_FR cmdFR; @@ -350,7 +423,6 @@ int numCatCommands = sizeof(catCommands) / sizeof(catCommands[0]); /**********************************************************************/ - void UBitxTS590::begin() { Serial.begin(9600); // USB is always 12 Mbit/sec #ifdef DEBUG @@ -391,7 +463,7 @@ typedef class TS590Command* PCmd; int compareCATCommands(const void* a, const void* b) { TS590Command const *B = *(TS590Command const **)b; - int cmp = strncmp((char*)a, (char*)B->prefix(), 2); + int cmp = strncmp((char*)a, (char*)B->prefix(), B->length()); #ifdef DEBUG Serial.print("Comparison: "); Serial.print((char*)a); diff --git a/TeensyDSP/TS590.h b/TeensyDSP/TS590.h index 833f592..26e1f06 100644 --- a/TeensyDSP/TS590.h +++ b/TeensyDSP/TS590.h @@ -2,6 +2,8 @@ #define __TS590_h__ #include +#include +#include #include "DSP.h" #include "Rig.h" @@ -35,6 +37,72 @@ enum TS590Error { ProcessError }; +/********************************************************************** + **********************************************************************/ +/* +class TS590BaseCommand { + public: + TS590BaseCommand(const char* prefix) + : myPrefix(prefix), prefixLength(strlen(prefix)) + {} + virtual ~TS590BaseCommand() = 0; + + inline const char* prefix() { return &myPrefix[0]; } + inline size_t length() { return prefixLength; } + + virtual void handleCommand(const char* cmd) = 0; + virtual void sendResponse(const char* cmd) = 0; + virtual bool isReadCommand(const char* cmd) const; + + inline void process(const char* cmd) { + theError = NoError; + + if (isReadCommand(cmd)) { + DBGCMD( sendResponse(cmd) ); + } else { + DBGCMD( handleCommand(cmd) ); + switch(theError) { + case NoError: + if (theRig->isAI()) { + DBGCMD( sendResponse(cmd) ); + } + break; + + case SyntaxError: + DBGCMD( ts590SyntaxError() ); + break; + + case CommError: + DBGCMD( ts590CommError() ); + break; + + case ProcessError: + DBGCMD( ts590ProcessError() ); + break; + } + } + } + + private: + const char* myPrefix; + size_t prefixLength; +}; +*/ +typedef etl::delegate ValidateFunc; +typedef etl::delegate IsReadFunc; +typedef etl::delegate ToggleFunc; + +/* +class TS590ToggleCommand : public TS590BaseCommand { + TS590ToggleCommand(const char* prefix, ToggleFunc& setter, ToggleFunc& getter) + : TS590BaseCommand(prefix) + {} + + private: + ToggleFunc& mySetter; + ToggleFunc& myGetter; +}; +*/ /**********************************************************************/ /*! @@ -44,7 +112,7 @@ enum TS590Error { class TS590Command { public: TS590Command(const char* pre); - virtual ~TS590Command() = 0; + virtual ~TS590Command(); /*! * @brief Return the 2-character prefix for the command. @@ -52,6 +120,8 @@ class TS590Command { */ inline const char* prefix() const { return &myPrefix[0]; } + inline size_t length() const { return prefixLength; } + /*! * @brief Return the rig that this command will be used to control. */ @@ -90,7 +160,8 @@ class TS590Command { static void setDSP(UBitxDSP* d); private: - char myPrefix[3] = "\0\0"; + const char* myPrefix; + size_t prefixLength; static TS590Error theError; static UBitxRig* theRig; static UBitxDSP* theDSP; @@ -98,6 +169,32 @@ class TS590Command { /**********************************************************************/ +typedef etl::delegate SetUL; +typedef etl::delegate GetUL; + +class TS590Command_UL : public TS590Command { + public: + TS590Command_UL(const char* prefix, size_t width, unsigned min, unsigned max, SetUL set, GetUL get) + : TS590Command(prefix), myWidth(width), myMin(min), myMax(max), mySlope(1), myIntercept(0), setter(set), getter(get) {} + + TS590Command_UL(const char* prefix, size_t width, unsigned min, unsigned max, unsigned slope, unsigned intercept, SetUL set, GetUL get) + : TS590Command(prefix), myWidth(width), myMin(min), myMax(max), mySlope(slope), myIntercept(intercept), setter(set), getter(get) {} + + virtual void handleCommand(const char* cmd); + virtual void sendResponse(const char* cmd); + + private: + size_t myWidth; + unsigned myMin; + unsigned myMax; + unsigned mySlope; + unsigned myIntercept; + SetUL setter; + GetUL getter; +}; + +/**********************************************************************/ + /*! * @brief CAT command for setting or reading the VFO A/B frequency. */