ubitx-v5d-xcvr/audio.ino
Rob French f819e211da Significant reorganization of the code. Got rid of the audio classes,
just moved all the audio stuff into its own files.  Created a structure
for storing configuration data in... the intent is that it will be
stored to EEPROM (using EEPROMAnything).  It does compile now, but
haven't actually tried it out.  Notable learning points:  need to set
micGain AFTER selecting the mic input.  So lot of code now to take care
of trying to smoothly mute and unmute things.
2020-05-02 00:54:58 -05:00

275 lines
8.4 KiB
C++

//======================================================================
// 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 <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioInputI2S inLine; //xy=224,194
AudioInputUSB inUSB; //xy=224,303
AudioAnalyzeRMS rmsRX; //xy=399,71
AudioAnalyzePeak peakRX; //xy=403,122
AudioMixer4 mixRX; //xy=460,187
AudioMixer4 mixTX; //xy=460,303
AudioAmplifier calRxUSB; //xy=650,189
AudioAmplifier calRxSpkr; //xy=654,79
AudioAmplifier calRxLine; //xy=657,136
AudioAmplifier calTxLine; //xy=669,272
AudioAmplifier calTxUSB; //xy=670,329
AudioAnalyzePeak peakTX; //xy=685,402
AudioAnalyzeRMS rmsTX; //xy=699,457
AudioOutputAnalog outSpkr; //xy=830,79
AudioOutputUSB outUSB; //xy=839,279
AudioOutputI2S outLine; //xy=842,228
AudioConnection patchCord1(inLine, 0, rmsRX, 0);
AudioConnection patchCord2(inLine, 0, peakRX, 0);
AudioConnection patchCord3(inLine, 0, mixRX, 0);
AudioConnection patchCord4(inLine, 1, mixTX, 0);
AudioConnection patchCord5(inUSB, 0, mixRX, 1);
AudioConnection patchCord6(inUSB, 1, mixTX, 1);
AudioConnection patchCord7(mixRX, calRxSpkr);
AudioConnection patchCord8(mixRX, calRxLine);
AudioConnection patchCord9(mixRX, calRxUSB);
AudioConnection patchCord10(mixTX, calTxLine);
AudioConnection patchCord11(mixTX, calTxUSB);
AudioConnection patchCord12(mixTX, peakTX);
AudioConnection patchCord13(mixTX, rmsTX);
AudioConnection patchCord14(calRxUSB, 0, outUSB, 0);
AudioConnection patchCord15(calRxSpkr, outSpkr);
AudioConnection patchCord16(calRxLine, 0, outLine, 0);
AudioConnection patchCord17(calTxLine, 0, outLine, 1);
AudioConnection patchCord18(calTxUSB, 0, outUSB, 1);
AudioControlSGTL5000 audioCtrl; //xy=407,467
// 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
// selectTxInput(TX_LINE_IN);
}
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 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 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 audioSelectTxInput(TxInput input)
{
if (audioTxInput != input) {
audioTxInput = input;
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()
{
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
// 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();
}
// 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);
}
}
// 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()
{
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.
if (audioTxInput == TX_MIC_IN) {
muteTxMicIn();
// Now switch to the line input, and restore mixer settings.
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
restoreTxLineIn();
}
restoreRxRigIn();
// 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);
}
}
//======================================================================
// EOF
//======================================================================