1166 lines
34 KiB
C
1166 lines
34 KiB
C
/* calcc.c
|
|
|
|
This file is part of a program that implements a Software-Defined Radio.
|
|
|
|
Copyright (C) 2013, 2014, 2016, 2019, 2023 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
|
|
|
|
*/
|
|
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
#include "comm.h"
|
|
|
|
void size_calcc (CALCC a)
|
|
{ // for change in ints or spi
|
|
int i;
|
|
a->nsamps = a->ints * a->spi;
|
|
|
|
a->tsamps = a->nsamps + a->npsamps;
|
|
a->env_TX = (double*)malloc0(a->nsamps * sizeof(double));
|
|
a->env_RX = (double*)malloc0(a->nsamps * sizeof(double));
|
|
a->x = (double*)malloc0(a->tsamps * sizeof(double));
|
|
a->ym = (double*)malloc0(a->tsamps * sizeof(double));
|
|
a->yc = (double*)malloc0(a->tsamps * sizeof(double));
|
|
a->ys = (double*)malloc0(a->tsamps * sizeof(double));
|
|
a->cat = (double*)malloc0(4 * a->nsamps * sizeof(double));
|
|
|
|
a->t = (double *) malloc0 ((a->ints + 1) * sizeof(double));
|
|
a->tmap = (double *) malloc0 ((a->ints + 1) * sizeof(double));
|
|
for (i = 0; i < a->ints + 1; i++)
|
|
a->t[i] = (double)i / (double)a->ints;
|
|
|
|
a->cm = (double *) malloc0 (a->ints * 4 * sizeof(double));
|
|
a->cc = (double *) malloc0 (a->ints * 4 * sizeof(double));
|
|
a->cs = (double *) malloc0 (a->ints * 4 * sizeof(double));
|
|
a->cm_old = (double *) malloc0 (a->ints * 4 * sizeof (double));
|
|
|
|
a->rxs = (double *) malloc0 (a->nsamps * sizeof (complex));
|
|
a->txs = (double *) malloc0 (a->nsamps * sizeof (complex));
|
|
|
|
a->ccbld = create_builder(a->nsamps + a->npsamps, a->ints);
|
|
|
|
a->ctrl.cpi = (int *) malloc0 (a->ints * sizeof (int));
|
|
a->ctrl.sindex = (int *) malloc0 (a->ints * sizeof (int));
|
|
a->ctrl.sbase = (int *) malloc0 (a->ints * sizeof (int));
|
|
|
|
for (i = 0; i < a->ints; i++)
|
|
{
|
|
a->ctrl.cpi[i] = 0;
|
|
a->ctrl.sindex[i] = 0;
|
|
a->ctrl.sbase[i] = i * a->spi;
|
|
}
|
|
|
|
a->disp.x = (double *) malloc0 (a->nsamps * sizeof (double));
|
|
a->disp.ym = (double *) malloc0 (a->nsamps * sizeof (double));
|
|
a->disp.yc = (double *) malloc0 (a->nsamps * sizeof (double));
|
|
a->disp.ys = (double *) malloc0 (a->nsamps * sizeof (double));
|
|
a->disp.cm = (double *) malloc0 (a->ints * 4 * sizeof(double));
|
|
a->disp.cc = (double *) malloc0 (a->ints * 4 * sizeof(double));
|
|
a->disp.cs = (double *) malloc0 (a->ints * 4 * sizeof(double));
|
|
|
|
a->util.pm = (double *) malloc0 (4 * a->util.ints * sizeof(double));
|
|
a->util.pc = (double *) malloc0 (4 * a->util.ints * sizeof(double));
|
|
a->util.ps = (double *) malloc0 (4 * a->util.ints * sizeof(double));
|
|
}
|
|
|
|
void desize_calcc (CALCC a)
|
|
{
|
|
_aligned_free(a->util.pm);
|
|
_aligned_free(a->util.pc);
|
|
_aligned_free(a->util.ps);
|
|
|
|
_aligned_free (a->disp.cs);
|
|
_aligned_free (a->disp.cc);
|
|
_aligned_free (a->disp.cm);
|
|
_aligned_free (a->disp.ys);
|
|
_aligned_free (a->disp.yc);
|
|
_aligned_free (a->disp.ym);
|
|
_aligned_free (a->disp.x);
|
|
|
|
_aligned_free (a->ctrl.sbase);
|
|
_aligned_free (a->ctrl.sindex);
|
|
_aligned_free (a->ctrl.cpi);
|
|
destroy_builder(a->ccbld);
|
|
_aligned_free (a->rxs);
|
|
_aligned_free (a->txs);
|
|
_aligned_free (a->cm_old);
|
|
_aligned_free (a->cm);
|
|
_aligned_free (a->cc);
|
|
_aligned_free (a->cs);
|
|
_aligned_free (a->tmap);
|
|
_aligned_free (a->t);
|
|
|
|
_aligned_free(a->cat);
|
|
_aligned_free(a->x);
|
|
_aligned_free(a->ym);
|
|
_aligned_free(a->yc);
|
|
_aligned_free(a->ys);
|
|
_aligned_free(a->env_TX);
|
|
_aligned_free(a->env_RX);
|
|
}
|
|
|
|
CALCC create_calcc (int channel, int runcal, int size, int rate, int ints, int spi, double hw_scale,
|
|
double moxdelay, double loopdelay, double ptol, int mox, int solidmox, int pin, int map, int stbl,
|
|
int npsamps, double alpha)
|
|
{
|
|
CALCC a = (CALCC) malloc0 (sizeof (calcc));
|
|
a->channel = channel;
|
|
a->runcal = runcal;
|
|
a->size = size;
|
|
a->rate = rate;
|
|
a->ints = ints;
|
|
a->spi = spi;
|
|
a->hw_scale = hw_scale;
|
|
a->ctrl.moxdelay = moxdelay;
|
|
a->ctrl.loopdelay = loopdelay;
|
|
a->ptol = ptol;
|
|
a->mox = mox;
|
|
a->solidmox = solidmox;
|
|
a->pin = pin;
|
|
a->map = map;
|
|
a->stbl = stbl;
|
|
a->npsamps = npsamps;
|
|
a->alpha = alpha;
|
|
|
|
a->info = (int *) malloc0 (16 * sizeof (int));
|
|
a->binfo = (int *) malloc0 (16 * sizeof (int));
|
|
|
|
a->ctrl.state = 0;
|
|
a->ctrl.reset = 0;
|
|
a->ctrl.automode = 0;
|
|
a->ctrl.mancal = 0;
|
|
a->ctrl.turnon = 0;
|
|
a->ctrl.moxsamps = (int)(a->rate * a->ctrl.moxdelay);
|
|
a->ctrl.moxcount = 0;
|
|
a->ctrl.count = 0;
|
|
a->ctrl.full_ints = 0;
|
|
a->ctrl.calcinprogress = 0;
|
|
a->ctrl.calcdone = 0;
|
|
a->ctrl.waitsamps = (int)(a->rate * a->ctrl.loopdelay);
|
|
a->ctrl.waitcount = 0;
|
|
a->ctrl.running = 0;
|
|
a->ctrl.current_state = 0;
|
|
InitializeCriticalSectionAndSpinCount (&txa[a->channel].calcc.cs_update, 2500);
|
|
InitializeCriticalSectionAndSpinCount (&a->ctrl.cs_SafeToEnd, 2500);
|
|
a->rxdelay = create_delay (
|
|
1, // run
|
|
0, // size [stuff later]
|
|
0, // input buffer [stuff later]
|
|
0, // output buffer [stuff later]
|
|
a->rate, // sample rate
|
|
20.0e-09, // delta (delay stepsize)
|
|
0.0); // delay
|
|
a->txdelay = create_delay (
|
|
1, // run
|
|
0, // size [stuff later]
|
|
0, // input buffer [stuff later]
|
|
0, // output buffer [stuff later]
|
|
a->rate, // sample rate
|
|
20.0e-09, // delta (delay stepsize)
|
|
0.0); // delay
|
|
|
|
InitializeCriticalSectionAndSpinCount (&a->disp.cs_disp, 2500);
|
|
a->util.ints = a->ints;
|
|
a->util.channel = a->channel;
|
|
|
|
size_calcc (a);
|
|
|
|
a->temprx = (double*)malloc0(2048 * sizeof(complex)); // remove later
|
|
a->temptx = (double*)malloc0(2048 * sizeof(complex)); // remove later
|
|
|
|
// correction save and restore threads
|
|
InterlockedBitTestAndReset(&a->savecorr_bypass, 0);
|
|
a->Sem_SaveCorr = CreateSemaphore(0, 0, 1, 0);
|
|
_beginthread(PSSaveCorrection, 0, (void*)a);
|
|
InterlockedBitTestAndReset(&a->restcorr_bypass, 0);
|
|
a->Sem_RestCorr = CreateSemaphore(0, 0, 1, 0);
|
|
_beginthread(PSRestoreCorrection, 0, (void*)a);
|
|
InterlockedBitTestAndReset(&a->calccorr_bypass, 0);
|
|
a->Sem_CalcCorr = CreateSemaphore(0, 0, 1, 0);
|
|
_beginthread(doPSCalcCorrection, 0, (void*)a);
|
|
InterlockedBitTestAndReset(&a->turnoff_bypass, 0);
|
|
a->Sem_TurnOff = CreateSemaphore(0, 0, 1, 0);
|
|
_beginthread(doPSTurnoff, 0, (void*)a);
|
|
|
|
return a;
|
|
}
|
|
|
|
void destroy_calcc (CALCC a)
|
|
{
|
|
// correction save and restore threads
|
|
InterlockedBitTestAndReset(&txa[a->channel].iqc.p1->busy, 0);
|
|
Sleep(10);
|
|
InterlockedBitTestAndSet(&a->savecorr_bypass, 0);
|
|
ReleaseSemaphore(a->Sem_SaveCorr, 1, 0);
|
|
while (InterlockedAnd(&a->savecorr_bypass, 0xffffffff)) Sleep(1);
|
|
CloseHandle(a->Sem_SaveCorr);
|
|
InterlockedBitTestAndSet(&a->restcorr_bypass, 0);
|
|
ReleaseSemaphore(a->Sem_RestCorr, 1, 0);
|
|
while (InterlockedAnd(&a->restcorr_bypass, 0xffffffff)) Sleep(1);
|
|
CloseHandle(a->Sem_RestCorr);
|
|
InterlockedBitTestAndSet(&a->calccorr_bypass, 0);
|
|
ReleaseSemaphore(a->Sem_CalcCorr, 1, 0);
|
|
while (InterlockedAnd(&a->calccorr_bypass, 0xffffffff)) Sleep(1);
|
|
CloseHandle(a->Sem_CalcCorr);
|
|
InterlockedBitTestAndSet(&a->turnoff_bypass, 0);
|
|
ReleaseSemaphore(a->Sem_TurnOff, 1, 0);
|
|
while (InterlockedAnd(&a->turnoff_bypass, 0xffffffff)) Sleep(1);
|
|
CloseHandle(a->Sem_TurnOff);
|
|
|
|
_aligned_free (a->temptx); // remove later
|
|
_aligned_free (a->temprx); // remove later
|
|
desize_calcc (a);
|
|
DeleteCriticalSection (&a->disp.cs_disp);
|
|
destroy_delay (a->txdelay);
|
|
destroy_delay (a->rxdelay);
|
|
DeleteCriticalSection (&a->ctrl.cs_SafeToEnd);
|
|
DeleteCriticalSection (&txa[a->channel].calcc.cs_update);
|
|
_aligned_free (a->binfo);
|
|
_aligned_free (a->info);
|
|
|
|
_aligned_free (a);
|
|
}
|
|
|
|
void flush_calcc (CALCC a)
|
|
{
|
|
flush_delay (a->rxdelay);
|
|
flush_delay (a->txdelay);
|
|
}
|
|
|
|
void scheck(CALCC a)
|
|
{
|
|
int i, j, k;
|
|
double v, dx, out, x, xold;
|
|
int intm1 = a->ints - 1;
|
|
const double diff_thresh = 0.05;
|
|
a->binfo[6] = 0x0000;
|
|
|
|
for (i = 0; i < 4 * a->ints; i++)
|
|
{
|
|
if (isnan (a->cm[i])) a->binfo[6] |= 0x0001;
|
|
if (isnan (a->cc[i])) a->binfo[6] |= 0x0001;
|
|
if (isnan (a->cs[i])) a->binfo[6] |= 0x0001;
|
|
}
|
|
|
|
for (i = 0; i < a->ints; i++)
|
|
if ((a->cm[4 * i + 0] == 0.0) && (a->cm[4 * i + 1] == 0.0) &&
|
|
(a->cm[4 * i + 2] == 0.0) && (a->cm[4 * i + 3] == 0.0)) a->binfo[6] |= 0x0002;
|
|
|
|
for (i = 0; i < a->ints; i++)
|
|
{
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
k = 4 * i + j;
|
|
v = (double)k / (4.0 * (double)a->ints);
|
|
dx = (a->t[i + 1] - a->t[i]) * (double)j / 4.0;
|
|
out = v * (a->cm[4 * i + 0] + dx * (a->cm[4 * i + 1] + dx * (a->cm[4 * i + 2] + dx * a->cm[4 * i + 3])));
|
|
if (out > 1.0)
|
|
a->binfo[6] |= 0x0004;
|
|
if (out < 0.0) a->binfo[6] |= 0x0010;
|
|
}
|
|
}
|
|
|
|
dx = a->t[a->ints] - a->t[intm1];
|
|
x = a->cm[4 * intm1 + 0] + dx * (a->cm[4 * intm1 + 1] + dx * (a->cm[4 * intm1 + 2] + dx * a->cm[4 * intm1 + 3]));
|
|
|
|
if (x > 1.07) // VALUE
|
|
a->binfo[6] |= 0x0008;
|
|
if (x < 0.0) a->binfo[6] |= 0x0020;
|
|
|
|
for (i = 4; i < a->ints; i++)
|
|
if (fabs (a->cm[4 * i + 0] - a->cm_old[4 * i + 0]) > diff_thresh) a->binfo[6] |= 0x0040;
|
|
xold = a->cm_old[4 * intm1 + 0] + dx * (a->cm_old[4 * intm1 + 1] + dx * (a->cm_old[4 * intm1 + 2] + dx * a->cm_old[4 * intm1 + 3]));
|
|
if (fabs (x - xold) > diff_thresh) a->binfo[6] |= 0x0040;
|
|
memcpy (a->cm_old, a->cm, a->ints * 4 * sizeof(double));
|
|
}
|
|
|
|
void rxscheck (int rints, double* tvec, double* coef, int* info)
|
|
{
|
|
int i, j, k;
|
|
int rintsm1 = rints - 1;
|
|
double v, dx, out;
|
|
*info = 0x0000;
|
|
for (i = 0; i < 4 * rints; i++)
|
|
if (isnan (coef[i])) *info |= 0x0001;
|
|
for (i = 0; i < rints; i++)
|
|
if ((coef[4 * i + 0] == 0.0) && (coef[4 * i + 1] == 0.0) && (coef[4 * i + 2] == 0.0) && (coef[4 * i + 3] == 0.0))
|
|
*info |= 0x0002;
|
|
for (i = 0; i < rints; i++)
|
|
{
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
k = 4 * i + j;
|
|
v = (double)k / (4.0 * (double)rints);
|
|
dx = (tvec[i + 1] - tvec[i]) * (double)j / 4.0;
|
|
out = v * (coef[4 * i + 0] + dx * (coef[4 * i + 1] + dx * (coef[4 * i + 2] + dx * coef[4 * i + 3])));
|
|
if (out > 1.0) // potentially use hw_scale here
|
|
*info |= 0x0004;
|
|
if (out < 0.0) *info |= 0x0010;
|
|
}
|
|
}
|
|
dx = tvec[rints] - tvec[rints - 1];
|
|
out = coef[4 * rintsm1 + 0] + dx * (coef[4 * rintsm1 + 1] + dx * (coef[4 * rintsm1 + 2] + dx * coef[4 * rintsm1 + 3]));
|
|
if (out > 1.07) *info |= 0x0008;
|
|
if (out < 0.00) *info |= 0x0020;
|
|
}
|
|
|
|
void calc (CALCC a)
|
|
{
|
|
int i;
|
|
double norm;
|
|
for (i = 0; i < a->nsamps; i++)
|
|
{
|
|
a->env_TX[i] = sqrt (a->txs[2 * i + 0] * a->txs[2 * i + 0] + a->txs[2 * i + 1] * a->txs[2 * i + 1]);
|
|
a->env_RX[i] = sqrt (a->rxs[2 * i + 0] * a->rxs[2 * i + 0] + a->rxs[2 * i + 1] * a->rxs[2 * i + 1]);
|
|
}
|
|
{
|
|
int rints, ix;
|
|
double dx;
|
|
double tvec[3];
|
|
double txrxcoefs[4 * 2];
|
|
double rx_scale;
|
|
if (a->ints < 16) rints = 1;
|
|
else rints = 2;
|
|
ix = rints - 1;
|
|
for (i = 0; i <= rints; i++)
|
|
tvec[i] = (double)i / (double)rints / a->hw_scale;
|
|
dx = tvec[rints] - tvec[rints - 1];
|
|
xbuilder(a->ccbld, a->nsamps, a->env_TX, a->env_RX, rints, tvec, &(a->binfo[0]), txrxcoefs, a->ptol);
|
|
rxscheck (rints, tvec, txrxcoefs, &a->binfo[7]);
|
|
if ((a->binfo[0] == 0) && (a->binfo[7] == 0))
|
|
rx_scale = 1.0 / (txrxcoefs[4 * ix + 0] + dx * (txrxcoefs[4 * ix + 1] + dx * (txrxcoefs[4 * ix + 2] + dx * txrxcoefs[4 * ix + 3])));
|
|
else
|
|
{
|
|
a->scOK = 0;
|
|
goto cleanup;
|
|
}
|
|
if (a->stbl && _InterlockedAnd (&a->ctrl.running, 1))
|
|
a->rx_scale = a->alpha * a->rx_scale + (1.0 - a->alpha) * rx_scale;
|
|
else
|
|
a->rx_scale = rx_scale;
|
|
}
|
|
|
|
a->binfo[4] = (int)(256.0 * (a->hw_scale / a->rx_scale));
|
|
a->binfo[5]++;
|
|
|
|
if (a->pin) // regress
|
|
{
|
|
const double slope = 0.001;
|
|
double max_rx;
|
|
for (i = 0; i < a->nsamps; i++)
|
|
{
|
|
max_rx = (1.0 - slope + slope * a->hw_scale * a->env_TX[i]) / a->rx_scale;
|
|
if (a->env_RX[i] > max_rx)
|
|
a->env_RX[i] = max_rx;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < a->nsamps; i++)
|
|
{
|
|
norm = a->env_TX[i] * a->env_RX[i];
|
|
a->x[i] = a->rx_scale * a->env_RX[i];
|
|
a->ym[i] = (a->hw_scale * a->env_TX[i]) / (a->rx_scale * a->env_RX[i]);
|
|
a->yc[i] = (+ a->txs[2 * i + 0] * a->rxs[2 * i + 0] + a->txs[2 * i + 1] * a->rxs[2 * i + 1]) / norm;
|
|
a->ys[i] = (- a->txs[2 * i + 0] * a->rxs[2 * i + 1] + a->txs[2 * i + 1] * a->rxs[2 * i + 0]) / norm;
|
|
if (a->stbl && _InterlockedAnd (&a->ctrl.running, 1) && a->scOK)
|
|
{
|
|
int k;
|
|
double dx, ymo, yco, yso;
|
|
if ((k = (int)(a->x[i] * a->ints)) > a->ints - 1) k = a->ints - 1;
|
|
dx = a->x[i] - a->t[k];
|
|
ymo = a->cm[4 * k + 0] + dx * (a->cm[4 * k + 1] + dx * (a->cm[4 * k + 2] + dx * a->cm[4 * k + 3]));
|
|
yco = a->cc[4 * k + 0] + dx * (a->cc[4 * k + 1] + dx * (a->cc[4 * k + 2] + dx * a->cc[4 * k + 3]));
|
|
yso = a->cs[4 * k + 0] + dx * (a->cs[4 * k + 1] + dx * (a->cs[4 * k + 2] + dx * a->cs[4 * k + 3]));
|
|
a->ym[i] = a->alpha * ymo + (1.0 - a->alpha) * a->ym[i];
|
|
a->yc[i] = a->alpha * yco + (1.0 - a->alpha) * a->yc[i];
|
|
a->ys[i] = a->alpha * yso + (1.0 - a->alpha) * a->ys[i];
|
|
}
|
|
}
|
|
|
|
if (a->pin) // pin
|
|
{
|
|
const double mval = 1.0e+00 - 1.0e-10;
|
|
double cval, sval;
|
|
for (i = 0; i < a->nsamps; i++)
|
|
{
|
|
a->cat[4 * i + 0] = a->x[i];
|
|
a->cat[4 * i + 1] = a->ym[i];
|
|
a->cat[4 * i + 2] = a->yc[i];
|
|
a->cat[4 * i + 3] = a->ys[i];
|
|
}
|
|
qsort(a->cat, a->nsamps, 4 * sizeof(double), fcompare);
|
|
for (i = 0; i < a->nsamps; i++)
|
|
{
|
|
a->x[i] = a->cat[4 * i + 0];
|
|
a->ym[i] = a->cat[4 * i + 1];
|
|
a->yc[i] = a->cat[4 * i + 2];
|
|
a->ys[i] = a->cat[4 * i + 3];
|
|
}
|
|
cval = 0.0;
|
|
sval = 0.0;
|
|
for (i = a->nsamps - 1; i > a->nsamps - 17; i--)
|
|
{
|
|
cval += a->yc[i];
|
|
sval += a->ys[i];
|
|
}
|
|
cval /= 16.0;
|
|
sval /= 16.0;
|
|
for (i = a->nsamps; i < a->tsamps; i++)
|
|
{
|
|
a->x[i] = mval;
|
|
a->ym[i] = mval;
|
|
a->yc[i] = cval;
|
|
a->ys[i] = sval;
|
|
}
|
|
xbuilder(a->ccbld, a->tsamps, a->x, a->ym, a->ints, a->t, &(a->binfo[1]), a->cm, a->ptol);
|
|
xbuilder(a->ccbld, a->tsamps, a->x, a->yc, a->ints, a->t, &(a->binfo[2]), a->cc, a->ptol);
|
|
xbuilder(a->ccbld, a->tsamps, a->x, a->ys, a->ints, a->t, &(a->binfo[3]), a->cs, a->ptol);
|
|
}
|
|
else
|
|
{
|
|
xbuilder(a->ccbld, a->nsamps, a->x, a->ym, a->ints, a->t, &(a->binfo[1]), a->cm, a->ptol);
|
|
xbuilder(a->ccbld, a->nsamps, a->x, a->yc, a->ints, a->t, &(a->binfo[2]), a->cc, a->ptol);
|
|
xbuilder(a->ccbld, a->nsamps, a->x, a->ys, a->ints, a->t, &(a->binfo[3]), a->cs, a->ptol);
|
|
}
|
|
|
|
if (a->pin) // tune
|
|
{
|
|
int k = a->ints - 1;
|
|
double dx = a->t[a->ints] - a->t[a->ints - 1];
|
|
double sf = 1.0 / (a->cm[4 * k + 0] + dx * (a->cm[4 * k + 1] + dx * (a->cm[4 * k + 2] + dx * a->cm[4 * k + 3])));
|
|
for (i = 0; i < 4 * a->ints; i++)
|
|
a->cm[i] *= sf;
|
|
}
|
|
|
|
scheck (a);
|
|
a->scOK = ((a->binfo[0] == 0) && (a->binfo[1] == 0) && (a->binfo[2] == 0) && (a->binfo[3] == 0) && (a->binfo[6] == 0));
|
|
|
|
if (a->scOK) // map calc
|
|
{
|
|
for (i = 0; i < a->ints; i++)
|
|
a->tmap[i] = a->cm[4 * i] * a->t[i];
|
|
a->tmap[a->ints] = 1.0;
|
|
a->convex = ((a->tmap[a->ints] - a->tmap[a->ints - 1]) > (a->t[a->ints] - a->t[a->ints - 1]));
|
|
}
|
|
|
|
EnterCriticalSection (&a->disp.cs_disp);
|
|
memcpy(a->disp.x, a->x, a->nsamps * sizeof (double));
|
|
memcpy(a->disp.ym, a->ym, a->nsamps * sizeof (double));
|
|
memcpy(a->disp.yc, a->yc, a->nsamps * sizeof (double));
|
|
memcpy(a->disp.ys, a->ys, a->nsamps * sizeof (double));
|
|
if (a->scOK)
|
|
{
|
|
memcpy(a->disp.cm, a->cm, a->ints * 4 * sizeof (double));
|
|
memcpy(a->disp.cc, a->cc, a->ints * 4 * sizeof (double));
|
|
memcpy(a->disp.cs, a->cs, a->ints * 4 * sizeof (double));
|
|
}
|
|
else
|
|
{
|
|
memset(a->disp.cm, 0, a->ints * 4 * sizeof (double));
|
|
memset(a->disp.cc, 0, a->ints * 4 * sizeof (double));
|
|
memset(a->disp.cs, 0, a->ints * 4 * sizeof (double));
|
|
}
|
|
LeaveCriticalSection (&a->disp.cs_disp);
|
|
cleanup:
|
|
return;
|
|
}
|
|
|
|
void __cdecl doPSCalcCorrection (void *arg)
|
|
{
|
|
CALCC a = (CALCC)arg;
|
|
while (!InterlockedAnd(&a->calccorr_bypass, 0xffffffff))
|
|
{
|
|
WaitForSingleObject(a->Sem_CalcCorr, INFINITE);
|
|
if (!InterlockedAnd(&a->calccorr_bypass, 0xffffffff))
|
|
{
|
|
calc(a);
|
|
if (a->scOK)
|
|
{
|
|
EnterCriticalSection (&a->ctrl.cs_SafeToEnd);
|
|
if (!InterlockedBitTestAndSet(&a->ctrl.running, 0))
|
|
SetTXAiqcStart(a->channel, a->cm, a->cc, a->cs);
|
|
else
|
|
SetTXAiqcSwap(a->channel, a->cm, a->cc, a->cs);
|
|
LeaveCriticalSection(&a->ctrl.cs_SafeToEnd);
|
|
}
|
|
InterlockedBitTestAndSet(&a->ctrl.calcdone, 0);
|
|
}
|
|
}
|
|
InterlockedBitTestAndReset(&a->calccorr_bypass, 0);
|
|
}
|
|
|
|
void __cdecl doPSTurnoff (void *arg)
|
|
{
|
|
CALCC a = (CALCC)arg;
|
|
while (!InterlockedAnd(&a->turnoff_bypass, 0xffffffff))
|
|
{
|
|
WaitForSingleObject(a->Sem_TurnOff, INFINITE);
|
|
if (!InterlockedAnd(&a->turnoff_bypass, 0xffffffff))
|
|
{
|
|
EnterCriticalSection(&a->ctrl.cs_SafeToEnd);
|
|
SetTXAiqcEnd(a->channel);
|
|
LeaveCriticalSection(&a->ctrl.cs_SafeToEnd);
|
|
}
|
|
}
|
|
InterlockedBitTestAndReset(&a->turnoff_bypass, 0);
|
|
}
|
|
|
|
enum _calcc_state
|
|
{
|
|
LRESET,
|
|
LWAIT,
|
|
LMOXDELAY,
|
|
LSETUP,
|
|
LCOLLECT,
|
|
MOXCHECK,
|
|
LCALC,
|
|
LDELAY,
|
|
LSTAYON,
|
|
LTURNON
|
|
};
|
|
|
|
void __cdecl PSSaveCorrection (void *pargs)
|
|
{
|
|
int i, k;
|
|
CALCC a = (CALCC)pargs;
|
|
while (!InterlockedAnd(&a->savecorr_bypass, 0xffffffff))
|
|
{
|
|
WaitForSingleObject(a->Sem_SaveCorr, INFINITE);
|
|
if (!InterlockedAnd(&a->savecorr_bypass, 0xffffffff))
|
|
{
|
|
FILE* file = fopen(a->util.savefile, "w");
|
|
if (file)
|
|
{
|
|
GetTXAiqcValues(a->util.channel, a->util.pm, a->util.pc, a->util.ps);
|
|
for (i = 0; i < a->util.ints; i++)
|
|
{
|
|
for (k = 0; k < 4; k++)
|
|
fprintf(file, "%.17e\t", a->util.pm[4 * i + k]);
|
|
fprintf(file, "\n");
|
|
for (k = 0; k < 4; k++)
|
|
fprintf(file, "%.17e\t", a->util.pc[4 * i + k]);
|
|
fprintf(file, "\n");
|
|
for (k = 0; k < 4; k++)
|
|
fprintf(file, "%.17e\t", a->util.ps[4 * i + k]);
|
|
fprintf(file, "\n\n");
|
|
}
|
|
fflush(file);
|
|
fclose(file);
|
|
}
|
|
}
|
|
}
|
|
InterlockedBitTestAndReset(&a->savecorr_bypass, 0);
|
|
}
|
|
|
|
void __cdecl PSRestoreCorrection(void *pargs)
|
|
{
|
|
int i, k;
|
|
CALCC a = (CALCC)pargs;
|
|
while (!InterlockedAnd(&a->restcorr_bypass, 0xffffffff))
|
|
{
|
|
WaitForSingleObject(a->Sem_RestCorr, INFINITE);
|
|
if (!InterlockedAnd(&a->restcorr_bypass, 0xffffffff))
|
|
{
|
|
FILE* file = fopen(a->util.restfile, "r");
|
|
if (file)
|
|
{
|
|
int error = 0;
|
|
for (i = 0; i < a->util.ints; i++)
|
|
{
|
|
// no additional reads after first error occurs
|
|
for (k = 0; k < 4; k++)
|
|
if (error == 0 && fscanf(file, "%le", &(a->util.pm[4 * i + k])) != 1) error = 1;
|
|
for (k = 0; k < 4; k++)
|
|
if (error == 0 && fscanf(file, "%le", &(a->util.pc[4 * i + k])) != 1) error = 1;
|
|
for (k = 0; k < 4; k++)
|
|
if (error == 0 && fscanf(file, "%le", &(a->util.ps[4 * i + k])) != 1) error = 1;
|
|
}
|
|
fclose(file);
|
|
if (!error)
|
|
{
|
|
if (!InterlockedBitTestAndSet(&a->ctrl.running, 0))
|
|
SetTXAiqcStart(a->channel, a->util.pm, a->util.pc, a->util.ps);
|
|
else
|
|
SetTXAiqcSwap(a->channel, a->util.pm, a->util.pc, a->util.ps);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
InterlockedBitTestAndReset(&a->restcorr_bypass, 0);
|
|
}
|
|
|
|
|
|
/********************************************************************************************************
|
|
* *
|
|
* Public Functions *
|
|
* *
|
|
********************************************************************************************************/
|
|
|
|
PORT
|
|
void pscc (int channel, int size, double* tx, double* rx)
|
|
{
|
|
int i, n, m;
|
|
double env;
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
if (a->runcal)
|
|
{
|
|
a->size = size;
|
|
if (InterlockedAnd (&a->mox, 1) && (a->txdelay->tdelay != 0.0 || a->rxdelay->tdelay != 0.0))
|
|
{
|
|
SetDelayBuffs (a->rxdelay, a->size, rx, rx);
|
|
xdelay (a->rxdelay);
|
|
SetDelayBuffs (a->txdelay, a->size, tx, tx);
|
|
xdelay (a->txdelay);
|
|
}
|
|
a->info[15] = a->ctrl.state;
|
|
|
|
switch (a->ctrl.state)
|
|
{
|
|
case LRESET:
|
|
InterlockedExchange (&a->ctrl.current_state, LRESET);
|
|
a->ctrl.reset = 0;
|
|
if (!a->ctrl.turnon)
|
|
if (InterlockedBitTestAndReset(&a->ctrl.running, 0))
|
|
ReleaseSemaphore(a->Sem_TurnOff, 1, 0);
|
|
a->info[14] = 0;
|
|
a->ctrl.env_maxtx = 0.0;
|
|
a->ctrl.bs_count = 0;
|
|
if (a->ctrl.turnon)
|
|
a->ctrl.state = LTURNON;
|
|
else if (a->ctrl.automode || a->ctrl.mancal)
|
|
a->ctrl.state = LWAIT;
|
|
break;
|
|
case LWAIT:
|
|
InterlockedExchange (&a->ctrl.current_state, LWAIT);
|
|
a->ctrl.mancal = 0;
|
|
a->ctrl.moxcount = 0;
|
|
if (a->ctrl.reset)
|
|
a->ctrl.state = LRESET;
|
|
else if (a->ctrl.turnon)
|
|
a->ctrl.state = LTURNON;
|
|
else if (InterlockedAnd (&a->mox, 1))
|
|
{
|
|
a->ctrl.state = LMOXDELAY;
|
|
InterlockedBitTestAndSet (&a->solidmox, 0);
|
|
}
|
|
break;
|
|
case LMOXDELAY:
|
|
InterlockedExchange (&a->ctrl.current_state, LMOXDELAY);
|
|
a->ctrl.moxcount += a->size;
|
|
if (a->ctrl.reset)
|
|
a->ctrl.state = LRESET;
|
|
else if (a->ctrl.turnon)
|
|
a->ctrl.state = LTURNON;
|
|
else if (!InterlockedAnd (&a->mox, 1) || !InterlockedAnd (&a->solidmox, 1))
|
|
a->ctrl.state = LWAIT;
|
|
else if ((a->ctrl.moxcount - a->size) >= a->ctrl.moxsamps)
|
|
a->ctrl.state = LSETUP;
|
|
break;
|
|
case LSETUP:
|
|
InterlockedExchange (&a->ctrl.current_state, LSETUP);
|
|
a->ctrl.count = 0;
|
|
for (i = 0; i < a->ints; i++)
|
|
{
|
|
a->ctrl.cpi[i] = 0;
|
|
a->ctrl.sindex[i] = 0;
|
|
}
|
|
a->ctrl.full_ints = 0;
|
|
a->ctrl.waitcount = 0;
|
|
|
|
if (a->ctrl.reset)
|
|
a->ctrl.state = LRESET;
|
|
else if (a->ctrl.turnon)
|
|
a->ctrl.state = LTURNON;
|
|
else if (InterlockedAnd (&a->mox, 1) && InterlockedAnd (&a->solidmox, 1))
|
|
{
|
|
a->ctrl.state = LCOLLECT;
|
|
SetTXAiqcDogCount (channel, a->info[13] = 0);
|
|
}
|
|
else
|
|
a->ctrl.state = LWAIT;
|
|
break;
|
|
case LCOLLECT:
|
|
InterlockedExchange (&a->ctrl.current_state, LCOLLECT);
|
|
for (i = 0; i < a->size; i++)
|
|
{
|
|
env = sqrt(tx[2 * i + 0] * tx[2 * i + 0] + tx[2 * i + 1] * tx[2 * i + 1]);
|
|
if (env > a->ctrl.env_maxtx)
|
|
a->ctrl.env_maxtx = env;
|
|
if ((env *= a->hw_scale) <= 1.0)
|
|
{
|
|
if (env == 1.0)
|
|
n = a->ints - 1;
|
|
else if (a->map && _InterlockedAnd (&a->ctrl.running, 1) && a->convex)
|
|
{
|
|
int nmin = 0;
|
|
int nmax = a->ints;
|
|
n = (nmin + nmax) / 2;
|
|
while (nmax - nmin > 1)
|
|
{
|
|
n = (nmin + nmax) / 2;
|
|
if (env >= a->tmap[n])
|
|
nmin = n;
|
|
else
|
|
nmax = n;
|
|
}
|
|
if (env < a->tmap[n]) n--;
|
|
}
|
|
else
|
|
n = (int)(env * (double)a->ints);
|
|
m = a->ctrl.sbase[n] + a->ctrl.sindex[n];
|
|
a->txs[2 * m + 0] = tx[2 * i + 0];
|
|
a->txs[2 * m + 1] = tx[2 * i + 1];
|
|
a->rxs[2 * m + 0] = rx[2 * i + 0];
|
|
a->rxs[2 * m + 1] = rx[2 * i + 1];
|
|
if (++a->ctrl.sindex[n] == a->spi) a->ctrl.sindex[n] = 0;
|
|
if (a->ctrl.cpi[n] != a->spi)
|
|
if (++a->ctrl.cpi[n] == a->spi) a->ctrl.full_ints++;
|
|
++a->ctrl.count;
|
|
}
|
|
}
|
|
GetTXAiqcDogCount (channel, &a->info[13]);
|
|
if (a->ctrl.reset)
|
|
a->ctrl.state = LRESET;
|
|
else if (a->ctrl.turnon)
|
|
a->ctrl.state = LTURNON;
|
|
else if (!InterlockedAnd (&a->mox, 1) || !InterlockedAnd (&a->solidmox, 1))
|
|
a->ctrl.state = LWAIT;
|
|
else if (a->ctrl.full_ints == a->ints)
|
|
a->ctrl.state = MOXCHECK;
|
|
else if (a->info[13] >= 6)
|
|
a->ctrl.state = LRESET;
|
|
else if (a->ctrl.count >= 4 * a->rate)
|
|
{
|
|
a->ctrl.count = 0;
|
|
for (i = 0; i < a->ints; i++)
|
|
{
|
|
a->ctrl.cpi[i] = 0;
|
|
a->ctrl.sindex[i] = 0;
|
|
}
|
|
a->ctrl.full_ints = 0;
|
|
}
|
|
break;
|
|
case MOXCHECK:
|
|
InterlockedExchange (&a->ctrl.current_state, MOXCHECK);
|
|
if (a->ctrl.reset)
|
|
a->ctrl.state = LRESET;
|
|
else if (a->ctrl.turnon)
|
|
a->ctrl.state = LTURNON;
|
|
else if (!InterlockedAnd (&a->mox, 1) || !InterlockedAnd (&a->solidmox, 1))
|
|
a->ctrl.state = LWAIT;
|
|
else
|
|
a->ctrl.state = LCALC;
|
|
break;
|
|
case LCALC:
|
|
InterlockedExchange (&a->ctrl.current_state, LCALC);
|
|
if (!a->ctrl.calcinprogress)
|
|
{
|
|
a->ctrl.calcinprogress = 1;
|
|
ReleaseSemaphore(a->Sem_CalcCorr, 1, 0);
|
|
}
|
|
|
|
if (InterlockedBitTestAndReset(&a->ctrl.calcdone, 0))
|
|
{
|
|
memcpy (a->info, a->binfo, 8 * sizeof (int));
|
|
a->info[14] = _InterlockedAnd (&a->ctrl.running, 1);
|
|
a->ctrl.calcinprogress = 0;
|
|
if (a->ctrl.reset)
|
|
a->ctrl.state = LRESET;
|
|
else if (a->ctrl.turnon)
|
|
a->ctrl.state = LTURNON;
|
|
else if (a->scOK)
|
|
{
|
|
a->ctrl.bs_count = 0;
|
|
a->ctrl.state = LDELAY;
|
|
}
|
|
else if (++(a->ctrl.bs_count) >= 2)
|
|
a->ctrl.state = LRESET;
|
|
else if (InterlockedAnd (&a->mox, 1) && InterlockedAnd (&a->solidmox, 1))
|
|
a->ctrl.state = LSETUP;
|
|
else a->ctrl.state = LWAIT;
|
|
}
|
|
break;
|
|
case LDELAY:
|
|
InterlockedExchange (&a->ctrl.current_state, LDELAY);
|
|
a->ctrl.waitcount += a->size;
|
|
if (a->ctrl.reset)
|
|
a->ctrl.state = LRESET;
|
|
else if (a->ctrl.turnon)
|
|
a->ctrl.state = LTURNON;
|
|
else if ((a->ctrl.waitcount - a->size) >= a->ctrl.waitsamps)
|
|
{
|
|
if (a->ctrl.automode)
|
|
{
|
|
if (InterlockedAnd (&a->mox, 1) && InterlockedAnd (&a->solidmox, 1))
|
|
a->ctrl.state = LSETUP;
|
|
else
|
|
a->ctrl.state = LWAIT;
|
|
}
|
|
else
|
|
a->ctrl.state = LSTAYON;
|
|
}
|
|
break;
|
|
case LSTAYON:
|
|
InterlockedExchange (&a->ctrl.current_state, LSTAYON);
|
|
if (a->ctrl.reset || a->ctrl.automode || a->ctrl.mancal)
|
|
a->ctrl.state = LRESET;
|
|
break;
|
|
case LTURNON:
|
|
InterlockedExchange (&a->ctrl.current_state, LTURNON);
|
|
a->ctrl.turnon = 0;
|
|
a->ctrl.automode = 0;
|
|
a->info[14] = 1;
|
|
a->ctrl.state = LSTAYON;
|
|
break;
|
|
}
|
|
}
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void psccF (int channel, int size, float *Itxbuff, float *Qtxbuff, float *Irxbuff, float *Qrxbuff, int mox, int solidmox)
|
|
{
|
|
int i;
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
// a->mox = mox;
|
|
// a->solidmox = solidmox;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
a->temptx[2 * i + 0] = (double)Itxbuff[i];
|
|
a->temptx[2 * i + 1] = (double)Qtxbuff[i];
|
|
a->temprx[2 * i + 0] = (double)Irxbuff[i];
|
|
a->temprx[2 * i + 1] = (double)Qrxbuff[i];
|
|
}
|
|
pscc (channel, size, a->temptx, a->temprx);
|
|
}
|
|
|
|
PORT
|
|
void PSSaveCorr (int channel, char* filename)
|
|
{
|
|
CALCC a;
|
|
int i = 0;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
while (a->util.savefile[i++] = *filename++);
|
|
ReleaseSemaphore(a->Sem_SaveCorr, 1, 0);
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void PSRestoreCorr (int channel, char* filename)
|
|
{
|
|
CALCC a;
|
|
int i = 0;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
while (a->util.restfile[i++] = *filename++);
|
|
a->ctrl.turnon = 1;
|
|
ReleaseSemaphore(a->Sem_RestCorr, 1, 0);
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
/********************************************************************************************************
|
|
* *
|
|
* Properties *
|
|
* *
|
|
********************************************************************************************************/
|
|
|
|
PORT
|
|
void SetPSRunCal (int channel, int run)
|
|
{
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
a->runcal = run;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSMox (int channel, int mox)
|
|
{
|
|
CALCC a = txa[channel].calcc.p;;
|
|
if (mox)
|
|
InterlockedBitTestAndSet (&a->mox, 0);
|
|
else
|
|
{
|
|
InterlockedBitTestAndReset (&a->mox, 0);
|
|
InterlockedBitTestAndReset (&a->solidmox, 0);
|
|
}
|
|
}
|
|
|
|
PORT
|
|
void GetPSInfo (int channel, int *info)
|
|
{
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
memcpy (info, a->info, 16 * sizeof(int));
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSReset (int channel, int reset)
|
|
{
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
a->ctrl.reset = reset;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSMancal (int channel, int mancal)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
txa[channel].calcc.p->ctrl.mancal = mancal;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSAutomode (int channel, int automode)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
txa[channel].calcc.p->ctrl.automode = automode;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSTurnon (int channel, int turnon)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
txa[channel].calcc.p->ctrl.turnon = turnon;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSControl (int channel, int reset, int mancal, int automode, int turnon)
|
|
{
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
a->ctrl.reset = reset;
|
|
a->ctrl.mancal = mancal;
|
|
a->ctrl.automode = automode;
|
|
a->ctrl.turnon = turnon;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSLoopDelay (int channel, double delay)
|
|
{
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
a->ctrl.loopdelay = delay;
|
|
a->ctrl.waitsamps = (int)(a->rate * a->ctrl.loopdelay);
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSMoxDelay (int channel, double delay)
|
|
{
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
a->ctrl.moxdelay = delay;
|
|
a->ctrl.moxsamps = (int)(a->rate * a->ctrl.moxdelay);
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
double SetPSTXDelay (int channel, double delay)
|
|
{
|
|
CALCC a;
|
|
double adelay;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
a->txdel = delay;
|
|
if (a->txdel >= 0.0)
|
|
{
|
|
adelay = SetDelayValue (a->txdelay, a->txdel);
|
|
SetDelayValue (a->rxdelay, 0.0);
|
|
}
|
|
else
|
|
{
|
|
adelay = -SetDelayValue (a->rxdelay, -a->txdel);
|
|
SetDelayValue (a->txdelay, 0.0);
|
|
}
|
|
//adelay = SetDelayValue (a->txdelay, a->txdel);
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
return adelay;
|
|
}
|
|
|
|
PORT
|
|
void SetPSHWPeak (int channel, double peak)
|
|
{
|
|
CALCC a;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a = txa[channel].calcc.p;
|
|
a->hw_scale = 1.0 / peak;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void GetPSHWPeak (int channel, double* peak)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
*peak = 1.0 / txa[channel].calcc.p->hw_scale;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void GetPSMaxTX (int channel, double* maxtx)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
*maxtx = txa[channel].calcc.p->ctrl.env_maxtx;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSPtol (int channel, double ptol)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
txa[channel].calcc.p->ptol = ptol;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void GetPSDisp (int channel, double* x, double* ym, double* yc, double* ys, double* cm, double* cc, double* cs)
|
|
{
|
|
CALCC a = txa[channel].calcc.p;
|
|
EnterCriticalSection (&a->disp.cs_disp);
|
|
memcpy (x, a->disp.x, a->nsamps * sizeof (double));
|
|
memcpy (ym, a->disp.ym, a->nsamps * sizeof (double));
|
|
memcpy (yc, a->disp.yc, a->nsamps * sizeof (double));
|
|
memcpy (ys, a->disp.ys, a->nsamps * sizeof (double));
|
|
memcpy (cm, a->disp.cm, a->ints * 4 * sizeof (double));
|
|
memcpy (cc, a->disp.cc, a->ints * 4 * sizeof (double));
|
|
memcpy (cs, a->disp.cs, a->ints * 4 * sizeof (double));
|
|
LeaveCriticalSection (&a->disp.cs_disp);
|
|
}
|
|
|
|
PORT
|
|
void SetPSFeedbackRate (int channel, int rate)
|
|
{
|
|
CALCC a = txa[channel].calcc.p;
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
a->rate = rate;
|
|
a->ctrl.moxsamps = (int)(a->rate * a->ctrl.moxdelay);
|
|
a->ctrl.waitsamps = (int)(a->rate * a->ctrl.loopdelay);
|
|
destroy_delay (a->txdelay);
|
|
destroy_delay (a->rxdelay);
|
|
a->rxdelay = create_delay (
|
|
1, // run
|
|
0, // size [stuff later]
|
|
0, // input buffer [stuff later]
|
|
0, // output buffer [stuff later]
|
|
a->rate, // sample rate
|
|
20.0e-09, // delta (delay stepsize)
|
|
0.0); // delay
|
|
a->txdelay = create_delay (
|
|
1, // run
|
|
0, // size [stuff later]
|
|
0, // input buffer [stuff later]
|
|
0, // output buffer [stuff later]
|
|
a->rate, // sample rate
|
|
20.0e-09, // delta (delay stepsize)
|
|
a->txdel); // delay
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSPinMode (int channel, int pin)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
txa[channel].calcc.p->pin = pin;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSMapMode (int channel, int map)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
txa[channel].calcc.p->map = map;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
PORT
|
|
void SetPSStabilize (int channel, int stbl)
|
|
{
|
|
EnterCriticalSection (&txa[channel].calcc.cs_update);
|
|
txa[channel].calcc.p->stbl = stbl;
|
|
LeaveCriticalSection (&txa[channel].calcc.cs_update);
|
|
}
|
|
|
|
void ForceShutDown (CALCC a, IQC b, int timeout)
|
|
{
|
|
a->runcal = 0; // close pscc() gate
|
|
InterlockedBitTestAndReset (&b->run, 0); // close xiqc() gate
|
|
Sleep (timeout); // wait for anything possibly running to clear
|
|
a->ctrl.state = LRESET; // set next_state
|
|
InterlockedBitTestAndReset (&a->ctrl.running, 0); // set running = 0
|
|
InterlockedBitTestAndReset (&b->busy, 0); // set busy = 0 so turnoff thread can finish & terminate
|
|
InterlockedBitTestAndReset (&a->ctrl.calcdone, 0);
|
|
a->info[14] = 0;
|
|
a->ctrl.env_maxtx = 0.0;
|
|
a->ctrl.bs_count = 0;
|
|
}
|
|
|
|
PORT
|
|
void SetPSIntsAndSpi (int channel, int ints, int spi)
|
|
{
|
|
CALCC a = txa[channel].calcc.p;
|
|
IQC b = txa[channel].iqc.p1;
|
|
if (b->ints != ints || b->dog.spi != spi || a->ints != ints || a->spi != spi)
|
|
{
|
|
// SHUT-DOWN
|
|
const int timeout = 50;
|
|
int runcal = a->runcal;
|
|
int mancal = a->ctrl.mancal;
|
|
int automode = a->ctrl.automode;
|
|
int turnon = a->ctrl.turnon;
|
|
int count = 0;
|
|
SetPSControl (a->channel, 1, 0, 0, 0);
|
|
while (count++ < timeout && (LRESET != _InterlockedAnd (&a->ctrl.current_state, 0xFFFFFFFF)
|
|
|| _InterlockedAnd (&a->ctrl.running, 1) || _InterlockedAnd (&b->run, 1)))
|
|
Sleep (1); // wait for normal shutdown (when samples are flowing)
|
|
if (LRESET != _InterlockedAnd (&a->ctrl.current_state, 0xFFFFFFFF)
|
|
|| _InterlockedAnd (&a->ctrl.running, 1) || _InterlockedAnd (&b->run, 1))
|
|
ForceShutDown(a, b, timeout); // apparently no sammples flowing; force shutdown.
|
|
// MAKE CHANGES
|
|
desize_iqc (b);
|
|
desize_calcc (a);
|
|
b->ints = ints;
|
|
b->dog.spi = spi;
|
|
a->ints = ints;
|
|
a->spi = spi;
|
|
size_calcc (a);
|
|
size_iqc (b);
|
|
// START-UP
|
|
SetPSControl (a->channel, 1, mancal, automode, turnon);
|
|
a->runcal = runcal;
|
|
}
|
|
}
|