ubitx-v5x/TeensyDSP/DSP.cpp

409 lines
11 KiB
C++

//======================================================================
// DSP.cpp
//======================================================================
#include "DSP.h"
#include <i2c_t3.h>
//#include <Wire.h>
//#include <SPI.h>
//#include <SD.h>
//#include <SerialFlash.h>
const int rxRigInChannel = RX_RIG_IN_CH;
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;
UBitxDSP DSP;
//static struct {
// GUItool: begin automatically generated code
AudioInputUSB usbIn; //xy=161,313
AudioInputI2S lineIn; //xy=169,205
AudioSynthWaveformSine tone1; //xy=234,386
AudioSynthWaveformSine tone2; //xy=234,422
AudioMixer4 rxAudio; //xy=426,119
AudioMixer4 txAudio; //xy=430,307
AudioAnalyzeRMS txVoxLevel; //xy=588,348
AudioFilterFIR rxFilter; //xy=591,111
AudioAmplifier usbOutAmp; //xy=756,107
AudioAmplifier lineOutAmp; //xy=757,170
AudioAmplifier usbBypassAmp; //xy=764,233
AudioAmplifier txOutAmp; //xy=811,309
AudioOutputI2S lineOut; //xy=974,302
AudioOutputUSB usbOut; //xy=976,263
AudioConnection patchCord1(usbIn, 0, txAudio, 1);
AudioConnection patchCord2(lineIn, 0, rxAudio, 0);
AudioConnection patchCord3(lineIn, 1, txAudio, 0);
AudioConnection patchCord4(tone1, 0, txAudio, 2);
AudioConnection patchCord5(tone2, 0, txAudio, 3);
AudioConnection patchCord6(rxAudio, rxFilter);
AudioConnection patchCord7(rxAudio, usbBypassAmp);
AudioConnection patchCord8(txAudio, txVoxLevel);
AudioConnection patchCord9(txAudio, txOutAmp);
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);
AudioConnection patchCord15(txOutAmp, 0, lineOut, 1);
AudioControlSGTL5000 audioCtrl; //xy=435,448
// GUItool: end automatically generated code
//} audio;
UBitxDSP::UBitxDSP() {
}
void UBitxDSP::begin() {
// 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)
txOutAmp.gain(1.0);
// Default to RX.
muteRxIn();
muteTxIn();
isTx = true; // so that rx() call works
rx();
// Setup the VOX - TBD
// Setup the RX Filter.
setRxFilter(300, 3000);
sinceLastUpdate = 0;
}
void UBitxDSP::update() {
// Only going to adjust the USB volume periodically.
if (sinceLastUpdate > DSP_MILLIS_PER_UPDATE) {
float vol = usbIn.volume();
setTxInLevel(TX_USB, vol);
sinceLastUpdate = 0;
}
// Update the VOX switches.
// TODO: Move the enable logic in here, so we don't process unnecessarily.
if (txVoxLevel.available()) {
if (txVoxLevel.read() > state.vox.threshold) {
state.vox.timeout = millis() + state.vox.delay;
state.vox.active = true;
}
}
if (millis() > state.vox.timeout) {
state.vox.active = false;
}
}
void UBitxDSP::end() {
}
void UBitxDSP::rx() {
if (isTx) {
muteTxIn();
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
unmuteRxIn(RX_AUDIO);
isTx = false;
}
}
void UBitxDSP::setRxInLevel(RxAudioCh ch, float level) {
if (ch < NUM_RX_AUDIO_CH) {
state.rx[ch].level = level;
rxAudio.gain(ch, state.rx[ch].mute ? 0.0 : state.rx[ch].level);
}
}
void UBitxDSP::muteRxIn() {
for (RxAudioCh i = RX_AUDIO; i < NUM_RX_AUDIO_CH; i++) {
state.rx[ch].mute = true;
rxAudio.gain(ch, 0.0);
}
}
void UBitxDSP::muteRxIn(RxAudioCh ch) {
if (ch < NUM_RX_AUDIO_CH) {
if (!state.rx[ch].mute) {
state.rx[ch].mute = true;
rxAudio.gain(ch, 0.0);
}
}
}
void UBitxDSP::unmuteRxIn(RxAudioCh ch) {
if (ch < NUM_RX_AUDIO_CH) {
if (state.rx[ch].mute) {
state.rx[ch].mute = false;
rxAudio.gain(ch, state.rx[ch].level);
}
}
}
void UBitxDSP::tx(TxAudioIn src) {
if (!isTx) {
muteRxIn(RX_AUDIO);
switch (src) {
case MIC_IN:
audioCtrl.inputSelect(AUDIO_INPUT_MIC);
audioCtrl.micGain(12); // TODO: Make this dynamic
unmuteTxIn(TX_LINE);
case LINE_IN:
audioCtrl.inputSelect(AUDIO_INPUT_LINEIN);
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;
}
isTx = true;
}
}
void UBitxDSP::setTxInLevel(TxAudioCh ch, float level) {
if (ch < NUM_TX_AUDIO_CH) {
state.tx[ch].level = level;
txAudio.gain(ch, state.tx[ch].mute ? 0.0 : state.tx[ch].level);
}
}
void UBitxDSP::muteTxIn() {
for (TxAudioCh i = TX_LINE; i < NUM_TX_AUDIO_CH; i++) {
state.tx[ch].mute = true;
txAudio.gain(ch, 0.0);
}
}
void UBitxDSP::muteTxIn(TxAudioCh ch) {
if (ch < NUM_TX_AUDIO_CH) {
if (!state.tx[ch].mute) {
state.tx[ch].mute = true;
txAudio.gain(ch, 0.0);
}
}
}
void UBitxDSP::unmuteTxIn(TxAudioCh ch) {
if (ch < NUM_TX_AUDIO_CH) {
if (state.tx[ch].mute) {
state.tx[ch].mute = false;
rxAudio.gain(ch, state.tx[ch].level);
}
}
}
/**********************************************************************/
// RX filter settings
const int minRxFilterLo = MIN_RX_FILTER_LO;
const int maxRxFilterHi = MAX_RX_FILTER_HI;
const int minRxFilterWidth = MIN_RX_FILTER_WIDTH;
const int maxRxFilterWidth = MAX_RX_FILTER_WIDTH;
const int minRxFilterCenter = MIN_RX_FILTER_CENTER;
const int maxRxFilterCenter = MAX_RX_FILTER_CENTER;
/*!
@brief Bypass the RX audio filter.
*/
void UBitxDSP::bypassRxFilter() {
rxFilter.begin(FIR_PASSTHRU, NUM_COEFFICIENTS);
}
/*!
@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);
}
void UBitxDSP::setRxFilter(int lo, int hi) {
if (hi < lo + minRxFilterWidth) {
hi = lo + minRxFilterWidth;
}
if (hi > maxRxFilterHi) {
hi = maxRxFilterHi;
}
if (lo > hi - minRxFilterWidth) {
lo = hi - minRxFilterWidth;
}
if (lo < minRxFilterLo) {
lo = minRxFilterLo;
}
state.rxFilterHi = hi;
state.rxFilterLo = lo;
updateRxFilter();
}
void UBitxDSP::setRxFilterLo(int lo) {
if (lo > state.rxFilterHi - minRxFilterWidth) {
lo = state.rxFilterHi - minRxFilterWidth;
}
if (lo < minRxFilterLo) {
lo = minRxFilterLo;
}
state.rxFilterLo = lo;
updateRxFilter();
}
void UBitxDSP::setRxFilterHi(int hi) {
if (hi < state.rxFilterLo + minRxFilterWidth) {
hi = state.rxFilterLo + minRxFilterWidth;
}
if (hi > maxRxFilterHi) {
hi = maxRxFilterHi;
}
state.rxFilterHi = hi;
updateRxFilter();
}
void UBitxDSP::setRxFilterWidth(int width) {
if (width < minRxFilterWidth) {
width = minRxFilterWidth;
} else if (width > maxRxFilterWidth) {
width = maxRxFilterWidth;
}
int center = (state.rxFilterHi + state.rxFilterLo) / 2;
int lo = center - (width / 2);
int hi = center + (width / 2);
setRxFilter(lo, hi);
}
void UBitxDSP::setRxFilterCenter(int center) {
if (center < minRxFilterCenter) {
center = minRxFilterCenter;
} else if (center > maxRxFilterCenter) {
center = maxRxFilterCenter;
}
int width = state.rxFilterHi - state.rxFilterLo;
int lo = center - (width / 2);
int hi = center + (width / 2);
setRxFilter(lo, hi);
}
/**********************************************************************/
// 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);
}
}
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);
}
}
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);
}
}
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);
}
}
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);
}
}
/*
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
//======================================================================