wdsp/eer.c
Uladzimir Karpenka 89c8a0e2b5 first commit
2026-06-01 15:58:45 +03:00

394 lines
9.8 KiB
C

/* eer.c
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2014 Warren Pratt, NR0V
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.h"
PORT
EER create_eer (int run, int size, double* in, double* out, double* outM, int rate, double mgain, double pgain, int rundelays, double mdelay, double pdelay, int amiq)
{
EER a = (EER) malloc0 (sizeof (eer));
a->run = run;
a->size = size;
a->in = in;
a->out = out;
a->outM = outM;
a->rate = rate;
a->mgain = mgain;
a->pgain = pgain;
a->rundelays = rundelays;
a->mdelay = mdelay;
a->pdelay = pdelay;
a->amiq = amiq;
a->mdel = create_delay (
a->rundelays, // run
a->size, // size
a->outM, // input buffer
a->outM, // output buffer
a->rate, // sample rate
20.0e-09, // delta (delay stepsize)
a->mdelay); // delay
a->pdel = create_delay (
a->rundelays, // run
a->size, // size
a->out, // input buffer
a->out, // output buffer
a->rate, // sample rate
20.0e-09, // delta (delay stepsize)
a->pdelay); // delay
InitializeCriticalSectionAndSpinCount(&a->cs_update, 2500);
a->legacy = (double *) malloc0 (2048 * sizeof (complex)); /////////////// legacy interface - remove
a->legacyM = (double *) malloc0 (2048 * sizeof (complex)); /////////////// legacy interface - remove
return a;
}
PORT
void destroy_eer (EER a)
{
DeleteCriticalSection (&a->cs_update);
destroy_delay (a->pdel);
destroy_delay (a->mdel);
_aligned_free (a);
}
PORT
void flush_eer (EER a)
{
flush_delay (a->mdel);
flush_delay (a->pdel);
}
PORT
void xeer (EER a)
{
EnterCriticalSection (&a->cs_update);
if (a->run)
{
int i;
double I, Q, mag;
for (i = 0; i < a->size; i++)
{
I = a->in[2 * i + 0];
Q = a->in[2 * i + 1];
a->outM[2 * i + 0] = I * a->mgain;
a->outM[2 * i + 1] = Q * a->mgain;
switch (a->amiq)
{
case 0: // send phase info only, magnitude is constant
mag = sqrt (I * I + Q * Q);
a->out [2 * i + 0] = a->pgain * I / mag;
a->out [2 * i + 1] = a->pgain * Q / mag;
break;
case 1: // send magnitude and phase information, I and Q
a->out [2 * i + 0] = a->pgain * I;
a->out [2 * i + 1] = a->pgain * Q;
break;
case 2: // send envelope
mag = sqrt (I * I + Q * Q);
a->out [2 * i + 0] = a->out[2 * i + 1] = a->pgain * mag;
break;
}
}
xdelay (a->mdel); // delay for outM
xdelay (a->pdel); // delay for out
}
else if (a->out != a->in)
memcpy (a->out, a->in, a->size * sizeof (complex));
LeaveCriticalSection (&a->cs_update);
}
/********************************************************************************************************
* *
* CALLS FOR EXTERNAL USE *
* *
********************************************************************************************************/
#define MAX_EXT_EERS (2) // maximum number of EERs called from outside wdsp
__declspec (align (16)) EER peer[MAX_EXT_EERS]; // array of pointers for EERs used EXTERNAL to wdsp
PORT
void create_eerEXT (int id, int run, int size, int rate, double mgain, double pgain, int rundelays, double mdelay, double pdelay, int amiq)
{
peer[id] = create_eer (run, size, 0, 0, 0, rate, mgain, pgain, rundelays, mdelay, pdelay, amiq);
}
PORT
void destroy_eerEXT (int id)
{
destroy_eer (peer[id]);
}
PORT
void flush_eerEXT (int id)
{
flush_eer (peer[id]);
}
PORT
void SetEERRun (int id, int run)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->run = run;
LeaveCriticalSection (&a->cs_update);
}
PORT
void SetEERAMIQ (int id, int amiq)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->amiq = amiq;
LeaveCriticalSection (&a->cs_update);
}
PORT
void SetEERMgain (int id, double gain)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->mgain = gain;
LeaveCriticalSection (&a->cs_update);
}
PORT
void SetEERPgain (int id, double gain)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->pgain = gain;
LeaveCriticalSection (&a->cs_update);
}
PORT
void SetEERRunDelays (int id, int run)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->rundelays = run;
SetDelayRun (a->mdel, a->rundelays);
SetDelayRun (a->pdel, a->rundelays);
LeaveCriticalSection (&a->cs_update);
}
PORT
void SetEERMdelay (int id, double delay)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->mdelay = delay;
SetDelayValue (a->mdel, a->mdelay);
LeaveCriticalSection (&a->cs_update);
}
PORT
void SetEERPdelay (int id, double delay)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->pdelay = delay;
SetDelayValue (a->pdel, a->pdelay);
LeaveCriticalSection (&a->cs_update);
}
PORT
void SetEERSize (int id, int size)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->size = size;
SetDelayBuffs (a->mdel, a->size, a->outM, a->outM);
SetDelayBuffs (a->pdel, a->size, a->out, a->out);
LeaveCriticalSection (&a->cs_update);
}
PORT
void SetEERSamplerate (int id, int rate)
{
EER a = peer[id];
EnterCriticalSection (&a->cs_update);
a->rate = rate;
destroy_delay (a->mdel);
destroy_delay (a->pdel);
a->mdel = create_delay (
a->rundelays, // run
a->size, // size
a->outM, // input buffer
a->outM, // output buffer
a->rate, // sample rate
20.0e-09, // delta (delay stepsize)
a->mdelay); // delay
a->pdel = create_delay (
a->rundelays, // run
a->size, // size
a->out, // input buffer
a->out, // output buffer
a->rate, // sample rate
20.0e-09, // delta (delay stepsize)
a->pdelay); // delay
LeaveCriticalSection (&a->cs_update);
}
/********************************************************************************************************
* *
* POINTER-BASED PROPERTIES *
* *
********************************************************************************************************/
PORT
void pSetEERRun (EER a, int run)
{
EnterCriticalSection (&a->cs_update);
a->run = run;
LeaveCriticalSection (&a->cs_update);
}
PORT
void pSetEERAMIQ (EER a, int amiq)
{
EnterCriticalSection (&a->cs_update);
a->amiq = amiq;
LeaveCriticalSection (&a->cs_update);
}
PORT
void pSetEERMgain (EER a, double gain)
{
EnterCriticalSection (&a->cs_update);
a->mgain = gain;
LeaveCriticalSection (&a->cs_update);
}
PORT
void pSetEERPgain (EER a, double gain)
{
EnterCriticalSection (&a->cs_update);
a->pgain = gain;
LeaveCriticalSection (&a->cs_update);
}
PORT
void pSetEERRunDelays (EER a, int run)
{
EnterCriticalSection (&a->cs_update);
a->rundelays = run;
SetDelayRun (a->mdel, a->rundelays);
SetDelayRun (a->pdel, a->rundelays);
LeaveCriticalSection (&a->cs_update);
}
PORT
void pSetEERMdelay (EER a, double delay)
{
EnterCriticalSection (&a->cs_update);
a->mdelay = delay;
SetDelayValue (a->mdel, a->mdelay);
LeaveCriticalSection (&a->cs_update);
}
PORT
void pSetEERPdelay (EER a, double delay)
{
EnterCriticalSection (&a->cs_update);
a->pdelay = delay;
SetDelayValue (a->pdel, a->pdelay);
LeaveCriticalSection (&a->cs_update);
}
PORT
void pSetEERSize (EER a, int size)
{
EnterCriticalSection (&a->cs_update);
a->size = size;
SetDelayBuffs (a->mdel, a->size, a->outM, a->outM);
SetDelayBuffs (a->pdel, a->size, a->out, a->out);
LeaveCriticalSection (&a->cs_update);
}
PORT
void pSetEERSamplerate (EER a, int rate)
{
EnterCriticalSection (&a->cs_update);
a->rate = rate;
destroy_delay (a->mdel);
destroy_delay (a->pdel);
a->mdel = create_delay (
a->rundelays, // run
a->size, // size
a->outM, // input buffer
a->outM, // output buffer
a->rate, // sample rate
20.0e-09, // delta (delay stepsize)
a->mdelay); // delay
a->pdel = create_delay (
a->rundelays, // run
a->size, // size
a->out, // input buffer
a->out, // output buffer
a->rate, // sample rate
20.0e-09, // delta (delay stepsize)
a->pdelay); // delay
LeaveCriticalSection (&a->cs_update);
}
/********************************************************************************************************
* *
* Legacy Interface *
* *
********************************************************************************************************/
PORT
void xeerEXTF (int id, float* inI, float* inQ, float* outI, float* outQ, float* outMI, float* outMQ, int mox, int size)
{
EER a = peer[id];
if (mox && a->run)
{
int i;
a->in = a->legacy;
a->out = a->legacy;
a->outM = a->legacyM;
a->size = size;
SetDelayBuffs (a->mdel, a->size, a->outM, a->outM);
SetDelayBuffs (a->pdel, a->size, a->out, a->out);
for (i = 0; i < a->size; i++)
{
a->legacy[2 * i + 0] = (double)inI[i];
a->legacy[2 * i + 1] = (double)inQ[i];
}
xeer (a);
for (i = 0; i < a->size; i++)
{
outI[i] = (float)a->legacy [2 * i + 0];
outQ[i] = (float)a->legacy [2 * i + 1];
outMI[i] = (float)a->legacyM[2 * i + 0];
outMQ[i] = (float)a->legacyM[2 * i + 1];
}
}
}