//====================================================================== // audio.ino //====================================================================== #include "audio.h" extern IOPConfig iopConfig; #define DEFAULT_RX_INPUT RIG #define DEFAULT_RX_OUTPUT SPKR #define DEFAULT_TX_INPUT MIC #define DEFAULT_TX_OUTPUT RIG #include #include #include #include #include // GUItool: begin automatically generated code AudioSynthWaveformSine sideTone; //xy=204,221 AudioInputI2S inLine; //xy=208,170 AudioSynthWaveformSine sine2; //xy=207,423 AudioInputUSB inUSB; //xy=208,279 AudioSynthWaveformSine sine1; //xy=208,382 AudioAnalyzeRMS rmsRX; //xy=383,47 AudioAnalyzePeak peakRX; //xy=387,98 AudioMixer4 mixRX; //xy=444,163 AudioMixer4 mixTX; //xy=444,279 AudioAmplifier calRxUSB; //xy=634,165 AudioAmplifier calRxSpkr; //xy=638,55 AudioAmplifier calRxLine; //xy=641,112 AudioAmplifier calTxLine; //xy=653,248 AudioAmplifier calTxUSB; //xy=654,305 AudioAnalyzePeak peakTX; //xy=669,378 AudioAnalyzeRMS rmsTX; //xy=683,433 AudioOutputAnalog outSpkr; //xy=814,55 AudioOutputUSB outUSB; //xy=823,255 AudioOutputI2S outLine; //xy=826,204 AudioConnection patchCord1(sideTone, 0, mixRX, 2); AudioConnection patchCord2(inLine, 0, rmsRX, 0); AudioConnection patchCord3(inLine, 0, peakRX, 0); AudioConnection patchCord4(inLine, 0, mixRX, 0); AudioConnection patchCord5(inLine, 1, mixTX, 0); AudioConnection patchCord6(sine2, 0, mixTX, 3); AudioConnection patchCord7(inUSB, 0, mixRX, 1); AudioConnection patchCord8(inUSB, 1, mixTX, 1); AudioConnection patchCord9(sine1, 0, mixTX, 2); AudioConnection patchCord10(mixRX, calRxSpkr); AudioConnection patchCord11(mixRX, calRxLine); AudioConnection patchCord12(mixRX, calRxUSB); AudioConnection patchCord13(mixTX, calTxLine); AudioConnection patchCord14(mixTX, calTxUSB); AudioConnection patchCord15(mixTX, peakTX); AudioConnection patchCord16(mixTX, rmsTX); AudioConnection patchCord17(calRxUSB, 0, outUSB, 0); AudioConnection patchCord18(calRxSpkr, outSpkr); AudioConnection patchCord19(calRxLine, 0, outLine, 0); AudioConnection patchCord20(calTxLine, 0, outLine, 1); AudioConnection patchCord21(calTxUSB, 0, outUSB, 1); AudioControlSGTL5000 audioCtrl; //xy=391,443 // GUItool: end automatically generated code RxInput audioRxInput; RxOutput audioRxOutput; TxInput audioTxInput; TxOutput audioTxOutput; // audioInit() // Setup the audio subsystem. void audioInit() { audioCtrl.enable(); audioCtrl.muteHeadphone(); // not using the headphone output audioCtrl.volume(0.0); // not using the headphone output audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); // required for RX audio audioCtrl.unmuteLineout(); // required for RX audio audioCtrl.lineInLevel(iopConfig.rxRigInLevel, iopConfig.txLineInLevel); // NOTE: need to see if this persists through input changes (see mic gain...) audioCtrl.lineOutLevel(iopConfig.rxLineOutLevel, iopConfig.txRigOutLevel); // NOTE: need to see if this persists through input changes (see mic gain...) audioCtrl.micGain(iopConfig.txMicInGain); // superfluous, as I have to do this anytime I switch to mic for some reason //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 updateRxRigIn(); updateRxSpkrOut(); updateRxLineOut(); updateRxUSBOut(); // Note - these really just need to be init functions; keep things muted while setting them up. updateTxMicIn(); updateTxLineIn(); updateTxUSBIn(); updateTxTwoToneIn(); updateTxRigOut(); audioSelectRxInput(RX_RIG_IN); audioSelectTxInput(TX_MIC_IN); // superfluous I think //audioCtrl.adcHighPassFilterDisable(); audioCtrl.audioPreProcessorEnable(); // setup the two-tone generator sine1.frequency(700); sine2.frequency(1900); sine1.amplitude(0); sine2.amplitude(0); } inline void updateRxRigIn() { audioCtrl.lineInLevel(iopConfig.rxRigInLevel, iopConfig.txLineInLevel); mixRX.gain(RX_RIG_IN, iopConfig.rxRigInVol * iopConfig.rxRigInCal); } inline void muteRxRigIn() { mixRX.gain(RX_RIG_IN, 0.0); } inline void restoreRxRigIn() { mixRX.gain(RX_RIG_IN, iopConfig.rxRigInVol * iopConfig.rxRigInCal); } inline void updateRxUSBIn() { if (iopConfig.rxUSBInEnable) { mixRX.gain(RX_USB_IN, iopConfig.rxUSBInVol * iopConfig.rxUSBInCal); } else { mixRX.gain(RX_USB_IN, 0.0); } } inline void muteRxUSBIn() { mixRX.gain(RX_USB_IN, 0.0); } inline void restoreRxUSBIn() { updateRxUSBIn(); } inline void updateRxSpkrOut() { calRxSpkr.gain(iopConfig.rxSpkrOutCal); } inline void updateRxLineOut() { calRxLine.gain(iopConfig.rxLineOutCal); audioCtrl.lineOutLevel(iopConfig.rxLineOutLevel, iopConfig.txRigOutLevel); } inline void updateRxUSBOut() { calRxUSB.gain(iopConfig.rxUSBOutCal); } inline void updateTxMicIn() { audioCtrl.micGain(iopConfig.txMicInGain); mixTX.gain(TX_LINE_IN, iopConfig.txMicInVol * iopConfig.txMicInCal); } inline void muteTxMicIn() { mixTX.gain(TX_LINE_IN, 0.0); } inline void restoreTxMicIn() { mixTX.gain(TX_LINE_IN, iopConfig.txMicInVol * iopConfig.txMicInCal); } inline void updateTxLineIn() { audioCtrl.lineInLevel(iopConfig.rxRigInLevel, iopConfig.txLineInLevel); mixTX.gain(TX_LINE_IN, iopConfig.txLineInVol * iopConfig.txLineInCal); } inline void muteTxLineIn() { mixTX.gain(TX_LINE_IN, 0.0); } inline void restoreTxLineIn() { mixTX.gain(TX_LINE_IN, iopConfig.txLineInVol * iopConfig.txLineInCal); } inline void updateTxUSBIn() { mixTX.gain(TX_USB_IN, iopConfig.txUSBInVol * iopConfig.txUSBInCal); } inline void muteTxUSBIn() { mixTX.gain(TX_USB_IN, 0.0); } inline void restoreTxUSBIn() { mixTX.gain(TX_USB_IN, iopConfig.txUSBInVol * iopConfig.txUSBInCal); } inline void updateTxTwoToneIn() { sine1.amplitude(0.5); sine2.amplitude(0.5); mixTX.gain(TX_TEST_IN, iopConfig.txSine1Vol); mixTX.gain(TX_TEST_IN + 1, iopConfig.txSine2Vol); } inline void muteTxTwoToneIn() { mixTX.gain(TX_TEST_IN, 0.0); mixTX.gain(TX_TEST_IN + 1, 0.0); sine1.amplitude(0); sine2.amplitude(0); } inline void restoreTxTwoToneIn() { sine1.amplitude(0.5); sine2.amplitude(0.5); mixTX.gain(TX_TEST_IN, iopConfig.txSine1Vol); mixTX.gain(TX_TEST_IN + 1, iopConfig.txSine2Vol); } inline void updateTxRigOut() { calTxLine.gain(iopConfig.txRigOutCal); audioCtrl.lineOutLevel(iopConfig.rxLineOutLevel, iopConfig.txRigOutLevel); } inline void updateTxUSBOut() { if (iopConfig.txUSBOutEnable) { calTxUSB.gain(iopConfig.txUSBOutCal); } else { calTxUSB.gain(0.0); } } void audioSelectRxInput(RxInput input) { if (audioRxInput != input) { audioRxInput = input; switch(input) { case RX_RIG_IN: muteRxUSBIn(); restoreRxRigIn(); mixRX.gain(2, 0); mixRX.gain(3, 0); break; case RX_USB_IN: muteRxRigIn(); restoreRxUSBIn(); mixRX.gain(2, 0); mixRX.gain(3, 0); break; } } } void audioSelectTxInput(TxInput input) { if (audioTxInput != input) { audioTxInput = input; //muteTxMicIn(); // redundant w/ Line-In muteTxLineIn(); muteTxUSBIn(); muteTxTwoToneIn(); /* switch(input) { case TX_MIC_IN: muteTxUSBIn(); restoreTxMicIn(); break; case TX_LINE_IN: muteTxUSBIn(); restoreTxLineIn(); break; case TX_USB_IN: 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 // sent to the Raduino, in order to ensure that any audio source // transitions occur before transmission begins. void audioTransmit() { 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) { audioCtrl.inputSelect(AUDIO_INPUT_MIC); updateTxMicIn(); #if defined(FACTORY_CALIBRATION) USBSERIAL.println("=============================="); USBSERIAL.println("Transmitting with Mic input"); USBSERIAL.print("Mic gain: "); USBSERIAL.println(iopConfig.txMicInGain); USBSERIAL.print("Mic volume: "); USBSERIAL.println(iopConfig.txMicInVol); USBSERIAL.print("Mic calibration: "); USBSERIAL.println(iopConfig.txMicInCal); USBSERIAL.print("TX audio level: "); USBSERIAL.println(iopConfig.txRigOutLevel); USBSERIAL.print("TX audio calibration: "); USBSERIAL.println(iopConfig.txRigOutCal); USBSERIAL.println("=============================="); #endif } else if (audioTxInput == TX_LINE_IN) { updateTxLineIn(); } break; 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; case MODE_TEST: muteRxRigIn(); updateTxTwoToneIn(); 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 // removed from the Raduino, in order to ensure that any audio source // transitions occur before receive begins. void audioReceive() { switch(rigMode) { //case MODE_CW: //break; case MODE_SSB: if (audioTxInput == TX_MIC_IN) { muteTxMicIn(); audioCtrl.inputSelect(AUDIO_INPUT_LINEIN); } else if (audioTxInput == TX_LINE_IN) { muteTxLineIn(); } restoreRxRigIn(); break; case MODE_DIGI: muteTxUSBIn(); restoreRxRigIn(); break; case MODE_TEST: muteTxTwoToneIn(); restoreRxRigIn(); break; } } //====================================================================== void audioCalibrate(IOPConfig* c, char cmd, char subcmd, char parm, float value, bool set_value=true) { switch(cmd) { case 'r': case 'R': // RX audio parameters switch(subcmd) { case 'r': case 'R': // Rig input switch(parm) { case 'l': case 'L': // level if (set_value) { c->rxRigInLevel = int(value); updateRxRigIn(); } USBSERIAL.print("rxRigInLevel: "); USBSERIAL.println(c->rxRigInLevel); break; case 'v': case 'V': // volume if (set_value) { c->rxRigInVol = value; updateRxRigIn(); } USBSERIAL.print("rxRigInVol: "); USBSERIAL.println(c->rxRigInVol); break; case 'c': case 'C': // calibration if (set_value) { c->rxRigInCal = value; updateRxRigIn(); } USBSERIAL.print("rxRigInCal: "); USBSERIAL.println(c->rxRigInCal); break; } break; case 's': case 'S': // Speaker output switch(parm) { case 'c': case 'C': // calibration if (set_value) { c->rxSpkrOutCal = value; updateRxSpkrOut(); } USBSERIAL.print("rxSpkrOutCal: "); USBSERIAL.println(c->rxSpkrOutCal); break; } break; case 'l': case 'L': // Line output switch(parm) { case 'l': case 'L': // level if (set_value) { c->rxLineOutLevel = int(value); updateRxLineOut(); } USBSERIAL.print("rxLineOutLevel: "); USBSERIAL.println(c->rxLineOutLevel); break; case 'c': case 'C': // calibration if (set_value) { c->rxLineOutCal = value; updateRxLineOut(); } USBSERIAL.print("rxLineOutCal: "); USBSERIAL.println(c->rxLineOutCal); break; } break; case 'u': case 'U': // USB output switch(parm) { case 'c': case 'C': // calibration if (set_value) { c->rxUSBOutCal = value; updateRxUSBOut(); } USBSERIAL.print("rxUSBOutCal: "); USBSERIAL.println(c->rxUSBOutCal); break; } break; } break; case 't': case 'T': //TX audio parameters switch(subcmd) { case 'm': case 'M': // Mic input switch(parm) { case 'g': case 'G': // mic gain if (set_value) { c->txMicInGain = int(value); updateTxMicIn(); } USBSERIAL.print("txMicInGain: "); USBSERIAL.println(c->txMicInGain); break; case 'v': case 'V': // volume if (set_value) { c->txMicInVol = value; updateTxMicIn(); } USBSERIAL.print("txMicInVol: "); USBSERIAL.println(c->txMicInVol); break; case 'c': case 'C': // calibration if (set_value) { c->txMicInCal = value; updateTxMicIn(); } USBSERIAL.print("txMicInCal: "); USBSERIAL.println(c->txMicInCal); break; } break; case 'l': case 'L': // Line input switch(parm) { case 'l': case 'L': // level if (set_value) { c->txLineInLevel = int(value); updateTxLineIn(); } USBSERIAL.print("txLineInLevel: "); USBSERIAL.println(c->txLineInLevel); break; case 'v': case 'V': // volume if (set_value) { c->txLineInVol = value; updateTxLineIn(); } USBSERIAL.print("txLineInVol: "); USBSERIAL.println(c->txLineInVol); break; case 'c': case 'C': // calibration if (set_value) { c->txLineInCal = value; updateTxLineIn(); } USBSERIAL.print("txLineInCal: "); USBSERIAL.println(c->txLineInCal); break; } break; case 'u': case 'U': // USB input switch(parm) { case 'v': case 'V': // volume if (set_value) { c->txUSBInVol = value; updateTxUSBIn(); } USBSERIAL.print("txUSBInVol: "); USBSERIAL.println(c->txUSBInVol); break; case 'c': case 'C': // calibration if (set_value) { c->txUSBInCal = value; updateTxUSBIn(); } USBSERIAL.print("txUSBInCal: "); USBSERIAL.println(c->txUSBInCal); break; } break; case 'r': case 'R': // Rig output switch(parm) { case 'l': case 'L': // level if (set_value) { c->txRigOutLevel = int(value); updateTxRigOut(); } USBSERIAL.print("txRigOutLevel: "); USBSERIAL.println(c->txRigOutLevel); break; case 'c': case 'C': // calibration if (set_value) { c->txRigOutCal = value; updateTxRigOut(); } USBSERIAL.print("txRigOutCal: "); USBSERIAL.println(c->txRigOutCal); break; } break; } break; } } int lpFilter[5]; int hpFilter[5]; void audioSSBFilter() { // calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*); calcBiquad(FILTER_LOPASS, 3300, 0, 0.707, 524288, 44100, lpFilter); calcBiquad(FILTER_HIPASS, 100, 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, 1300, 0, 0.707, 524288, 44100, lpFilter); calcBiquad(FILTER_HIPASS, 100, 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); } //====================================================================== // audioDigiFilter() // Create a very wide filter for digital modes... wider than the uBITX // needs, but just want to make sure we leave the full audio bandwidth // open for digimodes, while ensuring we've cut down any extraneous // noise outside the normal band. //====================================================================== void audioDigiFilter() { // calcBiquad(FilterType,FrequencyC,dBgain,Q,QuantizationUnit,SampleRate,int*); calcBiquad(FILTER_LOPASS, 5000, 0, 0.707, 524288, 44100, lpFilter); calcBiquad(FILTER_HIPASS, 100, 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); } //====================================================================== // EOF //======================================================================