Further updates to DSP, and significant changes to TS590. Implementing templated CAT commands using the delegate template from the ETL. Compiles, but not tested.

This commit is contained in:
Rob French 2021-03-16 23:11:17 -05:00
parent f724142fca
commit c8aecdfb0d
6 changed files with 353 additions and 20 deletions

BIN
References/B5A-0180-20.pdf Normal file

Binary file not shown.

Binary file not shown.

View File

@ -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<float>(level) / 9.0;
}
unsigned UBitxDSP::getLineVOXThresh9() const {
return static_cast<unsigned>(state.vox[TX_LINE].threshold * 9.0);
}
void UBitxDSP::setUSBVOXThresh9(unsigned level) {
state.vox[TX_USB].threshold = static_cast<float>(level) / 9.0;
}
unsigned UBitxDSP::getUSBVOXThresh9() const {
return static_cast<unsigned>(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
**********************************************************************/

View File

@ -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<unsigned MAX>
void setLineOutLevel(unsigned level) {
setLineOutLevel(static_cast<float>(level) / static_cast<float>(MAX));
}
//! Set the USB output level based on an integer value.
template<unsigned MAX>
void setUSBOutLevel(unsigned level) {
setUSBOutLevel(static_cast<float>(level) / static_cast<float>(MAX));
}
//! Get the line output level as an integer value.
template<unsigned MAX>
unsigned getLineOutLevel() const {
return static_cast<unsigned>(state.rxOut[LINE_OUT].level * static_cast<float>(MAX));
}
//! Get the USB output level as an integer value.
template<unsigned MAX>
unsigned getUSBOutLevel() const {
return static_cast<unsigned>(state.rxOut[USB_OUT].level * static_cast<float>(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<unsigned MAX>
void setLineInLevel(unsigned level) {
setLineInLevel(static_cast<float>(level) / static_cast<float>(MAX));
}
//! Set the USB input level based on an integer value.
template<unsigned MAX>
void setUSBInLevel(unsigned level) {
setUSBInLevel(static_cast<float>(level) / static_cast<float>(MAX));
}
//! Get the line input level as an integer value.
template<unsigned MAX>
unsigned getLineInLevel() const {
return static_cast<unsigned>(state.txIn[LINE_OUT].level * static_cast<float>(MAX));
}
//! Get the USB input level as an integer value.
template<unsigned MAX>
unsigned getUSBInLevel() const {
return static_cast<unsigned>(state.txIn[USB_OUT].level * static_cast<float>(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
********************************************************************/

View File

@ -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<unsigned>(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<UBitxDSP, &UBitxDSP::setLineOut255>(DSP);
GetUL getAG = GetUL::create<UBitxDSP, &UBitxDSP::getLineOut255>(DSP);
//SetUL setSidetone = SetUL::create<UBitxDSP, ...>(...);
//GetUL getSidetone = GetUL::create<UBitxDSP, ...>(...);
SetUL setUSBin = SetUL::create<UBitxDSP, &UBitxDSP::setUSBIn9>(DSP);
GetUL getUSBin = GetUL::create<UBitxDSP, &UBitxDSP::getUSBIn9>(DSP);
SetUL setUSBout = SetUL::create<UBitxDSP, &UBitxDSP::setUSBOut9>(DSP);
GetUL getUSBout = GetUL::create<UBitxDSP, &UBitxDSP::getUSBOut9>(DSP);
SetUL setACC2in = SetUL::create<UBitxDSP, &UBitxDSP::setLineIn9>(DSP);
GetUL getACC2in = GetUL::create<UBitxDSP, &UBitxDSP::getLineIn9>(DSP);
SetUL setACC2out = SetUL::create<UBitxDSP, &UBitxDSP::setLineOut9>(DSP);
GetUL getACC2out = GetUL::create<UBitxDSP, &UBitxDSP::getLineOut9>(DSP);
SetUL setVoxDelay = SetUL::create<UBitxDSP, &UBitxDSP::setDataVoxDelay>(DSP);
GetUL getVoxDelay = GetUL::create<UBitxDSP, &UBitxDSP::getDataVoxDelay>(DSP);
SetUL setUSBvox = SetUL::create<UBitxDSP, &UBitxDSP::setUSBVOXThresh9>(DSP);
GetUL getUSBvox = GetUL::create<UBitxDSP, &UBitxDSP::getUSBVOXThresh9>(DSP);
SetUL setACC2vox = SetUL::create<UBitxDSP, &UBitxDSP::setLineVOXThresh9>(DSP);
GetUL getACC2vox = GetUL::create<UBitxDSP, &UBitxDSP::getLineVOXThresh9>(DSP);
SetUL setID = SetUL::create<nullSetFunc>();
GetUL getID = GetUL::create<getIDFunc>();
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);

View File

@ -2,6 +2,8 @@
#define __TS590_h__
#include <Arduino.h>
#include <Embedded_Template_Library.h>
#include <etl/delegate.h>
#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<bool(const char*)> ValidateFunc;
typedef etl::delegate<bool(const char*)> IsReadFunc;
typedef etl::delegate<void(bool)> 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<void(unsigned)> SetUL;
typedef etl::delegate<unsigned(void)> 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.
*/