1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-25 01:18:38 -05:00
sdrangel/wdsp/siphon.cpp

265 lines
7.2 KiB
C++
Raw Normal View History

2024-06-16 05:31:13 -04:00
/* siphon.c
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2013 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 "meterlog10.hpp"
#include "siphon.hpp"
namespace WDSP {
2024-07-30 16:52:21 -04:00
void SIPHON::build_window()
2024-06-16 05:31:13 -04:00
{
int i;
2024-08-03 05:05:12 -04:00
double arg0;
double cosphi;
double sum;
float scale;
2024-07-30 16:52:21 -04:00
arg0 = 2.0 * PI / ((double) fftsize - 1.0);
2024-06-16 05:31:13 -04:00
sum = 0.0;
2024-07-30 16:52:21 -04:00
for (i = 0; i < fftsize; i++)
2024-06-16 05:31:13 -04:00
{
2024-06-24 21:50:48 -04:00
cosphi = cos (arg0 * (float)i);
2024-08-03 05:05:12 -04:00
window[i] = (float) (+ 6.3964424114390378e-02
2024-06-16 05:31:13 -04:00
+ cosphi * ( - 2.3993864599352804e-01
+ cosphi * ( + 3.5015956323820469e-01
+ cosphi * ( - 2.4774111897080783e-01
+ cosphi * ( + 8.5438256055858031e-02
+ cosphi * ( - 1.2320203369293225e-02
2024-08-03 05:05:12 -04:00
+ cosphi * ( + 4.3778825791773474e-04 )))))));
2024-07-30 16:52:21 -04:00
sum += window[i];
2024-06-16 05:31:13 -04:00
}
2024-08-03 05:05:12 -04:00
scale = 1.0f / (float) sum;
2024-07-30 16:52:21 -04:00
for (i = 0; i < fftsize; i++)
window[i] *= scale;
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
SIPHON::SIPHON(
int _run,
int _position,
int _mode,
int _disp,
int _insize,
float* _in,
int _sipsize,
int _fftsize,
int _specmode
2024-08-03 05:05:12 -04:00
) :
run(_run),
position(_position),
mode(_mode),
disp(_disp),
insize(_insize),
in(_in),
sipsize(_sipsize), // NOTE: sipsize MUST BE A POWER OF TWO!!
fftsize(_fftsize),
specmode(_specmode)
2024-06-16 05:31:13 -04:00
{
2024-08-03 05:05:12 -04:00
sipbuff.resize(sipsize * 2);
2024-07-30 16:52:21 -04:00
idx = 0;
2024-08-03 05:05:12 -04:00
sipout.resize(sipsize * 2);
specout.resize(fftsize * 2);
2024-07-30 16:52:21 -04:00
sipplan = fftwf_plan_dft_1d (fftsize, (fftwf_complex *) sipout.data(), (fftwf_complex *) specout.data(), FFTW_FORWARD, FFTW_PATIENT);
2024-08-03 05:05:12 -04:00
window.resize(fftsize * 2);
2024-07-30 16:52:21 -04:00
build_window();
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
SIPHON::~SIPHON()
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
fftwf_destroy_plan (sipplan);
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::flush()
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
std::fill(sipbuff.begin(), sipbuff.end(), 0);
std::fill(sipout.begin(), sipout.end(), 0);
std::fill(specout.begin(), specout.end(), 0);
idx = 0;
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::execute(int pos)
2024-06-16 05:31:13 -04:00
{
2024-08-03 05:05:12 -04:00
int first;
int second;
2024-07-13 17:59:46 -04:00
2024-08-03 05:05:12 -04:00
if (run && (position == pos) && (mode == 0))
2024-06-16 05:31:13 -04:00
{
2024-08-03 05:05:12 -04:00
if (insize >= sipsize)
std::copy(&(in[2 * (insize - sipsize)]), &(in[2 * (insize - sipsize)]) + sipsize * 2, sipbuff.begin());
else
2024-06-16 05:31:13 -04:00
{
2024-08-03 05:05:12 -04:00
if (insize > (sipsize - idx))
{
first = sipsize - idx;
second = insize - first;
}
2024-06-16 05:31:13 -04:00
else
{
2024-08-03 05:05:12 -04:00
first = insize;
second = 0;
2024-06-16 05:31:13 -04:00
}
2024-08-03 05:05:12 -04:00
std::copy(in, in + first * 2, sipbuff.begin() + 2 * idx);
std::copy(in + 2 * first, in + 2 * first + second * 2, sipbuff.begin());
if ((idx += insize) >= sipsize) idx -= sipsize;
2024-06-16 05:31:13 -04:00
}
}
}
2024-07-30 16:52:21 -04:00
void SIPHON::setBuffers(float* _in)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
in = _in;
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::setSamplerate(int)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
flush();
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::setSize(int size)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
insize = size;
flush();
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::suck()
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
if (outsize <= sipsize)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
int mask = sipsize - 1;
int j = (idx - outsize) & mask;
int size = sipsize - j;
if (size >= outsize)
std::copy(&(sipbuff[2 * j]), &(sipbuff[2 * j]) + outsize * 2, sipout.begin());
2024-06-16 05:31:13 -04:00
else
{
2024-07-30 16:52:21 -04:00
std::copy(&(sipbuff[2 * j]), &(sipbuff[2 * j]) + size * 2, sipout.begin());
std::copy(sipbuff.begin(), sipbuff.begin() + (outsize - size) * 2, &(sipout[2 * size]));
2024-06-16 05:31:13 -04:00
}
}
}
2024-07-30 16:52:21 -04:00
void SIPHON::sip_spectrum()
2024-06-16 05:31:13 -04:00
{
2024-08-03 05:05:12 -04:00
for (int i = 0; i < fftsize; i++)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
sipout[2 * i + 0] *= window[i];
sipout[2 * i + 1] *= window[i];
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
fftwf_execute (sipplan);
2024-06-16 05:31:13 -04:00
}
/********************************************************************************************************
* *
* RXA Properties *
* *
********************************************************************************************************/
2024-07-30 16:52:21 -04:00
void SIPHON::getaSipF(float* _out, int _size)
2024-06-16 05:31:13 -04:00
{ // return raw samples as floats
2024-07-30 16:52:21 -04:00
outsize = _size;
suck ();
2024-07-13 17:59:46 -04:00
2024-07-30 16:52:21 -04:00
for (int i = 0; i < _size; i++) {
2024-08-03 05:05:12 -04:00
_out[i] = sipout[2 * i + 0];
2024-06-16 05:31:13 -04:00
}
}
2024-07-30 16:52:21 -04:00
void SIPHON::getaSipF1(float* _out, int _size)
2024-06-16 05:31:13 -04:00
{ // return raw samples as floats
2024-07-30 16:52:21 -04:00
outsize = _size;
suck();
2024-07-13 17:59:46 -04:00
2024-07-30 16:52:21 -04:00
for (int i = 0; i < _size; i++)
2024-06-16 05:31:13 -04:00
{
2024-08-03 05:05:12 -04:00
_out[2 * i + 0] = sipout[2 * i + 0];
_out[2 * i + 1] = sipout[2 * i + 1];
2024-06-16 05:31:13 -04:00
}
}
/********************************************************************************************************
* *
* TXA Properties *
* *
********************************************************************************************************/
2024-07-30 16:52:21 -04:00
void SIPHON::setSipPosition(int _pos)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
position = _pos;
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::setSipMode(int _mode)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
mode = _mode;
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::setSipDisplay(int _disp)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
disp = _disp;
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::setSipSpecmode(int _mode)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
if (_mode == 0)
specmode = 0;
2024-06-16 05:31:13 -04:00
else
2024-07-30 16:52:21 -04:00
specmode = 1;
2024-06-16 05:31:13 -04:00
}
2024-07-30 16:52:21 -04:00
void SIPHON::getSpecF1(float* _out)
2024-06-16 05:31:13 -04:00
{ // return spectrum magnitudes in dB
2024-08-03 05:05:12 -04:00
int i;
int j;
int mid;
int m;
int n;
2024-07-30 16:52:21 -04:00
outsize = fftsize;
suck();
sip_spectrum();
mid = fftsize / 2;
2024-07-13 17:59:46 -04:00
2024-07-30 16:52:21 -04:00
if (specmode != 1)
2024-07-13 17:59:46 -04:00
{
2024-06-16 05:31:13 -04:00
// swap the halves of the spectrum
for (i = 0, j = mid; i < mid; i++, j++)
{
2024-07-30 16:52:21 -04:00
_out[i] = (float)(10.0 * MemLog::mlog10 (specout[2 * j + 0] * specout[2 * j + 0] + specout[2 * j + 1] * specout[2 * j + 1] + 1.0e-60));
_out[j] = (float)(10.0 * MemLog::mlog10 (specout[2 * i + 0] * specout[2 * i + 0] + specout[2 * i + 1] * specout[2 * i + 1] + 1.0e-60));
2024-06-16 05:31:13 -04:00
}
2024-07-13 17:59:46 -04:00
}
2024-06-16 05:31:13 -04:00
else
2024-07-13 17:59:46 -04:00
{
2024-06-16 05:31:13 -04:00
// mirror each half of the spectrum in-place
2024-07-30 16:52:21 -04:00
for (i = 0, j = mid - 1, m = mid, n = fftsize - 1; i < mid; i++, j--, m++, n--)
2024-06-16 05:31:13 -04:00
{
2024-07-30 16:52:21 -04:00
_out[i] = (float)(10.0 * MemLog::mlog10 (specout[2 * j + 0] * specout[2 * j + 0] + specout[2 * j + 1] * specout[2 * j + 1] + 1.0e-60));
_out[m] = (float)(10.0 * MemLog::mlog10 (specout[2 * n + 0] * specout[2 * n + 0] + specout[2 * n + 1] * specout[2 * n + 1] + 1.0e-60));
2024-06-16 05:31:13 -04:00
}
2024-07-13 17:59:46 -04:00
}
2024-06-16 05:31:13 -04:00
}
} // namespace WDSP