1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-22 16:08:39 -05:00
sdrangel/wdsp/RXA.cpp
2024-06-16 19:14:31 +02:00

1046 lines
49 KiB
C++

/* RXA.c
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2013, 2014, 2015, 2016, 2023 Warren Pratt, NR0V
Copyright (C) 2024 Edouard Griffiths, F4EXB Adapted to SDRangel
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
The author can be reached by email at
warren@wpratt.com
*/
#include "comm.hpp"
#include "RXA.hpp"
#include "amd.hpp"
#include "meter.hpp"
#include "shift.hpp"
#include "resample.hpp"
#include "gen.hpp"
#include "bandpass.hpp"
#include "bps.hpp"
#include "nbp.hpp"
#include "snb.hpp"
#include "sender.hpp"
#include "amsq.hpp"
#include "fmd.hpp"
#include "fmsq.hpp"
#include "eq.hpp"
#include "anf.hpp"
#include "anr.hpp"
#include "emnr.hpp"
#include "patchpanel.hpp"
#include "siphon.hpp"
#include "cblock.hpp"
#include "ssql.hpp"
#include "iir.hpp"
#include "firmin.hpp"
#include "wcpAGC.hpp"
namespace WDSP {
RXA* RXA::create_rxa (
int in_rate, // input samplerate
int out_rate, // output samplerate
int in_size, // input buffsize (complex samples) in a fexchange() operation
int dsp_rate, // sample rate for mainstream dsp processing
int dsp_size, // number complex samples processed per buffer in mainstream dsp processing
int dsp_insize, // size (complex samples) of the output of the r1 (input) buffer
int dsp_outsize, // size (complex samples) of the input of the r2 (output) buffer
int out_size // output buffsize (complex samples) in a fexchange() operation
)
{
RXA* rxa = new RXA;
rxa->in_rate = in_rate;
rxa->out_rate = out_rate;
rxa->in_size = in_size;
rxa->dsp_rate = dsp_rate;
rxa->dsp_size = dsp_size;
rxa->dsp_insize = dsp_insize;
rxa->dsp_outsize = dsp_outsize;
rxa->out_size = out_size;
rxa->mode = RXA_LSB;
rxa->inbuff = new double[1 * rxa->dsp_insize * 2]; // (double *) malloc0 (1 * ch.dsp_insize * sizeof (complex));
rxa->outbuff = new double[1 * rxa->dsp_outsize * 2]; // (double *) malloc0 (1 * ch.dsp_outsize * sizeof (complex));
rxa->midbuff = new double[2 * rxa->dsp_size * 2]; // (double *) malloc0 (2 * ch.dsp_size * sizeof (complex));
// shift to select a slice of spectrum
rxa->shift.p = SHIFT::create_shift (
1, // run
rxa->dsp_insize, // input buffer size
rxa->inbuff, // pointer to input buffer
rxa->inbuff, // pointer to output buffer
rxa->in_rate, // samplerate
0.0); // amount to shift (Hz)
// resample to dsp rate for main processing
rxa->rsmpin.p = RESAMPLE::create_resample (
0, // run - will be turned ON below if needed
rxa->dsp_insize, // input buffer size
rxa->inbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
rxa->in_rate, // input samplerate
rxa->dsp_rate, // output samplerate
0.0, // select cutoff automatically
0, // select ncoef automatically
1.0); // gain
// signal generator
rxa->gen0.p = GEN::create_gen (
0, // run
rxa->dsp_size, // buffer size
rxa->midbuff, // input buffer
rxa->midbuff, // output buffer
rxa->dsp_rate, // sample rate
2); // mode
// adc (input) meter
rxa->adcmeter.p = METER::create_meter (
1, // run
0, // optional pointer to another 'run'
rxa->dsp_size, // size
rxa->midbuff, // pointer to buffer
rxa->dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
rxa->meter, // result vector
rxa->pmtupdate, // locks for meter access
RXA_ADC_AV, // index for average value
RXA_ADC_PK, // index for peak value
-1, // index for gain value
0); // pointer for gain computation
// notch database
rxa->ndb.p = NOTCHDB::create_notchdb (
0, // master run for all nbp's
1024); // max number of notches
// notched bandpass
rxa->nbp0.p = NBP::create_nbp (
1, // run, always runs
0, // run the notches
0, // position
rxa->dsp_size, // buffer size
std::max(2048, rxa->dsp_size), // number of coefficients
0, // minimum phase flag
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
-4150.0, // lower filter frequency
-150.0, // upper filter frequency
rxa->dsp_rate, // sample rate
0, // wintype
1.0, // gain
1, // auto-increase notch width
1025, // max number of passbands
rxa->ndb.p); // addr of database pointer
// bandpass for snba
rxa->bpsnba.p = BPSNBA::create_bpsnba (
0, // bpsnba run flag
0, // run the notches
0, // position
rxa->dsp_size, // size
std::max(2048, rxa->dsp_size), // number of filter coefficients
0, // minimum phase flag
rxa->midbuff, // input buffer
rxa->midbuff, // output buffer
rxa->dsp_rate, // samplerate
+ 250.0, // abs value of cutoff nearest zero
+ 5700.0, // abs value of cutoff farthest zero
- 5700.0, // current low frequency
- 250.0, // current high frequency
0, // wintype
1.0, // gain
1, // auto-increase notch width
1025, // max number of passbands
rxa->ndb.p); // addr of database pointer
// send spectrum display
rxa->sender.p = SENDER::create_sender (
0, // run
0, // flag
0, // mode
rxa->dsp_size, // size
rxa->midbuff, // pointer to input buffer
0, // arg0 <- disp
1, // arg1 <- ss
0, // arg2 <- LO
0); // arg3 <- NOT USED
// S-meter
rxa->smeter.p = METER::create_meter (
1, // run
0, // optional pointer to another 'run'
rxa->dsp_size, // size
rxa->midbuff, // pointer to buffer
rxa->dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
rxa->meter, // result vector
rxa->pmtupdate, // locks for meter access
RXA_S_AV, // index for average value
RXA_S_PK, // index for peak value
-1, // index for gain value
0); // pointer for gain computation
// AM squelch
rxa->amsq.p = AMSQ::create_amsq (
0, // run
rxa->dsp_size, // buffer size
rxa->midbuff, // pointer to signal input buffer used by xamsq
rxa->midbuff, // pointer to signal output buffer used by xamsq
rxa->midbuff, // pointer to trigger buffer that xamsqcap will capture
rxa->dsp_rate, // sample rate
0.010, // time constant for averaging signal level
0.070, // signal up transition time
0.070, // signal down transition time
0.009, // signal level to initiate tail
0.010, // signal level to initiate unmute
0.000, // minimum tail length
1.500, // maximum tail length
0.0); // muted gain
// AM demod
rxa->amd.p = AMD::create_amd (
0, // run - OFF by default
rxa->dsp_size, // buffer size
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
0, // mode: 0->AM, 1->SAM
1, // levelfade: 0->OFF, 1->ON
0, // sideband mode: 0->OFF
rxa->dsp_rate, // sample rate
-2000.0, // minimum lock frequency
+2000.0, // maximum lock frequency
1.0, // zeta
250.0, // omegaN
0.02, // tauR
1.4); // tauI
// FM demod
rxa->fmd.p = FMD::create_fmd (
0, // run
rxa->dsp_size, // buffer size
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
rxa->dsp_rate, // sample rate
5000.0, // deviation
300.0, // f_low
3000.0, // f_high
-8000.0, // fmin
+8000.0, // fmax
1.0, // zeta
20000.0, // omegaN
0.02, // tau - for dc removal
0.5, // audio gain
1, // run tone filter
254.1, // ctcss frequency
std::max(2048, rxa->dsp_size), // # coefs for de-emphasis filter
0, // min phase flag for de-emphasis filter
std::max(2048, rxa->dsp_size), // # coefs for audio cutoff filter
0); // min phase flag for audio cutoff filter
// FM squelch
rxa->fmsq.p = FMSQ::create_fmsq (
0, // run
rxa->dsp_size, // buffer size
rxa->midbuff, // pointer to input signal buffer
rxa->midbuff, // pointer to output signal buffer
rxa->fmd.p->audio, // pointer to trigger buffer
rxa->dsp_rate, // sample rate
5000.0, // cutoff freq for noise filter (Hz)
&rxa->fmd.p->pllpole, // pointer to pole frequency of the fmd pll (Hz)
0.100, // delay time after channel flush
0.001, // tau for noise averaging
0.100, // tau for long noise averaging
0.050, // signal up transition time
0.010, // signal down transition time
0.750, // noise level to initiate tail
0.562, // noise level to initiate unmute
0.000, // minimum tail time
1.200, // maximum tail time
std::max(2048, rxa->dsp_size), // number of coefficients for noise filter
0); // minimum phase flag
// snba
rxa->snba.p = SNBA::create_snba (
0, // run
rxa->midbuff, // input buffer
rxa->midbuff, // output buffer
rxa->dsp_rate, // input / output sample rate
12000, // internal processing sample rate
rxa->dsp_size, // buffer size
4, // overlap factor to use
256, // frame size to use; sized for 12K rate
64, // asize
2, // npasses
8.0, // k1
20.0, // k2
10, // b
2, // pre
2, // post
0.5, // pmultmin
200.0, // output resampler low cutoff
5400.0); // output resampler high cutoff
// EQ
{
double default_F[11] = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0};
//double default_G[11] = {0.0, -12.0, -12.0, -12.0, -1.0, +1.0, +4.0, +9.0, +12.0, -10.0, -10.0};
double default_G[11] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
rxa->eqp.p = EQP::create_eqp (
0, // run - OFF by default
rxa->dsp_size, // buffer size
std::max(2048, rxa->dsp_size), // number of filter coefficients
0, // minimum phase flag
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
10, // number of frequencies
default_F, // frequency vector
default_G, // gain vector
0, // cutoff mode
0, // wintype
rxa->dsp_rate); // sample rate
}
// ANF
rxa->anf.p = ANF::create_anf (
0, // run - OFF by default
0, // position
rxa->dsp_size, // buffer size
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
ANF_DLINE_SIZE, // dline_size
64, // taps
16, // delay
0.0001, // two_mu
0.1, // gamma
1.0, // lidx
0.0, // lidx_min
200.0, // lidx_max
6.25e-12, // ngamma
6.25e-10, // den_mult
1.0, // lincr
3.0); // ldecr
// ANR
rxa->anr.p = ANR::create_anr (
0, // run - OFF by default
0, // position
rxa->dsp_size, // buffer size
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
ANR_DLINE_SIZE, // dline_size
64, // taps
16, // delay
0.0001, // two_mu
0.1, // gamma
120.0, // lidx
120.0, // lidx_min
200.0, // lidx_max
0.001, // ngamma
6.25e-10, // den_mult
1.0, // lincr
3.0); // ldecr
// EMNR
rxa->emnr.p = EMNR::create_emnr (
0, // run
0, // position
rxa->dsp_size, // buffer size
rxa->midbuff, // input buffer
rxa->midbuff, // output buffer
4096, // FFT size
4, // overlap
rxa->dsp_rate, // samplerate
0, // window type
1.0, // gain
2, // gain method
0, // npe_method
1); // ae_run
// AGC
rxa->agc.p = WCPAGC::create_wcpagc (
1, // run
3, // mode
1, // peakmode = envelope
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
rxa->dsp_size, // buffer size
rxa->dsp_rate, // sample rate
0.001, // tau_attack
0.250, // tau_decay
4, // n_tau
10000.0, // max_gain
1.5, // var_gain
1000.0, // fixed_gain
1.0, // max_input
1.0, // out_target
0.250, // tau_fast_backaverage
0.005, // tau_fast_decay
5.0, // pop_ratio
1, // hang_enable
0.500, // tau_hang_backmult
0.250, // hangtime
0.250, // hang_thresh
0.100); // tau_hang_decay
// agc gain meter
rxa->agcmeter.p = METER::create_meter (
1, // run
0, // optional pointer to another 'run'
rxa->dsp_size, // size
rxa->midbuff, // pointer to buffer
rxa->dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
rxa->meter, // result vector
rxa->pmtupdate, // locks for meter access
RXA_AGC_AV, // index for average value
RXA_AGC_PK, // index for peak value
RXA_AGC_GAIN, // index for gain value
&rxa->agc.p->gain); // pointer for gain computation
// bandpass filter
rxa->bp1.p = BANDPASS::create_bandpass (
1, // run - used only with ( AM || ANF || ANR || EMNR)
0, // position
rxa->dsp_size, // buffer size
std::max(2048, rxa->dsp_size), // number of coefficients
0, // flag for minimum phase
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
-4150.0, // lower filter frequency
-150.0, // upper filter frequency
rxa->dsp_rate, // sample rate
1, // wintype
1.0); // gain
// pull phase & scope display data
rxa->sip1.p = SIPHON::create_siphon (
1, // run - needed only for phase display
0, // position
0, // mode
0, // disp
rxa->dsp_size, // size of input buffer
rxa->midbuff, // input buffer
4096, // number of samples to store
4096, // fft size for spectrum
0); // specmode
// carrier block
rxa->cbl.p = CBL::create_cbl (
0, // run - needed only if set to ON
rxa->dsp_size, // buffer size
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
0, // mode
rxa->dsp_rate, // sample rate
0.02); // tau
// peaking filter
rxa->speak.p = SPEAK::create_speak (
0, // run
rxa->dsp_size, // buffer size,
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
rxa->dsp_rate, // sample rate
600.0, // center frequency
100.0, // bandwidth
2.0, // gain
4, // number of stages
1); // design
// multiple peak filter
{
int def_enable[2] = {1, 1};
double def_freq[2] = {2125.0, 2295.0};
double def_bw[2] = {75.0, 75.0};
double def_gain[2] = {1.0, 1.0};
rxa->mpeak.p = MPEAK::create_mpeak (
0, // run
rxa->dsp_size, // size
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
rxa->dsp_rate, // sample rate
2, // number of peaking filters
def_enable, // enable vector
def_freq, // frequency vector
def_bw, // bandwidth vector
def_gain, // gain vector
4 ); // number of stages
}
// syllabic squelch
rxa->ssql.p = SSQL::create_ssql(
0, // run
rxa->dsp_size, // size
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
rxa->dsp_rate, // sample rate
0.070, // signal up transition time
0.070, // signal down transition time
0.0, // muted gain
0.1, // mute time-constant
0.1, // unmute time-constant
0.08, // window threshold
0.8197, // trigger threshold
2400, // ring size for f_to_v converter
2000.0); // max freq for f_to_v converter
// patchpanel
rxa->panel.p = PANEL::create_panel (
1, // run
rxa->dsp_size, // size
rxa->midbuff, // pointer to input buffer
rxa->midbuff, // pointer to output buffer
4.0, // gain1
1.0, // gain2I
1.0, // gain2Q
3, // 3 for I and Q
0); // no copy
// resample
rxa->rsmpout.p = RESAMPLE::create_resample (
0, // run - will be turned ON below if needed
rxa->dsp_size, // input buffer size
rxa->midbuff, // pointer to input buffer
rxa->outbuff, // pointer to output buffer
rxa->dsp_rate, // input sample rate
rxa->out_rate, // output sample rate
0.0, // select cutoff automatically
0, // select ncoef automatically
1.0); // gain
// turn OFF / ON resamplers as needed
ResCheck (*rxa);
return rxa;
}
void RXA::destroy_rxa (RXA *rxa)
{
RESAMPLE::destroy_resample (rxa->rsmpout.p);
PANEL::destroy_panel (rxa->panel.p);
SSQL::destroy_ssql (rxa->ssql.p);
MPEAK::destroy_mpeak (rxa->mpeak.p);
SPEAK::destroy_speak (rxa->speak.p);
CBL::destroy_cbl (rxa->cbl.p);
SIPHON::destroy_siphon (rxa->sip1.p);
BANDPASS::destroy_bandpass (rxa->bp1.p);
METER::destroy_meter (rxa->agcmeter.p);
WCPAGC::destroy_wcpagc (rxa->agc.p);
EMNR::destroy_emnr (rxa->emnr.p);
ANR::destroy_anr (rxa->anr.p);
ANF::destroy_anf (rxa->anf.p);
EQP::destroy_eqp (rxa->eqp.p);
SNBA::destroy_snba (rxa->snba.p);
FMSQ::destroy_fmsq (rxa->fmsq.p);
FMD::destroy_fmd (rxa->fmd.p);
AMD::destroy_amd (rxa->amd.p);
AMSQ::destroy_amsq (rxa->amsq.p);
METER::destroy_meter (rxa->smeter.p);
SENDER::destroy_sender (rxa->sender.p);
BPSNBA::destroy_bpsnba (rxa->bpsnba.p);
NBP::destroy_nbp (rxa->nbp0.p);
NOTCHDB::destroy_notchdb (rxa->ndb.p);
METER::destroy_meter (rxa->adcmeter.p);
GEN::destroy_gen (rxa->gen0.p);
RESAMPLE::destroy_resample (rxa->rsmpin.p);
SHIFT::destroy_shift (rxa->shift.p);
delete[] (rxa->midbuff);
delete[] (rxa->outbuff);
delete[] (rxa->inbuff);
delete rxa;
}
void RXA::flush_rxa (RXA *rxa)
{
memset (rxa->inbuff, 0, 1 * rxa->dsp_insize * sizeof (dcomplex));
memset (rxa->outbuff, 0, 1 * rxa->dsp_outsize * sizeof (dcomplex));
memset (rxa->midbuff, 0, 2 * rxa->dsp_size * sizeof (dcomplex));
SHIFT::flush_shift (rxa->shift.p);
RESAMPLE::flush_resample (rxa->rsmpin.p);
GEN::flush_gen (rxa->gen0.p);
METER::flush_meter (rxa->adcmeter.p);
NBP::flush_nbp (rxa->nbp0.p);
BPSNBA::flush_bpsnba (rxa->bpsnba.p);
SENDER::flush_sender (rxa->sender.p);
METER::flush_meter (rxa->smeter.p);
AMSQ::flush_amsq (rxa->amsq.p);
AMD::flush_amd (rxa->amd.p);
FMD::flush_fmd (rxa->fmd.p);
FMSQ::flush_fmsq (rxa->fmsq.p);
SNBA::flush_snba (rxa->snba.p);
EQP::flush_eqp (rxa->eqp.p);
ANF::flush_anf (rxa->anf.p);
ANR::flush_anr (rxa->anr.p);
EMNR::flush_emnr (rxa->emnr.p);
WCPAGC::flush_wcpagc (rxa->agc.p);
METER::flush_meter (rxa->agcmeter.p);
BANDPASS::flush_bandpass (rxa->bp1.p);
SIPHON::flush_siphon (rxa->sip1.p);
CBL::flush_cbl (rxa->cbl.p);
SPEAK::flush_speak (rxa->speak.p);
MPEAK::flush_mpeak (rxa->mpeak.p);
SSQL::flush_ssql (rxa->ssql.p);
PANEL::flush_panel (rxa->panel.p);
RESAMPLE::flush_resample (rxa->rsmpout.p);
}
void RXA::xrxa (RXA *rxa)
{
SHIFT::xshift (rxa->shift.p);
RESAMPLE::xresample (rxa->rsmpin.p);
GEN::xgen (rxa->gen0.p);
METER::xmeter (rxa->adcmeter.p);
BPSNBA::xbpsnbain (rxa->bpsnba.p, 0);
NBP::xnbp (rxa->nbp0.p, 0);
METER::xmeter (rxa->smeter.p);
SENDER::xsender (rxa->sender.p);
AMSQ::xamsqcap (rxa->amsq.p);
BPSNBA::xbpsnbaout (rxa->bpsnba.p, 0);
AMD::xamd (rxa->amd.p);
FMD::xfmd (rxa->fmd.p);
FMSQ::xfmsq (rxa->fmsq.p);
BPSNBA::xbpsnbain (rxa->bpsnba.p, 1);
BPSNBA::xbpsnbaout (rxa->bpsnba.p, 1);
SNBA::xsnba (rxa->snba.p);
EQP::xeqp (rxa->eqp.p);
ANF::xanf (rxa->anf.p, 0);
ANR::xanr (rxa->anr.p, 0);
EMNR::xemnr (rxa->emnr.p, 0);
BANDPASS::xbandpass (rxa->bp1.p, 0);
WCPAGC::xwcpagc (rxa->agc.p);
ANF::xanf (rxa->anf.p, 1);
ANR::xanr (rxa->anr.p, 1);
EMNR::xemnr (rxa->emnr.p, 1);
BANDPASS::xbandpass (rxa->bp1.p, 1);
METER::xmeter (rxa->agcmeter.p);
SIPHON::xsiphon (rxa->sip1.p, 0);
CBL::xcbl (rxa->cbl.p);
SPEAK::xspeak (rxa->speak.p);
MPEAK::xmpeak (rxa->mpeak.p);
SSQL::xssql (rxa->ssql.p);
PANEL::xpanel (rxa->panel.p);
AMSQ::xamsq (rxa->amsq.p);
RESAMPLE::xresample (rxa->rsmpout.p);
}
void RXA::setInputSamplerate (RXA *rxa, int dsp_insize, int in_rate)
{
rxa->csDSP.lock();
rxa->dsp_insize = dsp_insize;
rxa->in_rate = in_rate;
// buffers
delete[] (rxa->inbuff);
rxa->inbuff = new double[1 * rxa->dsp_insize * 2]; // (double *)malloc0(1 * ch.dsp_insize * sizeof(complex));
// shift
SHIFT::setBuffers_shift (rxa->shift.p, rxa->inbuff, rxa->inbuff);
SHIFT::setSize_shift (rxa->shift.p, rxa->dsp_insize);
SHIFT::setSamplerate_shift (rxa->shift.p, rxa->in_rate);
// input resampler
RESAMPLE::setBuffers_resample (rxa->rsmpin.p, rxa->inbuff, rxa->midbuff);
RESAMPLE::setSize_resample (rxa->rsmpin.p, rxa->dsp_insize);
RESAMPLE::setInRate_resample (rxa->rsmpin.p, rxa->in_rate);
ResCheck (*rxa);
rxa->csDSP.unlock();
}
void RXA::setOutputSamplerate (RXA *rxa, int dsp_outsize, int out_rate)
{
rxa->csDSP.lock();
rxa->dsp_outsize = dsp_outsize;
rxa->out_rate = out_rate;
// buffers
delete[] (rxa->outbuff);
rxa->outbuff = new double[1 * rxa->dsp_outsize * 2]; // (double *)malloc0(1 * ch.dsp_outsize * sizeof(complex));
// output resampler
RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff);
RESAMPLE::setOutRate_resample (rxa->rsmpout.p, rxa->out_rate);
ResCheck (*rxa);
rxa->csDSP.unlock();
}
void RXA::setDSPSamplerate (RXA *rxa, int dsp_insize, int dsp_outsize, int dsp_rate)
{
rxa->csDSP.lock();
rxa->dsp_insize = dsp_insize;
rxa->dsp_outsize = dsp_outsize;
rxa->dsp_rate = dsp_rate;
// buffers
delete[] (rxa->inbuff);
rxa->inbuff = new double[1 * rxa->dsp_insize * 2]; // (double *)malloc0(1 * rxa->dsp_insize * sizeof(complex));
delete[] (rxa->outbuff);
rxa->outbuff = new double[1 * rxa->dsp_outsize * 2]; // (double *)malloc0(1 * rxa->dsp_outsize * sizeof(complex));
// shift
SHIFT::setBuffers_shift (rxa->shift.p, rxa->inbuff, rxa->inbuff);
SHIFT::setSize_shift (rxa->shift.p, rxa->dsp_insize);
// input resampler
RESAMPLE::setBuffers_resample (rxa->rsmpin.p, rxa->inbuff, rxa->midbuff);
RESAMPLE::setSize_resample (rxa->rsmpin.p, rxa->dsp_insize);
RESAMPLE::setOutRate_resample (rxa->rsmpin.p, rxa->dsp_rate);
// dsp_rate blocks
GEN::setSamplerate_gen (rxa->gen0.p, rxa->dsp_rate);
METER::setSamplerate_meter (rxa->adcmeter.p, rxa->dsp_rate);
NBP::setSamplerate_nbp (rxa->nbp0.p, rxa->dsp_rate);
BPSNBA::setSamplerate_bpsnba (rxa->bpsnba.p, rxa->dsp_rate);
METER::setSamplerate_meter (rxa->smeter.p, rxa->dsp_rate);
SENDER::setSamplerate_sender (rxa->sender.p, rxa->dsp_rate);
AMSQ::setSamplerate_amsq (rxa->amsq.p, rxa->dsp_rate);
AMD::setSamplerate_amd (rxa->amd.p, rxa->dsp_rate);
FMD::setSamplerate_fmd (rxa->fmd.p, rxa->dsp_rate);
FMSQ::setBuffers_fmsq (rxa->fmsq.p, rxa->midbuff, rxa->midbuff, rxa->fmd.p->audio);
FMSQ::setSamplerate_fmsq (rxa->fmsq.p, rxa->dsp_rate);
SNBA::setSamplerate_snba (rxa->snba.p, rxa->dsp_rate);
EQP::setSamplerate_eqp (rxa->eqp.p, rxa->dsp_rate);
ANF::setSamplerate_anf (rxa->anf.p, rxa->dsp_rate);
ANR::setSamplerate_anr (rxa->anr.p, rxa->dsp_rate);
EMNR::setSamplerate_emnr (rxa->emnr.p, rxa->dsp_rate);
BANDPASS::setSamplerate_bandpass (rxa->bp1.p, rxa->dsp_rate);
WCPAGC::setSamplerate_wcpagc (rxa->agc.p, rxa->dsp_rate);
METER::setSamplerate_meter (rxa->agcmeter.p, rxa->dsp_rate);
SIPHON::setSamplerate_siphon (rxa->sip1.p, rxa->dsp_rate);
CBL::setSamplerate_cbl (rxa->cbl.p, rxa->dsp_rate);
SPEAK::setSamplerate_speak (rxa->speak.p, rxa->dsp_rate);
MPEAK::setSamplerate_mpeak (rxa->mpeak.p, rxa->dsp_rate);
SSQL::setSamplerate_ssql (rxa->ssql.p, rxa->dsp_rate);
PANEL::setSamplerate_panel (rxa->panel.p, rxa->dsp_rate);
// output resampler
RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff);
RESAMPLE::setInRate_resample (rxa->rsmpout.p, rxa->dsp_rate);
ResCheck (*rxa);
rxa->csDSP.unlock();
}
void RXA::setDSPBuffsize (RXA *rxa, int dsp_insize, int dsp_size, int dsp_outsize)
{
rxa->csDSP.lock();
rxa->dsp_insize = dsp_insize;
rxa->dsp_size = dsp_size;
rxa->dsp_outsize = dsp_outsize;
// buffers
delete[](rxa->inbuff);
rxa->inbuff = new double[1 * rxa->dsp_insize * 2]; // (double *)malloc0(1 * rxa->dsp_insize * sizeof(complex));
delete[] (rxa->midbuff);
rxa->midbuff = new double[2 * rxa->dsp_size * 2]; // (double *)malloc0(2 * rxa->dsp_size * sizeof(complex));
delete[] (rxa->outbuff);
rxa->outbuff = new double[1 * rxa->dsp_outsize * 2]; // (double *)malloc0(1 * rxa->dsp_outsize * sizeof(complex));
// shift
SHIFT::setBuffers_shift (rxa->shift.p, rxa->inbuff, rxa->inbuff);
SHIFT::setSize_shift (rxa->shift.p, rxa->dsp_insize);
// input resampler
RESAMPLE::setBuffers_resample (rxa->rsmpin.p, rxa->inbuff, rxa->midbuff);
RESAMPLE::setSize_resample (rxa->rsmpin.p, rxa->dsp_insize);
// dsp_size blocks
GEN::setBuffers_gen (rxa->gen0.p, rxa->midbuff, rxa->midbuff);
GEN::setSize_gen (rxa->gen0.p, rxa->dsp_size);
METER::setBuffers_meter (rxa->adcmeter.p, rxa->midbuff);
METER::setSize_meter (rxa->adcmeter.p, rxa->dsp_size);
NBP::setBuffers_nbp (rxa->nbp0.p, rxa->midbuff, rxa->midbuff);
NBP::setSize_nbp (rxa->nbp0.p, rxa->dsp_size);
BPSNBA::setBuffers_bpsnba (rxa->bpsnba.p, rxa->midbuff, rxa->midbuff);
BPSNBA::setSize_bpsnba (rxa->bpsnba.p, rxa->dsp_size);
METER::setBuffers_meter (rxa->smeter.p, rxa->midbuff);
METER::setSize_meter (rxa->smeter.p, rxa->dsp_size);
SENDER::setBuffers_sender (rxa->sender.p, rxa->midbuff);
SENDER::setSize_sender (rxa->sender.p, rxa->dsp_size);
AMSQ::setBuffers_amsq (rxa->amsq.p, rxa->midbuff, rxa->midbuff, rxa->midbuff);
AMSQ::setSize_amsq (rxa->amsq.p, rxa->dsp_size);
AMD::setBuffers_amd (rxa->amd.p, rxa->midbuff, rxa->midbuff);
AMD::setSize_amd (rxa->amd.p, rxa->dsp_size);
FMD::setBuffers_fmd (rxa->fmd.p, rxa->midbuff, rxa->midbuff);
FMD::setSize_fmd (rxa->fmd.p, rxa->dsp_size);
FMSQ::setBuffers_fmsq (rxa->fmsq.p, rxa->midbuff, rxa->midbuff, rxa->fmd.p->audio);
FMSQ::setSize_fmsq (rxa->fmsq.p, rxa->dsp_size);
SNBA::setBuffers_snba (rxa->snba.p, rxa->midbuff, rxa->midbuff);
SNBA::setSize_snba (rxa->snba.p, rxa->dsp_size);
EQP::setBuffers_eqp (rxa->eqp.p, rxa->midbuff, rxa->midbuff);
EQP::setSize_eqp (rxa->eqp.p, rxa->dsp_size);
ANF::setBuffers_anf (rxa->anf.p, rxa->midbuff, rxa->midbuff);
ANF::setSize_anf (rxa->anf.p, rxa->dsp_size);
ANR::setBuffers_anr (rxa->anr.p, rxa->midbuff, rxa->midbuff);
ANR::setSize_anr (rxa->anr.p, rxa->dsp_size);
EMNR::setBuffers_emnr (rxa->emnr.p, rxa->midbuff, rxa->midbuff);
EMNR::setSize_emnr (rxa->emnr.p, rxa->dsp_size);
BANDPASS::setBuffers_bandpass (rxa->bp1.p, rxa->midbuff, rxa->midbuff);
BANDPASS::setSize_bandpass (rxa->bp1.p, rxa->dsp_size);
WCPAGC::setBuffers_wcpagc (rxa->agc.p, rxa->midbuff, rxa->midbuff);
WCPAGC::setSize_wcpagc (rxa->agc.p, rxa->dsp_size);
METER::setBuffers_meter (rxa->agcmeter.p, rxa->midbuff);
METER::setSize_meter (rxa->agcmeter.p, rxa->dsp_size);
SIPHON::setBuffers_siphon (rxa->sip1.p, rxa->midbuff);
SIPHON::setSize_siphon (rxa->sip1.p, rxa->dsp_size);
CBL::setBuffers_cbl (rxa->cbl.p, rxa->midbuff, rxa->midbuff);
CBL::setSize_cbl (rxa->cbl.p, rxa->dsp_size);
SPEAK::setBuffers_speak (rxa->speak.p, rxa->midbuff, rxa->midbuff);
SPEAK::setSize_speak (rxa->speak.p, rxa->dsp_size);
MPEAK::setBuffers_mpeak (rxa->mpeak.p, rxa->midbuff, rxa->midbuff);
MPEAK::setSize_mpeak (rxa->mpeak.p, rxa->dsp_size);
SSQL::setBuffers_ssql (rxa->ssql.p, rxa->midbuff, rxa->midbuff);
SSQL::setSize_ssql (rxa->ssql.p, rxa->dsp_size);
PANEL::setBuffers_panel (rxa->panel.p, rxa->midbuff, rxa->midbuff);
PANEL::setSize_panel (rxa->panel.p, rxa->dsp_size);
// output resampler
RESAMPLE::setBuffers_resample (rxa->rsmpout.p, rxa->midbuff, rxa->outbuff);
RESAMPLE::setSize_resample (rxa->rsmpout.p, rxa->dsp_size);
rxa->csDSP.unlock();
}
/********************************************************************************************************
* *
* RXA Mode & Filter Controls *
* *
********************************************************************************************************/
void RXA::SetMode (RXA& rxa, int mode)
{
if (rxa.mode != mode)
{
int amd_run = (mode == RXA_AM) || (mode == RXA_SAM);
bpsnbaCheck (rxa, mode, rxa.ndb.p->master_run);
bp1Check (
rxa,
amd_run,
rxa.snba.p->run,
rxa.emnr.p->run,
rxa.anf.p->run,
rxa.anr.p->run)
;
rxa.csDSP.lock();
rxa.mode = mode;
rxa.amd.p->run = 0;
rxa.fmd.p->run = 0;
rxa.agc.p->run = 1;
switch (mode)
{
case RXA_AM:
rxa.amd.p->run = 1;
rxa.amd.p->mode = 0;
break;
case RXA_SAM:
rxa.amd.p->run = 1;
rxa.amd.p->mode = 1;
break;
case RXA_DSB:
break;
case RXA_FM:
rxa.fmd.p->run = 1;
rxa.agc.p->run = 0;
break;
default:
break;
}
bp1Set (rxa);
bpsnbaSet (rxa); // update variables
rxa.csDSP.unlock();
}
}
void RXA::ResCheck (RXA& rxa)
{
// turn OFF/ON resamplers depending upon whether they're needed
RESAMPLE *a = rxa.rsmpin.p;
if (rxa.in_rate != rxa.dsp_rate)
a->run = 1;
else
a->run = 0;
a = rxa.rsmpout.p;
if (rxa.dsp_rate != rxa.out_rate)
a->run = 1;
else
a->run = 0;
}
void RXA::bp1Check (
RXA& rxa,
int amd_run,
int snba_run,
int emnr_run,
int anf_run,
int anr_run
)
{
BANDPASS *a = rxa.bp1.p;
double gain;
if (amd_run ||
snba_run ||
emnr_run ||
anf_run ||
anr_run
)
gain = 2.0;
else
gain = 1.0;
if (a->gain != gain)
BANDPASS::setGain_bandpass (a, gain, 0);
}
void RXA::bp1Set (RXA& rxa)
{
BANDPASS *a = rxa.bp1.p;
int old = a->run;
if ((rxa.amd.p->run == 1) ||
(rxa.snba.p->run == 1) ||
(rxa.emnr.p->run == 1) ||
(rxa.anf.p->run == 1) ||
(rxa.anr.p->run == 1)
)
a->run = 1;
else
a->run = 0;
if (!old && a->run)
BANDPASS::flush_bandpass (a);
FIRCORE::setUpdate_fircore (a->p);
}
void RXA::bpsnbaCheck (RXA& rxa, int mode, int notch_run)
{
// for BPSNBA: set run, position, freqs, run_notches
// call this upon change in RXA_mode, snba_run, notch_master_run
BPSNBA *a = rxa.bpsnba.p;
double f_low = 0.0, f_high = 0.0;
int run_notches = 0;
switch (mode)
{
case RXA_LSB:
case RXA_CWL:
case RXA_DIGL:
f_low = -a->abs_high_freq;
f_high = -a->abs_low_freq;
run_notches = notch_run;
break;
case RXA_USB:
case RXA_CWU:
case RXA_DIGU:
f_low = +a->abs_low_freq;
f_high = +a->abs_high_freq;
run_notches = notch_run;
break;
case RXA_AM:
case RXA_SAM:
case RXA_DSB:
f_low = +a->abs_low_freq;
f_high = +a->abs_high_freq;
run_notches = 0;
break;
case RXA_FM:
f_low = +a->abs_low_freq;
f_high = +a->abs_high_freq;
run_notches = 0;
break;
case RXA_DRM:
case RXA_SPEC:
break;
}
// 'run' and 'position' are examined at run time; no filter changes required.
// Recalculate filter if frequencies OR 'run_notches' changed.
if ((a->f_low != f_low ) ||
(a->f_high != f_high ) ||
(a->run_notches != run_notches))
{
a->f_low = f_low;
a->f_high = f_high;
a->run_notches = run_notches;
// f_low, f_high, run_notches are needed for the filter recalculation
BPSNBA::recalc_bpsnba_filter (a, 0);
}
}
void RXA::bpsnbaSet (RXA& rxa)
{
// for BPSNBA: set run, position, freqs, run_notches
// call this upon change in RXA_mode, snba_run, notch_master_run
BPSNBA *a = rxa.bpsnba.p;
switch (rxa.mode)
{
case RXA_LSB:
case RXA_CWL:
case RXA_DIGL:
a->run = rxa.snba.p->run;
a->position = 0;
break;
case RXA_USB:
case RXA_CWU:
case RXA_DIGU:
a->run = rxa.snba.p->run;
a->position = 0;
break;
case RXA_AM:
case RXA_SAM:
case RXA_DSB:
a->run = rxa.snba.p->run;
a->position = 1;
break;
case RXA_FM:
a->run = rxa.snba.p->run;
a->position = 1;
break;
case RXA_DRM:
case RXA_SPEC:
a->run = 0;
break;
}
FIRCORE::setUpdate_fircore (a->bpsnba->p);
}
/********************************************************************************************************
* *
* Collectives *
* *
********************************************************************************************************/
void RXA::SetPassband (RXA& rxa, double f_low, double f_high)
{
BANDPASS::SetBandpassFreqs (rxa, f_low, f_high);
SNBA::SetSNBAOutputBandwidth (rxa, f_low, f_high);
NBP::NBPSetFreqs (rxa, f_low, f_high);
}
void RXA::SetNC (RXA& rxa, int nc)
{
int oldstate = rxa.state;
NBP::NBPSetNC (rxa, nc);
BPSNBA::BPSNBASetNC (rxa, nc);
BANDPASS::SetBandpassNC (rxa, nc);
EQP::SetEQNC (rxa, nc);
FMSQ::SetFMSQNC (rxa, nc);
FMD::SetFMNCde (rxa, nc);
FMD::SetFMNCaud (rxa, nc);
rxa.state = oldstate;
}
void RXA::SetMP (RXA& rxa, int mp)
{
NBP::NBPSetMP (rxa, mp);
BPSNBA::BPSNBASetMP (rxa, mp);
BANDPASS::SetBandpassMP (rxa, mp);
EQP::SetEQMP (rxa, mp);
FMSQ::SetFMSQMP (rxa, mp);
FMD::SetFMMPde (rxa, mp);
FMD::SetFMMPaud (rxa, mp);
}
} // namespace WDSP