9 Commits

Author SHA1 Message Date
295b99ef36 making sure any outstanding updates are committed 2025-02-15 09:48:00 -06:00
Rob French
e6009989db Reorganizing DSP and TR. Thoroughly broken ATM, just committing for backup. 2021-03-30 12:31:44 -05:00
Rob French
1f3585d8e4 Various changes. Compiles. Hasn't been tested. 2021-03-19 15:30:30 -05:00
Rob French
c8aecdfb0d Further updates to DSP, and significant changes to TS590. Implementing templated CAT commands using the delegate template from the ETL. Compiles, but not tested. 2021-03-16 23:11:17 -05:00
Rob French
f724142fca Updated DSP. Compiles, no warnings/errors. Going to do some work on CAT. 2021-03-16 18:37:14 -05:00
Rob French
869e47d430 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. 2021-03-14 23:18:24 -05:00
Rob French
20b475dace Updates to the DSP. One issue that needs to be resolved: in order to use the VOX the way it is currently setup, muting of the overall TX chain needs to be at the END, not the beginning; whatever is setup as the default TX audio source, needs to be unmuted even during RX. 2021-03-04 23:12:41 -06:00
Rob French
962a3ce80f Revert "Updated with some of the changes I made on travel. Will probably break everything..."
This reverts commit 86ae1ddb2f.
2021-03-04 07:16:14 -06:00
Rob French
86ae1ddb2f Updated with some of the changes I made on travel. Will probably break everything... 2021-03-03 10:44:25 -06:00
13 changed files with 900 additions and 370 deletions

View File

@@ -1 +0,0 @@
../TeensyDSP/Debug.h

0
Raduino/Debug.h Executable file
View File

View File

@@ -1 +0,0 @@
../TeensyDSP/RigState.cpp

0
Raduino/RigState.cpp Executable file
View File

View File

@@ -1 +0,0 @@
../TeensyDSP/RigState.h

0
Raduino/RigState.h Executable file
View File

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

Binary file not shown.

Binary file not shown.

View File

@@ -10,209 +10,344 @@
//#include <SD.h>
//#include <SerialFlash.h>
#define RX_AUDIO_CH 0
const int txMicInChannel = TX_MIC_IN_CH;
const int txLineInChannel = TX_LINE_IN_CH;
const int txUSBInChannel = TX_USB_IN_CH;
const int txNumChannels = TX_NUM_CHANNELS;
const int txLineInVOX = TX_LINE_IN_VOX;
const int txUSBInLVOX = TX_USB_IN_L_VOX;
const int txUSBInRVOX = TX_USB_IN_R_VOX;
const int txNumVOX = TX_NUM_VOX;
UBitxDSP DSP;
//static struct {
// GUItool: begin automatically generated code
AudioInputUSB usbIn; //xy=153,341
AudioInputI2S lineIn; //xy=161,233
AudioAnalyzeRMS usbInRMS_R; //xy=276,431
AudioAnalyzeRMS usbInRMS_L; //xy=335,392
AudioAnalyzeRMS lineInRMS; //xy=387,273
AudioMixer4 rxAudio; //xy=418,147
AudioMixer4 txAudio; //xy=422,335
AudioFilterFIR rxFilter; //xy=583,139
AudioAmplifier usbOutAmp; //xy=748,135
AudioAmplifier lineOutAmp; //xy=749,198
AudioAmplifier usbBypassAmp; //xy=756,261
AudioOutputI2S lineOut; //xy=966,330
AudioOutputUSB usbOut; //xy=968,291
AudioInputUSB usbIn; //xy=63,305
AudioInputI2S lineIn; //xy=71,197
AudioSynthWaveformSine tone1; //xy=111,369
AudioSynthWaveformSine tone2; //xy=111,410
AudioMixer4 rxAudio; //xy=328,111
AudioMixer4 txAudio; //xy=332,299
AudioAnalyzeRMS txVoxLevel; //xy=490,340
AudioFilterFIR rxFilter; //xy=493,103
AudioAmplifier usbOutAmp; //xy=658,99
AudioAmplifier lineOutAmp; //xy=659,162
AudioAmplifier usbBypassAmp; //xy=666,225
AudioAmplifier txOutAmp; //xy=713,301
AudioOutputI2S lineOut; //xy=876,294
AudioOutputUSB usbOut; //xy=878,255
AudioConnection patchCord1(usbIn, 0, txAudio, 1);
AudioConnection patchCord2(usbIn, 0, usbInRMS_L, 0);
AudioConnection patchCord3(usbIn, 1, usbInRMS_R, 0);
AudioConnection patchCord4(lineIn, 0, rxAudio, 0);
AudioConnection patchCord5(lineIn, 1, txAudio, 0);
AudioConnection patchCord6(lineIn, 1, lineInRMS, 0);
AudioConnection patchCord7(rxAudio, rxFilter);
AudioConnection patchCord8(rxAudio, usbBypassAmp);
AudioConnection patchCord9(txAudio, 0, lineOut, 1);
AudioConnection patchCord10(rxFilter, usbOutAmp);
AudioConnection patchCord11(rxFilter, lineOutAmp);
AudioConnection patchCord12(usbOutAmp, 0, usbOut, 0);
AudioConnection patchCord13(lineOutAmp, 0, lineOut, 0);
AudioConnection patchCord14(usbBypassAmp, 0, usbOut, 1);
AudioControlSGTL5000 audioCtrl; //xy=427,476
AudioConnection patchCord2(lineIn, 0, rxAudio, 0);
AudioConnection patchCord3(lineIn, 1, txAudio, 0);
AudioConnection patchCord4(tone1, 0, txAudio, 2);
AudioConnection patchCord5(tone1, 0, rxAudio, 2);
AudioConnection patchCord6(tone2, 0, txAudio, 3);
AudioConnection patchCord7(tone2, 0, rxAudio, 3);
AudioConnection patchCord8(rxAudio, rxFilter);
AudioConnection patchCord9(rxAudio, usbBypassAmp);
AudioConnection patchCord10(txAudio, txVoxLevel);
AudioConnection patchCord11(txAudio, txOutAmp);
AudioConnection patchCord12(rxFilter, usbOutAmp);
AudioConnection patchCord13(rxFilter, lineOutAmp);
AudioConnection patchCord14(usbOutAmp, 0, usbOut, 0);
AudioConnection patchCord15(lineOutAmp, 0, lineOut, 0);
AudioConnection patchCord16(usbBypassAmp, 0, usbOut, 1);
AudioConnection patchCord17(txOutAmp, 0, lineOut, 1);
AudioControlSGTL5000 audioCtrl; //xy=337,440
// GUItool: end automatically generated code
//} audio;
UBitxDSP::UBitxDSP() {
voxRMS[txLineInVOX] = &lineInRMS;
voxRMS[txUSBInLVOX] = &usbInRMS_L;
voxRMS[txUSBInRVOX] = &usbInRMS_R;
}
void UBitxDSP::begin() {
AudioMemory(16);
// Basic audio setup
AudioMemory(16); // TODO: optimize this
audioCtrl.enable();
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)
setupRxAudio();
setupTxAudio();
// Default to RX.
muteRxIn(); // redundant?
muteTxIn(); // redundant?
isTx = true; // so that rx() call works
rx();
// Setup the VOX - clean this up
state.voxActive[TX_LINE_IN_VOX] = false;
state.voxThresh[TX_LINE_IN_VOX] = TX_LINE_IN_VOX_THRESH;
state.voxDelay[TX_LINE_IN_VOX] = TX_LINE_IN_VOX_DELAY;
state.voxTimeout[TX_LINE_IN_VOX] = 0;
state.voxActive[TX_USB_IN_L_VOX] = false;
state.voxThresh[TX_USB_IN_L_VOX] = TX_USB_IN_L_VOX_THRESH;
state.voxDelay[TX_USB_IN_L_VOX] = TX_USB_IN_L_VOX_DELAY;
state.voxTimeout[TX_USB_IN_L_VOX] = 0;
state.voxActive[TX_USB_IN_R_VOX] = false;
state.voxThresh[TX_USB_IN_R_VOX] = TX_USB_IN_R_VOX_THRESH;
state.voxDelay[TX_USB_IN_R_VOX] = TX_USB_IN_R_VOX_DELAY;
state.voxTimeout[TX_USB_IN_R_VOX] = 0;
// Setup the VOX - TBD
// Setup the RX Filter.
setRxFilter(300, 3000);
setRxFilter(300.0, 3000.0);
sinceLastUpdate = 0;
}
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();
setTxInputLevel(txUSBInChannel, 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.
for (int i = 0; i < txNumVOX; i++) {
if (voxRMS[i]->available()) {
float lvl = voxRMS[i]->read();
if (lvl > state.voxThresh[i]) {
state.voxTimeout[i] = millis() + state.voxDelay[i];
state.voxActive[i] = true;
}
}
if (millis() > state.voxTimeout[i]) {
state.voxActive[i] = false;
}
}
}
void UBitxDSP::end() {
bypassRxFilter();
}
/**********************************************************************
* Transmit/Receive switching
**********************************************************************/
/*!
* Return 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() {
// mute all tx audio
audioCtrl.micGain(0);
for (int i = 0; i < 4; i++) {
if (isTx) {
muteTxOut();
if (txSrcLatched != txSrc) {
setTxAudioIn(txSrc);
}
if (txSrcLatched == MIC_IN) {
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
}
unmuteRxIn(RX_AUDIO);
isTx = false;
}
}
/*!
* Enter transmit (TX) mode from receive (RX) mode.
*/
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(micGain);
}
unmuteTxOut();
isTx = true;
}
}
/**********************************************************************
* General audio setup -- called via begin()
**********************************************************************/
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)
setLineOutLevel(1.0);
// USB Output (RX)
setUSBOutLevel(1.0);
}
void UBitxDSP::setupTxAudio() {
for (int i = 0; i < NUM_TX_AUDIO_CH; i++) {
txAudio.gain(i, 0.0);
}
// select line in for rx
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
// restore rx audio
rxAudio.gain(RX_AUDIO_CH, 1.0); // restore the RX audio
// 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::txMicIn() {
// mute the rx audio
rxAudio.gain(RX_AUDIO_CH, 0.0);
// restore the tx mic audio
audioCtrl.inputSelect(AUDIO_INPUT_MIC);
audioCtrl.micGain(12);
for (int i = 0; i < 4; i++) {
if (i == TX_MIC_IN_CH)
txAudio.gain(i, 0.1);
else
txAudio.gain(i, 0.0);
/**********************************************************************
* Receive audio chain
**********************************************************************/
void UBitxDSP::setRxInLevel(RxAudioCh ch, float level) {
if (ch < NUM_RX_AUDIO_CH) {
state.rxIn[ch].level = level;
rxAudio.gain(ch, state.rxIn[ch].mute ? 0.0 : state.rxIn[ch].level);
}
}
void UBitxDSP::txLineIn() {
// mute the rx audio
rxAudio.gain(RX_AUDIO_CH, 0.0);
// restore the tx line in audio
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
for (int i = 0; i < 4; i++) {
if (i == TX_LINE_IN_CH)
txAudio.gain(i, 0.1);
else
txAudio.gain(i, 0.0);
void UBitxDSP::muteRxIn() {
for (int i = 0; i < NUM_RX_AUDIO_CH; i++) {
state.rxIn[RxAudioCh(i)].mute = true;
rxAudio.gain(i, 0.0);
}
}
void UBitxDSP::txUSBIn() {
// mute the rx audio
rxAudio.gain(RX_AUDIO_CH, 0.0);
// restore the tx usb in audio
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
for (int i = 0; i < 4; i++) {
if (i == TX_USB_IN_CH)
txAudio.gain(i, 0.1);
else
txAudio.gain(i, 0.0);
void UBitxDSP::muteRxIn(RxAudioCh ch) {
if (ch < NUM_RX_AUDIO_CH) {
if (!state.rxIn[ch].mute) {
state.rxIn[ch].mute = true;
rxAudio.gain(ch, 0.0);
}
}
}
/**********************************************************************/
// RX filter settings
void UBitxDSP::unmuteRxIn(RxAudioCh ch) {
if (ch < NUM_RX_AUDIO_CH) {
if (state.rxIn[ch].mute) {
state.rxIn[ch].mute = false;
rxAudio.gain(ch, state.rxIn[ch].level);
}
}
}
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);
}
/**********************************************************************
* Transmit audio chain
**********************************************************************/
void UBitxDSP::setTxInLevel(TxAudioCh ch, float level) {
if (ch < NUM_TX_AUDIO_CH) {
state.txIn[ch].level = level;
txAudio.gain(ch, state.txIn[ch].mute ? 0.0 : state.txIn[ch].level);
}
}
void UBitxDSP::muteTxIn() {
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.txIn[ch].mute) {
state.txIn[ch].mute = true;
txAudio.gain(ch, 0.0);
}
}
}
void UBitxDSP::unmuteTxIn(TxAudioCh ch) {
if (ch < NUM_TX_AUDIO_CH) {
if (state.txIn[ch].mute) {
state.txIn[ch].mute = false;
rxAudio.gain(ch, state.txIn[ch].level);
}
}
}
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::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::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
break;
}
}
}
/**********************************************************************
* Receive audio filter (band pass)
**********************************************************************/
const int minRxFilterLo = MIN_RX_FILTER_LO;
const int maxRxFilterHi = MAX_RX_FILTER_HI;
@@ -229,10 +364,10 @@ void UBitxDSP::bypassRxFilter() {
}
/*!
* @brief Update the RX audio filter using the currently set low and
* high frequencies. This is called by each of the public
* filter methods to update the filter with new frequencies.
*/
@brief Update the RX audio filter using the currently set low and
high frequencies. This is called by each of the public
filter methods to update the filter with new frequencies.
*/
void UBitxDSP::updateRxFilter() {
audioFilter(coefficients, NUM_COEFFICIENTS, ID_BANDPASS, W_HAMMING, double(state.rxFilterLo), double(state.rxFilterHi));
rxFilter.begin(coefficients, NUM_COEFFICIENTS);
@@ -247,7 +382,7 @@ void UBitxDSP::setRxFilter(int lo, int hi) {
}
if (lo > hi - minRxFilterWidth) {
lo = hi - minRxFilterWidth;
}
}
if (lo < minRxFilterLo) {
lo = minRxFilterLo;
}
@@ -302,58 +437,43 @@ void UBitxDSP::setRxFilterCenter(int center) {
setRxFilter(lo, hi);
}
/**********************************************************************
* Transmit Voice-Operated-Switch (VOX)
**********************************************************************/
/**********************************************************************/
// 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);
float UBitxDSP::getVoxLevel() const {
if (return txVoxLevel.available()) {
prevVox = txVoxLevel.read();
}
return prevVox;
}
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);
}
}
/**********************************************************************
* Singleton - the DSP instance
**********************************************************************/
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);
}
}
// TODO: Fix this. This won't work... this compilation unit won't be
// able to instantiate a class it doesn't know about.
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);
}
}
#ifndef UBITXDSP_CLASS
#define UBITXDSP_CLASS UBitxDSP
#endif
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);
}
}
UBITXDSP_CLASS theDSP;
UBitxDSP& DSP = theDSP;
// VOX settings
bool UBitxDSP::isVoxActive(int vox) {
if ((vox > -1) && (vox < 3)) {
return state.voxActive[vox];
} else {
return false;
}
}
/*
NOTES
Major functions:
- tx() - start transmitting / pause receiving
- rx() - stop transmitting / resume receiving
- setTxSource() - set the TX audio source to MIC_IN, LINE_IN, or USB_IN
- also sets the relevant VOX source/parameters (as applicable)
Receive audio chain:
-
*/
//======================================================================
// EOF

View File

@@ -9,134 +9,272 @@
#include <dynamicFilters.h>
#include "Debug.h"
#define MIN_RX_FILTER_LO 0
#define MAX_RX_FILTER_HI 5000
#define MIN_RX_FILTER_WIDTH 0
#define MAX_RX_FILTER_WIDTH 5000
#define MIN_RX_FILTER_CENTER 0
#define MAX_RX_FILTER_CENTER 5000
/**********************************************************************
* Macros
**********************************************************************/
#define DSP_MILLIS_PER_UPDATE 100
#define MIN_RX_FILTER_LO (0.0) //! Min allowable value of the RX filter low-cut frequency
#define MAX_RX_FILTER_HI (5000.0) //! Max allowable value of the RX filter hi-cut frequency
#define MIN_RX_FILTER_WIDTH (0.0) //! Min allowable value of the RX filter bandwidth
#define MAX_RX_FILTER_WIDTH (5000.0) //! Max allowable value of the RX filter bandwidth
#define MIN_RX_FILTER_CENTER (0.0) //! Min allowable value of the RX filter center frequency
#define MAX_RX_FILTER_CENTER (5000.0) //! Max allowable value of the RX filter center frequency
#define TX_MIC_IN_CH 0
#define TX_LINE_IN_CH 0
#define TX_USB_IN_CH 1
#define TX_NUM_CHANNELS 2
#define DSP_MILLIS_PER_UPDATE (100) //! Number of milliseconds between update of the DSP object
#define TX_LINE_IN_VOX 0
#define TX_USB_IN_L_VOX 1
#define TX_USB_IN_R_VOX 2
#define TX_NUM_VOX 3
#define TX_VOX_MIC_THRESH (0.0) //! Threshold for mic VOX (not implemented, since mic requires special handling)
#define TX_VOX_LINE_THRESH (0.25) //! Threshold for line in VOX
#define TX_VOX_USB_THRESH (0.25) //! Threshold for USB VOX
#define TX_VOX_TUNE_THRESH (0.0) //! Threshold for tune (single tone) VOX (not expected to be used)
#define TX_VOX_TT_THRESH (0.0) //! Threshold for two-tone VOX (not expected to be used)
#define TX_VOX_DELAY (500) //! VOX delay in milliseconds
#define TX_LINE_IN_VOX_THRESH 0.25
#define TX_USB_IN_L_VOX_THRESH 0.25
#define TX_USB_IN_R_VOX_THRESH 0.25
/**********************************************************************
* Enumerations
**********************************************************************/
#define TX_LINE_IN_VOX_DELAY 500
#define TX_USB_IN_L_VOX_DELAY 500
#define TX_USB_IN_R_VOX_DELAY 500
//! Defines the four separate RX audio input channels available.
enum RxAudioCh {
RX_AUDIO = 0, // Normal receiver audio input channel
RX_SPARE, // Not used
RX_TONE1 , // Optional tone #1 input channel (currently not used)
RX_TONE2, // Optional tone #2 input channel (currently not used)
NUM_RX_AUDIO_CH // Total number of channels
};
//! Defines the different RX audio inputs (not channels).
enum RxAudioIn {
RIG_IN = 0, // Normal rig input (receiver audio)
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
TX_USB, // USB audio input channel
TX_TONE1, // Audio tone #1 input channel
TX_TONE2, // Audio tone #2 input channel
NUM_TX_AUDIO_CH // Toal number of channels
};
//! Defines the different TX audio input sources (not channels!).
enum TxAudioIn {
MIC_IN = 0, // Microphone transmit audio input
LINE_IN, // Line ("AUX") transmit audio input
USB_IN, // USB transmit audio input
TUNE_IN, // Tune input (transmits a single tone)
TWO_TONE_IN, // Two tone audio input (transmits two tones)
NUM_TX_AUDIO_IN // Total number of inputs
};
/**********************************************************************
* Classes
**********************************************************************/
//! Defines parameters for a simple audio channel that can be muted.
struct AudioChannel {
bool mute = false;
float level = 0.0;
};
/*!
* Contains the current 'persistent' state of the DSP.
* This includes all audio-specific state that can be saved to, or
* restored from, EEPROM. It does not include 'transient' state (such
* as whether we're currently transmitting or receiving).
*/
struct DSPState {
// RX audio output settings
//! Receiver audio inputs; all default to muted.
AudioChannel rxIn[NUM_RX_AUDIO_CH] = {
{true, 1.0}, // audio
{true, 0.0}, // spare 1
{true, 0.0}, // spare 2
{true, 0.0} // spare 3
};
// RX filter settings
int rxFilterLo = 300;
int rxFilterHi = 3000;
//! Receiver audio output; defaults to un
muted.
AudioChannel rxOut[NUM_RX_AUDIO_OUT] = {
{false, 1.0}, // line
{false, 1.0} // USB
};
// TX audio input settings
float txInLvl[4] = {0.5, 0.5, 0.0, 0.0};
int txInEnable[4] = {1, 1, 0, 0};
int txInTx[4] = {0, 0, 0, 0};
//! Transmitter audio inputs; all default to muted.
AudioChannel txIn[NUM_TX_AUDIO_CH] = {
{true, 0.1}, // line
{true, 0.1}, // USB
{true, 0.1}, // tone 1
{true, 0.1} // tone 2
};
// VOX settings
bool voxActive[3];
float voxThresh[3];
unsigned voxDelay[3];
unsigned voxTimeout[3];
};
enum TRState {
TRANSMIT,
RECEIVE
};
enum RxAudioIn {
RIG_AUDIO
};
enum TxAudioIn {
MIC_IN,
LINE_IN,
USB_IN
//! Tranmitter audio output; defaults to muted.
AudioChannel txOut = {true, 1.0};
//! Current RX filter settings
float rxFilterLo = 300.0;
float rxFilterHi = 3000.0;
};
/*!
* Defines the DSP subsystem of the UBitx V5X.
* The DSP subsystem, which relies on the Teensy Audio Library, is
* responsible for setting up the audio inputs and outputs for both
* receive (RX) and transmit (TX) audio, maintaining the correct path
* between inputs and outputs based on current TX/RX state, and setting
* up audio filters and other audio-based modules for the RX and TX
* audio paths.
*/
class UBitxDSP {
public:
UBitxDSP();
/********************************************************************
* Object creation/deletion
********************************************************************/
public:
UBitxDSP() {}
/********************************************************************
* Basic administration
********************************************************************/
public:
void begin();
void update();
void end();
void end();
/********************************************************************
* Transmit/Receive switching
********************************************************************/
public:
void rx();
void txMicIn();
void txLineIn();
void txUSBIn();
inline void tx() { tx(txSrc); }
void tx(TxAudioIn src);
// RX audio output settings
/********************************************************************
* General audio setup -- called via begin()
********************************************************************/
// RX filter settings
protected:
virtual void setupRxAudio();
virtual void setupTxAudio();
/********************************************************************
* Receive audio chain
********************************************************************/
// 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 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).
/********************************************************************
* Transmit audio chain
********************************************************************/
// Basic control of TX audio inputs and outputs.
public:
void setTxInLevel(TxAudioCh ch, float level); // Set the audio input level for a given channel.
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).
// 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.
inline TxAudioIn getTxAudioIn() const { return txSrc; } // Return the current TX audio input.
// Mic input controls.
public:
inline void setMicGain(float level) { micGain = static_cast<unsigned>(level * 63.0); } // Set the mic gain.
/********************************************************************
* Receive audio filter (band pass)
********************************************************************/
public:
void bypassRxFilter();
void setRxFilter(int lo, int hi);
void setRxFilterLo(int lo);
void setRxFilterHi(int hi);
void setRxFilterWidth(int width);
void setRxFilterCenter(int center);
/*!
* @brief Get the current low frequency bound of the RX band pass filter.
* @return The low frequency bound.
*/
inline int getRxFilterLo() { return state.rxFilterLo; }
/*!
* @brief Get the current high frequency bound of the RX band pass filter.
* @return The high frequency bound.
*/
inline int getRxFilterHi() { return state.rxFilterHi; }
/*!
* @brief Get the current width of the RX band pass filter.
* @return The filter width.
*/
inline int getRxFilterWidth() { return state.rxFilterHi - state.rxFilterLo; }
/*!
* @brief Get the current center frequency of the RX band pass filter.
* @return The center frequency.
*/
inline int getRxFilterCenter() { return (state.rxFilterHi + state.rxFilterLo) / 2; }
// TX audio input settings
void setTxInputLevel(int ch, float lvl);
void enableTxInput(int ch);
void disableTxInput(int ch);
void startTxInput(int ch);
void stopTxInput(int ch);
// VOX settings
bool isVoxActive(int vox);
private:
void updateRxFilter();
DSPState state;
short coefficients[NUM_COEFFICIENTS];
elapsedMillis sinceLastUpdate;
void setRxFilter(float lo, float hi);
void setRxFilterLo(float lo);
void setRxFilterHi(float hi);
void setRxFilterWidth(float width);
void setRxFilterCenter(float center);
AudioAnalyzeRMS* voxRMS[3];
/*!
* Get the current low frequency bound of the RX band pass filter.
* @return The low frequency bound.
*/
inline float getRxFilterLo() const { return state.rxFilterLo; }
/*!
* Get the current high frequency bound of the RX band pass filter.
* @return The high frequency bound.
*/
inline float getRxFilterHi() const { return state.rxFilterHi; }
/*!
* Get the current width of the RX band pass filter.
* @return The filter width.
*/
inline float getRxFilterWidth() const { return state.rxFilterHi - state.rxFilterLo; }
/*!
* Get the current center frequency of the RX band pass filter.
* @return The center frequency.
*/
inline float getRxFilterCenter() const { return (state.rxFilterHi + state.rxFilterLo) / 2.0; }
/********************************************************************
* Transmit Voice-Operated-Switch (VOX)
********************************************************************/
public:
float getVoxLevel() const;
/********************************************************************
* Private state
********************************************************************/
private:
DSPState state;
bool isTx = false;
TxAudioIn txSrc = MIC_IN;
TxAudioIn txSrcLatched = MIC_IN;
short coefficients[NUM_COEFFICIENTS] = {0};
elapsedMillis sinceLastUpdate = 0;
float usbVol = 0.0;
unsigned micGain = 0;
float prevVox = 0.0;
};
extern UBitxDSP DSP;
extern UBitxDSP& DSP;
#endif

View File

@@ -3,6 +3,9 @@
#include "RigState.h"
struct RigState {
};
class UBitxRig {
public:
inline void begin() {}
@@ -41,6 +44,7 @@ class UBitxRig {
inline void setUSB() { catState.setUSB(); }
inline void setLSB() { catState.setLSB(); }
inline void setAI(bool on) { autoInfo = on; }
inline void aiOn() { autoInfo = true; }
inline void aiOff() { autoInfo = false; }
@@ -61,7 +65,7 @@ class UBitxRig {
private:
UBitxRigState catState;
UBitxRigState radState;
bool autoInfo = false;
bool autoInfo = false; // TODO: Move this to rig state struct
};
extern UBitxRig Rig;

View File

@@ -8,7 +8,7 @@
UBitxTR TR(DSP);
void UBitxTR::update(bool cw, bool extKey) {
updateKey();
updateLinePTT();
if (cw) {
if ((keyEnable && keyDown) || extKey) {
@@ -19,33 +19,35 @@ void UBitxTR::update(bool cw, bool extKey) {
return;
}
updatePTT();
updateVOX();
updateMicPTT();
updateMicVOX();
updateDataVOX();
if (isTX) {
// If we are currently transmitting, then ANY T/R release (key
// release) will result in exitting transmit... except for VOX
// release) will result in exiting transmit... except for VOX
// and CAT which can only function as a release if it was enabled.
if (pttReleased() || keyReleased() ||
(voxEnable && voxDeactivated()) ||
(catEnable && catDeactivated())) {
if (micPTTReleased() || linePTTReleased() ||
(micVOXEnabled() && micVOXDeactivated()) ||
(catEnabled() && catDeactivated()) ||
(dataVOXEnabled() && dataVOXDeactivated())) {
// first, stop transmitting; then, setup RX audio
DBGCMD( setRX() );
DBGCMD( dsp.rx() );
}
} else {
if ((pttEnable && pttPressed()) || (voxEnable && voxActivated())) {
if ((micPTTEnabled() && micPTTPressed()) || (micVOXEnabled() && micVOXActivated())) {
// first, setup TX audio; then, start transmitting (from Mic)
DBGCMD( dsp.txMicIn() );
DBGCMD( setTX() );
} else if (keyEnable && keyPressed()) {
DBGCMD( dsp.tx(MIC_IN) );
DBGCMD( setTX() );
} else if ((linePTTEnabled() && linePTTPressed())) {
// first, setup TX audio; then, start transmitting (from Line In)
DBGCMD( dsp.txLineIn() );
DBGCMD( setTX() );
DBGCMD( dsp.tx(LINE_IN) );
DBGCMD( setTX() );
} else if (catEnable && catActivated()) {
// first, setup TX audio; then, start transmitting (USB)
DBGCMD( dsp.txUSBIn() );
DBGCMD( setTX() );
DBGCMD( dsp.tx(USB_IN) );
DBGCMD( setTX() );
}
}
}

View File

@@ -32,34 +32,40 @@ class UBitxTR {
ptt.interval(5);
// default configuration: PTT, key, and CAT enabled; VOX disabled
DBGCMD( enablePTT() );
DBGCMD( disableVOX() );
DBGCMD( enableKey() );
DBGCMD( enableMicPTT() );
DBGCMD( disableMicVOX() );
DBGCMD( enableLinePTT() );
DBGCMD( enableCAT() );
DBGCMD( setRX() );
}
inline void enablePTT() { pttEnable = true; }
inline void enableVOX() { voxEnable = true; }
inline void enableKey() { keyEnable = true; }
inline void enableMicPTT() { pttEnable = true; }
inline void enableLinePTT() { keyEnable = true; }
inline void enableMicVOX() { voxEnable = true; }
inline void enableDataVOX() { dvoxEnable = true; }
inline void enableCAT() { catEnable = true; }
inline void disablePTT() { pttEnable = false; }
inline void disableVOX() { voxEnable = false; }
inline void disableKey() { keyEnable = false; }
inline void disableMicPTT() { pttEnable = false; }
inline void disableLinePTT() { keyEnable = false; }
inline void disableMicVOX() { voxEnable = false; }
inline void disableDataVOX() { dvoxEnable = false; }
inline void disableCAT() { catEnable = false; }
inline bool pttEnabled() { return pttEnable; }
inline bool voxEnabled() { return voxEnable; }
inline bool keyEnabled() { return keyEnable; }
inline bool catEnabled() { return catEnable; }
inline bool micPTTEnabled() const { return pttEnable; }
inline bool linePTTEnabled() const { return keyEnable; }
inline bool micVOXEnabled() const { return voxEnable; }
inline bool dataVOXEnabled() const { return dvoxEnable; }
inline bool catEnabled() const { return catEnable; }
inline bool pttPressed() { return ptt.fell(); }
inline bool pttReleased() { return ptt.rose(); }
inline bool voxActivated() { return (L_voxActive != voxActive) && L_voxActive; }
inline bool voxDeactivated() { return (L_voxActive != voxActive) && voxActive; }
inline bool keyPressed() { return (L_keyDown != keyDown) && L_keyDown; }
inline bool keyReleased() { return (L_keyDown != keyDown) && keyDown; }
inline bool micPTTPressed() { return ptt.fell(); }
inline bool micPTTReleased() { return ptt.rose(); }
inline bool linePTTPressed() { return (L_keyDown != keyDown) && L_keyDown; }
inline bool linePTTReleased() { return (L_keyDown != keyDown) && keyDown; }
inline bool micVOXActivated() { return (L_voxActive != voxActive) && L_voxActive; }
inline bool micVOXDeactivated() { return (L_voxActive != voxActive) && voxActive; }
inline bool dataVOXActivated() { return (L_dvoxActive != dvoxActive) && L_dvoxActive; }
inline bool dataVOXDeactivated() { return (L_dvoxActive != dvoxActive) && dvoxActive; }
inline bool catActivated() { return (L_catActive != catActive) && L_catActive; }
inline bool catDeactivated() { return (L_catActive != catActive) && catActive; }
@@ -109,42 +115,58 @@ class UBitxTR {
digitalWrite(outPin, HIGH);
}
inline void updatePTT() {
inline void updateMicPTT() {
ptt.update();
}
inline void updateVOX() {
inline void updateLinePTT() {
L_keyDown = keyDown;
keyDown = (digitalRead(keyPin) == LOW);
}
inline void updateMicVOX() {
L_voxActive = voxActive;
voxActive = (digitalRead(voxPin) == LOW);
}
inline void updateKey() {
L_keyDown = keyDown;
keyDown = (digitalRead(keyPin) == LOW);
inline void updateDataVOX() {
L_dvoxActive = dvoxActive;
if (dsp.getVoxLevel() > dvoxThreshold) {
dvoxActive = true;
dvoxElapsed = 0;
} else if (dvoxActive && (dvoxElapsed > dvoxDelay)) {
dvoxActive = false;
}
}
UBitxDSP& dsp;
Bounce ptt;
int outPin;
int pttPin;
int voxPin;
int keyPin;
int outPin;
bool isTX = false;
bool pttEnable = false;
bool voxEnable = false;
bool dvoxEnable = false;
bool keyEnable = false;
bool catEnable = false;
bool voxActive = false;
bool L_voxActive = false;
bool dvoxActive = false;
bool L_dvoxActive = false;
bool keyDown = false;
bool L_keyDown = false;
bool catActive = false;
bool L_catActive = false;
elapsedMillis dvoxElapsed = 0;
unsigned dvoxDelay = 250; // TODO: make dynamic
};
extern UBitxTR TR;

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,39 @@ TS590Error TS590Command::theError = NoError;
/**********************************************************************/
void TS590Command_Bool::handleCommand(const char* cmd) {
setter(cmd[length()] == '0' ? false : true);
}
void TS590Command_Bool::sendResponse(const char* cmd) {
ts590SendCommand("%s%s", prefix(), getter() ? "1" : "0");
}
/**********************************************************************/
void TS590Command_UL::handleCommand(const char* cmd) {
unsigned val = static_cast<unsigned>(strtoul(&cmd[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]) {
@@ -319,6 +349,79 @@ void TS590_SL::sendResponse(const char* cmd) {
/**********************************************************************/
void TS590_VX::handleCommand(const char* cmd) {
}
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 setAI = [](unsigned v) -> void { v == 0 ? Rig.aiOff() : Rig.aiOn(); };
GetUL getAI = []() -> unsigned { return Rig.isAI() ? 4 : 0; };
//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);
TS590Command_UL TS590_AI("AI", 1, 0, 4, setAI, getAI);
// TS590_AS
// TS590_BD
// TS590_BU
// TS590_CA
// TS590_CD0
// TS590_CD1
// TS590_CD2
// TS590_CH
#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;
@@ -340,7 +443,6 @@ int numCatCommands = sizeof(catCommands) / sizeof(catCommands[0]);
/**********************************************************************/
void UBitxTS590::begin() {
Serial.begin(9600); // USB is always 12 Mbit/sec
#ifdef DEBUG
@@ -381,7 +483,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,68 @@ class TS590Command {
/**********************************************************************/
typedef etl::delegate<void(bool)> SetBool;
typedef etl::delegate<bool(void)> GetBool;
class TS590Command_Bool : public TS590Command {
public:
TS590Command_Bool(const char* prefix, SetBool set, GetBool get)
: TS590Command(prefix), setter(set), getter(get) {}
virtual void handleCommand(const char* cmd);
virtual void sendResponse(const char* cmd);
private:
SetBool setter;
GetBool getter;
};
/**********************************************************************/
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;
};
/**********************************************************************/
/*
typedef etl::delegate<void(bool)> SetULArray;
typedef etl::delegate<bool(void)> GetULArray;
class TS590Command_ULArray : public TS590Command {
public:
TS590Command_ULArray(const char* prefix, SetUL set, GetUL get)
: TS590Command(prefix), setter(set), getter(get) {}
virtual void handleCommand(const char* cmd);
virtual void sendResponse(const char* cmd);
private:
SetUL setter;
GetUL getter;
};
*/
/**********************************************************************/
/*!
* @brief CAT command for setting or reading the VFO A/B frequency.
*/
@@ -192,6 +325,18 @@ class TS590_SL : public TS590Command {
unsigned index;
};
/*!
* CAT command for enabling or disabling the mic VOX.
*/
class TS590_VX : public TS590Command {
public:
TS590_VX(): TS590Command("VX") {}
virtual void handleCommand(const char* cmd);
virtual void sendResponse(const char* cmd);
private:
unsigned index;
};
/**********************************************************************/
class UBitxTS590 {

View File

@@ -593,11 +593,11 @@ void loop()
Serial.println(AudioMemoryUsageMax());
Serial.println("----------------------------------------------------------------------");
Serial.print("Enabled/Active: PTT: ");
Serial.print(TR.pttEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.pttPressed() ? "Y" : "N");
Serial.print(TR.micPTTEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.micPTTPressed() ? "Y" : "N");
Serial.print(", VOX: ");
Serial.print(TR.voxEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.voxActivated() ? "Y" : "N");
Serial.print(TR.micVOXEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.micVOXActivated() ? "Y" : "N");
Serial.print(", Key: ");
Serial.print(TR.keyEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.keyPressed() ? "Y" : "N");
Serial.print(TR.linePTTEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.linePTTPressed() ? "Y" : "N");
Serial.print(", CAT: ");
Serial.print(TR.catEnabled() ? "Y" : "N"); Serial.print("/"); Serial.print(TR.catActivated() ? "Y" : "N");
Serial.println();