spdxl/src/sdrtest.c

1227 wiersze
35 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 X2C_H_
#include "X2C.h"
#endif
#define sdrtest_C_
#ifndef osi_H_
#include "osi.h"
#endif
#include <osic.h>
#ifndef aprsstr_H_
#include "aprsstr.h"
#endif
#ifndef sdr_H_
#include "sdr.h"
#endif
#include <stdio.h>
#include "sondetypes.h"
/* test rtl_tcp iq fm demodulator by OE5DXL */
#define sdrtest_MAXCHANNELS 64
#define sdrtest_DEFAULTPOWERSAVE 0
#define sdrtest_SAMPSIZE 32
/* samples per sdr call */
#define sdrtest_TUNESTEP 1000
/* minimal tuning step */
#define sdrtest_TUNEBAND 200000
/* step to minimize freq jumps from inexact pll */
#define sdrtest_DEFAULTMAXWAKE 2000
/* ms stay awake after squelch close */
struct FREQTAB;
struct FREQTAB {
/* khz, */
uint32_t hz;
uint32_t width;
uint32_t agc;
int32_t afc;
int32_t shiftf;
char modulation;
int st;
};
struct STICKPARM;
struct STICKPARM {
uint32_t val;
char ok0;
char changed;
};
struct SQUELCH;
struct SQUELCH {
float lev;
float lp;
float u1;
float u2;
float il;
float medmed;
float mutlev;
int32_t sqsave;
int32_t wakeness;
int32_t pcmc;
uint32_t nexttick;
uint32_t waterp;
uint32_t waterdat[16];
};
static int32_t fd;
static uint32_t sndw;
static uint32_t freqc;
static uint32_t midfreq;
static uint32_t lastmidfreq;
static uint32_t downsamp;
static uint32_t mixto;
static uint32_t powersave;
static short sndbuf[1024],sndbufft[1024];
static uint8_t sndbuf8[1024];
static struct sdr_RX rxx[64];
static sdr_pRX prx[65];
static short sampx[64][32];
static struct STICKPARM stickparm[256];
static struct SQUELCH squelchs[65];
static uint32_t iqrate;
static uint32_t samphz;
static uint32_t maxrx;
static uint32_t maxwake;
static char url[1001];
static char port[1001];
static char soundfn[1001];
static char parmfn[1001];
static char verb;
static char reconn;
static char pcm8;
static char nosquelch;
static double offset;
static int wtfno;
time_t oldMTime;
static void card(const char s[], uint32_t s_len, uint32_t * p,
uint32_t * n, char * ok0)
{
*ok0 = 0;
*n = 0UL;
while ((uint8_t)s[*p]>='0' && (uint8_t)s[*p]<='9') {
*n = ( *n*10UL+(uint32_t)(uint8_t)s[*p])-48UL;
*ok0 = 1;
++*p;
}
} /* end card() */
static void cardi(const char s[], uint32_t s_len, uint32_t * p, int32_t * n, char * ok0)
{
*ok0 = 0;
*n = 0UL;
int32_t mn=1;
if(s[*p]=='-'){
mn=-1;
++*p;
}
while ((uint8_t)s[*p]>='0' && (uint8_t)s[*p]<='9') {
*n = ( *n*10UL+(int32_t)(uint8_t)s[*p])-48UL;
*ok0 = 1;
++*p;
}
*n*=mn;
} /* end card() */
static void int0(const char s[], uint32_t s_len, uint32_t * p,
int32_t * n, char * ok0)
{
char sgn;
uint32_t c;
if (s[*p]=='-') {
sgn = 1;
++*p;
}
else sgn = 0;
card(s, s_len, p, &c, ok0);
if (sgn) *n = -(int32_t)c;
else *n = (int32_t)c;
} /* end int() */
static void fix(const char s[], uint32_t s_len, uint32_t * p,
double * x, char * ok0)
{
double m;
char sgn;
if (s[*p]=='-') {
sgn = 1;
++*p;
}
else sgn = 0;
m = 1.0;
*ok0 = 0;
*x = 0.0;
while ((uint8_t)s[*p]>='0' && (uint8_t)s[*p]<='9' || s[*p]=='.') {
if (s[*p]=='.') m = 0.1;
else if (m==1.0) {
*x = *x*10.0+(double)((uint32_t)(uint8_t)s[*p]-48UL);
}
else {
*x = *x+(double)((uint32_t)(uint8_t)s[*p]-48UL)*m;
m = m*0.1;
}
*ok0 = 1;
++*p;
}
if (sgn) *x = -*x;
} /* end fix() */
static void Parms(void)
{
char s[1001];
uint32_t n;
uint32_t m;
int32_t ni;
char ok0;
reconn = 0;
verb = 0;
pcm8 = 0;
downsamp = 0UL;
mixto = 0UL;
strncpy(url,"127.0.0.1",1001u);
strncpy(port,"1234",1001u);
soundfn[0] = 0;
iqrate = 2048000UL;
samphz = 16000UL;
offset = 0.0;
strncpy(parmfn,"sdrcfg.txt",1001u);
powersave = 0UL;
maxrx = 63UL;
nosquelch = 0;
/* watermark:=FALSE; */
maxwake = 2000UL;
for (;;) {
osi_NextArg(s, 1001ul);
if (s[0U]==0) break;
if ((s[0U]=='-' && s[1U]) && s[2U]==0) {
if (s[1U]=='s') {
osi_NextArg(soundfn, 1001ul);
pcm8 = 0;
}
else if (s[1U]=='S') {
osi_NextArg(soundfn, 1001ul);
pcm8 = 1;
}
else if (s[1U]=='c') osi_NextArg(parmfn, 1001ul);
else if (s[1U]=='o') {
/* offset */
osi_NextArg(s, 1001ul);
n = 0UL;
fix(s, 1001ul, &n, &offset, &ok0);
if (!ok0) printf(" -o <MHz>\n");
}
else if (s[1U]=='d') {
/* sampelrate to output divide */
osi_NextArg(s, 1001ul);
if (!aprsstr_StrToCard(s, 1001ul, &downsamp) || downsamp<1UL) {
printf(" -p <ratio>\n");
}
--downsamp;
}
else if (s[1U]=='m') {
/* downmix to */
osi_NextArg(s, 1001ul);
if ((!aprsstr_StrToCard(s, 1001ul,
&mixto) || mixto<1UL) || mixto>2UL) {
printf(" -m <1..2>\n");
}
}
else if (s[1U]=='a') {
/* maximal active rx */
osi_NextArg(s, 1001ul);
if (!aprsstr_StrToCard(s, 1001ul, &maxrx)) {
printf(" -a <number>\n");
}
}
else if (s[1U]=='t') {
osi_NextArg(s, 1001ul); /* url */
n = 0UL;
while ((n<1000UL && s[n]) && s[n]!=':') {
if (n<1000UL) url[n] = s[n];
++n;
}
if (n>1000UL) n = 1000UL;
url[n] = 0;
if (s[n]==':') {
m = 0UL;
++n;
while ((n<1000UL && s[n]) && m<1000UL) {
port[m] = s[n];
++n;
++m;
}
if (m>1000UL) m = 1000UL;
port[m] = 0;
}
}
else if (s[1U]=='r') {
/* sampelrate */
osi_NextArg(s, 1001ul);
if (!aprsstr_StrToCard(s, 1001ul, &samphz) || samphz>192000UL) {
printf(" -r <Hz>\n");
}
}
else if (s[1U]=='i') {
/* iq sampelrate */
osi_NextArg(s, 1001ul);
if (!aprsstr_StrToCard(s, 1001ul,&iqrate) || iqrate!=1024000UL && (iqrate<2048000UL || iqrate>2500000UL)
) printf(" -i <Hz> 2048000 or 1024000\n");
}
else if (s[1U]=='v') verb = 1;
else if (s[1U]=='k') reconn = 1;
else if (s[1U]=='w') {
/* maximum wake time */
osi_NextArg(s, 1001ul);
if (!aprsstr_StrToCard(s, 1001ul, &maxwake)) {
printf(" -w <ms>\n");
}
}
else if (s[1U]=='z') {
/* powersave time */
osi_NextArg(s, 1001ul);
if (!aprsstr_StrToCard(s, 1001ul, &powersave)) {
printf(" -z <ms>\n");
}
nosquelch = 0;
}
else if (s[1U]=='Z') {
/* powersave time */
osi_NextArg(s, 1001ul);
if (!aprsstr_StrToCard(s, 1001ul, &powersave)) {
printf(" -Z <ms>\n");
}
nosquelch = 1;
}
else if (s[1U]=='n') {
/* powersave time */
osi_NextArg(s, 1001ul);
if (!aprsstr_StrToCard(s, 1001ul, &wtfno)) {
printf(" -n <number>\n");
}
nosquelch = 0;
}
else {
if (s[1U]=='h') {
printf("\n\nAM/FM/SSB Multirx from rtl_tcp (8 bit IQ via tcpip) to audio channel(s) 8/16 bit PCM\n");
printf(" -a <number> maximum active rx to limit cpu load, if number is reached,\n");
printf(" no more inactive rx will listen to become active\n");
printf(" -c <configfilename> read channels config from file (sdrcfg.txt)\n");
printf(" -d <ratio> downsample output (1)\n");
printf(" -h help\n");
printf(" -i <kHz> input sampelrate kHz 1024000 or 2048000..2500000 (2048000)\n");
printf(" if >2048000, AM/FM-IF-width will increase proportional\n");
printf(" -k keep connection\n");
printf(" -m <audiochannels> mix up/down all rx channels to 1 or 2 audiochannels (mono/stereo)\n");
printf(" for 2 channels the rx audios will be arranged from left to right\n");
printf(" -o <mhz> offset for entered frequencies if Converters are used\n");
printf(" -p <cmd> <value> send rtl_tcp parameter, ppm, tunergain ...\n");
printf(" -r <Hz> output sampelrate Hz for all channels 8000..192000 (16000)\n");
printf(" -s <soundfilename> 16bit signed n-channel sound stream/pipe\n");
printf(" -S <soundfilename> 8bit unsigned n-channel sound stream/pipe\n");
printf(" -t <url:port> connect rtl_tcp server (127.0.0.1:1234)\n");
printf(" -v show rssi (dB) and afc (khz)\n");
printf(" -w <ms> max stay awake (use CPU) time after squelch close (2000)\n");
printf(" -z <ms> sleep time (no cpu) for inactive rx if squelch closed (-z 100)\n");
printf(" -Z <ms> same but fast open with no audio quieting for sending\n");
printf(" to decoders and not human ears\n");
printf(" -n <number> save waterfall to /tmp/wtf<number>.bin\n");
printf("example: -m 1 -d 2 -S /dev/dsp -t 127.0.0.1:1234 -p 5 72 -p 8 1 -v\n\n");
printf("config file: (re-read every some seconds and may be modified any time)\n");
printf(" # comment\n");
printf(" p <cmd> <value> rtl_tcp parameter like \'p 5 50\' ppm, \'p 8 1\' autogain on\n");
printf(" f <mhz> <AFC-range> <squelch%> <lowpass%> <IF-width> FM Demodulator\n");
printf(" a <mhz> 0 <squelch%> <lowpass%> <IF-width> AM Demodulator\n");
printf(" u <mhz> <IF-shift> 0 <agc speed> <IF-width> USB Demodulator\n");
printf(" l same for LSB\n");
printf(" AFC-range in +-kHz, offset to AFC +- in Hz, Squelch 0 off, 100 open, 70 may do\n");
printf(" audio lowpass in % Nyquist frequ. of output sampelrate, 0 is off\n");
printf(" IF-width 3000 6000 12000 24000 48000 96000 192000Hz for low CPU usage\n");
printf(" (192000 only with >=2048khz iq-rate), (4th order IIR)\n");
printf(" (SSB 8th order IF-IIR), OTHER values with MORE CPU-load (12000 default)\n\n");
printf(" example:\n");
printf(" p 5 50\n");
printf(" p 8 1\n");
printf(" f 438.825 5 -5000 75 70 (afc, offset to afc in Hz, squelch, audio lowpass, 12khz IF)\n");
printf(" f 439.275 0 0 0 80 20000 (20khz IF, uses more CPU)\n");
printf(" u 439.5001 -700 0 0 600 (USB with 600Hz CW-Filter at 800Hz\n\n");
printf(" will generate 3 channel 16bit PCM stream (up to 64 channels with -z or -Z)\n");
printf(" use max. 95% of -i span. Rtl-stick will be tuned to center of the span\n");
printf(" rx in center of band will be +-10khz relocated to avoid ADC-DC offset pseudo\n");
printf(" carriers, SSB-only will be relocated 10..210khz to avoid inexact tuning steps\n\n");
printf(" f 100.1 0 0 15 96000 (WFM with \"-r 192000 -d 4\" for 1 channnel 48khz\n\n");
exit(0);
}
if (s[1U]=='p') {
osi_NextArg(s, 1001ul);
if (aprsstr_StrToCard(s, 1001ul, &m) && m<256UL) {
osi_NextArg(s, 1001ul);
if (aprsstr_StrToInt(s, 1001ul, &ni)) {
stickparm[m].val = (uint32_t)ni; /* stick parameter */
stickparm[m].ok0 = 1;
stickparm[m].changed = 1;
}
else printf(" -p <cmd> <value>");
}
else {
printf(" -p <cmd> <value>\n");
}
}
else printf("-h\n");
}
}
else printf("-h\n");
}
powersave = (powersave*samphz)/32000UL;
maxwake = (maxwake*samphz)/32000UL;
} /* end Parms() */
static void setparms(char all)
{
uint32_t i;
char nl;
char s[31];
nl = 1;
for (i = 0UL; i<=255UL; i++) {
if (stickparm[i].ok0 && (all || stickparm[i].changed)) {
sdr_setparm(i, stickparm[i].val);
if (verb) {
if (nl) {
printf("\n");
nl = 0;
}
printf("parm:%i %i\n",i,stickparm[i].val);
/*skp aprsstr_IntToStr((int32_t)i, 0UL, s, 31ul);
osi_Werr(s, 31ul);
osi_Werr(" ", 2ul);
aprsstr_IntToStr((int32_t)stickparm[i].val, 0UL, s, 31ul);
osi_WerrLn(s, 31ul);
*/
}
}
stickparm[i].changed = 0;
} /* end for */
} /* end setparms() */
static void setstickparm(uint32_t cmd, uint32_t value)
{
if (!stickparm[cmd].ok0 || stickparm[cmd].val!=value) {
stickparm[cmd].val = value;
stickparm[cmd].changed = 1;
}
stickparm[cmd].ok0 = 1;
} /* end setstickparm() */
#define sdrtest_OFFSET 10000
static void centerfreq(const struct FREQTAB freq[], uint32_t freq_len)
{
uint32_t max0;
uint32_t min0;
uint32_t i;
int32_t nomid;
char ssb;
double rem;
double fhz;
double khz;
midfreq = 0UL;
i = 0UL;
max0 = 0UL;
min0 = 0xFFFFFFFF;
while (i<freqc) {
/*WrStr("rx"); WrInt(i+1, 0); WrInt(freq[i].khz, 0); WrStrLn("kHz"); */
if (freq[i].hz>max0) max0 = freq[i].hz;
if (freq[i].hz<min0) min0 = freq[i].hz;
++i;
}
if (max0>=min0) {
if (max0-min0>=iqrate){
printf("freq span > iq-sampelrate\n");
//exit(0);
}
midfreq = (max0+min0)/2UL;
nomid = 0x7FFFFFFF;
i = 0UL;
ssb = 0;
while (i<freqc) {
if (labs((int32_t)(freq[i].hz-midfreq))<labs(nomid)) {
nomid = (int32_t)(freq[i].hz-midfreq);
}
if (freq[i].modulation=='s') ssb = 1;
++i;
}
if (labs(nomid)>10000L) nomid = 0L;
else if (nomid<0L) nomid = 10000L+nomid;
else nomid -= 10000L;
midfreq += (uint32_t)nomid;
if (ssb && max0-min0<200000UL) {
midfreq = (midfreq/200000UL)*200000UL+10000UL;
}
else midfreq = (midfreq/1000UL)*1000UL;
i = 0UL;
while (i<freqc) {
/* FILL(ADR(rxx[i]), 0C, SIZE(rxx[0])); */
prx[i] = &rxx[i];
khz = 1.0;
if (iqrate>2048000UL) khz = 2.048E+6/(double)iqrate;
fhz = (double)((int32_t)freq[i].hz-(int32_t)midfreq)*khz;
rxx[i].df = ((int32_t)X2C_TRUNCI(fhz,(-0x7FFFFFFFL-1),0x7FFFFFFF)/1000L);
rem = fhz-(double)(((int32_t)X2C_TRUNCI(fhz,(-0x7FFFFFFFL-1),0x7FFFFFFF)/1000L)*1000L);
rxx[i].dffrac = (uint32_t)X2C_TRUNCC(rem/khz+0.5,0UL, 0xFFFFFFFF);
/* rxx[i].df:=(freq[i].hz DIV 1000 - midfreq DIV 1000); */
/* rxx[i].dffrac:=(freq[i].hz-rxx[i].df*1000) MOD 1000; */
/*WrInt(nomid, 15);WrInt(midfreq, 15);WrInt(freq[i].hz, 15);
WrInt(rxx[i].df, 15); WrInt(rxx[i].dffrac, 15);
WrStrLn("n m h d fr"); */
rxx[i].maxafc = freq[i].afc;
rxx[i].squelch = squelchs[i].lev!=0.0f;
rxx[i].width = freq[i].width;
rxx[i].agc = freq[i].agc;
rxx[i].modulation = freq[i].modulation;
rxx[i].shiftf=freq[i].shiftf;
rxx[i].st=freq[i].st;
++i;
}
prx[i] = 0;
}
if (midfreq<20000000UL) printf("no valid frequency\n");
else if (midfreq!=lastmidfreq) {
setstickparm(1UL, midfreq);
/*WrStr("set ");WrInt(midfreq, 0); WrStrLn("kHz"); */
lastmidfreq = midfreq;
}
} /* end centerfreq() */
static void skip(const char s[], uint32_t s_len, uint32_t * p)
{
while (s[*p] && s[*p]==' ') ++*p;
} /* end skip() */
// send freq table
static void updateChanT(){
int i,j,l;
char tmp[15],tmp1[25];
double fhz;
double khz;
long int qrg;
khz = 1.0;
if (iqrate>2048000) khz = (double)iqrate/(double)2048000;
double tt;
tt=0;
if(rxx[i].df>0) tt=0.5;
j=0;
while (prx[i]) {
if(j==0){
sndbufft[0]=0;
strcat(sndbufft,"9 S K P ");
}
qrg=midfreq/1000+(int32_t)rxx[i].df*khz+tt;
if(qrg>999000) qrg=(long int)(qrg/10);
rxx[i].afckhz=0; // reset AFC
sprintf(tmp,"%02i%06li%c",i+1,(long int)(qrg),65+rxx[i].st);
tmp1[0]=tmp[0];
tmp1[1]=' ';
tmp1[2]=tmp[1];
tmp1[3]=' ';
tmp1[4]=tmp[2];
tmp1[5]=' ';
tmp1[6]=tmp[3];
tmp1[7]=' ';
tmp1[8]=tmp[4];
tmp1[9]=' ';
tmp1[10]=tmp[5];
tmp1[11]=' ';
tmp1[12]=tmp[6];
tmp1[13]=' ';
tmp1[14]=tmp[7];
tmp1[15]=' ';
tmp1[16]=tmp[8];
tmp1[17]=' ';
tmp1[18]=tmp[9];
tmp1[19]=' ';
tmp1[20]=0;
printf("DEB:%s\n",tmp);
strcat(sndbufft,tmp1);
++i;
j++;
if(j>14){
if(fd){
l=strlen(sndbufft);
sndbufft[l]=0;
sndbufft[l+1]=0;
osi_WrBin(fd, (char *)sndbufft, 1024, 1024);
j=0;
}
}
}
if(fd){
l=strlen(sndbufft);
sndbufft[l]=0;
sndbufft[l+1]=0;
printf(sndbufft);
osi_WrBin(fd, (char *)sndbufft, 1024, 1024);
j=0;
}
}
int file_is_modified(const char *path) {
struct stat file_stat;
float ret;
int err = stat(path, &file_stat);
ret= file_stat.st_mtime > oldMTime;
oldMTime = file_stat.st_mtime;
return (int)ret;
}
static void rdconfig(void)
{
uint32_t fmn=999999999,fmx=0;
int32_t len;
int32_t fd0;
uint32_t sq;
uint32_t wid;
uint32_t lpp;
uint32_t p;
uint32_t lino;
uint32_t n;
uint32_t i;
int32_t ssbsh;
int32_t m;
uint32_t st;
float sqcor;
double x;
char ok0;
char b[10001];
char li[256];
struct FREQTAB freq[64];
char mo;
fd0 = osi_OpenRead(parmfn, 1001ul);
if (fd0>=0L) {
len = osi_RdBin(fd0, (char *)b, 10001u/1u, 10001UL);
if ((len>0L && len<10000L) && (uint8_t)b[len-1L]>=' ') b[len-1L] = 0;
p = 0UL;
lino = 1UL;
freqc = 0UL;
i = 0UL;
while ((int32_t)p<len) {
if ((uint8_t)b[p]>=' ') {
if (i<255UL) {
li[i] = b[p];
++i;
}
}
else if (i>0UL) {
li[i] = 0;
i = 0UL;
skip(li, 256ul, &i);
mo = X2C_CAP(li[i]);
if (mo=='P') {
++i;
skip(li, 256ul, &i);
card(li, 256ul, &i, &n, &ok0);
if (n>255UL || !ok0)
printf("wrong parameter number\n");
else {
skip(li, 256ul, &i);
int0(li, 256ul, &i, &m, &ok0);
if (!ok0) printf("wrong value\n");
else setstickparm(n, (uint32_t)m);
}
i = 0UL;
}
else if (((mo=='F' || mo=='A') || mo=='U') || mo=='L') {
if (mo=='A') freq[freqc].modulation = 'a';
else if (mo=='F') freq[freqc].modulation = 'f';
else if (mo=='U') freq[freqc].modulation = 's';
else if (mo=='L') freq[freqc].modulation = 's';
else freq[freqc].modulation = 'f';
++i;
skip(li, 256ul, &i);
fix(li, 256ul, &i, &x, &ok0);
if (!ok0) printf("wrong MHz\n");
skip(li, 256ul, &i);
int0(li, 256ul, &i, &m, &ok0);
if (!ok0) m = 0L;
ssbsh = 0L;
if (mo=='U') {
m += 1500L;
ssbsh = m;
}
else if (mo=='L') {
m -= 1500L;
ssbsh = m;
}
skip(li, 256ul, &i);
cardi(li, 256ul, &i, &n, &ok0);
if (!ok0) n=0;
skip(li, 256ul, &i);
card(li, 256ul, &i, &sq, &ok0);
if (!ok0) sq = 0UL;
if (sq>200UL) sq = 200UL;
skip(li, 256ul, &i);
card(li, 256ul, &i, &lpp, &ok0);
if (!ok0) lpp = 0UL;
if (freq[freqc].modulation!='s' && lpp>100UL) lpp = 100UL;
skip(li, 256ul, &i);
card(li, 256ul, &i, &wid, &ok0);
if (!ok0) {
if (freq[freqc].modulation=='s') wid = 2800UL;
else if (freq[freqc].modulation=='a') wid = 6000UL;
else wid = 12000UL;
}
if (wid>1000000UL) wid = 1000000UL;
skip(li, 256ul, &i);
card(li, 256ul, &i, &st, &ok0);
if (!ok0) {
st=0;
}
if (freqc>63UL) printf("freq table full\n");
else {
x = x+offset;
if (x<=0.0 || x>=2.147483E+6) {
printf("freq out of range\n");
x = 0.0;
}
x = x*1.E+6+(double)ssbsh;
freq[freqc].hz = (uint32_t)X2C_TRUNCC(x+0.5,0UL, 0xFFFFFFFF);
freq[freqc].afc = m;
freq[freqc].shiftf = n;
freq[freqc].width = wid;
freq[freqc].agc = lpp;
freq[freqc].st=st;
if(freq[freqc].hz>fmx)fmx=freq[freqc].hz;
if(freq[freqc].hz<fmn)fmn=freq[freqc].hz;
printf ("%u AFC:%u, SH:%i, WI:%u AGC:%i, Stype:%i\r\n",freq[freqc].hz,freq[freqc].afc,freq[freqc].shiftf,freq[freqc].width,freq[freqc].agc,freq[freqc].st);
sqcor=32+(192000/(samphz/1.14)-13.68);
squelchs[freqc].lev = X2C_DIVR((float)sq*sqcor,200.0f);
if (freq[freqc].modulation=='s') squelchs[freqc].lp = 0.0f;
else squelchs[freqc].lp = X2C_DIVR((float)lpp,200.0f);
++freqc;
}
i = 0UL;
}
else if (mo=='#' || (uint8_t)mo<=' ') i = 0UL;
else printf("unkown command\n");
++lino;
}
++p;
}
osic_Close(fd0);
if(fmx>403150000 && fmn<403150000){
freq[freqc].hz = (uint32_t)X2C_TRUNCC(403150000+0.5,0UL, 0xFFFFFFFF);
freq[freqc].afc = 20;
freq[freqc].shiftf = 0;
freq[freqc].width = 24000;
freq[freqc].agc = 0;
freq[freqc].st=ST_SKP;
++freqc;
}
}
else printf("config file not readable\n");
centerfreq(freq, 64ul);
} /* end rdconfig() */
static void showrssi(void)
{
int wfall[] = {238,17,18,19,20,21,27,33,39,28,34,40,46,118,154,190,226,208,214,202,198,197,196};
unsigned char k,j, i;
int lvl;
float lvlf;
char s[31],tmp[10];
char fname[30],line[120];
FILE* stream;
double khz;
khz = 1.0;
if (iqrate>2048000) khz = (double)iqrate/(double)2048000;
i = 0UL;
printf("\e[1;1H\e[2J");
printf("Param[1]: %i\n",stickparm[1].val);
printf("Param[5]: %i\n",stickparm[5].val);
printf("Param[8]: %i\n\n",stickparm[8].val);
if(wtfno>0){
sprintf(fname,"/tmp/sdr%d.bin",wtfno);
stream = fopen(fname, "w");
sprintf(line,"1;%i\n",stickparm[1].val);
fputs(line,stream);
sprintf(line,"5;%i\n",stickparm[5].val);
fputs(line,stream);
sprintf(line,"8;%i\n",stickparm[8].val);
fputs(line,stream);
}
printf("Ch.|Freq kHz| RSSI |Shift kHz\n");
printf("-------------------------------------------------\n");
while (prx[i]) {
j = prx[i]->idx;
double tt;
tt=0.0;
if(rxx[j].df>0) tt=0.5;
lvlf=osic_ln((rxx[j].rssit[0]+1.0f)*3.0517578125E-5f)*4.342944819f;
printf("%02i | %li | %2.1f",j+1,(long int)((midfreq/1000+(int32_t)rxx[j].df*khz+tt)),lvlf);
if (squelchs[j].sqsave<=0L) printf("db");
else printf("dB");
if(wtfno>0){
for(k=15;k>0;k--){
rxx[j].rssitf[k]=rxx[j].rssitf[k-1];
}
rxx[j].rssitf[0]=lvlf;
sprintf(line,"%02i;%li;%05i;%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\r\n",j+1,(long int)((midfreq/1000+(int32_t)rxx[j].df*khz+tt)),rxx[j].afckhz,
(unsigned char)rxx[j].rssitf[0],
(unsigned char)rxx[j].rssitf[1],
(unsigned char)rxx[j].rssitf[2],
(unsigned char)rxx[j].rssitf[3],
(unsigned char)rxx[j].rssitf[4],
(unsigned char)rxx[j].rssitf[5],
(unsigned char)rxx[j].rssitf[6],
(unsigned char)rxx[j].rssitf[7],
(unsigned char)rxx[j].rssitf[8],
(unsigned char)rxx[j].rssitf[9],
(unsigned char)rxx[j].rssitf[10],
(unsigned char)rxx[j].rssitf[11],
(unsigned char)rxx[j].rssitf[12],
(unsigned char)rxx[j].rssitf[13],
(unsigned char)rxx[j].rssitf[14],
(unsigned char)rxx[j].rssitf[15]);
fputs(line,stream);
}
lvl=(int)((lvlf-25)/2)-1;
if(lvl>22) lvl=22;
if(lvl<0) lvl=0;
printf(" \e[48;5;%im \e[48;5;0m",wfall[lvl]);
// osi_Werr(tmp,strlen(tmp));
for(k=1;k<16;k++){
if(rxx[j].rssit[k]>22) rxx[j].rssit[k]=22;
if(rxx[j].rssit[k]<0) rxx[j].rssit[k]=0;
printf("\e[48;5;%im \e[48;5;0m",wfall[(int)rxx[j].rssit[k]]);
//osi_Werr(tmp,strlen(tmp));
}
for(k=15;k>0;k--){
rxx[j].rssit[k]=rxx[j].rssit[k-1];
}
rxx[j].rssit[1]=(float)lvl;
/*
IF NOT nosquelch & rxx[j].squelch THEN
Werr(" "); FixToStr(squelchs[j].medmed*(1.0/SAMPSIZE), 3, s);
Werr(s);
END;
*/
if (rxx[j].modulation=='f') {
printf(" | %i\n",rxx[j].afckhz);
// aprsstr_IntToStr(rxx[j].afckhz, 0UL, s, 31ul);
// osi_Werr(s, 31ul);
// osi_Werr(" \n", 2ul);
}
/*Werr(" "); IntToStr(squelchs[j].wakeness, 0, s); Werr(s); Werr(" ");
*/
++i;
}
printf(" \015");
osic_flush();
if(wtfno>0) fclose(stream);
} /* end showrssi() */
static int32_t sp;
static int32_t sn;
static uint32_t rp;
static uint32_t actch;
static uint32_t ticker;
static uint32_t ix;
static uint32_t tshow;
static uint32_t dsamp;
static char recon;
static int32_t pcm;
static int32_t mixleft;
static int32_t mixright;
static int32_t levdiv2;
static void sendaudio(int32_t pcm0, char pcm80, uint32_t ch)
{
if (pcm0>32767L) pcm0 = 32767L;
else if (pcm0<-32767L) pcm0 = -32767L;
if (pcm80) sndbuf8[sndw] = (uint8_t)((uint32_t)(pcm0+32768L)/256UL);
else {
/* code data in watermark */
/*
IF watermark THEN
pcm:=CAST(INTEGER, CAST(SET32, pcm)*SET32{2..15}
); (* use bit 1 *)
WITH squelchs[ch] DO
IF waterp>0 THEN (* data to send *)
wb:=waterdat[waterp]
IF wb*SET32{0}<>SET32{}
) THEN INC(pcm, 2) END; (* send a 1 *)
wb:=SHIFT(wb, -1);
waterdat[waterp]:=wb;
IF wb=SET32{0}) THEN DEC(waterp) END; (* next 9 bit word *)
END;
END;
ELSE
*/
pcm0 = (int32_t)((uint32_t)pcm0&0xFFFEUL);
/*
END;
*/
if (ch==0UL) ++pcm0;
/* code data in watermark */
sndbuf[sndw] = (short)pcm0;
}
++sndw;
if (sndw>1023UL) {
if (pcm80) osi_WrBin(fd, (char *)sndbuf8, 1024u/1u, sndw);
else osi_WrBin(fd, (char *)sndbuf, 2048u/1u, sndw*2UL);
sndw = 0UL;
}
} /* end sendaudio() */
static void userio(void)
{
if (file_is_modified(parmfn)){
rdconfig();
setparms(recon);
updateChanT();
}
recon = 0;
if (verb) showrssi();
} /* end userio() */
static void schedule(void)
{
uint32_t j;
uint32_t i;
i = 0UL;
j = 0UL;
while (j<freqc && i<maxrx) {
/* first append wake rx */
if (squelchs[j].wakeness<=0L) {
/* rx awake */
squelchs[j].nexttick = ticker;
prx[i] = &rxx[j];
++i;
}
++j;
}
j = 0UL;
while (j<freqc && i<maxrx) {
/* then sleeping rx until maxrx */
if (squelchs[j].wakeness>0L && (int32_t)(ticker-squelchs[j].nexttick)
>=0L) {
/* rx run */
squelchs[j].nexttick = ticker;
prx[i] = &rxx[j];
++i;
}
++j;
}
prx[i] = 0;
} /* end schedule() */
X2C_STACK_LIMIT(100000l)
extern int main(int argc, char **argv)
{
int32_t tmp;
X2C_BEGIN(&argc,argv,1,4000000l,8000000l);
sdr_BEGIN();
aprsstr_BEGIN();
osi_BEGIN();
midfreq = 0UL;
lastmidfreq = 0UL;
tshow = 0UL;
levdiv2 = 256L;
memset((char *)rxx,(char)0,sizeof(struct sdr_RX [64]));
memset((char *)stickparm,(char)0,sizeof(struct STICKPARM [256]));
memset((char *)squelchs,(char)0,sizeof(struct SQUELCH [65]));
Parms();
oldMTime=0;
actch = 0UL;
ticker = 0UL;
prx[0U] = 0;
for (freqc = 0UL; freqc<=63UL; freqc++) {
rxx[freqc].samples = (sdr_pAUDIOSAMPLE)sampx[freqc];
rxx[freqc].idx = freqc;
} /* end for */
if (sdr_startsdr(url, 1001ul, port, 1001ul, iqrate, samphz, reconn)) {
rdconfig();
updateChanT();
sndw = 0UL;
fd = osi_OpenWrite(soundfn, 1001ul);
if (fd>=0L) {
recon = 1;
rdconfig();
updateChanT();
for (;;) {
if (tshow==0UL) {
userio();
tshow = samphz/32UL;
}
else --tshow;
schedule();
sn = sdr_getsdr(32UL, prx, 65ul);
if (sn<0L) {
if (verb) {
if (sn==-2L) {
printf("impossible sampelrate conversion\n");
}
else printf("connection lost\n");
}
recon = 1;
if (!reconn) break;
}
else {
rp = 0UL;
while (prx[rp]) {
ix = prx[rp]->idx;
{ /* with */
struct SQUELCH * anonym = &squelchs[ix];
if (anonym->lev==0.0f || prx[rp]->modulation=='s') {
squelchs[ix].mutlev = 1.0f;
}
else {
if (anonym->lev<rxx[ix].sqsum) {
/* noise */
if (anonym->sqsave>0L) {
--anonym->sqsave;
}
else {
if (anonym->wakeness<(int32_t)powersave) {
++anonym->wakeness;
}
anonym->nexttick = ticker+(uint32_t) anonym->wakeness;
}
}
else {
/* squelch open */
if (anonym->sqsave<(int32_t)maxwake) {
++anonym->sqsave;
}
if (anonym->wakeness>-100L) {
--anonym->wakeness;
}
}
if (nosquelch || rxx[ix].modulation=='s') {
anonym->mutlev = 1.0f;
}
else {
anonym->medmed = anonym->medmed+(rxx[ix].sqsum-anonym->medmed)*0.1f;
anonym->mutlev = (anonym->lev-anonym->medmed)*0.3125f;
if (anonym->mutlev<0.0f) {
anonym->mutlev = 0.0f;
}
else if (anonym->mutlev>1.0f) {
anonym->mutlev = 1.0f;
}
}
}
}
rxx[ix].sqsum = 0.0f;
++rp;
}
tmp = sn-1L;
sp = 0L;
if (sp<=tmp) for (;; sp++) {
rp = 0UL;
while (prx[rp]) {
ix = prx[rp]->idx;
{ /* with */
struct SQUELCH * anonym0 = &squelchs[ix];
anonym0->pcmc = (int32_t)rxx[ix].samples[sp];
if (!nosquelch) {
anonym0->pcmc = (int32_t)(short)X2C_TRUNCI((float)anonym0->pcmc*anonym0->mutlev,-32768,32767);
}
/* lowpass */
if (anonym0->lp!=0.0f) {
anonym0->u1 = anonym0->u1+(((float)(anonym0->pcmc*2L)-anonym0->u1)-anonym0->il)*anonym0->lp;
anonym0->u2 = anonym0->u2+(anonym0->il-anonym0->u2)*anonym0->lp;
anonym0->il = anonym0->il+(anonym0->u1-anonym0->u2)*anonym0->lp*2.0f;
anonym0->pcmc = (int32_t)X2C_TRUNCI(anonym0->u2,(-0x7FFFFFFFL-1),0x7FFFFFFF);
}
}
/* lowpass */
++rp;
}
if (dsamp==0UL) {
rp = 0UL;
while (rp<freqc) {
pcm = squelchs[rp].pcmc;
squelchs[rp].pcmc = 0L;
/* channel mixer */
if (mixto==1UL) mixleft += pcm;
else if (mixto==2UL) {
if (freqc<=1UL) {
mixleft = pcm;
mixright = pcm;
}
else {
mixleft += pcm*(int32_t)rp;
mixright += pcm*(int32_t)((freqc-rp)-1UL);
}
}
/* channel mixer */
if (mixto==0UL || rp==0UL) {
if (mixto==0UL || freqc==0UL) {
sendaudio(pcm, pcm8, rp);
}
else {
sendaudio(mixleft*levdiv2>>8, pcm8, rp);
if (mixto==2UL) {
sendaudio(mixright*levdiv2>>8, pcm8, rp);
}
if (labs(mixleft)>32767L || labs(mixright) >32767L) {
if (levdiv2>20L) {
--levdiv2;
}
}
else if (levdiv2<256L) {
++levdiv2;
}
mixleft = 0L;
mixright = 0L;
}
}
++rp;
}
}
if (dsamp==0UL) dsamp = downsamp;
else --dsamp;
if (sp==tmp) break;
} /* end for */
}
++ticker;
}
}
else {
osi_Werr(soundfn, 1001ul);
printf(" sound file open error\n");
}
if (verb) printf("connection lost\n");
}
else printf("not connected\n");
X2C_EXIT();
return 0;
}
X2C_MAIN_DEFINITION