spdxl/src/sdr.c

1019 wiersze
25 KiB
C

/*
* dxlAPRS toolchain
*
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
* Modified by SP9SKP
*
* SPDX-License-Identifier: GPL-2.0+
*/
#define X2C_int32
#define X2C_index32
#ifndef sdr_H_
#include "sdr.h"
#endif
#define sdr_C_
#ifndef osi_H_
#include "osi.h"
#endif
#include <osic.h>
#ifndef mlib_H_
#include "mlib.h"
#endif
#ifndef tcp_H_
#include "tcp.h"
#endif
#ifndef tcpb_H_
#include "tcpb.h"
#endif
#ifndef aprsstr_H_
#include "aprsstr.h"
#endif
#include <stdio.h>
/* rtl_tcp iq fm demodulator by OE5DXL */
#define sdr_IQBUF 65536
#define sdr_DDSMAXLEN 2048
#define sdr_AFCSPEED 400000000
/* slower afc reaction */
#define sdr_AFCRECENTER 1024
/* pull afc to middle */
#define sdr_SSBDDSSIZE 2048
#define sdr_SSBDDSSIZE4 512
struct Complex;
struct Complex {
float Re;
float Im;
};
static int32_t fd;
static uint32_t audiohz;
static uint32_t rtlhz;
static char reconnect;
static uint8_t iqbuf[65536];
static short DDS[2048];
static float DDSR[2048];
static char url[1001];
static char port[11];
static uint32_t sampsum;
static uint32_t sampsize;
static uint32_t reduce;
static uint32_t ddslen;
static uint32_t ddslen4;
static float SSBDDS[2048];
static void initdds(uint32_t size)
{
uint32_t i;
float d;
uint32_t tmp;
if (size>2047UL) size = 2048UL;
d = X2C_DIVR(6.2831853071796f,(float)size);
tmp = size-1UL;
i = 0UL;
if (i<=tmp) for (;; i++) {
DDSR[i] = 32767.5f*osic_sin((float)i*d);
DDS[i] = (short)(int32_t)X2C_TRUNCI(DDSR[i],X2C_min_longint,
X2C_max_longint);
if (i==tmp) break;
} /* end for */
ddslen = (uint32_t)(size-1UL);
ddslen4 = size/4UL;
} /* end initdds() */
static void initssbdds(float dds[], uint32_t dds_len)
{
uint32_t i;
float d;
uint32_t tmp;
d = X2C_DIVR(6.2831853071796f,(float)((dds_len-1)+1UL));
tmp = dds_len-1;
i = 0UL;
if (i<=tmp) for (;; i++) {
dds[i] = osic_sin((float)i*d);
if (i==tmp) break;
} /* end for */
} /* end initssbdds() */
#define sdr_FG (-9)
static void iir512(sdr_pRX rx, uint32_t a, uint32_t b)
{
uint32_t dfc;
uint32_t ph;
uint32_t i;
int32_t i3;
int32_t i2;
int32_t i1;
int32_t r3;
int32_t r2;
int32_t r1;
int32_t ddsi;
int32_t ddsr;
int32_t xi;
int32_t xr;
struct sdr_TAP * anonym;
struct sdr_TAP * anonym0;
struct sdr_TAP * anonym1;
struct sdr_TAP * anonym2;
{ /* with */
struct sdr_TAP * anonym = &rx->tapre;
r1 = anonym->uc1;
r2 = anonym->uc2;
r3 = anonym->il;
}
{ /* with */
struct sdr_TAP * anonym0 = &rx->tapim;
i1 = anonym0->uc1;
i2 = anonym0->uc2;
i3 = anonym0->il;
}
ph = rx->phase;
dfc = rx->df+(uint32_t)rx->afckhz;
i = a;
do {
xr = (int32_t)iqbuf[i]-127L;
++i;
xi = (int32_t)iqbuf[i]-127L;
++i;
ddsr = (int32_t)DDS[ph]; /* mix osz sin */
ddsi = (int32_t)DDS[(uint32_t)((uint32_t)(ph+ddslen4)&ddslen)];
/* mix osz cos */
ph = (uint32_t)((uint32_t)(ph+dfc)&ddslen); /* drive mix osz */
r1 += ((xr*ddsr-xi*ddsi)-r1)-r3>>9; /* mixer + lowpass i */
r2 += r3-r2>>9;
r3 += r1-r2>>8;
i1 += ((xr*ddsi+xi*ddsr)-i1)-i3>>9; /* mixer + lowpass q */
i2 += i3-i2>>9;
i3 += i1-i2>>8;
} while (i<=b);
{ /* with */
struct sdr_TAP * anonym1 = &rx->tapre;
anonym1->uc1 = r1;
anonym1->uc2 = r2;
anonym1->il = r3;
anonym1->ucr2 = (float)r2;
}
{ /* with */
struct sdr_TAP * anonym2 = &rx->tapim;
anonym2->uc1 = i1;
anonym2->uc2 = i2;
anonym2->il = i3;
anonym2->ucr2 = (float)i2;
}
rx->phase = ph;
} /* end iir512() */
#define sdr_FG0 (-8)
static void iir256(sdr_pRX rx, uint32_t a, uint32_t b)
{
uint32_t dfc;
uint32_t ph;
uint32_t i;
int32_t i3;
int32_t i2;
int32_t i1;
int32_t r3;
int32_t r2;
int32_t r1;
int32_t ddsi;
int32_t ddsr;
int32_t xi;
int32_t xr;
struct sdr_TAP * anonym;
struct sdr_TAP * anonym0;
struct sdr_TAP * anonym1;
struct sdr_TAP * anonym2;
{ /* with */
struct sdr_TAP * anonym = &rx->tapre;
r1 = anonym->uc1;
r2 = anonym->uc2;
r3 = anonym->il;
}
{ /* with */
struct sdr_TAP * anonym0 = &rx->tapim;
i1 = anonym0->uc1;
i2 = anonym0->uc2;
i3 = anonym0->il;
}
ph = rx->phase;
dfc = rx->df+(uint32_t)rx->afckhz;
i = a;
do {
xr = (int32_t)iqbuf[i]-127L;
++i;
xi = (int32_t)iqbuf[i]-127L;
++i;
ddsr = (int32_t)DDS[ph]; /* mix osz sin */
ddsi = (int32_t)DDS[(uint32_t)((uint32_t)(ph+ddslen4)&ddslen)];
/* mix osz cos */
ph = (uint32_t)((uint32_t)(ph+dfc)&ddslen); /* drive mix osz */
r1 += ((xr*ddsr-xi*ddsi)-r1)-r3>>8; /* mixer + lowpass i */
r2 += r3-r2>>8;
r3 += r1-r2>>7;
i1 += ((xr*ddsi+xi*ddsr)-i1)-i3>>8; /* mixer + lowpass q */
i2 += i3-i2>>8;
i3 += i1-i2>>7;
} while (i<=b);
{ /* with */
struct sdr_TAP * anonym1 = &rx->tapre;
anonym1->uc1 = r1;
anonym1->uc2 = r2;
anonym1->il = r3;
anonym1->ucr2 = (float)r2;
}
{ /* with */
struct sdr_TAP * anonym2 = &rx->tapim;
anonym2->uc1 = i1;
anonym2->uc2 = i2;
anonym2->il = i3;
anonym2->ucr2 = (float)i2;
}
rx->phase = ph;
} /* end iir256() */
#define sdr_FG1 (-7)
static void iir128(sdr_pRX rx, uint32_t a, uint32_t b)
{
uint32_t dfc;
uint32_t ph;
uint32_t i;
int32_t i3;
int32_t i2;
int32_t i1;
int32_t r3;
int32_t r2;
int32_t r1;
int32_t ddsi;
int32_t ddsr;
int32_t xi;
int32_t xr;
struct sdr_TAP * anonym;
struct sdr_TAP * anonym0;
struct sdr_TAP * anonym1;
struct sdr_TAP * anonym2;
{ /* with */
struct sdr_TAP * anonym = &rx->tapre;
r1 = anonym->uc1;
r2 = anonym->uc2;
r3 = anonym->il;
}
{ /* with */
struct sdr_TAP * anonym0 = &rx->tapim;
i1 = anonym0->uc1;
i2 = anonym0->uc2;
i3 = anonym0->il;
}
ph = rx->phase;
dfc = rx->df +(uint32_t)rx->afckhz;
i = a;
do {
xr = (int32_t)iqbuf[i]-127L;
++i;
xi = (int32_t)iqbuf[i]-127L;
++i;
ddsr = (int32_t)DDS[ph]; /* mix osz sin */
ddsi = (int32_t)DDS[(uint32_t)((uint32_t)(ph+ddslen4)&ddslen)];
/* mix osz cos */
ph = (uint32_t)((uint32_t)(ph+dfc)&ddslen); /* drive mix osz */
r1 += ((xr*ddsr-xi*ddsi)-r1)-r3>>7; /* mixer + lowpass i */
r2 += r3-r2>>7;
r3 += r1-r2>>6;
i1 += ((xr*ddsi+xi*ddsr)-i1)-i3>>7; /* mixer + lowpass q */
i2 += i3-i2>>7;
i3 += i1-i2>>6;
} while (i<=b);
{ /* with */
struct sdr_TAP * anonym1 = &rx->tapre;
anonym1->uc1 = r1;
anonym1->uc2 = r2;
anonym1->il = r3;
anonym1->ucr2 = (float)r2;
}
{ /* with */
struct sdr_TAP * anonym2 = &rx->tapim;
anonym2->uc1 = i1;
anonym2->uc2 = i2;
anonym2->il = i3;
anonym2->ucr2 = (float)i2;
}
rx->phase = ph;
} /* end iir128() */
#define sdr_FG2 (-6)
static void iir64(sdr_pRX rx, uint32_t a, uint32_t b)
{
uint32_t dfc;
uint32_t ph;
uint32_t i;
int32_t i3;
int32_t i2;
int32_t i1;
int32_t r3;
int32_t r2;
int32_t r1;
int32_t ddsi;
int32_t ddsr;
int32_t xi;
int32_t xr;
struct sdr_TAP * anonym;
struct sdr_TAP * anonym0;
struct sdr_TAP * anonym1;
struct sdr_TAP * anonym2;
{ /* with */
struct sdr_TAP * anonym = &rx->tapre;
r1 = anonym->uc1;
r2 = anonym->uc2;
r3 = anonym->il;
}
{ /* with */
struct sdr_TAP * anonym0 = &rx->tapim;
i1 = anonym0->uc1;
i2 = anonym0->uc2;
i3 = anonym0->il;
}
ph = rx->phase;
dfc = rx->df+(uint32_t)rx->afckhz;
i = a;
do {
xr = (int32_t)iqbuf[i]-127L;
++i;
xi = (int32_t)iqbuf[i]-127L;
++i;
ddsr = (int32_t)DDS[ph]; /* mix osz sin */
ddsi = (int32_t)DDS[(uint32_t)((uint32_t)(ph+ddslen4)&ddslen)];
/* mix osz cos */
ph = (uint32_t)((uint32_t)(ph+dfc)&ddslen); /* drive mix osz */
r1 += ((xr*ddsr-xi*ddsi)-r1)-r3>>6; /* mixer + lowpass i */
r2 += r3-r2>>6;
r3 += r1-r2>>5;
i1 += ((xr*ddsi+xi*ddsr)-i1)-i3>>6; /* mixer + lowpass q */
i2 += i3-i2>>6;
i3 += i1-i2>>5;
} while (i<=b);
{ /* with */
struct sdr_TAP * anonym1 = &rx->tapre;
anonym1->uc1 = r1;
anonym1->uc2 = r2;
anonym1->il = r3;
anonym1->ucr2 = (float)r2;
}
{ /* with */
struct sdr_TAP * anonym2 = &rx->tapim;
anonym2->uc1 = i1;
anonym2->uc2 = i2;
anonym2->il = i3;
anonym2->ucr2 = (float)i2;
}
rx->phase = ph;
} /* end iir64() */
#define sdr_FG3 (-5)
static void iir32(sdr_pRX rx, uint32_t a, uint32_t b)
{
uint32_t dfc;
uint32_t ph;
uint32_t i;
int32_t i3;
int32_t i2;
int32_t i1;
int32_t r3;
int32_t r2;
int32_t r1;
int32_t ddsi;
int32_t ddsr;
int32_t xi;
int32_t xr;
struct sdr_TAP * anonym;
struct sdr_TAP * anonym0;
struct sdr_TAP * anonym1;
struct sdr_TAP * anonym2;
{ /* with */
struct sdr_TAP * anonym = &rx->tapre;
r1 = anonym->uc1;
r2 = anonym->uc2;
r3 = anonym->il;
}
{ /* with */
struct sdr_TAP * anonym0 = &rx->tapim;
i1 = anonym0->uc1;
i2 = anonym0->uc2;
i3 = anonym0->il;
}
ph = rx->phase;
dfc = rx->df+(uint32_t)rx->afckhz;
i = a;
do {
xr = (int32_t)iqbuf[i]-127L;
++i;
xi = (int32_t)iqbuf[i]-127L;
++i;
ddsr = (int32_t)DDS[ph]; /* mix osz sin */
ddsi = (int32_t)DDS[(uint32_t)((uint32_t)(ph+ddslen4)&ddslen)];
/* mix osz cos */
ph = (uint32_t)((uint32_t)(ph+dfc)&ddslen); /* drive mix osz */
r1 += ((xr*ddsr-xi*ddsi)-r1)-r3>>5; /* mixer + lowpass i */
r2 += r3-r2>>5;
r3 += r1-r2>>4;
i1 += ((xr*ddsi+xi*ddsr)-i1)-i3>>5; /* mixer + lowpass q */
i2 += i3-i2>>5;
i3 += i1-i2>>4;
} while (i<=b);
{ /* with */
struct sdr_TAP * anonym1 = &rx->tapre;
anonym1->uc1 = r1;
anonym1->uc2 = r2;
anonym1->il = r3;
anonym1->ucr2 = (float)r2;
}
{ /* with */
struct sdr_TAP * anonym2 = &rx->tapim;
anonym2->uc1 = i1;
anonym2->uc2 = i2;
anonym2->il = i3;
anonym2->ucr2 = (float)i2;
}
rx->phase = ph;
} /* end iir32() */
#define sdr_FG4 (-4)
static void iir16(sdr_pRX rx, uint32_t a, uint32_t b)
{
uint32_t dfc;
uint32_t ph;
uint32_t i;
int32_t i3;
int32_t i2;
int32_t i1;
int32_t r3;
int32_t r2;
int32_t r1;
int32_t ddsi;
int32_t ddsr;
int32_t xi;
int32_t xr;
struct sdr_TAP * anonym;
struct sdr_TAP * anonym0;
struct sdr_TAP * anonym1;
struct sdr_TAP * anonym2;
{ /* with */
struct sdr_TAP * anonym = &rx->tapre;
r1 = anonym->uc1;
r2 = anonym->uc2;
r3 = anonym->il;
}
{ /* with */
struct sdr_TAP * anonym0 = &rx->tapim;
i1 = anonym0->uc1;
i2 = anonym0->uc2;
i3 = anonym0->il;
}
ph = rx->phase;
dfc = rx->df+(uint32_t)rx->afckhz;
i = a;
do {
xr = (int32_t)iqbuf[i]-127L;
++i;
xi = (int32_t)iqbuf[i]-127L;
++i;
ddsr = (int32_t)DDS[ph]; /* mix osz sin */
ddsi = (int32_t)DDS[(uint32_t)((uint32_t)(ph+ddslen4)&ddslen)];
/* mix osz cos */
ph = (uint32_t)((uint32_t)(ph+dfc)&ddslen); /* drive mix osz */
r1 += ((xr*ddsr-xi*ddsi)-r1)-r3>>4; /* mixer + lowpass i */
r2 += r3-r2>>4;
r3 += r1-r2>>3;
i1 += ((xr*ddsi+xi*ddsr)-i1)-i3>>4; /* mixer + lowpass q */
i2 += i3-i2>>4;
i3 += i1-i2>>3;
} while (i<=b);
{ /* with */
struct sdr_TAP * anonym1 = &rx->tapre;
anonym1->uc1 = r1;
anonym1->uc2 = r2;
anonym1->il = r3;
anonym1->ucr2 = (float)r2;
}
{ /* with */
struct sdr_TAP * anonym2 = &rx->tapim;
anonym2->uc1 = i1;
anonym2->uc2 = i2;
anonym2->il = i3;
anonym2->ucr2 = (float)i2;
}
rx->phase = ph;
} /* end iir16() */
#define sdr_FG5 (-3)
static void iir8(sdr_pRX rx, uint32_t a, uint32_t b)
{
uint32_t dfc;
uint32_t ph;
uint32_t i;
int32_t i3;
int32_t i2;
int32_t i1;
int32_t r3;
int32_t r2;
int32_t r1;
int32_t ddsi;
int32_t ddsr;
int32_t xi;
int32_t xr;
struct sdr_TAP * anonym;
struct sdr_TAP * anonym0;
struct sdr_TAP * anonym1;
struct sdr_TAP * anonym2;
{ /* with */
struct sdr_TAP * anonym = &rx->tapre;
r1 = anonym->uc1;
r2 = anonym->uc2;
r3 = anonym->il;
}
{ /* with */
struct sdr_TAP * anonym0 = &rx->tapim;
i1 = anonym0->uc1;
i2 = anonym0->uc2;
i3 = anonym0->il;
}
ph = rx->phase;
dfc = (uint32_t)((uint32_t)(rx->df+(uint32_t)rx->afckhz)&ddslen);
i = a;
do {
xr = (int32_t)iqbuf[i]-127L;
++i;
xi = (int32_t)iqbuf[i]-127L;
++i;
ddsr = (int32_t)DDS[ph]; /* mix osz sin */
ddsi = (int32_t)DDS[(uint32_t)((uint32_t)(ph+ddslen4)&ddslen)];
/* mix osz cos */
ph = (uint32_t)((uint32_t)(ph+dfc)&ddslen); /* drive mix osz */
r1 += ((xr*ddsr-xi*ddsi)-r1)-r3>>3; /* mixer + lowpass i */
r2 += r3-r2>>3;
r3 += r1-r2>>2;
i1 += ((xr*ddsi+xi*ddsr)-i1)-i3>>3; /* mixer + lowpass q */
i2 += i3-i2>>3;
i3 += i1-i2>>2;
} while (i<=b);
{ /* with */
struct sdr_TAP * anonym1 = &rx->tapre;
anonym1->uc1 = r1;
anonym1->uc2 = r2;
anonym1->il = r3;
anonym1->ucr2 = (float)r2;
}
{ /* with */
struct sdr_TAP * anonym2 = &rx->tapim;
anonym2->uc1 = i1;
anonym2->uc2 = i2;
anonym2->il = i3;
anonym2->ucr2 = (float)i2;
}
rx->phase = ph;
} /* end iir8() */
#define sdr_FG6 128
static void iirvar(sdr_pRX rx, uint32_t a, uint32_t b, float bw)
/* variable bandwidth */
{
uint32_t dfc;
uint32_t ph;
uint32_t i;
float ddsi;
float ddsr;
float bw2;
float i3;
float i2;
float i1;
float r3;
float r2;
float r1;
float xi;
float xr;
/*WrFixed(bw, 5,1);WrStrLn(""); */
struct sdr_TAP * anonym;
struct sdr_TAP * anonym0;
struct sdr_TAP * anonym1;
struct sdr_TAP * anonym2;
{ /* with */
struct sdr_TAP * anonym = &rx->tapre;
r1 = anonym->ucr1;
r2 = anonym->ucr2;
r3 = anonym->ilr;
}
{ /* with */
struct sdr_TAP * anonym0 = &rx->tapim;
i1 = anonym0->ucr1;
i2 = anonym0->ucr2;
i3 = anonym0->ilr;
}
ph = rx->phase;
dfc = rx->df+(uint32_t)rx->afckhz;
i = a;
bw2 = bw*2.0f;
do {
xr = (float)iqbuf[i]-127.5f;
++i;
xi = (float)iqbuf[i]-127.5f;
++i;
ddsr = DDSR[ph]; /* mix osz sin */
ddsi = DDSR[(uint32_t)((uint32_t)(ph+ddslen4)&ddslen)];
/* mix osz cos */
ph = (uint32_t)((uint32_t)(ph+dfc)&ddslen); /* drive mix osz */
r1 = r1+(((xr*ddsr-xi*ddsi)-r1)-r3)*bw; /* mixer + lowpass i */
r2 = r2+(r3-r2)*bw;
r3 = r3+(r1-r2)*bw2;
i1 = i1+(((xr*ddsi+xi*ddsr)-i1)-i3)*bw; /* mixer + lowpass q */
i2 = i2+(i3-i2)*bw;
i3 = i3+(i1-i2)*bw2;
} while (i<=b);
{ /* with */
struct sdr_TAP * anonym1 = &rx->tapre;
anonym1->ucr1 = r1;
anonym1->ucr2 = r2;
anonym1->ilr = r3;
anonym1->ucr2 = r2;
}
{ /* with */
struct sdr_TAP * anonym2 = &rx->tapim;
anonym2->ucr1 = i1;
anonym2->ucr2 = i2;
anonym2->ilr = i3;
anonym2->ucr2 = i2;
}
rx->phase = ph;
} /* end iirvar() */
/*
PROCEDURE genfirtab(VAR t:ARRAY OF REAL; fg:REAL);
VAR i,f,h:CARDINAL;
f1, e:REAL;
BEGIN
h:=(HIGH(t)+1) DIV 2;
FOR i:=0 TO h-1 DO t[h+i]:=0.5 END;
f1:=fg*FLOAT(h);
FOR f:=1 TO TRUNC(f1)+1 DO
e:=1.0;
IF f=TRUNC(f1)+1 THEN e:=f1-FLOAT(TRUNC(f1)) END;
FOR i:=0 TO h-1 DO t[i+h]:=t[i+h]+e*cos(pi*FLOAT(i*f)/FLOAT(h)) END;
END;
FOR i:=0 TO h-1 DO
e:=0.54+0.46*cos(pi*(FLOAT(i)/FLOAT(h)));
t[i+h]:=t[i+h]*e END; (* hamming window *)
FOR i:=0 TO h-1 DO t[h-i-1]:=t[i+h] END;
--FOR i:=0 TO HIGH(t) DO WrFixed(t[i], 2,0); WrStr(" ") END; WrStrLn("");
END genfirtab;
PROCEDURE fir(rx:pRX; VAR u:Complex);
VAR i,j:CARDINAL;
BEGIN
WITH rx^ DO
i:=ifp;
ifre[i]:=u.Re;
ifim[i]:=u.Im;
u.Re:=0.0;
u.Im:=0.0;
FOR j:=0 TO HIGH(iftab) DO
i:=(i+1) MOD (HIGH(iftab)+1);
u.Re:=u.Re + ifre[i]*iftab[j];
u.Im:=u.Im + ifim[i]*iftab[j];
END;
ifp:=(i+1) MOD (HIGH(iftab)+1);
END;
END fir;
*/
static void ssbiir(struct sdr_SSBTAP * tap, float fg, float fgq,
float * u)
{
struct sdr_SSBTAP * anonym;
{ /* with */
struct sdr_SSBTAP * anonym = tap;
anonym->uc1 = (anonym->uc1+(*u-anonym->uc1)*fg)-anonym->il;
anonym->uc2 = (anonym->uc2+anonym->il)-anonym->il2;
anonym->uc3 = (anonym->uc3+anonym->il2)-anonym->uc3*fg;
anonym->il = anonym->il+(anonym->uc1-anonym->uc2)*fgq;
anonym->il2 = anonym->il2+(anonym->uc2-anonym->uc3)*fgq;
*u = anonym->uc3;
}
} /* end ssbiir() */
static void rotvector(struct Complex * v, float rr, float ri)
{
float t;
t = v->Re*rr-v->Im*ri;
v->Im = v->Re*ri+v->Im*rr;
v->Re = t;
} /* end rotvector() */
static short getsamp(sdr_pRX rx, char notfirst)
{
struct Complex abs0;
struct Complex u;
float af;
float w;
float l;
float lev;
u.Re = rx->tapre.ucr2;
u.Im = rx->tapim.ucr2;
/* fine shift rest of full 1khz */
if (rx->fine>0UL) {
rx->fracphase = (uint32_t)((uint32_t)(rx->fracphase+rx->fine) &0x7FFUL);
rotvector(&u, SSBDDS[rx->fracphase], SSBDDS[(uint32_t)((uint32_t)(rx->fracphase+512UL) &0x7FFUL)]);
}
/* fine shift rest of full 1khz */
/* additional IF fir */
if (rx->modulation=='s') {
/* ssb */
/* additional IF fir */
ssbiir(&rx->ssbre, rx->ssbfg, rx->ssbfgq, &u.Re);
ssbiir(&rx->ssbim, rx->ssbfg, rx->ssbfgq, &u.Im);
/* additional IF fir */
/* rssi */
lev = 1.0f+u.Re*u.Re+u.Im*u.Im;
l = lev-rx->rssit[0];
if (l>=0.0f) l = l*0.1f;
else l = l*rx->agcspeed;
rx->rssit[0] = rx->rssit[0]+l;
/* rssi */
/* ssb */
rx->bfophase = (uint32_t)((uint32_t)(rx->bfophase+rx->bfo)&0x7FFUL)
;
af = X2C_DIVR((u.Re*SSBDDS[rx->bfophase]-u.Im*SSBDDS[(uint32_t)
((uint32_t)(rx->bfophase+512UL)&0x7FFUL)])*25000.0f,
osic_sqrt(rx->rssit[0]));
}
else {
/* ssb */
/* AM FM */
/* rssi */
lev = 1.0f+u.Re*u.Re+u.Im*u.Im;
l = lev-rx->rssit[0];
rx->rssit[0] = rx->rssit[0]+l*0.001f;
/* rssi */
/* complex to phase */
abs0.Re = (float)fabs(u.Re);
abs0.Im = (float)fabs(u.Im);
if (abs0.Im>abs0.Re) {
if (abs0.Im>0.0f) w = X2C_DIVR(abs0.Re,abs0.Im);
else w = 0.0f;
w = 1.5707963267949f-(w*1.055f-w*w*0.267f); /* arctan */
}
else {
if (abs0.Re>0.0f) w = X2C_DIVR(abs0.Im,abs0.Re);
else w = 0.0f;
w = w*1.055f-w*w*0.267f;
}
if (u.Re<0.0f) w = 3.1415926535898f-w;
if (u.Im<0.0f) w = -w;
/* complex to phase */
/* phase highpass make FM */
af = w-rx->w1;
rx->w1 = w;
if (af>3.1415926535898f) af = af-6.2831853071796f;
if (af<(-3.1415926535898f)) af = af+6.2831853071796f;
/* phase highpass make FM */
if (rx->modulation=='a') {
/* am squelch */
if (rx->squelch) {
if (notfirst) rx->sqsum = rx->sqsum+(float)fabs(rx->a1-af);
rx->a1 = af;
}
/* am squelch */
/* am demod */
lev = osic_sqrt(lev); /* amplitude */
af = lev-rx->lastlev; /* - median aplitude */
rx->lastlev = rx->lastlev+af*0.001f;
af = (X2C_DIVR(af,rx->lastlev))*32000.0f; /* agc */
}
else {
/* am demod */
/* fm squelch */
if (rx->squelch) {
if (notfirst) {
rx->sqsum = rx->sqsum+X2C_DIVR((float)fabs(rx->lastlev-lev),rx->lastlev+lev);
}
rx->lastlev = lev;
}
/* fm squelch */
af = af*7.9577471545948E+3f;
}
}
if (af>32000.0f) af = 32000.0f;
else if (af<(-3.2E+4f)) af = (-3.2E+4f);
return (short)X2C_TRUNCI(af,-32768,32767);
} /* end getsamp() */
#define sdr_FINESTEP 1024
extern int32_t sdr_getsdr(uint32_t samps, sdr_pRX rx[],uint32_t rx_len)
{
uint32_t wssb;
uint32_t ws;
uint32_t bs;
uint32_t as;
uint32_t b;
uint32_t a;
uint32_t r;
uint32_t s;
int32_t u;
struct sdr_RX * anonym;
struct sdr_RX * anonym0;
uint32_t tmp;
if (reconnect && fd<0L) {
usleep(1000000UL);
fd = connecttob(url, port);
}
if (fd>=0L) {
sampsum = sampsum&1023UL; /* partial sample reminder of last block */
if (samps*(sampsize+1UL)>32768UL) samps = 32768UL/(sampsize+1UL);
if (readsockb(fd, (char *)iqbuf,
(int32_t)(((samps*reduce+sampsum)/1024UL)*2UL))<0L) {
/* connect lost */
osic_Close(fd);
fd = -1L;
return -1L;
}
a = sampsum; /* continue from last partial step */
tmp = samps-1UL;
s = 0UL;
if (s<=tmp) for (;; s++) {
r = 0UL;
b = a+reduce;
as = (a/1024UL)*2UL;
bs = (b/1024UL)*2UL-2UL;
while (rx[r]) {
{ /* with */
struct sdr_RX * anonym = rx[r];
ws = anonym->width;
if (anonym->modulation=='s') {
wssb = (anonym->width*5UL)/4UL;
ws = 3000UL;
while (ws<wssb) ws = ws*2UL;
/*WrInt(ws, 0);WrStrLn(" ws"); */
anonym->ssbfg = X2C_DIVR((float)anonym->width,(float)audiohz);
anonym->ssbfgq = anonym->ssbfg*anonym->ssbfg*2.0f;
anonym->bfo = ((uint32_t)labs(anonym->maxafc)*2048UL)/audiohz;
if (anonym->maxafc>0L) anonym->bfo = 2048UL-anonym->bfo;
/*WrInt(bfo, 0);WrStrLn(" bfo"); */
anonym->fine = (anonym->dffrac*2048UL)/audiohz;
if (anonym->agc>0UL) {
anonym->agcspeed = X2C_DIVR(0.2f,(float)anonym->agc);
}
else anonym->agcspeed = 0.00025f;
}
else {
anonym->fine = 0UL;
anonym->agcspeed = 0.001f;
}
if (rtlhz<2048000UL) ws = ws*2UL;
if (ws==3000UL) iir512(rx[r], as, bs);
else if (ws==6000UL) iir256(rx[r], as, bs);
else if (ws==12000UL) iir128(rx[r], as, bs);
else if (ws==24000UL) iir64(rx[r], as, bs);
else if (ws==48000UL) iir32(rx[r], as, bs);
else if (ws==96000UL) iir16(rx[r], as, bs);
else if (ws==192000UL) iir8(rx[r], as, bs);
else iirvar(rx[r], as, bs, (float)ws*6.7934782608696E-7f);
u = (int32_t)getsamp(rx[r], s>0UL)+anonym->shiftf; //+/-AFC w Hz
// printf("\r\nSH:%i\r\n",anonym->shiftf);
anonym->samples[s] = (short)u;
anonym->median = anonym->median+u; /* afc */
}
++r;
}
a = b;
if (s==tmp) break;
} /* end for */
sampsum = a;
/*AFC */
r = 0UL;
while (rx[r]) {
{ /* with */
struct sdr_RX * anonym0 = rx[r];
if (anonym0->modulation=='f' && anonym0->maxafc>0L) {
anonym0->median = anonym0->median-(anonym0->afckhz*(int32_t)samps*1024L)/anonym0->maxafc; /* weak pull to middle */
if (anonym0->median>400000000L) {
if (anonym0->afckhz<anonym0->maxafc) {
++anonym0->afckhz;
}
anonym0->median = 0L;
}
else if (anonym0->median<-400000000L) {
if (anonym0->afckhz>-anonym0->maxafc) --anonym0->afckhz;
anonym0->median = 0L;
}
}
}
++r;
}
/*AFC */
return (int32_t)samps;
}
else return -1L;
return 0;
} /* end getsdr() */
extern void sdr_setparm(uint32_t num, uint32_t value)
{
int32_t res;
char tbuf[5];
tbuf[0U] = (char)num;
tbuf[1U] = (char)(value/16777216UL);
tbuf[2U] = (char)(value/65536UL&255UL);
tbuf[3U] = (char)(value/256UL&255UL);
tbuf[4U] = (char)(value&255UL);
res = sendsock(fd, tbuf, 5L);
} /* end setparm() */
extern char sdr_startsdr(char ip[], uint32_t ip_len,
char tport[], uint32_t tport_len, uint32_t inhz,
uint32_t outhz, char reconn)
{
aprsstr_Assign(url, 1001ul, ip, ip_len);
aprsstr_Assign(port, 11ul, tport, tport_len);
reconnect = reconn;
if (inhz>0UL) rtlhz = inhz;
if (rtlhz!=1024000UL && (rtlhz<2048000UL || rtlhz>2500000UL)) return 0;
if (outhz>0UL) audiohz = outhz;
reduce = (1024UL*rtlhz+audiohz/2UL)/audiohz; /* sample reduction * 1024 */
sampsize = reduce/1024UL; /* input samples per output sample, trunc */
if (fd<0L) fd = connecttob(url, port);
if (fd>=0L) {
sdr_setparm(2UL, rtlhz);
if (inhz>=2048000UL) initdds(2048UL);
else initdds(1024UL);
initssbdds(SSBDDS, 2048ul);
}
return fd>=0L;
} /* end startsdr() */
extern void sdr_BEGIN(void)
{
static int sdr_init = 0;
if (sdr_init) return;
sdr_init = 1;
if (sizeof(sdr_AUDIOSAMPLE)!=131072) X2C_ASSERT(0);
aprsstr_BEGIN();
osi_BEGIN();
fd = -1L;
reconnect = 0;
rtlhz = 2048000UL;
audiohz = 16000UL;
}