Significant updates to DSP. Compiles. Likely doesn't work at the moment. Next step should be to get it running again on the rig, NOT to try any more fancy updates to CAT etc.

This commit is contained in:
Rob French
2021-03-14 23:18:24 -05:00
parent 20b475dace
commit 869e47d430
3 changed files with 347 additions and 228 deletions
+199 -155
View File
@@ -56,7 +56,8 @@ AudioControlSGTL5000 audioCtrl; //xy=435,448
//} audio;
UBitxDSP::UBitxDSP() {
UBitxDSP::UBitxDSP()
: txSrc(MIC_IN), txSrcLatched(MIC_IN) {
}
void UBitxDSP::begin() {
@@ -67,47 +68,12 @@ void UBitxDSP::begin() {
audioCtrl.volume(0.0); // headphone volume...
audioCtrl.muteHeadphone(); // ...not used by UBitxDSP
for (int i = 0; i < 4; i++) {
if (i == RX_AUDIO_CH)
rxAudio.gain(i, 1.0);
else
rxAudio.gain(i, 0.0);
}
for (int i = 0; i < 4; i++) {
txAudio.gain(i, 0.0);
}
// SETUP THE AUDIO INPUTS
// Rig (Line) Input (RX)
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
audioCtrl.unmuteLineout();
audioCtrl.lineInLevel(9, 5); // RX, TX
audioCtrl.lineOutLevel(29, 31); // RX, TX
// Mic Input (TX)
audioCtrl.micGain(0); // TODO: set value
// Line Input (TX)
// USB Input (TX)
// SETUP THE AUDIO OUTPUTS
// Line Output (RX)
lineOutAmp.gain(1.0);
// USB Output (RX)
usbOutAmp.gain(1.0);
usbBypassAmp.gain(1.0);
// Rig (Line) Output (TX)
txOutAmp.gain(1.0);
setupRxAudio();
setupTxAudio();
// Default to RX.
muteRxIn();
muteTxIn();
muteRxIn(); // redundant?
muteTxIn(); // redundant?
isTx = true; // so that rx() call works
rx();
@@ -120,56 +86,123 @@ void UBitxDSP::begin() {
}
void UBitxDSP::update() {
// Only going to adjust the USB volume periodically.
// Update the USB volume (level of TX USB output) periodically.
if (sinceLastUpdate > DSP_MILLIS_PER_UPDATE) {
float vol = usbIn.volume();
setTxInLevel(TX_USB, vol);
if (vol != usbVol) {
setTxInLevel(TX_USB, vol);
usbVol = vol;
}
sinceLastUpdate = 0;
}
// Update the VOX switches.
// TODO: Move the enable logic in here, so we don't process unnecessarily.
if (txVoxLevel.available()) {
if (txVoxLevel.read() > state.vox.threshold) {
state.vox.timeout = millis() + state.vox.delay;
state.vox.active = true;
if (state.vox[txSrc].enable && txVoxLevel.available()) {
if (txVoxLevel.read() > state.vox[txSrc].threshold) {
voxTimeout = millis() + state.voxDelay;
state.voxActive = true;
}
}
if (millis() > state.vox.timeout) {
state.vox.active = false;
if (millis() > voxTimeout) {
state.voxActive = false;
}
}
void UBitxDSP::end() {
}
//======================================================================
// Transmit/Receive (T/R) Switching
//======================================================================
/*!
* @brief Revert to receive (RX) mode from transmit (TX) mode. First
* the transmit audio output is muted, to ensure that no more
* audio goes to the rig. Then we check to see if the latched
* TX audio source was different than the selected TX audio
* source; this happens if the radio is currently set for a
* particular input (which determines what is monitored by the
* VOX), but then is commanded to transmit a different source
* (e.g. based on a CAT command). The actual transmit audio
* source is latched during transmit, but upon returning to
* receive, we restore the selected transmit audio.
*/
void UBitxDSP::rx() {
if (isTx) {
muteTxIn();
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
muteTxOut();
if (txSrcLatched != txSrc) {
setTxAudioIn(txSrc);
}
if (txSrcLatched == MIC_IN) {
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
}
unmuteRxIn(RX_AUDIO);
isTx = false;
}
}
void UBitxDSP::tx(TxAudioIn src) {
if (!isTx) {
muteRxIn(RX_AUDIO);
txSrcLatched = src;
if (txSrcLatched != txSrc) {
setTxAudioIn(txSrcLatched, true);
}
if (txSrcLatched == MIC_IN) {
audioCtrl.inputSelect(AUDIO_INPUT_MIC);
audioCtrl.micGain(12); // TODO: Make this dynamic
}
unmuteTxOut();
isTx = true;
}
}
//======================================================================
// Receive (RX) Audio Chain
//======================================================================
void UBitxDSP::setupRxAudio() {
for (int i = 0; i < NUM_RX_AUDIO_CH; i++) {
if (i == RX_AUDIO)
rxAudio.gain(i, 1.0);
else
rxAudio.gain(i, 0.0);
}
// Rig (Line) Input (RX)
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
audioCtrl.unmuteLineout();
audioCtrl.lineInLevel(9, 5); // RX, TX
audioCtrl.lineOutLevel(29, 31); // RX, TX
// Line Output (RX)
lineOutAmp.gain(1.0);
// USB Output (RX)
usbOutAmp.gain(1.0);
usbBypassAmp.gain(1.0);
}
void UBitxDSP::setRxInLevel(RxAudioCh ch, float level) {
if (ch < NUM_RX_AUDIO_CH) {
state.rx[ch].level = level;
rxAudio.gain(ch, state.rx[ch].mute ? 0.0 : state.rx[ch].level);
state.rxin[ch].level = level;
rxAudio.gain(ch, state.rxin[ch].mute ? 0.0 : state.rxin[ch].level);
}
}
void UBitxDSP::muteRxIn() {
for (RxAudioCh i = RX_AUDIO; i < NUM_RX_AUDIO_CH; i++) {
state.rx[ch].mute = true;
rxAudio.gain(ch, 0.0);
for (int i = 0; i < NUM_RX_AUDIO_CH; i++) {
state.rxin[RxAudioCh(i)].mute = true;
rxAudio.gain(i, 0.0);
}
}
void UBitxDSP::muteRxIn(RxAudioCh ch) {
if (ch < NUM_RX_AUDIO_CH) {
if (!state.rx[ch].mute) {
state.rx[ch].mute = true;
if (!state.rxin[ch].mute) {
state.rxin[ch].mute = true;
rxAudio.gain(ch, 0.0);
}
}
@@ -177,70 +210,58 @@ void UBitxDSP::muteRxIn(RxAudioCh ch) {
void UBitxDSP::unmuteRxIn(RxAudioCh ch) {
if (ch < NUM_RX_AUDIO_CH) {
if (state.rx[ch].mute) {
state.rx[ch].mute = false;
rxAudio.gain(ch, state.rx[ch].level);
if (state.rxin[ch].mute) {
state.rxin[ch].mute = false;
rxAudio.gain(ch, state.rxin[ch].level);
}
}
}
void UBitxDSP::tx(TxAudioIn src) {
if (!isTx) {
muteRxIn(RX_AUDIO);
switch (src) {
case MIC_IN:
audioCtrl.inputSelect(AUDIO_INPUT_MIC);
audioCtrl.micGain(12); // TODO: Make this dynamic
unmuteTxIn(TX_LINE);
//======================================================================
// Transmit (TX) Audio Chain
//======================================================================
case LINE_IN:
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
unmuteTxIn(TX_LINE);
break;
case USB_IN:
unmuteTxIn(TX_USB);
break;
case TUNE_IN:
tone1.amplitude(1.0); // TODO - just do this once.
tone1.frequency(1500); // TODO: Make this dynamic based on CW (sidetone freq) versus data (1500 Hz)
unmuteTxIn(TX_TONE1);
break;
case TWO_TONE_IN:
tone1.amplitude(1.0); // TODO - just do this once.
tone1.amplitude(1.0); // TODO - just do this once.
tone1.frequency(700);
tone2.frequency(1900);
unmuteTxIn(TX_TONE1);
unmuteTxIn(TX_TONE2);
break;
}
isTx = true;
void UBitxDSP::setupTxAudio() {
for (int i = 0; i < NUM_TX_AUDIO_CH; i++) {
txAudio.gain(i, 0.0);
}
// Mic Input (TX)
audioCtrl.micGain(0); // TODO: set value
// Line Input (TX)
// USB Input (TX)
// Rig (Line) Output (TX)
txOutAmp.gain(1.0);
tone1.amplitude(1.0); // TODO - just do this once.
tone1.frequency(1500); // TODO: Make this dynamic based on CW (sidetone freq) versus data (1500 Hz)
tone1.amplitude(1.0); // TODO - just do this once.
tone1.amplitude(1.0); // TODO - just do this once.
tone1.frequency(700);
tone2.frequency(1900);
}
void UBitxDSP::setTxInLevel(TxAudioCh ch, float level) {
if (ch < NUM_TX_AUDIO_CH) {
state.tx[ch].level = level;
txAudio.gain(ch, state.tx[ch].mute ? 0.0 : state.tx[ch].level);
state.txin[ch].level = level;
txAudio.gain(ch, state.txin[ch].mute ? 0.0 : state.txin[ch].level);
}
}
void UBitxDSP::muteTxIn() {
for (TxAudioCh i = TX_LINE; i < NUM_TX_AUDIO_CH; i++) {
state.tx[ch].mute = true;
txAudio.gain(ch, 0.0);
for (int i = 0; i < NUM_TX_AUDIO_CH; i++) {
state.txin[TxAudioCh(i)].mute = true;
txAudio.gain(i, 0.0);
}
}
void UBitxDSP::muteTxIn(TxAudioCh ch) {
if (ch < NUM_TX_AUDIO_CH) {
if (!state.tx[ch].mute) {
state.tx[ch].mute = true;
if (!state.txin[ch].mute) {
state.txin[ch].mute = true;
txAudio.gain(ch, 0.0);
}
}
@@ -248,15 +269,82 @@ void UBitxDSP::muteTxIn(TxAudioCh ch) {
void UBitxDSP::unmuteTxIn(TxAudioCh ch) {
if (ch < NUM_TX_AUDIO_CH) {
if (state.tx[ch].mute) {
state.tx[ch].mute = false;
rxAudio.gain(ch, state.tx[ch].level);
if (state.txin[ch].mute) {
state.txin[ch].mute = false;
rxAudio.gain(ch, state.txin[ch].level);
}
}
}
/**********************************************************************/
// RX filter settings
void UBitxDSP::setTxOutLevel(float level) {
state.txout.level = level;
txOutAmp.gain(state.txout.mute ? 0.0 : state.txout.level);
}
void UBitxDSP::muteTxOut() {
if (!state.txout.mute) {
state.txout.mute = true;
txOutAmp.gain(0.0);
}
}
void UBitxDSP::unmuteTxOut() {
if (state.txout.mute) {
state.txout.mute = false;
txOutAmp.gain(state.txout.level);
}
}
void UBitxDSP::setTxAudioIn(TxAudioIn src, bool isTemp) {
if (!isTemp) {
txSrc = src;
}
if (!isTx) {
muteTxIn(); // Mute all channels, then unmute the desired ones.
switch (src) { // Don't switch inputs while transmitting.
case MIC_IN:
// Note that we can't actually use the VOX code on the mic input,
// because we can't make the actual mic input active without
// losing our receive audio. So, mic input is never actually
// selected until it is time for it to transmit, which makes the
// VOX moot. The caller must make use of an external, analog VOX
// circuit driving a GPIO pin, or something similar (or the PTT of
// course) to begin actually using the mic input. So this case
// just falls through to the line input.
case LINE_IN:
unmuteTxIn(TX_LINE);
break;
case USB_IN:
unmuteTxIn(TX_USB);
break;
case TUNE_IN:
tone1.amplitude(1.0); // TODO - just do this once.
tone1.frequency(1500); // TODO: Make this dynamic based on CW (sidetone freq) versus data (1500 Hz)
unmuteTxIn(TX_TONE1);
break;
case TWO_TONE_IN:
tone1.amplitude(1.0); // TODO - just do this once.
tone1.amplitude(1.0); // TODO - just do this once.
tone1.frequency(700);
tone2.frequency(1900);
unmuteTxIn(TX_TONE1);
unmuteTxIn(TX_TONE2);
break;
default:
// should never happen
}
}
}
//======================================================================
// RX Audio Filter Settings
//======================================================================
const int minRxFilterLo = MIN_RX_FILTER_LO;
const int maxRxFilterHi = MAX_RX_FILTER_HI;
@@ -266,8 +354,8 @@ const int minRxFilterCenter = MIN_RX_FILTER_CENTER;
const int maxRxFilterCenter = MAX_RX_FILTER_CENTER;
/*!
@brief Bypass the RX audio filter.
*/
* @brief Bypass the RX audio filter.
*/
void UBitxDSP::bypassRxFilter() {
rxFilter.begin(FIR_PASSTHRU, NUM_COEFFICIENTS);
}
@@ -346,50 +434,6 @@ void UBitxDSP::setRxFilterCenter(int center) {
setRxFilter(lo, hi);
}
/**********************************************************************/
// TX audio input settings
void UBitxDSP::setTxInputLevel(int ch, float lvl) {
if ((ch > -1) && (ch < txNumChannels)) {
state.txInLvl[ch] = lvl;
float vol = lvl * float(state.txInEnable[ch] * state.txInTx[ch]);
txAudio.gain(ch, vol);
}
}
void UBitxDSP::enableTxInput(int ch) {
if ((ch > -1) && (ch < txNumChannels)) {
state.txInEnable[ch] = 1;
float vol = state.txInLvl[ch] * float(state.txInEnable[ch] * state.txInTx[ch]);
txAudio.gain(ch, vol);
}
}
void UBitxDSP::disableTxInput(int ch) {
if ((ch > -1) && (ch < txNumChannels)) {
state.txInEnable[ch] = 0;
float vol = state.txInLvl[ch] * float(state.txInEnable[ch] * state.txInTx[ch]);
txAudio.gain(ch, vol);
}
}
void UBitxDSP::startTxInput(int ch) {
if ((ch > -1) && (ch < txNumChannels)) {
state.txInTx[ch] = 1;
float vol = state.txInLvl[ch] * float(state.txInEnable[ch] * state.txInTx[ch]);
txAudio.gain(ch, vol);
}
}
void UBitxDSP::stopTxInput(int ch) {
if ((ch > -1) && (ch < txNumChannels)) {
state.txInTx[ch] = 0;
float vol = state.txInLvl[ch] * float(state.txInEnable[ch] * state.txInTx[ch]);
txAudio.gain(ch, vol);
}
}
/*
NOTES