ubitx-v5d-xcvr/ubitx_iop/audio.ino

557 lines
15 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
audioSelectTxInput(TX_MIC_IN); // superfluous I think
audioCWFilterNarrow(); // test
}
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();
#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
}
// 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);
}
}
//======================================================================
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 updateFilter[5];
void audioCWFilterNarrow()
{
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);
}
//======================================================================
// EOF
//======================================================================