Working with Raduino! High pitched whine in RX audio. Goes away when

USB unplugged.  Not immediate, so not a ground loop... seems to be
associated with one of my mixers...
This commit is contained in:
Rob French 2020-05-08 00:19:07 -05:00
parent 4c2f6453f1
commit 57c97d9f98
4 changed files with 343 additions and 113 deletions

View File

@ -75,9 +75,10 @@ void audioInit()
//audioCtrl.dacVolumeRamp(); // if this seems too slow, might try dacVolumeRampLinear().
//audioCtrl.dacVolume(1.0, 0.0); // we're going to mute TX audio via the DAC unless we're transmitting
audioSelectRxInput(RX_RIG_IN);
audioSelectTxInput(TX_MIC_IN); // superfluous I think
audioCWFilterNarrow(); // test
audioCtrl.audioPreProcessorEnable();
}
inline void updateRxRigIn()
@ -105,6 +106,16 @@ inline void updateRxUSBIn()
}
}
inline void muteRxUSBIn()
{
mixRX.gain(RX_USB_IN, 0.0);
}
inline void restoreRxUSBIn()
{
updateRxUSBIn();
}
inline void updateRxSpkrOut()
{
calRxSpkr.gain(iopConfig.rxSpkrOutCal);
@ -183,11 +194,32 @@ inline void updateTxUSBOut()
}
}
void audioSelectRxInput(RxInput input)
{
if (audioRxInput != input) {
audioRxInput = input;
switch(input) {
case RX_RIG_IN:
muteRxUSBIn();
restoreRxRigIn();
break;
case RX_USB_IN:
muteRxRigIn();
restoreRxUSBIn();
break;
}
}
}
void audioSelectTxInput(TxInput input)
{
if (audioTxInput != input) {
audioTxInput = input;
switch(input) {
//muteTxMicIn(); // redundant w/ Line-In
muteTxLineIn();
muteTxUSBIn();
/* switch(input) {
case TX_MIC_IN:
muteTxUSBIn();
restoreTxMicIn();
@ -202,10 +234,12 @@ void audioSelectTxInput(TxInput input)
muteTxLineIn();
restoreTxUSBIn();
break;
}
}*/
}
}
//======================================================================
// audioTransmit()
// This should be called anytime transmit mode is entered. It should
// in theory be called BEFORE the actual transmit signal (key/PTT) is
@ -213,23 +247,17 @@ void audioSelectTxInput(TxInput input)
// transitions occur before transmission begins.
void audioTransmit()
{
if (rigMode == MODE_SSB || rigMode == MODE_DIGI) {
// First we're going to set the RX and TX audio DAC volumes to
// zero while we change other mixer settings, to try to use the
// DAC's volume ramping to minimize pops.
// NOTE: Might need to add a brief delay?
//audioCtrl.dacVolume(0.0, 0.0);
// Next mute the incoming RX audio. Can't think of a good reason
switch(rigMode) {
// Nothing special for CW, TX audio inputs are already muted.
//case MODE_CW:
//break;
case MODE_SSB:
// Mute the incoming RX audio. Can't think of a good reason
// to let RX audio in while we're transmitting.
muteRxRigIn();
if (audioTxInput == TX_MIC_IN) {
// Mute the TX line in in this case, too, because we need to
// switch over to the mic input.
muteTxLineIn();
// Now switch to the mic input, and set the mic gain.
audioCtrl.inputSelect(AUDIO_INPUT_MIC);
updateTxMicIn();
#if defined(FACTORY_CALIBRATION)
@ -247,14 +275,22 @@ void audioTransmit()
USBSERIAL.println(iopConfig.txRigOutCal);
USBSERIAL.println("==============================");
#endif
} else if (audioTxInput == TX_LINE_IN) {
updateTxLineIn();
}
break;
// Allow both transmit and receive audio output channels. This is safe
// because the RX input is muted, and we might want to inject something else.
//audioCtrl.dacVolume(1.0, 1.0);
case MODE_DIGI:
// Mute the incoming RX audio. Can't think of a good reason
// to let RX audio in while we're transmitting.
muteRxRigIn();
updateTxUSBIn();
break;
}
}
//======================================================================
// audioReceive()
// This should be called anytime receive mode is entered. It should
// in theory be called AFTER the actual transmit signal (key/PTT) is
@ -262,27 +298,24 @@ void audioTransmit()
// transitions occur before receive begins.
void audioReceive()
{
if (rigMode == MODE_SSB || rigMode == MODE_DIGI) {
// First we're going to set the RX and TX audio DAC volumes to
// zero while we switch inputs, because the DAC volumes can be
// smoothly ramped by the SGTL5000 to avoid pops.
//audioCtrl.dacVolume(0.0, 0.0);
// Mute the mic, since we're going to be switching back to line
// input for RX and TX.
switch(rigMode) {
//case MODE_CW:
//break;
case MODE_SSB:
if (audioTxInput == TX_MIC_IN) {
muteTxMicIn();
// Now switch to the line input, and restore mixer settings.
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
restoreTxLineIn();
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
} else if (audioTxInput == TX_LINE_IN) {
muteTxLineIn();
}
restoreRxRigIn();
break;
// Now bring back up the DAC volumes. Hopefully this reduced pops...
// When going back to receive, we leave transmit DAC at zero.
//audioCtrl.dacVolume(1.0, 0.0);
case MODE_DIGI:
muteTxUSBIn();
restoreRxRigIn();
break;
}
}
@ -540,15 +573,46 @@ void audioCalibrate(IOPConfig* c, char cmd, char subcmd, char parm, float value,
}
}
int updateFilter[5];
int lpFilter[5];
int hpFilter[5];
void audioCWFilterNarrow()
void audioSSBFilter()
{
audioCtrl.audioPreProcessorEnable();
// calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*);
calcBiquad(FILTER_BANDPASS, 700, 0, 2, 524288, 44100, updateFilter);
audioCtrl.eqFilter(0, updateFilter);
audioCtrl.eqFilter(1, updateFilter);
calcBiquad(FILTER_LOPASS, 3100, 0, 0.707, 524288, 44100, lpFilter);
calcBiquad(FILTER_HIPASS, 300, 0, 0.707, 524288, 44100, hpFilter);
audioCtrl.eqFilter(0, lpFilter);
audioCtrl.eqFilter(1, hpFilter);
audioCtrl.eqFilter(2, lpFilter);
audioCtrl.eqFilter(3, hpFilter);
audioCtrl.eqFilter(4, lpFilter);
audioCtrl.eqFilter(5, hpFilter);
}
void audioCWFilter()
{
// calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*);
calcBiquad(FILTER_LOPASS, 700, 0, 0.707, 524288, 44100, lpFilter);
calcBiquad(FILTER_HIPASS, 300, 0, 0.707, 524288, 44100, hpFilter);
audioCtrl.eqFilter(0, lpFilter);
audioCtrl.eqFilter(1, hpFilter);
audioCtrl.eqFilter(2, lpFilter);
audioCtrl.eqFilter(3, hpFilter);
audioCtrl.eqFilter(4, lpFilter);
audioCtrl.eqFilter(5, hpFilter);
}
void audioDigiFilter()
{
// calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*);
calcBiquad(FILTER_LOPASS, 3100, 0, 0.707, 524288, 44100, lpFilter);
calcBiquad(FILTER_HIPASS, 300, 0, 0.707, 524288, 44100, hpFilter);
audioCtrl.eqFilter(0, lpFilter);
audioCtrl.eqFilter(1, hpFilter);
audioCtrl.eqFilter(2, lpFilter);
audioCtrl.eqFilter(3, hpFilter);
audioCtrl.eqFilter(4, lpFilter);
audioCtrl.eqFilter(5, hpFilter);
}
//======================================================================

View File

@ -10,10 +10,12 @@
#define EEPROM_READ_PREFIX 0xE0
#define EEPROM_WRITE_PREFIX 0xF0
#define IOP_MODE_COMMAND 0x00
#define IOP_MODE_SSB 0x01
#define IOP_MODE_DIGI 0x02
#define IOP_MODE_CW 0x03
#define IOP_MODE_COMMAND 0x00
#define IOP_START_TX_COMMAND 0x01
#define IOP_STOP_TX_COMMAND 0x02
#define IOP_MODE_SSB 0x00
#define IOP_MODE_DIGI 0x01
#define IOP_MODE_CW 0x02
//======================================================================
// CAT from PC-to-IOP
@ -55,9 +57,31 @@ void processIOPCommand(const byte* buf, int len)
if (len < 2) {
return;
} else {
rigMode = RigMode(buf[1]);
setRigMode(RigMode(buf[1]));
#if defined(DEBUG)
USBSERIAL.print("DEBUG: mode ");
switch(rigMode) {
case MODE_CW:
USBSERIAL.println("CW");
break;
case MODE_SSB:
USBSERIAL.println("SSB");
break;
case MODE_DIGI:
USBSERIAL.println("DIGI");
break;
}
#endif
}
break;
case IOP_START_TX_COMMAND:
catPTTOn();
break;
case IOP_STOP_TX_COMMAND:
catPTTOff();
break;
}
}
}

View File

@ -19,6 +19,14 @@ enum RigMode {
MODE_CW = 2,
};
enum TxState {
TX_OFF = 0,
TX_MIC,
TX_LINE,
TX_CAT,
TX_KEYER,
};
extern RigMode rigMode;
#endif

View File

@ -17,59 +17,208 @@ IOPConfig iopConfig;
Bounce micPTT = Bounce();
Bounce linePTT = Bounce();
bool micPTT_active = false;
bool linePTT_active = false;
TxState txState = TX_OFF;
void checkPTT()
//======================================================================
// catPTTOn()
//
// NOTE: Should probably move this to cat.ino.
//======================================================================
void catPTTOn()
{
// Update the PTT lines. USB/DIGI is not part of this. CW should work, however.
micPTT.update();
linePTT.update();
if (rigMode == MODE_SSB || rigMode == MODE_CW) {
if (micPTT_active) {
// ignore line PTT; just wait for release of mic PTT
if (micPTT.rose()) {
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
audioReceive();
micPTT_active = false;
}
} else if (linePTT_active) {
// ignore mic PTT; just wait for release of line PTT
if (linePTT.rose()) {
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
audioReceive();
linePTT_active = false;
}
} else {
// Whichever PTT source was last active, will determine the TX audio source.
if (micPTT.fell()) {
audioSelectTxInput(TX_MIC_IN);
micPTT_active = true;
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
} else if (linePTT.fell()) {
audioSelectTxInput(TX_LINE_IN);
linePTT_active = true;
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
}
}
}
#if defined(DEBUG)
if (micPTT.fell()) {
USBSERIAL.println("Mic PTT pressed!");
} else if (micPTT.rose()) {
USBSERIAL.println("Mic PTT released!");
}
if (linePTT.fell()) {
USBSERIAL.println("Line PTT pressed!");
} else if (linePTT.rose()) {
USBSERIAL.println("Line PTT released!");
}
#endif
// Check if we're already transmitting. If so, then this command
// does nothing: existing transmission, from existing source and PTT,
// will continue.
if (txState != TX_OFF) return;
switch(rigMode) {
// CAT should not start or stop TX in CW mode... we really should
// not even get this command. But maybe the rig control software is
// doing it (but then, we should inhibit this in the Raduino).
//case MODE_CW:
//break;
case MODE_SSB:
// In SSB mode, CAT-PTT will always (de-)activate the Line-In TX
// audio source.
txState = TX_CAT;
audioSelectTxInput(TX_LINE_IN); // in case Mic-In is selected
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
// In Digital (USB) mode, CAT-PTT will always (de-)activate the
// USB-In TX audio source.
txState = TX_CAT;
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
}
}
//======================================================================
// catPTTOff()
//
// NOTE: Should probably move this to cat.ino.
//======================================================================
void catPTTOff()
{
// If we're not transmitting, or the active PTT is not CAT, then this
// command does nothing: CAT cannot interrupt other transmissions.
if (txState != TX_CAT) return;
switch(rigMode) {
// CAT should not start or stop TX in CW mode... we really should
// not even get this command. But maybe the rig control software is
// doing it (but then, we should inhibit this in the Raduino).
//case MODE_CW:
//break;
case MODE_SSB:
// In SSB mode, CAT-PTT will always (de-)activate the Line-In TX
// audio source.
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
audioReceive();
txState = TX_OFF;
break;
case MODE_DIGI:
// In Digital (USB) mode, CAT-PTT will always (de-)activate the
// USB-In TX audio source.
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
audioReceive();
txState = TX_OFF;
break;
}
}
//======================================================================
// checkMicPTT()
//======================================================================
void checkMicPTT()
{
micPTT.update();
// If we're transmitting, then we're just going to check if Mic-PTT
// was released--the Mic-PTT can always be used to terminate a
// transmission from another source.
if ((txState != TX_OFF) && micPTT.rose()) {
#if defined(DEBUG)
USBSERIAL.println("DEBUG: mic PTT released");
#endif
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
// In CW mode, we get a sidetone from the uBITX, so we don't mute
// the receive audio.
if (rigMode != MODE_CW) audioReceive();
txState = TX_OFF;
return;
}
if ((txState == TX_OFF) && micPTT.fell()) {
#if defined(DEBUG)
USBSERIAL.println("DEBUG: mic PTT depressed");
#endif
switch(rigMode) {
case MODE_CW:
txState = TX_MIC;
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_SSB:
txState = TX_MIC;
audioSelectTxInput(TX_MIC_IN);
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
// Mic PTT actuation during Digital does nothing.
break;
}
}
}
//======================================================================
// checkLinePTT()
//======================================================================
void checkLinePTT()
{
linePTT.update();
// If we're transmitting, then we're just going to check if Line-PTT
// was released--the Line-PTT can always be used to terminate a
// transmission from another source.
if ((txState != TX_OFF) && linePTT.rose()) {
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
// In CW mode, we get a sidetone from the uBITX, so we don't mute
// the receive audio.
if (rigMode != MODE_CW) audioReceive();
txState = TX_OFF;
return;
}
if ((txState == TX_OFF) && linePTT.fell()) {
switch(rigMode) {
case MODE_CW:
txState = TX_LINE;
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_SSB:
txState = TX_LINE;
audioSelectTxInput(TX_LINE_IN);
audioTransmit();
digitalWrite(PTT_KEY_OUT_PIN, LOW);
break;
case MODE_DIGI:
// Line PTT actuation during Digital does nothing.
break;
}
}
}
//======================================================================
void setRigMode(RigMode m)
{
rigMode = m;
switch(rigMode) {
case MODE_SSB:
// SSB sets the TX audio input to line-in. Note that this will be
// automatically overridden by mic-in, if the mic PTT is pressed.
audioSelectTxInput(TX_LINE_IN);
audioSSBFilter();
break;
case MODE_DIGI:
// Digi sets the TX audio input to USB-in. Keying in this case must
// be via CAT control. Digital modes can also be used through the
// line-in, but the rig mode should be set to SSB in that case, and
// the rig could be keyed either via the line-in PTT, or via CAT.
// Digimodes could also be used through the mic-in, but in that case,
// the mic PTT line would need to be keyed by the computer rather
// than using CAT for PTT control.
audioSelectTxInput(TX_USB_IN);
audioDigiFilter();
break;
case MODE_CW:
// CW just gets the radio off of Mic-In; but it won't use Line-In.
audioSelectTxInput(TX_LINE_IN);
audioCWFilter();
break;
}
}
//======================================================================
void setup() {
// put your setup code here, to run once:
initCAT(38400, SERIAL_8N1);
@ -85,23 +234,7 @@ void setup() {
digitalWrite(PTT_KEY_OUT_PIN, HIGH);
audioInit();
}
//======================================================================
void setRigMode(RigMode m)
{
rigMode = m;
switch(rigMode) {
case MODE_SSB:
break;
case MODE_DIGI:
break;
case MODE_CW:
break;
}
setRigMode(MODE_SSB);
}
//======================================================================
@ -109,7 +242,8 @@ void setRigMode(RigMode m)
void loop() {
elapsedMillis frame_timer = 0;
checkPTT();
checkMicPTT();
checkLinePTT();
serviceCAT();
/*
#if defined(DEBUG)